@@ -91,6 +91,7 @@ function tokenize(str, options) {
91
91
} ;
92
92
var create = function ( token ) { currtoken = token ; return true ; } ;
93
93
var parseerror = function ( ) { console . log ( "Parse error at index " + i + ", processing codepoint 0x" + code . toString ( 16 ) + " in state " + state + "." ) ; return true ; } ;
94
+ var catchfire = function ( msg ) { console . log ( "MAJOR SPEC ERROR: " + msg ) ; return true ; }
94
95
var switchto = function ( newstate ) {
95
96
state = newstate ;
96
97
//console.log('Switching to ' + state);
@@ -140,15 +141,14 @@ function tokenize(str, options) {
140
141
else if ( code == 0x2d ) {
141
142
if ( next ( 1 ) == 0x2d && next ( 2 ) == 0x3e ) consume ( 2 ) && emit ( new CDCToken ) ;
142
143
else if ( digit ( next ( ) ) || ( next ( 1 ) == 0x2e && digit ( next ( 2 ) ) ) ) switchto ( "number" ) && reconsume ( ) ;
143
- else if ( namestartchar ( next ( ) ) ) switchto ( "identifier" ) && reconsume ( ) ;
144
- else emit ( new DelimToken ( code ) ) ;
144
+ else switchto ( 'ident' ) && reconsume ( ) ;
145
145
}
146
146
else if ( code == 0x2e ) {
147
147
if ( digit ( next ( ) ) ) switchto ( "number" ) && reconsume ( ) ;
148
148
else emit ( new DelimToken ( code ) ) ;
149
149
}
150
150
else if ( code == 0x2f ) {
151
- if ( next ( ) == 0x2a ) switchto ( "comment" ) ;
151
+ if ( next ( ) == 0x2a ) consume ( ) && switchto ( "comment" ) ;
152
152
else emit ( new DelimToken ( code ) ) ;
153
153
}
154
154
else if ( code == 0x3a ) emit ( new ColonToken ) ;
@@ -161,18 +161,17 @@ function tokenize(str, options) {
161
161
else if ( code == 0x5b ) emit ( new OpenSquareToken ) ;
162
162
else if ( code == 0x5c ) {
163
163
if ( badescape ( next ( ) ) ) parseerror ( ) && emit ( new DelimToken ( code ) ) ;
164
- else switchto ( "identifier" ) && reconsume ( ) ;
164
+ else switchto ( 'ident' ) && reconsume ( ) ;
165
165
}
166
166
else if ( code == 0x5d ) emit ( new CloseSquareToken ) ;
167
167
else if ( code == 0x7b ) emit ( new OpenCurlyToken ) ;
168
168
else if ( code == 0x7d ) emit ( new CloseCurlyToken ) ;
169
169
else if ( digit ( code ) ) switchto ( "number" ) && reconsume ( ) ;
170
170
else if ( code == 0x55 || code == 0x75 ) {
171
171
if ( next ( 1 ) == 0x2b && hexdigit ( next ( 2 ) ) ) consume ( ) && switchto ( "unicode-range" ) ;
172
- else if ( ( next ( 1 ) == 0x52 || next ( 1 ) == 0x72 ) && ( next ( 2 ) == 0x4c || next ( 2 ) == 0x6c ) && ( next ( 3 ) == 0x28 ) ) consume ( 3 ) && switchto ( "url" ) ;
173
- else switchto ( "identifier" ) && reconsume ( ) ;
172
+ else switchto ( 'ident' ) && reconsume ( ) ;
174
173
}
175
- else if ( namestartchar ( code ) ) switchto ( "identifier" ) && reconsume ( ) ;
174
+ else if ( namestartchar ( code ) ) switchto ( 'ident' ) && reconsume ( ) ;
176
175
else if ( eof ( ) ) { emit ( new EOFToken ) ; return tokens ; }
177
176
else emit ( new DelimToken ( code ) ) ;
178
177
break ;
@@ -181,7 +180,7 @@ function tokenize(str, options) {
181
180
if ( currtoken == undefined ) create ( new StringToken ) ;
182
181
183
182
if ( code == 0x22 ) emit ( ) && switchto ( "data" ) ;
184
- else if ( eof ( ) ) parseerror ( ) && emit ( ) && switchto ( "data" ) ;
183
+ else if ( eof ( ) ) parseerror ( ) && emit ( ) && switchto ( "data" ) && reconsume ( ) ;
185
184
else if ( newline ( code ) ) parseerror ( ) && emit ( new BadStringToken ) && switchto ( "data" ) && reconsume ( ) ;
186
185
else if ( code == 0x5c ) {
187
186
if ( badescape ( next ( ) ) ) parseerror ( ) && emit ( new BadStringToken ) && switchto ( "data" ) ;
@@ -217,7 +216,7 @@ function tokenize(str, options) {
217
216
case "hash-rest" :
218
217
if ( namechar ( code ) ) currtoken . append ( code ) ;
219
218
else if ( code == 0x5c ) {
220
- if ( badescape ( next ( ) ) ) parseerror ( ) && emit ( new DelimToken ( 0x23 ) ) && switchto ( "data" ) && reconsume ( ) ;
219
+ if ( badescape ( next ( ) ) ) parseerror ( ) && emit ( ) && switchto ( "data" ) && reconsume ( ) ;
221
220
else currtoken . append ( consumeEscape ( ) ) ;
222
221
}
223
222
else emit ( ) && switchto ( 'data' ) && reconsume ( ) ;
@@ -234,8 +233,9 @@ function tokenize(str, options) {
234
233
235
234
case "at-keyword" :
236
235
if ( code == 0x2d ) {
237
- if ( namestartchar ( next ( ) ) ) consume ( ) && create ( new AtKeywordToken ( [ 0x40 , code ] ) ) && switchto ( 'at-keyword-rest' ) ;
238
- else emit ( new DelimToken ( 0x40 ) ) && switchto ( 'data' ) && reconsume ( ) ;
236
+ if ( namestartchar ( next ( ) ) ) create ( new AtKeywordToken ( 0x2d ) ) && switchto ( 'at-keyword-rest' ) ;
237
+ else if ( next ( 1 ) == 0x5c && ! badescape ( next ( 2 ) ) ) create ( new AtKeywordtoken ( 0x2d ) ) && switchto ( 'at-keyword-rest' ) ;
238
+ else parseerror ( ) && emit ( new DelimToken ( 0x40 ) ) && switchto ( 'data' ) && reconsume ( ) ;
239
239
}
240
240
else if ( namestartchar ( code ) ) create ( new AtKeywordToken ( code ) ) && switchto ( 'at-keyword-rest' ) ;
241
241
else if ( code == 0x5c ) {
@@ -254,32 +254,36 @@ function tokenize(str, options) {
254
254
else emit ( ) && switchto ( 'data' ) && reconsume ( ) ;
255
255
break ;
256
256
257
- case "identifier " :
257
+ case "ident " :
258
258
if ( code == 0x2d ) {
259
- if ( namestartchar ( next ( ) ) ) create ( new IdentifierToken ( code ) ) && switchto ( 'identifier-rest' ) ;
260
- else switchto ( 'data' ) && reconsume ( ) ;
259
+ if ( namestartchar ( next ( ) ) ) create ( new IdentifierToken ( code ) ) && switchto ( 'ident-rest' ) ;
260
+ else if ( next ( 1 ) == 0x5c && ! badescape ( next ( 2 ) ) ) create ( new IdentifierToken ( code ) ) && switchto ( 'ident-rest' ) ;
261
+ else emit ( new DelimToken ( 0x2d ) ) && switchto ( 'data' ) ;
261
262
}
262
- else if ( namestartchar ( code ) ) create ( new IdentifierToken ( code ) ) && switchto ( 'identifier -rest' ) ;
263
+ else if ( namestartchar ( code ) ) create ( new IdentifierToken ( code ) ) && switchto ( 'ident -rest' ) ;
263
264
else if ( code == 0x5c ) {
264
265
if ( badescape ( next ( ) ) ) parseerror ( ) && switchto ( "data" ) && reconsume ( ) ;
265
- else create ( new IdentifierToken ( consumeEscape ( ) ) ) && switchto ( 'identifier -rest' ) ;
266
+ else create ( new IdentifierToken ( consumeEscape ( ) ) ) && switchto ( 'ident -rest' ) ;
266
267
}
267
- else switchto ( 'data' ) && reconsume ( ) ;
268
+ else catchfire ( "Hit the generic 'else' clause in ident state." ) && switchto ( 'data' ) && reconsume ( ) ;
268
269
break ;
269
270
270
- case "identifier -rest" :
271
+ case "ident -rest" :
271
272
if ( namechar ( code ) ) currtoken . append ( code ) ;
272
273
else if ( code == 0x5c ) {
273
274
if ( badescape ( next ( ) ) ) parseerror ( ) && emit ( ) && switchto ( "data" ) && reconsume ( ) ;
274
275
else currtoken . append ( consumeEscape ( ) ) ;
275
276
}
276
- else if ( code == 0x28 ) emit ( new FunctionToken ( currtoken ) ) && switchto ( 'data' ) ;
277
- else if ( whitespace ( code ) && options . transformFunctionWhitespace ) switchto ( 'transform-function-whitespace' ) ;
277
+ else if ( code == 0x28 ) {
278
+ if ( currtoken . ASCIImatch ( 'url' ) ) switchto ( 'url' ) ;
279
+ else emit ( new FunctionToken ( currtoken ) ) && switchto ( 'data' ) ;
280
+ }
281
+ else if ( whitespace ( code ) && options . transformFunctionWhitespace ) switchto ( 'transform-function-whitespace' ) && reconsume ( ) ;
278
282
else emit ( ) && switchto ( 'data' ) && reconsume ( ) ;
279
283
break ;
280
284
281
285
case "transform-function-whitespace" :
282
- if ( whitespace ( code ) ) donothing ( ) ;
286
+ if ( whitespace ( next ( ) ) ) donothing ( ) ;
283
287
else if ( code == 0x28 ) emit ( new FunctionToken ( currtoken ) ) && switchto ( 'data' ) ;
284
288
else emit ( ) && switchto ( 'data' ) && reconsume ( ) ;
285
289
break ;
@@ -313,8 +317,7 @@ function tokenize(str, options) {
313
317
}
314
318
else if ( code == 0x25 ) emit ( new PercentageToken ( currtoken ) ) && switchto ( 'data' ) ;
315
319
else if ( code == 0x45 || code == 0x65 ) {
316
- if ( ! options . scientificNotation ) create ( new DimensionToken ( currtoken , code ) ) && switchto ( 'dimension' ) ;
317
- else if ( digit ( next ( ) ) ) consume ( ) && currtoken . append ( [ 0x25 , code ] ) && switchto ( 'sci-notation' ) ;
320
+ if ( digit ( next ( ) ) ) consume ( ) && currtoken . append ( [ 0x25 , code ] ) && switchto ( 'sci-notation' ) ;
318
321
else if ( ( next ( 1 ) == 0x2b || next ( 1 ) == 0x2d ) && digit ( next ( 2 ) ) ) currtoken . append ( [ 0x25 , next ( 1 ) , next ( 2 ) ] ) && consume ( 2 ) && switchto ( 'sci-notation' ) ;
319
322
else create ( new DimensionToken ( currtoken , code ) ) && switchto ( 'dimension' ) ;
320
323
}
@@ -326,7 +329,7 @@ function tokenize(str, options) {
326
329
}
327
330
else if ( namestartchar ( code ) ) create ( new DimensionToken ( currtoken , code ) ) && switchto ( 'dimension' ) ;
328
331
else if ( code == 0x5c ) {
329
- if ( badescape ( next ) ) emit ( ) && switchto ( 'data' ) && reconsume ( ) ;
332
+ if ( badescape ( next ) ) parseerror ( ) && emit ( ) && switchto ( 'data' ) && reconsume ( ) ;
330
333
else create ( new DimensionToken ( currtoken , consumeEscape ) ) && switchto ( 'dimension' ) ;
331
334
}
332
335
else emit ( ) && switchto ( 'data' ) && reconsume ( ) ;
@@ -336,12 +339,10 @@ function tokenize(str, options) {
336
339
currtoken . type = "number" ;
337
340
338
341
if ( digit ( code ) ) currtoken . append ( code ) ;
339
- else if ( code == 0x2e ) emit ( ) && switchto ( 'data' ) && reconsume ( ) ;
340
342
else if ( code == 0x25 ) emit ( new PercentageToken ( currtoken ) ) && switchto ( 'data' ) ;
341
343
else if ( code == 0x45 || code == 0x65 ) {
342
- if ( ! options . scientificNotation ) create ( new DimensionToken ( currtoken , code ) ) && switchto ( 'dimension' ) ;
343
- else if ( digit ( next ( ) ) ) consume ( ) && currtoken . append ( [ 0x25 , code ] ) && switchto ( 'sci-notation' ) ;
344
- else if ( ( next ( 1 ) == 0x2b || next ( 1 ) == 0x2d ) && digit ( next ( 2 ) ) ) currtoken . append ( [ 0x25 , next ( 1 ) , next ( 2 ) ] ) && consume ( 2 ) && switchto ( 'sci-notation' ) ;
344
+ if ( digit ( next ( ) ) ) consume ( ) && currtoken . append ( [ 0x65 , code ] ) && switchto ( 'sci-notation' ) ;
345
+ else if ( ( next ( 1 ) == 0x2b || next ( 1 ) == 0x2d ) && digit ( next ( 2 ) ) ) currtoken . append ( [ 0x65 , next ( 1 ) , next ( 2 ) ] ) && consume ( 2 ) && switchto ( 'sci-notation' ) ;
345
346
else create ( new DimensionToken ( currtoken , code ) ) && switchto ( 'dimension' ) ;
346
347
}
347
348
else if ( code == 0x2d ) {
@@ -352,8 +353,8 @@ function tokenize(str, options) {
352
353
}
353
354
else if ( namestartchar ( code ) ) create ( new DimensionToken ( currtoken , code ) ) && switchto ( 'dimension' ) ;
354
355
else if ( code == 0x5c ) {
355
- if ( badescape ( next ) ) emit ( ) && switchto ( 'data' ) && reconsume ( ) ;
356
- else create ( new DimensionToken ( currtoken , consumeEscape ) ) && switchto ( 'dimension' ) ;
356
+ if ( badescape ( next ) ) parseerror ( ) && emit ( ) && switchto ( 'data' ) && reconsume ( ) ;
357
+ else create ( new DimensionToken ( currtoken , consumeEscape ( ) ) ) && switchto ( 'dimension' ) ;
357
358
}
358
359
else emit ( ) && switchto ( 'data' ) && reconsume ( ) ;
359
360
break ;
@@ -368,22 +369,26 @@ function tokenize(str, options) {
368
369
break ;
369
370
370
371
case "sci-notation" :
372
+ currtoken . type = "number" ;
373
+
371
374
if ( digit ( code ) ) currtoken . append ( code ) ;
372
375
else emit ( ) && switchto ( 'data' ) && reconsume ( ) ;
373
376
break ;
374
377
375
378
case "url" :
376
- if ( code == 0x22 ) switchto ( 'url-double-quote' ) ;
379
+ if ( eof ( ) ) parseerror ( ) && emit ( new BadURLToken ) && switchto ( 'data' ) ;
380
+ else if ( code == 0x22 ) switchto ( 'url-double-quote' ) ;
377
381
else if ( code == 0x27 ) switchto ( 'url-single-quote' ) ;
378
382
else if ( code == 0x29 ) emit ( new URLToken ) && switchto ( 'data' ) ;
379
383
else if ( whitespace ( code ) ) donothing ( ) ;
380
384
else switchto ( 'url-unquoted' ) && reconsume ( ) ;
381
385
break ;
382
386
383
387
case "url-double-quote" :
384
- if ( currtoken == undefined ) create ( new URLToken ) ;
388
+ if ( ! ( currtoken instanceof URLToken ) ) create ( new URLToken ) ;
385
389
386
- if ( code == 0x22 ) switchto ( 'url-end' ) ;
390
+ if ( eof ( ) ) parseerror ( ) && emit ( new BadURLToken ) && switchto ( 'data' ) ;
391
+ else if ( code == 0x22 ) switchto ( 'url-end' ) ;
387
392
else if ( newline ( code ) ) parseerror ( ) && switchto ( 'bad-url' ) ;
388
393
else if ( code == 0x5c ) {
389
394
if ( newline ( next ( ) ) ) consume ( ) ;
@@ -394,9 +399,10 @@ function tokenize(str, options) {
394
399
break ;
395
400
396
401
case "url-single-quote" :
397
- if ( currtoken == undefined ) create ( new URLToken ) ;
402
+ if ( ! ( currtoken instanceof URLToken ) ) create ( new URLToken ) ;
398
403
399
- if ( code == 0x27 ) switchto ( 'url-end' ) ;
404
+ if ( eof ( ) ) parseerror ( ) && emit ( new BadURLToken ) && switchto ( 'data' ) ;
405
+ else if ( code == 0x27 ) switchto ( 'url-end' ) ;
400
406
else if ( newline ( code ) ) parseerror ( ) && switchto ( 'bad-url' ) ;
401
407
else if ( code == 0x5c ) {
402
408
if ( newline ( next ( ) ) ) consume ( ) ;
@@ -407,15 +413,17 @@ function tokenize(str, options) {
407
413
break ;
408
414
409
415
case "url-end" :
410
- if ( whitespace ( code ) ) donothing ( ) ;
416
+ if ( eof ( ) ) parseerror ( ) && emit ( new BadURLToken ) && switchto ( 'data' ) ;
417
+ else if ( whitespace ( code ) ) donothing ( ) ;
411
418
else if ( code == 0x29 ) emit ( ) && switchto ( 'data' ) ;
412
419
else parseerror ( ) && switchto ( 'bad-url' ) && reconsume ( ) ;
413
420
break ;
414
421
415
422
case "url-unquoted" :
416
- if ( currtoken == undefined ) create ( new URLToken ) ;
423
+ if ( ! ( currtoken instanceof URLToken ) ) create ( new URLToken ) ;
417
424
418
- if ( whitespace ( code ) ) switchto ( 'url-end' ) ;
425
+ if ( eof ( ) ) parseerror ( ) && emit ( new BadURLToken ) && switchto ( 'data' ) ;
426
+ else if ( whitespace ( code ) ) switchto ( 'url-end' ) ;
419
427
else if ( code == 0x29 ) emit ( ) && switchto ( 'data' ) ;
420
428
else if ( code == 0x22 || code == 0x27 || code == 0x28 || nonprintable ( code ) ) parseerror ( ) && switchto ( 'bad-url' ) ;
421
429
else if ( code == 0x5c ) {
@@ -426,10 +434,11 @@ function tokenize(str, options) {
426
434
break ;
427
435
428
436
case "bad-url" :
429
- if ( code == 0x29 ) emit ( new BadURLToken ) && switchto ( 'data' ) ;
437
+ if ( eof ( ) ) parseerror ( ) && emit ( new BadURLToken ) && switchto ( 'data' ) ;
438
+ else if ( code == 0x29 ) emit ( new BadURLToken ) && switchto ( 'data' ) ;
430
439
else if ( code == 0x5c ) {
431
440
if ( badescape ( next ( ) ) ) donothing ( ) ;
432
- else consumeEscape ( )
441
+ else consumeEscape ( ) ;
433
442
}
434
443
else donothing ( ) ;
435
444
break ;
@@ -476,7 +485,7 @@ function tokenize(str, options) {
476
485
break ;
477
486
478
487
default :
479
- console . log ( "Unknown state '" + state + "'" ) ;
488
+ catchfire ( "Unknown state '" + state + "'" ) ;
480
489
}
481
490
}
482
491
}
@@ -568,9 +577,25 @@ StringValuedToken.prototype.append = function(val) {
568
577
return true ;
569
578
}
570
579
StringValuedToken . prototype . finish = function ( ) {
571
- this . value = stringFromCodeArray ( this . value ) ;
580
+ this . value = this . valueAsString ( ) ;
572
581
return this ;
573
582
}
583
+ StringValuedToken . prototype . ASCIImatch = function ( str ) {
584
+ return this . valueAsString ( ) . toLowerCase ( ) == str . toLowerCase ( ) ;
585
+ }
586
+ StringValuedToken . prototype . valueAsString = function ( ) {
587
+ if ( typeof this . value == 'string' ) return this . value ;
588
+ return stringFromCodeArray ( this . value ) ;
589
+ }
590
+ StringValuedToken . prototype . valueAsCodes = function ( ) {
591
+ if ( typeof this . value == 'string' ) {
592
+ var ret = [ ] ;
593
+ for ( var i = 0 ; i < this . value . length ; i ++ )
594
+ ret . push ( this . value . charCodeAt ( i ) ) ;
595
+ return ret ;
596
+ }
597
+ return this . value . filter ( function ( e ) { return e ; } ) ;
598
+ }
574
599
575
600
function IdentifierToken ( val ) {
576
601
this . value = [ ] ;
@@ -584,7 +609,7 @@ function FunctionToken(val) {
584
609
// These are always constructed by passing an IdentifierToken
585
610
this . value = val . finish ( ) . value ;
586
611
}
587
- FunctionToken . prototype = new CSSParserToken ;
612
+ FunctionToken . prototype = new StringValuedToken ;
588
613
FunctionToken . prototype . tokenType = "FUNCTION" ;
589
614
FunctionToken . prototype . toString = function ( ) { return "FUNCTION(" + this . value + ")" ; }
590
615
@@ -633,7 +658,7 @@ NumberToken.prototype.toString = function() {
633
658
return "NUMBER(" + this . value + ")" ;
634
659
}
635
660
NumberToken . prototype . finish = function ( ) {
636
- this . repr = stringFromCodeArray ( this . value ) ;
661
+ this . repr = this . valueAsString ( ) ;
637
662
this . value = this . repr * 1 ;
638
663
if ( Math . abs ( this . value ) % 1 != 0 ) this . type = "number" ;
639
664
return this ;
0 commit comments