@@ -22,6 +22,9 @@ exports.TYPES = {
2222 UNIDENT : 0x8000 ,
2323} ;
2424
25+ // CSS global values
26+ exports . GLOBAL_VALUES = Object . freeze ( [ 'initial' , 'inherit' , 'unset' , 'revert' , 'revert-layer' ] ) ;
27+
2528// regular expressions
2629var DIGIT = '(?:0|[1-9]\\d*)' ;
2730var NUMBER = `[+-]?(?:${ DIGIT } (?:\\.\\d*)?|\\.\\d+)(?:e-?${ DIGIT } )?` ;
@@ -37,6 +40,7 @@ var calcRegEx =
3740
3841// This will return one of the above types based on the passed in string
3942exports . valueType = function valueType ( val ) {
43+ // see https://webidl.spec.whatwg.org/#LegacyNullToEmptyString
4044 if ( val === '' || val === null ) {
4145 return exports . TYPES . NULL_OR_EMPTY_STR ;
4246 }
@@ -53,7 +57,7 @@ exports.valueType = function valueType(val) {
5357 return exports . TYPES . CALC ;
5458 }
5559 if ( unitRegEx . test ( val ) ) {
56- const [ , , unit ] = unitRegEx . exec ( val ) ;
60+ var [ , , unit ] = unitRegEx . exec ( val ) ;
5761 if ( ! unit ) {
5862 return exports . TYPES . NUMBER ;
5963 }
@@ -162,7 +166,7 @@ exports.parseLength = function parseLength(val) {
162166 format : 'specifiedValue' ,
163167 } ) ;
164168 case exports . TYPES . LENGTH : {
165- const [ , numVal , unit ] = unitRegEx . exec ( val ) ;
169+ var [ , numVal , unit ] = unitRegEx . exec ( val ) ;
166170 return `${ parseFloat ( numVal ) } ${ unit } ` ;
167171 }
168172 default :
@@ -186,9 +190,10 @@ exports.parsePercent = function parsePercent(val) {
186190 return cssCalc ( val , {
187191 format : 'specifiedValue' ,
188192 } ) ;
189- case exports . TYPES . PERCENT :
190- const [ , numVal , unit ] = unitRegEx . exec ( val ) ;
193+ case exports . TYPES . PERCENT : {
194+ var [ , numVal , unit ] = unitRegEx . exec ( val ) ;
191195 return `${ parseFloat ( numVal ) } ${ unit } ` ;
196+ }
192197 default :
193198 if ( varContainedRegEx . test ( val ) ) {
194199 return val ;
@@ -212,9 +217,10 @@ exports.parseMeasurement = function parseMeasurement(val) {
212217 format : 'specifiedValue' ,
213218 } ) ;
214219 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 ) ;
217222 return `${ parseFloat ( numVal ) } ${ unit } ` ;
223+ }
218224 default :
219225 if ( varContainedRegEx . test ( val ) ) {
220226 return val ;
@@ -236,7 +242,7 @@ exports.parseInheritingMeasurement = function parseInheritingMeasurement(val) {
236242exports . parseUrl = function parseUrl ( val ) {
237243 var type = exports . valueType ( val ) ;
238244 if ( type === exports . TYPES . NULL_OR_EMPTY_STR ) {
239- return val ;
245+ return '' ;
240246 }
241247 var res = urlRegEx . exec ( val ) ;
242248 // does it match the regex?
@@ -293,10 +299,11 @@ exports.parseUrl = function parseUrl(val) {
293299 return 'url("' + urlstr + '")' ;
294300} ;
295301
302+ // NOTE: seems not in use?
296303exports . parseString = function parseString ( val ) {
297304 var type = exports . valueType ( val ) ;
298305 if ( type === exports . TYPES . NULL_OR_EMPTY_STR ) {
299- return val ;
306+ return '' ;
300307 }
301308 if ( type !== exports . TYPES . STRING ) {
302309 return undefined ;
@@ -320,14 +327,38 @@ exports.parseString = function parseString(val) {
320327 return val ;
321328} ;
322329
323- exports . parseColor = function parseColor ( val ) {
330+ exports . parseKeyword = function parseKeyword ( val , validKeywords = [ ] ) {
324331 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 ) ) {
326343 return val ;
327344 }
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+ }
328353 if ( type === exports . TYPES . UNDEFINED ) {
329354 return undefined ;
330355 }
356+ if ( type === exports . TYPES . VAR ) {
357+ return val ;
358+ }
359+ if ( type === exports . TYPES . KEYWORD ) {
360+ return exports . parseKeyword ( val ) ;
361+ }
331362 if ( / ^ [ a - z ] + $ / i. test ( val ) && type === exports . TYPES . COLOR ) {
332363 return val ;
333364 }
@@ -346,7 +377,7 @@ exports.parseColor = function parseColor(val) {
346377exports . parseAngle = function parseAngle ( val ) {
347378 var type = exports . valueType ( val ) ;
348379 if ( type === exports . TYPES . NULL_OR_EMPTY_STR ) {
349- return val ;
380+ return '' ;
350381 }
351382 if ( type !== exports . TYPES . ANGLE ) {
352383 return undefined ;
@@ -368,34 +399,19 @@ exports.parseAngle = function parseAngle(val) {
368399 return flt + 'deg' ;
369400} ;
370401
371- exports . parseKeyword = function parseKeyword ( val , validKeywords ) {
402+ exports . parseImage = function parseImage ( val ) {
372403 var type = exports . valueType ( val ) ;
373404 if ( type === exports . TYPES . NULL_OR_EMPTY_STR ) {
374- return val ;
405+ return '' ;
375406 }
376- if ( type !== exports . TYPES . KEYWORD ) {
407+ if ( type === exports . TYPES . UNDEFINED ) {
377408 return undefined ;
378409 }
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 ) {
395411 return val ;
396412 }
397- if ( type === exports . TYPES . UNDEFINED ) {
398- return undefined ;
413+ if ( type === exports . TYPES . KEYWORD ) {
414+ return exports . parseKeyword ( val , [ 'none' ] ) ;
399415 }
400416 var values = splitValue ( val , {
401417 delimiter : ',' ,
@@ -445,11 +461,11 @@ exports.dashedToCamelCase = function (dashed) {
445461 return camel ;
446462} ;
447463
448- var isSpace = / \s / ;
449- var openingDeliminators = [ '"' , "'" , '(' ] ;
450- var closingDeliminators = [ '"' , "'" , ')' ] ;
451464// this splits on whitespace, but keeps quoted and parened parts together
452465var getParts = function ( str ) {
466+ var isSpace = / \s / ;
467+ var openingDeliminators = [ '"' , "'" , '(' ] ;
468+ var closingDeliminators = [ '"' , "'" , ')' ] ;
453469 var deliminatorStack = [ ] ;
454470 var length = str . length ;
455471 var i ;
@@ -489,12 +505,12 @@ var getParts = function (str) {
489505 return parts ;
490506} ;
491507
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
498514exports . shorthandParser = function parse ( v , shorthandFor ) {
499515 var obj = { } ;
500516 var type = exports . valueType ( v ) ;
@@ -504,19 +520,19 @@ exports.shorthandParser = function parse(v, shorthandFor) {
504520 } ) ;
505521 return obj ;
506522 }
507-
523+ if ( type === exports . TYPES . UNDEFINED ) {
524+ return undefined ;
525+ }
508526 if ( typeof v === 'number' ) {
509527 v = v . toString ( ) ;
510528 }
511-
512529 if ( typeof v !== 'string' ) {
513530 return undefined ;
514531 }
515-
516532 if ( v . toLowerCase ( ) === 'inherit' ) {
517533 return { } ;
518534 }
519- var parts = getParts ( v ) ;
535+ var parts = splitValue ( v ) ;
520536 var valid = true ;
521537 parts . forEach ( function ( part , i ) {
522538 var partValid = false ;
@@ -526,21 +542,29 @@ exports.shorthandParser = function parse(v, shorthandFor) {
526542 obj [ property ] = part ;
527543 }
528544 } ) ;
529- valid = valid && partValid ;
545+ if ( valid ) {
546+ valid = partValid ;
547+ }
530548 } ) ;
531549 if ( ! valid ) {
532550 return undefined ;
533551 }
534552 return obj ;
535553} ;
536554
555+ // FIXME: check against shorthandParser and reduce Object.keys().forEach() loops
537556exports . shorthandSetter = function ( property , shorthandFor ) {
538557 return function ( v ) {
558+ if ( v === undefined ) {
559+ return ;
560+ }
561+ if ( v === null ) {
562+ v = '' ;
563+ }
539564 var obj = exports . shorthandParser ( v , shorthandFor ) ;
540565 if ( obj === undefined ) {
541566 return ;
542567 }
543- //console.log('shorthandSetter for:', property, 'obj:', obj);
544568 Object . keys ( obj ) . forEach ( function ( subprop ) {
545569 // in case subprop is an implicit property, this will clear
546570 // *its* subpropertiesX
@@ -572,6 +596,7 @@ exports.shorthandSetter = function (property, shorthandFor) {
572596 } ;
573597} ;
574598
599+ // FIXME: move shorthandGetter() and shorthandSetter to CSSStyleDeclaration()
575600exports . shorthandGetter = function ( property , shorthandFor ) {
576601 return function ( ) {
577602 if ( this . _values [ property ] !== undefined ) {
@@ -646,12 +671,10 @@ exports.implicitSetter = function (propertyBefore, propertyAfter, isValid, parse
646671 } ;
647672} ;
648673
649- //
650674// Companion to implicitSetter, but for the individual parts.
651675// This sets the individual value, and checks to see if all four
652676// sub-parts are set. If so, it sets the shorthand version and removes
653677// the individual parts from the cssText.
654- //
655678exports . subImplicitSetter = function ( prefix , part , isValid , parser ) {
656679 var property = prefix + '-' + part ;
657680 var subparts = [ prefix + '-top' , prefix + '-right' , prefix + '-bottom' , prefix + '-left' ] ;
@@ -698,12 +721,12 @@ exports.subImplicitSetter = function (prefix, part, isValid, parser) {
698721 } ;
699722} ;
700723
701- var camelToDashed = / [ A - Z ] / g;
702- var firstSegment = / ^ \( [ ^ - ] \) - / ;
703- var vendorPrefixes = [ 'o' , 'moz' , 'ms' , 'webkit' ] ;
704724exports . camelToDashed = function ( camelCase ) {
725+ var upperCase = / [ A - Z ] / g;
726+ var firstSegment = / ^ \( [ ^ - ] \) - / ;
727+ var vendorPrefixes = [ 'o' , 'moz' , 'ms' , 'webkit' ] ;
705728 var match ;
706- var dashed = camelCase . replace ( camelToDashed , '-$&' ) . toLowerCase ( ) ;
729+ var dashed = camelCase . replace ( upperCase , '-$&' ) . toLowerCase ( ) ;
707730 match = dashed . match ( firstSegment ) ;
708731 if ( match && vendorPrefixes . indexOf ( match [ 1 ] ) !== - 1 ) {
709732 dashed = '-' + dashed ;
0 commit comments