@@ -8,32 +8,27 @@ const { resolve: resolveColor, utils } = require('@asamuzakjp/css-color');
88const { cssCalc, isColor, isGradient, splitValue } = utils ;
99
1010exports . TYPES = {
11- INTEGER : 1 ,
12- NUMBER : 2 ,
13- LENGTH : 3 ,
14- PERCENT : 4 ,
15- URL : 5 ,
16- COLOR : 6 ,
17- STRING : 7 ,
18- ANGLE : 8 ,
19- KEYWORD : 9 ,
20- NULL_OR_EMPTY_STR : 10 ,
21- CALC : 11 ,
22- VAR : 12 ,
23- GRADIENT : 13 ,
11+ UNDEFINED : 0 ,
12+ NULL_OR_EMPTY_STR : 1 ,
13+ VAR : 2 ,
14+ NUMBER : 4 ,
15+ PERCENT : 8 ,
16+ LENGTH : 0x10 ,
17+ ANGLE : 0x20 ,
18+ CALC : 0x40 ,
19+ COLOR : 0x80 ,
20+ STRING : 0x100 ,
21+ KEYWORD : 0x200 ,
22+ UNIDENT : 0x8000 ,
2423} ;
2524
2625// regular expressions
2726var DIGIT = '(?:0|[1-9]\\d*)' ;
2827var NUMBER = `[+-]?(?:${ DIGIT } (?:\\.\\d*)?|\\.\\d+)(?:e-?${ DIGIT } )?` ;
29- var integerRegEx = new RegExp ( `^[+-]?${ DIGIT } $` ) ;
30- var numberRegEx = new RegExp ( `^${ NUMBER } $` ) ;
31- var lengthRegEx = new RegExp (
32- `^${ NUMBER } (?:[cm]m|[dls]?v(?:[bhiw]|max|min)|in|p[ctx]|q|r?(?:[cl]h|cap|e[mx]|ic))$`
33- ) ;
34- var percentRegEx = new RegExp ( `^${ NUMBER } %$` ) ;
28+ var unitRegEx = new RegExp ( `^(${ NUMBER } )([a-z]+|%)?$` ) ;
3529var angleRegEx = new RegExp ( `^${ NUMBER } (?:deg|g?rad|turn)$` ) ;
3630var urlRegEx = / ^ u r l \( \s * ( (?: [ ^ ) ] | \\ \) ) * ) \s * \) $ / ;
31+ var keywordRegEx = / ^ [ a - z ] + (?: \- [ a - z ] + ) * $ / i;
3732var stringRegEx = / ^ ( " [ ^ " ] * " | ' [ ^ ' ] * ' ) $ / ;
3833var varRegEx = / ^ v a r \( | (?< = [ * / \s ( ] ) v a r \( / ;
3934var calcRegEx =
@@ -48,46 +43,55 @@ exports.valueType = function valueType(val) {
4843 val = val . toString ( ) ;
4944 }
5045 if ( typeof val !== 'string' ) {
51- return undefined ;
52- }
53- if ( integerRegEx . test ( val ) ) {
54- return exports . TYPES . INTEGER ;
55- }
56- if ( numberRegEx . test ( val ) ) {
57- return exports . TYPES . NUMBER ;
58- }
59- if ( lengthRegEx . test ( val ) ) {
60- return exports . TYPES . LENGTH ;
61- }
62- if ( percentRegEx . test ( val ) ) {
63- return exports . TYPES . PERCENT ;
64- }
65- if ( val . startsWith ( 'url(' ) && val . endsWith ( ')' ) ) {
66- if ( urlRegEx . test ( val ) ) {
67- return exports . TYPES . URL ;
68- }
69- return undefined ;
46+ return exports . TYPES . UNDEFINED ;
7047 }
7148 if ( varRegEx . test ( val ) ) {
7249 return exports . TYPES . VAR ;
7350 }
7451 if ( calcRegEx . test ( val ) ) {
7552 return exports . TYPES . CALC ;
7653 }
77- if ( stringRegEx . test ( val ) ) {
78- return exports . TYPES . STRING ;
79- }
80- if ( angleRegEx . test ( val ) ) {
81- return exports . TYPES . ANGLE ;
54+ if ( unitRegEx . test ( val ) ) {
55+ const [ , , unit ] = unitRegEx . exec ( val ) ;
56+ if ( ! unit ) {
57+ return exports . TYPES . NUMBER ;
58+ }
59+ if ( unit === '%' ) {
60+ return exports . TYPES . PERCENT ;
61+ }
62+ if ( / ^ (?: [ c m ] m | [ d l s ] ? v (?: [ b h i w ] | m a x | m i n ) | i n | p [ c t x ] | q | r ? (?: [ c l ] h | c a p | e [ m x ] | i c ) ) $ / . test ( unit ) ) {
63+ return exports . TYPES . LENGTH ;
64+ }
65+ if ( / ^ (?: d e g | g ? r a d | t u r n ) $ / . test ( unit ) ) {
66+ return exports . TYPES . ANGLE ;
67+ }
8268 }
8369 if ( isColor ( val ) ) {
8470 return exports . TYPES . COLOR ;
8571 }
86- if ( isGradient ( val ) ) {
87- return exports . TYPES . GRADIENT ;
72+ if ( stringRegEx . test ( val ) ) {
73+ return exports . TYPES . STRING ;
8874 }
8975
9076 switch ( val . toLowerCase ( ) ) {
77+ // system color keywords
78+ case 'accentcolor' :
79+ case 'accentcolortext' :
80+ case 'activetext' :
81+ case 'buttonborder' :
82+ case 'buttonface' :
83+ case 'buttontext' :
84+ case 'canvas' :
85+ case 'canvastext' :
86+ case 'field' :
87+ case 'fieldtext' :
88+ case 'graytext' :
89+ case 'highlight' :
90+ case 'highlighttext' :
91+ case 'linktext' :
92+ case 'mark' :
93+ case 'marktext' :
94+ case 'visitedtext' :
9195 // the following are deprecated in CSS3
9296 case 'activeborder' :
9397 case 'activecaption' :
@@ -119,87 +123,97 @@ exports.valueType = function valueType(val) {
119123 case 'windowtext' :
120124 return exports . TYPES . COLOR ;
121125 default :
122- return exports . TYPES . KEYWORD ;
123- }
124- } ;
125-
126- exports . parseInteger = function parseInteger ( val ) {
127- var type = exports . valueType ( val ) ;
128- if ( type === exports . TYPES . NULL_OR_EMPTY_STR ) {
129- return val ;
130- }
131- if ( type !== exports . TYPES . INTEGER ) {
132- return undefined ;
126+ if ( keywordRegEx . test ( val ) ) {
127+ return exports . TYPES . KEYWORD ;
128+ }
129+ return exports . TYPES . UNIDENT ;
133130 }
134- return String ( parseInt ( val , 10 ) ) ;
135131} ;
136132
137133exports . parseNumber = function parseNumber ( val ) {
138134 var type = exports . valueType ( val ) ;
139- if ( type === exports . TYPES . NULL_OR_EMPTY_STR ) {
140- return val ;
141- }
142- if ( type !== exports . TYPES . NUMBER && type !== exports . TYPES . INTEGER ) {
143- return undefined ;
135+ switch ( type ) {
136+ case exports . TYPES . NULL_OR_EMPTY_STR :
137+ case exports . TYPES . VAR :
138+ return val ;
139+ case exports . TYPES . NUMBER :
140+ return `${ parseFloat ( val ) } ` ;
141+ default :
142+ return undefined ;
144143 }
145- return String ( parseFloat ( val ) ) ;
146144} ;
147145
148146exports . parseLength = function parseLength ( val ) {
149- if ( val === 0 || val === '0' ) {
150- return '0px' ;
151- }
152147 var type = exports . valueType ( val ) ;
153- if ( type === exports . TYPES . NULL_OR_EMPTY_STR ) {
154- return val ;
155- }
156- if ( type !== exports . TYPES . LENGTH ) {
157- return undefined ;
148+ switch ( type ) {
149+ case exports . TYPES . NULL_OR_EMPTY_STR :
150+ case exports . TYPES . VAR :
151+ return val ;
152+ case exports . TYPES . CALC :
153+ return cssCalc ( val , {
154+ format : 'specifiedValue' ,
155+ } ) ;
156+ case exports . TYPES . LENGTH : {
157+ const [ , numVal , unit ] = unitRegEx . exec ( val ) ;
158+ return `${ parseFloat ( numVal ) } ${ unit } ` ;
159+ }
160+ default :
161+ if ( type === exports . TYPES . NUMBER && parseFloat ( val ) === 0 ) {
162+ return '0px' ;
163+ }
164+ return undefined ;
158165 }
159- return val ;
160166} ;
161167
162168exports . parsePercent = function parsePercent ( val ) {
163- if ( val === 0 || val === '0' ) {
164- return '0%' ;
165- }
166169 var type = exports . valueType ( val ) ;
167- if ( type === exports . TYPES . NULL_OR_EMPTY_STR ) {
168- return val ;
169- }
170- if ( type !== exports . TYPES . PERCENT ) {
171- return undefined ;
170+ switch ( type ) {
171+ case exports . TYPES . NULL_OR_EMPTY_STR :
172+ case exports . TYPES . VAR :
173+ return val ;
174+ case exports . TYPES . CALC :
175+ return cssCalc ( val , {
176+ format : 'specifiedValue' ,
177+ } ) ;
178+ case exports . TYPES . PERCENT :
179+ const [ , numVal , unit ] = unitRegEx . exec ( val ) ;
180+ return `${ parseFloat ( numVal ) } ${ unit } ` ;
181+ default :
182+ if ( type === exports . TYPES . NUMBER && parseFloat ( val ) === 0 ) {
183+ return '0%' ;
184+ }
185+ return undefined ;
172186 }
173- return val ;
174187} ;
175188
176189// either a length or a percent
177190exports . parseMeasurement = function parseMeasurement ( val ) {
178191 var type = exports . valueType ( val ) ;
179- if ( type === exports . TYPES . VAR ) {
180- return val ;
181- }
182- if ( type === exports . TYPES . CALC ) {
183- return cssCalc ( val , {
184- format : 'specifiedValue' ,
185- } ) ;
186- }
187-
188- var length = exports . parseLength ( val ) ;
189- if ( length !== undefined ) {
190- return length ;
192+ switch ( type ) {
193+ case exports . TYPES . NULL_OR_EMPTY_STR :
194+ case exports . TYPES . VAR :
195+ return val ;
196+ case exports . TYPES . CALC :
197+ return cssCalc ( val , {
198+ format : 'specifiedValue' ,
199+ } ) ;
200+ case exports . TYPES . LENGTH :
201+ case exports . TYPES . PERCENT :
202+ const [ , numVal , unit ] = unitRegEx . exec ( val ) ;
203+ return `${ parseFloat ( numVal ) } ${ unit } ` ;
204+ default :
205+ if ( type === exports . TYPES . NUMBER && parseFloat ( val ) === 0 ) {
206+ return '0px' ;
207+ }
208+ return undefined ;
191209 }
192- return exports . parsePercent ( val ) ;
193210} ;
194211
195- exports . parseInheritingMeasurement = function parseInheritingMeasurement ( v ) {
196- if ( String ( v ) . toLowerCase ( ) === 'auto' ) {
197- return 'auto' ;
198- }
199- if ( String ( v ) . toLowerCase ( ) === 'inherit' ) {
200- return 'inherit' ;
212+ exports . parseInheritingMeasurement = function parseInheritingMeasurement ( val ) {
213+ if ( / ^ (?: a u t o | i n h e r i t ) $ / i. test ( val ) ) {
214+ return val . toLowerCase ( ) ;
201215 }
202- return exports . parseMeasurement ( v ) ;
216+ return exports . parseMeasurement ( val ) ;
203217} ;
204218
205219exports . parseUrl = function parseUrl ( val ) {
@@ -291,9 +305,12 @@ exports.parseString = function parseString(val) {
291305
292306exports . parseColor = function parseColor ( val ) {
293307 var type = exports . valueType ( val ) ;
294- if ( type === exports . TYPES . NULL_OR_EMPTY_STR ) {
308+ if ( type & ( exports . TYPES . NULL_OR_EMPTY_STR | exports . TYPES . VAR ) ) {
295309 return val ;
296310 }
311+ if ( type === exports . TYPES . UNDEFINED ) {
312+ return undefined ;
313+ }
297314 if ( / ^ [ a - z ] + $ / i. test ( val ) && type === exports . TYPES . COLOR ) {
298315 return val ;
299316 }
@@ -306,6 +323,9 @@ exports.parseColor = function parseColor(val) {
306323 return undefined ;
307324} ;
308325
326+ // FIXME:
327+ // This function seems to be incorrect.
328+ // However, this has no impact so far, as this function is only used by the deprecated `azimuth` property.
309329exports . parseAngle = function parseAngle ( val ) {
310330 var type = exports . valueType ( val ) ;
311331 if ( type === exports . TYPES . NULL_OR_EMPTY_STR ) {
@@ -331,7 +351,7 @@ exports.parseAngle = function parseAngle(val) {
331351 return flt + 'deg' ;
332352} ;
333353
334- exports . parseKeyword = function parseKeyword ( val , valid_keywords ) {
354+ exports . parseKeyword = function parseKeyword ( val , validKeywords ) {
335355 var type = exports . valueType ( val ) ;
336356 if ( type === exports . TYPES . NULL_OR_EMPTY_STR ) {
337357 return val ;
@@ -341,36 +361,38 @@ exports.parseKeyword = function parseKeyword(val, valid_keywords) {
341361 }
342362 val = val . toString ( ) . toLowerCase ( ) ;
343363 var i ;
344- for ( i = 0 ; i < valid_keywords . length ; i ++ ) {
345- if ( valid_keywords [ i ] . toLowerCase ( ) === val ) {
346- return valid_keywords [ i ] ;
364+ for ( i = 0 ; i < validKeywords . length ; i ++ ) {
365+ if ( validKeywords [ i ] . toLowerCase ( ) === val ) {
366+ return validKeywords [ i ] ;
347367 }
348368 }
349369 return undefined ;
350370} ;
351371
352372exports . parseImage = function parseImage ( val ) {
353373 if ( / ^ (?: n o n e | i n h e r i t ) $ / i. test ( val ) ) {
354- return val ;
374+ return val . toLowerCase ( ) ;
355375 }
356376 var type = exports . valueType ( val ) ;
357- if ( type === exports . TYPES . NULL_OR_EMPTY_STR || type === exports . TYPES . VAR ) {
377+ if ( type & ( exports . TYPES . NULL_OR_EMPTY_STR | exports . TYPES . VAR ) ) {
358378 return val ;
359379 }
380+ if ( type === exports . TYPES . UNDEFINED ) {
381+ return undefined ;
382+ }
360383 var values = splitValue ( val , ',' ) ;
361384 var isImage = ! ! values . length ;
362385 var i ;
363386 for ( i = 0 ; i < values . length ; i ++ ) {
364387 var image = values [ i ] ;
365- var t = exports . valueType ( image ) ;
366- if ( t === exports . TYPES . NULL_OR_EMPTY_STR ) {
388+ if ( exports . valueType ( image ) === exports . TYPES . NULL_OR_EMPTY_STR ) {
367389 return image ;
368390 }
369- if ( t === exports . TYPES . GRADIENT || / ^ (?: n o n e | i n h e r i t ) $ / i. test ( image ) ) {
391+ if ( isGradient ( image ) || / ^ (?: n o n e | i n h e r i t ) $ / i. test ( image ) ) {
370392 continue ;
371393 }
372394 var imageUrl = exports . parseUrl ( image ) ;
373- if ( exports . valueType ( imageUrl ) === exports . TYPES . URL ) {
395+ if ( imageUrl ) {
374396 values [ i ] = imageUrl ;
375397 } else {
376398 isImage = false ;
0 commit comments