@@ -22,6 +22,9 @@ exports.TYPES = {
22
22
UNIDENT : 0x8000 ,
23
23
} ;
24
24
25
+ // CSS global values
26
+ exports . GLOBAL_VALUES = Object . freeze ( [ 'initial' , 'inherit' , 'unset' , 'revert' , 'revert-layer' ] ) ;
27
+
25
28
// regular expressions
26
29
var DIGIT = '(?:0|[1-9]\\d*)' ;
27
30
var NUMBER = `[+-]?(?:${ DIGIT } (?:\\.\\d*)?|\\.\\d+)(?:e-?${ DIGIT } )?` ;
@@ -37,6 +40,7 @@ var calcRegEx =
37
40
38
41
// This will return one of the above types based on the passed in string
39
42
exports . valueType = function valueType ( val ) {
43
+ // see https://webidl.spec.whatwg.org/#LegacyNullToEmptyString
40
44
if ( val === '' || val === null ) {
41
45
return exports . TYPES . NULL_OR_EMPTY_STR ;
42
46
}
@@ -53,7 +57,7 @@ exports.valueType = function valueType(val) {
53
57
return exports . TYPES . CALC ;
54
58
}
55
59
if ( unitRegEx . test ( val ) ) {
56
- const [ , , unit ] = unitRegEx . exec ( val ) ;
60
+ var [ , , unit ] = unitRegEx . exec ( val ) ;
57
61
if ( ! unit ) {
58
62
return exports . TYPES . NUMBER ;
59
63
}
@@ -162,7 +166,7 @@ exports.parseLength = function parseLength(val) {
162
166
format : 'specifiedValue' ,
163
167
} ) ;
164
168
case exports . TYPES . LENGTH : {
165
- const [ , numVal , unit ] = unitRegEx . exec ( val ) ;
169
+ var [ , numVal , unit ] = unitRegEx . exec ( val ) ;
166
170
return `${ parseFloat ( numVal ) } ${ unit } ` ;
167
171
}
168
172
default :
@@ -186,9 +190,10 @@ exports.parsePercent = function parsePercent(val) {
186
190
return cssCalc ( val , {
187
191
format : 'specifiedValue' ,
188
192
} ) ;
189
- case exports . TYPES . PERCENT :
190
- const [ , numVal , unit ] = unitRegEx . exec ( val ) ;
193
+ case exports . TYPES . PERCENT : {
194
+ var [ , numVal , unit ] = unitRegEx . exec ( val ) ;
191
195
return `${ parseFloat ( numVal ) } ${ unit } ` ;
196
+ }
192
197
default :
193
198
if ( varContainedRegEx . test ( val ) ) {
194
199
return val ;
@@ -212,9 +217,10 @@ exports.parseMeasurement = function parseMeasurement(val) {
212
217
format : 'specifiedValue' ,
213
218
} ) ;
214
219
case exports . TYPES . LENGTH :
215
- case exports . TYPES . PERCENT :
216
- const [ , numVal , unit ] = unitRegEx . exec ( val ) ;
220
+ case exports . TYPES . PERCENT : {
221
+ var [ , numVal , unit ] = unitRegEx . exec ( val ) ;
217
222
return `${ parseFloat ( numVal ) } ${ unit } ` ;
223
+ }
218
224
default :
219
225
if ( varContainedRegEx . test ( val ) ) {
220
226
return val ;
@@ -236,7 +242,7 @@ exports.parseInheritingMeasurement = function parseInheritingMeasurement(val) {
236
242
exports . parseUrl = function parseUrl ( val ) {
237
243
var type = exports . valueType ( val ) ;
238
244
if ( type === exports . TYPES . NULL_OR_EMPTY_STR ) {
239
- return val ;
245
+ return '' ;
240
246
}
241
247
var res = urlRegEx . exec ( val ) ;
242
248
// does it match the regex?
@@ -293,10 +299,11 @@ exports.parseUrl = function parseUrl(val) {
293
299
return 'url("' + urlstr + '")' ;
294
300
} ;
295
301
302
+ // NOTE: seems not in use?
296
303
exports . parseString = function parseString ( val ) {
297
304
var type = exports . valueType ( val ) ;
298
305
if ( type === exports . TYPES . NULL_OR_EMPTY_STR ) {
299
- return val ;
306
+ return '' ;
300
307
}
301
308
if ( type !== exports . TYPES . STRING ) {
302
309
return undefined ;
@@ -320,14 +327,38 @@ exports.parseString = function parseString(val) {
320
327
return val ;
321
328
} ;
322
329
323
- exports . parseColor = function parseColor ( val ) {
330
+ exports . parseKeyword = function parseKeyword ( val , validKeywords = [ ] ) {
324
331
var type = exports . valueType ( val ) ;
325
- if ( type === exports . TYPES . NULL_OR_EMPTY_STR || type === exports . TYPES . VAR ) {
332
+ if ( type === exports . TYPES . NULL_OR_EMPTY_STR ) {
333
+ return '' ;
334
+ }
335
+ if ( type === exports . TYPES . VAR ) {
336
+ return val ;
337
+ }
338
+ if ( type !== exports . TYPES . KEYWORD ) {
339
+ return undefined ;
340
+ }
341
+ val = val . toString ( ) . toLowerCase ( ) ;
342
+ if ( validKeywords . includes ( val ) || exports . GLOBAL_VALUES . includes ( val ) ) {
326
343
return val ;
327
344
}
345
+ return undefined ;
346
+ } ;
347
+
348
+ exports . parseColor = function parseColor ( val ) {
349
+ var type = exports . valueType ( val ) ;
350
+ if ( type === exports . TYPES . NULL_OR_EMPTY_STR ) {
351
+ return '' ;
352
+ }
328
353
if ( type === exports . TYPES . UNDEFINED ) {
329
354
return undefined ;
330
355
}
356
+ if ( type === exports . TYPES . VAR ) {
357
+ return val ;
358
+ }
359
+ if ( type === exports . TYPES . KEYWORD ) {
360
+ return exports . parseKeyword ( val ) ;
361
+ }
331
362
if ( / ^ [ a - z ] + $ / i. test ( val ) && type === exports . TYPES . COLOR ) {
332
363
return val ;
333
364
}
@@ -346,7 +377,7 @@ exports.parseColor = function parseColor(val) {
346
377
exports . parseAngle = function parseAngle ( val ) {
347
378
var type = exports . valueType ( val ) ;
348
379
if ( type === exports . TYPES . NULL_OR_EMPTY_STR ) {
349
- return val ;
380
+ return '' ;
350
381
}
351
382
if ( type !== exports . TYPES . ANGLE ) {
352
383
return undefined ;
@@ -368,34 +399,19 @@ exports.parseAngle = function parseAngle(val) {
368
399
return flt + 'deg' ;
369
400
} ;
370
401
371
- exports . parseKeyword = function parseKeyword ( val , validKeywords ) {
402
+ exports . parseImage = function parseImage ( val ) {
372
403
var type = exports . valueType ( val ) ;
373
404
if ( type === exports . TYPES . NULL_OR_EMPTY_STR ) {
374
- return val ;
405
+ return '' ;
375
406
}
376
- if ( type !== exports . TYPES . KEYWORD ) {
407
+ if ( type === exports . TYPES . UNDEFINED ) {
377
408
return undefined ;
378
409
}
379
- val = val . toString ( ) . toLowerCase ( ) ;
380
- var i ;
381
- for ( i = 0 ; i < validKeywords . length ; i ++ ) {
382
- if ( validKeywords [ i ] . toLowerCase ( ) === val ) {
383
- return validKeywords [ i ] ;
384
- }
385
- }
386
- return undefined ;
387
- } ;
388
-
389
- exports . parseImage = function parseImage ( val ) {
390
- if ( / ^ (?: n o n e | i n h e r i t ) $ / i. test ( val ) ) {
391
- return val . toLowerCase ( ) ;
392
- }
393
- var type = exports . valueType ( val ) ;
394
- if ( type === exports . TYPES . NULL_OR_EMPTY_STR || type === exports . TYPES . VAR ) {
410
+ if ( type === exports . TYPES . VAR ) {
395
411
return val ;
396
412
}
397
- if ( type === exports . TYPES . UNDEFINED ) {
398
- return undefined ;
413
+ if ( type === exports . TYPES . KEYWORD ) {
414
+ return exports . parseKeyword ( val , [ 'none' ] ) ;
399
415
}
400
416
var values = splitValue ( val , {
401
417
delimiter : ',' ,
@@ -445,11 +461,11 @@ exports.dashedToCamelCase = function (dashed) {
445
461
return camel ;
446
462
} ;
447
463
448
- var isSpace = / \s / ;
449
- var openingDeliminators = [ '"' , "'" , '(' ] ;
450
- var closingDeliminators = [ '"' , "'" , ')' ] ;
451
464
// this splits on whitespace, but keeps quoted and parened parts together
452
465
var getParts = function ( str ) {
466
+ var isSpace = / \s / ;
467
+ var openingDeliminators = [ '"' , "'" , '(' ] ;
468
+ var closingDeliminators = [ '"' , "'" , ')' ] ;
453
469
var deliminatorStack = [ ] ;
454
470
var length = str . length ;
455
471
var i ;
@@ -489,12 +505,12 @@ var getParts = function (str) {
489
505
return parts ;
490
506
} ;
491
507
492
- /*
493
- * this either returns undefined meaning that it isn't valid
494
- * or returns an object where the keys are dashed short
495
- * hand properties and the values are the values to set
496
- * on them
497
- */
508
+ // this either returns undefined meaning that it isn't valid
509
+ // or returns an object where the keys are dashed short
510
+ // hand properties and the values are the values to set
511
+ // on them
512
+ // FIXME: need additional argument which indicates syntax
513
+ // and/or use Map() for shorthandFor to ensure order of the longhand properties
498
514
exports . shorthandParser = function parse ( v , shorthandFor ) {
499
515
var obj = { } ;
500
516
var type = exports . valueType ( v ) ;
@@ -504,19 +520,19 @@ exports.shorthandParser = function parse(v, shorthandFor) {
504
520
} ) ;
505
521
return obj ;
506
522
}
507
-
523
+ if ( type === exports . TYPES . UNDEFINED ) {
524
+ return undefined ;
525
+ }
508
526
if ( typeof v === 'number' ) {
509
527
v = v . toString ( ) ;
510
528
}
511
-
512
529
if ( typeof v !== 'string' ) {
513
530
return undefined ;
514
531
}
515
-
516
532
if ( v . toLowerCase ( ) === 'inherit' ) {
517
533
return { } ;
518
534
}
519
- var parts = getParts ( v ) ;
535
+ var parts = splitValue ( v ) ;
520
536
var valid = true ;
521
537
parts . forEach ( function ( part , i ) {
522
538
var partValid = false ;
@@ -526,21 +542,29 @@ exports.shorthandParser = function parse(v, shorthandFor) {
526
542
obj [ property ] = part ;
527
543
}
528
544
} ) ;
529
- valid = valid && partValid ;
545
+ if ( valid ) {
546
+ valid = partValid ;
547
+ }
530
548
} ) ;
531
549
if ( ! valid ) {
532
550
return undefined ;
533
551
}
534
552
return obj ;
535
553
} ;
536
554
555
+ // FIXME: check against shorthandParser and reduce Object.keys().forEach() loops
537
556
exports . shorthandSetter = function ( property , shorthandFor ) {
538
557
return function ( v ) {
558
+ if ( v === undefined ) {
559
+ return ;
560
+ }
561
+ if ( v === null ) {
562
+ v = '' ;
563
+ }
539
564
var obj = exports . shorthandParser ( v , shorthandFor ) ;
540
565
if ( obj === undefined ) {
541
566
return ;
542
567
}
543
- //console.log('shorthandSetter for:', property, 'obj:', obj);
544
568
Object . keys ( obj ) . forEach ( function ( subprop ) {
545
569
// in case subprop is an implicit property, this will clear
546
570
// *its* subpropertiesX
@@ -572,6 +596,7 @@ exports.shorthandSetter = function (property, shorthandFor) {
572
596
} ;
573
597
} ;
574
598
599
+ // FIXME: move shorthandGetter() and shorthandSetter to CSSStyleDeclaration()
575
600
exports . shorthandGetter = function ( property , shorthandFor ) {
576
601
return function ( ) {
577
602
if ( this . _values [ property ] !== undefined ) {
@@ -646,12 +671,10 @@ exports.implicitSetter = function (propertyBefore, propertyAfter, isValid, parse
646
671
} ;
647
672
} ;
648
673
649
- //
650
674
// Companion to implicitSetter, but for the individual parts.
651
675
// This sets the individual value, and checks to see if all four
652
676
// sub-parts are set. If so, it sets the shorthand version and removes
653
677
// the individual parts from the cssText.
654
- //
655
678
exports . subImplicitSetter = function ( prefix , part , isValid , parser ) {
656
679
var property = prefix + '-' + part ;
657
680
var subparts = [ prefix + '-top' , prefix + '-right' , prefix + '-bottom' , prefix + '-left' ] ;
@@ -698,12 +721,12 @@ exports.subImplicitSetter = function (prefix, part, isValid, parser) {
698
721
} ;
699
722
} ;
700
723
701
- var camelToDashed = / [ A - Z ] / g;
702
- var firstSegment = / ^ \( [ ^ - ] \) - / ;
703
- var vendorPrefixes = [ 'o' , 'moz' , 'ms' , 'webkit' ] ;
704
724
exports . camelToDashed = function ( camelCase ) {
725
+ var upperCase = / [ A - Z ] / g;
726
+ var firstSegment = / ^ \( [ ^ - ] \) - / ;
727
+ var vendorPrefixes = [ 'o' , 'moz' , 'ms' , 'webkit' ] ;
705
728
var match ;
706
- var dashed = camelCase . replace ( camelToDashed , '-$&' ) . toLowerCase ( ) ;
729
+ var dashed = camelCase . replace ( upperCase , '-$&' ) . toLowerCase ( ) ;
707
730
match = dashed . match ( firstSegment ) ;
708
731
if ( match && vendorPrefixes . indexOf ( match [ 1 ] ) !== - 1 ) {
709
732
dashed = '-' + dashed ;
0 commit comments