@@ -8,32 +8,27 @@ const { resolve: resolveColor, utils } = require('@asamuzakjp/css-color');
8
8
const { cssCalc, isColor, isGradient, splitValue } = utils ;
9
9
10
10
exports . 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 ,
24
23
} ;
25
24
26
25
// regular expressions
27
26
var DIGIT = '(?:0|[1-9]\\d*)' ;
28
27
var 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]+|%)?$` ) ;
35
29
var angleRegEx = new RegExp ( `^${ NUMBER } (?:deg|g?rad|turn)$` ) ;
36
30
var urlRegEx = / ^ u r l \( \s * ( (?: [ ^ ) ] | \\ \) ) * ) \s * \) $ / ;
31
+ var keywordRegEx = / ^ [ a - z ] + (?: \- [ a - z ] + ) * $ / i;
37
32
var stringRegEx = / ^ ( " [ ^ " ] * " | ' [ ^ ' ] * ' ) $ / ;
38
33
var varRegEx = / ^ v a r \( | (?< = [ * / \s ( ] ) v a r \( / ;
39
34
var calcRegEx =
@@ -48,46 +43,55 @@ exports.valueType = function valueType(val) {
48
43
val = val . toString ( ) ;
49
44
}
50
45
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 ;
70
47
}
71
48
if ( varRegEx . test ( val ) ) {
72
49
return exports . TYPES . VAR ;
73
50
}
74
51
if ( calcRegEx . test ( val ) ) {
75
52
return exports . TYPES . CALC ;
76
53
}
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
+ }
82
68
}
83
69
if ( isColor ( val ) ) {
84
70
return exports . TYPES . COLOR ;
85
71
}
86
- if ( isGradient ( val ) ) {
87
- return exports . TYPES . GRADIENT ;
72
+ if ( stringRegEx . test ( val ) ) {
73
+ return exports . TYPES . STRING ;
88
74
}
89
75
90
76
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' :
91
95
// the following are deprecated in CSS3
92
96
case 'activeborder' :
93
97
case 'activecaption' :
@@ -119,87 +123,97 @@ exports.valueType = function valueType(val) {
119
123
case 'windowtext' :
120
124
return exports . TYPES . COLOR ;
121
125
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 ;
133
130
}
134
- return String ( parseInt ( val , 10 ) ) ;
135
131
} ;
136
132
137
133
exports . parseNumber = function parseNumber ( val ) {
138
134
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 ;
144
143
}
145
- return String ( parseFloat ( val ) ) ;
146
144
} ;
147
145
148
146
exports . parseLength = function parseLength ( val ) {
149
- if ( val === 0 || val === '0' ) {
150
- return '0px' ;
151
- }
152
147
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 ;
158
165
}
159
- return val ;
160
166
} ;
161
167
162
168
exports . parsePercent = function parsePercent ( val ) {
163
- if ( val === 0 || val === '0' ) {
164
- return '0%' ;
165
- }
166
169
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 ;
172
186
}
173
- return val ;
174
187
} ;
175
188
176
189
// either a length or a percent
177
190
exports . parseMeasurement = function parseMeasurement ( val ) {
178
191
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 ;
191
209
}
192
- return exports . parsePercent ( val ) ;
193
210
} ;
194
211
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 ( ) ;
201
215
}
202
- return exports . parseMeasurement ( v ) ;
216
+ return exports . parseMeasurement ( val ) ;
203
217
} ;
204
218
205
219
exports . parseUrl = function parseUrl ( val ) {
@@ -291,9 +305,12 @@ exports.parseString = function parseString(val) {
291
305
292
306
exports . parseColor = function parseColor ( val ) {
293
307
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 ) ) {
295
309
return val ;
296
310
}
311
+ if ( type === exports . TYPES . UNDEFINED ) {
312
+ return undefined ;
313
+ }
297
314
if ( / ^ [ a - z ] + $ / i. test ( val ) && type === exports . TYPES . COLOR ) {
298
315
return val ;
299
316
}
@@ -306,6 +323,9 @@ exports.parseColor = function parseColor(val) {
306
323
return undefined ;
307
324
} ;
308
325
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.
309
329
exports . parseAngle = function parseAngle ( val ) {
310
330
var type = exports . valueType ( val ) ;
311
331
if ( type === exports . TYPES . NULL_OR_EMPTY_STR ) {
@@ -331,7 +351,7 @@ exports.parseAngle = function parseAngle(val) {
331
351
return flt + 'deg' ;
332
352
} ;
333
353
334
- exports . parseKeyword = function parseKeyword ( val , valid_keywords ) {
354
+ exports . parseKeyword = function parseKeyword ( val , validKeywords ) {
335
355
var type = exports . valueType ( val ) ;
336
356
if ( type === exports . TYPES . NULL_OR_EMPTY_STR ) {
337
357
return val ;
@@ -341,36 +361,38 @@ exports.parseKeyword = function parseKeyword(val, valid_keywords) {
341
361
}
342
362
val = val . toString ( ) . toLowerCase ( ) ;
343
363
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 ] ;
347
367
}
348
368
}
349
369
return undefined ;
350
370
} ;
351
371
352
372
exports . parseImage = function parseImage ( val ) {
353
373
if ( / ^ (?: n o n e | i n h e r i t ) $ / i. test ( val ) ) {
354
- return val ;
374
+ return val . toLowerCase ( ) ;
355
375
}
356
376
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 ) ) {
358
378
return val ;
359
379
}
380
+ if ( type === exports . TYPES . UNDEFINED ) {
381
+ return undefined ;
382
+ }
360
383
var values = splitValue ( val , ',' ) ;
361
384
var isImage = ! ! values . length ;
362
385
var i ;
363
386
for ( i = 0 ; i < values . length ; i ++ ) {
364
387
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 ) {
367
389
return image ;
368
390
}
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 ) ) {
370
392
continue ;
371
393
}
372
394
var imageUrl = exports . parseUrl ( image ) ;
373
- if ( exports . valueType ( imageUrl ) === exports . TYPES . URL ) {
395
+ if ( imageUrl ) {
374
396
values [ i ] = imageUrl ;
375
397
} else {
376
398
isImage = false ;
0 commit comments