cssstyle 5.3.7 → 6.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/CSSStyleDeclaration.js +359 -395
- package/lib/generated/.gitkeep +0 -0
- package/lib/generated/propertyDefinitions.js +3718 -1474
- package/lib/generated/propertyDescriptors.js +1711 -0
- package/lib/index.js +9 -0
- package/lib/normalize.js +127 -253
- package/lib/parsers.js +160 -180
- package/lib/properties/background.js +201 -202
- package/lib/properties/backgroundAttachment.js +35 -33
- package/lib/properties/backgroundClip.js +35 -33
- package/lib/properties/backgroundColor.js +26 -24
- package/lib/properties/backgroundImage.js +36 -34
- package/lib/properties/backgroundOrigin.js +35 -33
- package/lib/properties/backgroundPosition.js +57 -57
- package/lib/properties/backgroundRepeat.js +40 -37
- package/lib/properties/backgroundSize.js +38 -34
- package/lib/properties/border.js +41 -34
- package/lib/properties/{webkitBorderEndColor.js → borderBlockEndColor.js} +26 -22
- package/lib/properties/{webkitBorderAfterColor.js → borderBlockStartColor.js} +26 -22
- package/lib/properties/borderBottom.js +40 -36
- package/lib/properties/borderBottomColor.js +25 -21
- package/lib/properties/borderBottomStyle.js +25 -21
- package/lib/properties/borderBottomWidth.js +28 -24
- package/lib/properties/borderCollapse.js +25 -21
- package/lib/properties/borderColor.js +36 -33
- package/lib/properties/{webkitBorderStartColor.js → borderInlineEndColor.js} +26 -22
- package/lib/properties/borderInlineStartColor.js +49 -0
- package/lib/properties/borderLeft.js +40 -36
- package/lib/properties/borderLeftColor.js +25 -21
- package/lib/properties/borderLeftStyle.js +25 -21
- package/lib/properties/borderLeftWidth.js +28 -24
- package/lib/properties/borderRight.js +40 -36
- package/lib/properties/borderRightColor.js +25 -21
- package/lib/properties/borderRightStyle.js +25 -21
- package/lib/properties/borderRightWidth.js +28 -24
- package/lib/properties/borderSpacing.js +33 -29
- package/lib/properties/borderStyle.js +36 -33
- package/lib/properties/borderTop.js +40 -36
- package/lib/properties/borderTopColor.js +25 -21
- package/lib/properties/borderTopStyle.js +25 -21
- package/lib/properties/borderTopWidth.js +28 -24
- package/lib/properties/borderWidth.js +36 -33
- package/lib/properties/bottom.js +27 -23
- package/lib/properties/clear.js +25 -21
- package/lib/properties/clip.js +37 -31
- package/lib/properties/color.js +25 -21
- package/lib/properties/display.js +36 -30
- package/lib/properties/flex.js +53 -45
- package/lib/properties/flexBasis.js +28 -26
- package/lib/properties/flexGrow.js +28 -26
- package/lib/properties/flexShrink.js +28 -26
- package/lib/properties/float.js +25 -21
- package/lib/properties/floodColor.js +25 -21
- package/lib/properties/font.js +89 -118
- package/lib/properties/fontFamily.js +38 -33
- package/lib/properties/fontSize.js +29 -27
- package/lib/properties/fontStyle.js +38 -34
- package/lib/properties/fontVariant.js +35 -33
- package/lib/properties/fontWeight.js +33 -31
- package/lib/properties/height.js +28 -24
- package/lib/properties/left.js +27 -23
- package/lib/properties/lightingColor.js +25 -21
- package/lib/properties/lineHeight.js +28 -26
- package/lib/properties/margin.js +40 -34
- package/lib/properties/marginBottom.js +30 -27
- package/lib/properties/marginLeft.js +30 -27
- package/lib/properties/marginRight.js +30 -27
- package/lib/properties/marginTop.js +30 -27
- package/lib/properties/opacity.js +27 -23
- package/lib/properties/outlineColor.js +25 -21
- package/lib/properties/padding.js +40 -34
- package/lib/properties/paddingBottom.js +31 -28
- package/lib/properties/paddingLeft.js +31 -28
- package/lib/properties/paddingRight.js +31 -28
- package/lib/properties/paddingTop.js +31 -28
- package/lib/properties/right.js +27 -23
- package/lib/properties/stopColor.js +25 -21
- package/lib/properties/{webkitBorderBeforeColor.js → textEmphasisColor.js} +26 -22
- package/lib/properties/top.js +27 -23
- package/lib/properties/webkitTextFillColor.js +25 -21
- package/lib/properties/webkitTextStrokeColor.js +25 -21
- package/lib/properties/width.js +28 -24
- package/lib/utils/propertyDescriptors.js +129 -42
- package/lib/utils/strings.js +11 -156
- package/package.json +12 -22
- package/lib/generated/allProperties.js +0 -653
- package/lib/generated/implementedProperties.js +0 -1466
- package/lib/generated/properties.js +0 -6637
- package/lib/properties/webkitColumnRuleColor.js +0 -45
- package/lib/properties/webkitTapHighlightColor.js +0 -45
- package/lib/properties/webkitTextEmphasisColor.js +0 -45
- package/lib/utils/allExtraProperties.js +0 -155
- package/lib/utils/camelize.js +0 -37
package/lib/parsers.js
CHANGED
|
@@ -7,8 +7,12 @@ const {
|
|
|
7
7
|
const { next: syntaxes } = require("@csstools/css-syntax-patches-for-csstree");
|
|
8
8
|
const csstree = require("css-tree");
|
|
9
9
|
const { LRUCache } = require("lru-cache");
|
|
10
|
+
const propertyDefinitions = require("./generated/propertyDefinitions");
|
|
10
11
|
const { asciiLowercase } = require("./utils/strings");
|
|
11
12
|
|
|
13
|
+
// Constants
|
|
14
|
+
const CALC_FUNC_NAMES = "(?:a?(?:cos|sin|tan)|abs|atan2|calc|clamp|exp|hypot|log|max|min|mod|pow|rem|round|sign|sqrt)";
|
|
15
|
+
|
|
12
16
|
// CSS global keywords
|
|
13
17
|
// @see https://drafts.csswg.org/css-cascade-5/#defaulting-keywords
|
|
14
18
|
const GLOBAL_KEYS = new Set(["initial", "inherit", "unset", "revert", "revert-layer"]);
|
|
@@ -76,8 +80,6 @@ const AST_TYPES = Object.freeze({
|
|
|
76
80
|
});
|
|
77
81
|
|
|
78
82
|
// Regular expressions
|
|
79
|
-
const CALC_FUNC_NAMES =
|
|
80
|
-
"(?:a?(?:cos|sin|tan)|abs|atan2|calc|clamp|exp|hypot|log|max|min|mod|pow|rem|round|sign|sqrt)";
|
|
81
83
|
const calcRegEx = new RegExp(`^${CALC_FUNC_NAMES}\\(`);
|
|
82
84
|
const calcContainedRegEx = new RegExp(`(?<=[*/\\s(])${CALC_FUNC_NAMES}\\(`);
|
|
83
85
|
const calcNameRegEx = new RegExp(`^${CALC_FUNC_NAMES}$`);
|
|
@@ -98,14 +100,14 @@ const lruCache = new LRUCache({
|
|
|
98
100
|
* @param {string|number|null|undefined} value - The value to prepare.
|
|
99
101
|
* @returns {string} The prepared value.
|
|
100
102
|
*/
|
|
101
|
-
|
|
103
|
+
function prepareValue(value) {
|
|
102
104
|
// `null` is converted to an empty string.
|
|
103
105
|
// @see https://webidl.spec.whatwg.org/#LegacyNullToEmptyString
|
|
104
106
|
if (value === null) {
|
|
105
107
|
return "";
|
|
106
108
|
}
|
|
107
109
|
return `${value}`.trim();
|
|
108
|
-
}
|
|
110
|
+
}
|
|
109
111
|
|
|
110
112
|
/**
|
|
111
113
|
* Checks if the value is a global keyword.
|
|
@@ -113,9 +115,9 @@ const prepareValue = (value) => {
|
|
|
113
115
|
* @param {string} val - The value to check.
|
|
114
116
|
* @returns {boolean} True if the value is a global keyword, false otherwise.
|
|
115
117
|
*/
|
|
116
|
-
|
|
118
|
+
function isGlobalKeyword(val) {
|
|
117
119
|
return GLOBAL_KEYS.has(asciiLowercase(val));
|
|
118
|
-
}
|
|
120
|
+
}
|
|
119
121
|
|
|
120
122
|
/**
|
|
121
123
|
* Checks if the value starts with or contains a CSS var() function.
|
|
@@ -123,9 +125,9 @@ const isGlobalKeyword = (val) => {
|
|
|
123
125
|
* @param {string} val - The value to check.
|
|
124
126
|
* @returns {boolean} True if the value contains a var() function, false otherwise.
|
|
125
127
|
*/
|
|
126
|
-
|
|
128
|
+
function hasVarFunc(val) {
|
|
127
129
|
return varRegEx.test(val) || varContainedRegEx.test(val);
|
|
128
|
-
}
|
|
130
|
+
}
|
|
129
131
|
|
|
130
132
|
/**
|
|
131
133
|
* Checks if the value starts with or contains CSS calc() or math functions.
|
|
@@ -133,26 +135,20 @@ const hasVarFunc = (val) => {
|
|
|
133
135
|
* @param {string} val - The value to check.
|
|
134
136
|
* @returns {boolean} True if the value contains calc() or math functions, false otherwise.
|
|
135
137
|
*/
|
|
136
|
-
|
|
138
|
+
function hasCalcFunc(val) {
|
|
137
139
|
return calcRegEx.test(val) || calcContainedRegEx.test(val);
|
|
138
|
-
}
|
|
140
|
+
}
|
|
139
141
|
|
|
140
142
|
/**
|
|
141
143
|
* Parses a CSS string into an AST.
|
|
142
144
|
*
|
|
143
145
|
* @param {string} val - The CSS string to parse.
|
|
144
146
|
* @param {object} opt - The options for parsing.
|
|
145
|
-
* @
|
|
146
|
-
* @returns {object} The AST or a plain object.
|
|
147
|
+
* @returns {object} The AST.
|
|
147
148
|
*/
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
if (toObject) {
|
|
152
|
-
return cssTree.toPlainObject(ast);
|
|
153
|
-
}
|
|
154
|
-
return ast;
|
|
155
|
-
};
|
|
149
|
+
function parseCSS(val, opt) {
|
|
150
|
+
return cssTree.parse(prepareValue(val), opt);
|
|
151
|
+
}
|
|
156
152
|
|
|
157
153
|
/**
|
|
158
154
|
* Checks if the value is a valid property value.
|
|
@@ -162,20 +158,14 @@ const parseCSS = (val, opt, toObject = false) => {
|
|
|
162
158
|
* @param {string} val - The property value.
|
|
163
159
|
* @returns {boolean} True if the value is valid, false otherwise.
|
|
164
160
|
*/
|
|
165
|
-
|
|
161
|
+
function isValidPropertyValue(prop, val) {
|
|
162
|
+
if (!propertyDefinitions.has(prop)) {
|
|
163
|
+
return false;
|
|
164
|
+
}
|
|
166
165
|
val = prepareValue(val);
|
|
167
166
|
if (val === "") {
|
|
168
167
|
return true;
|
|
169
168
|
}
|
|
170
|
-
// cssTree.lexer does not support deprecated system colors
|
|
171
|
-
// @see https://github.com/w3c/webref/issues/1519#issuecomment-3120290261
|
|
172
|
-
// @see https://github.com/w3c/webref/issues/1647
|
|
173
|
-
if (SYS_COLORS.has(asciiLowercase(val))) {
|
|
174
|
-
if (/^(?:-webkit-)?(?:[a-z][a-z\d]*-)*color$/i.test(prop)) {
|
|
175
|
-
return true;
|
|
176
|
-
}
|
|
177
|
-
return false;
|
|
178
|
-
}
|
|
179
169
|
const cacheKey = `isValidPropertyValue_${prop}_${val}`;
|
|
180
170
|
const cachedValue = lruCache.get(cacheKey);
|
|
181
171
|
if (typeof cachedValue === "boolean") {
|
|
@@ -193,7 +183,7 @@ const isValidPropertyValue = (prop, val) => {
|
|
|
193
183
|
}
|
|
194
184
|
lruCache.set(cacheKey, result);
|
|
195
185
|
return result;
|
|
196
|
-
}
|
|
186
|
+
}
|
|
197
187
|
|
|
198
188
|
/**
|
|
199
189
|
* Resolves CSS math functions.
|
|
@@ -202,7 +192,7 @@ const isValidPropertyValue = (prop, val) => {
|
|
|
202
192
|
* @param {object} [opt={ format: "specifiedValue" }] - The options for resolving.
|
|
203
193
|
* @returns {string|undefined} The resolved value.
|
|
204
194
|
*/
|
|
205
|
-
|
|
195
|
+
function resolveCalc(val, opt = { format: "specifiedValue" }) {
|
|
206
196
|
val = prepareValue(val);
|
|
207
197
|
if (val === "" || hasVarFunc(val) || !hasCalcFunc(val)) {
|
|
208
198
|
return val;
|
|
@@ -212,13 +202,12 @@ const resolveCalc = (val, opt = { format: "specifiedValue" }) => {
|
|
|
212
202
|
if (typeof cachedValue === "string") {
|
|
213
203
|
return cachedValue;
|
|
214
204
|
}
|
|
215
|
-
const
|
|
216
|
-
if (!
|
|
205
|
+
const ast = parseCSS(val, { context: "value" });
|
|
206
|
+
if (!ast?.children) {
|
|
217
207
|
return;
|
|
218
208
|
}
|
|
219
|
-
const { children: items } = obj;
|
|
220
209
|
const values = [];
|
|
221
|
-
for (const item of
|
|
210
|
+
for (const item of ast.children) {
|
|
222
211
|
const { type: itemType, name: itemName, value: itemValue } = item;
|
|
223
212
|
if (itemType === AST_TYPES.FUNCTION) {
|
|
224
213
|
const value = cssTree
|
|
@@ -240,7 +229,7 @@ const resolveCalc = (val, opt = { format: "specifiedValue" }) => {
|
|
|
240
229
|
const resolvedValue = values.join(" ");
|
|
241
230
|
lruCache.set(cacheKey, resolvedValue);
|
|
242
231
|
return resolvedValue;
|
|
243
|
-
}
|
|
232
|
+
}
|
|
244
233
|
|
|
245
234
|
/**
|
|
246
235
|
* Parses a property value.
|
|
@@ -251,8 +240,11 @@ const resolveCalc = (val, opt = { format: "specifiedValue" }) => {
|
|
|
251
240
|
* @param {object} [opt={}] - The options for parsing.
|
|
252
241
|
* @returns {string|Array<object>|undefined} The parsed value.
|
|
253
242
|
*/
|
|
254
|
-
|
|
255
|
-
|
|
243
|
+
function parsePropertyValue(prop, val, opt = {}) {
|
|
244
|
+
if (!propertyDefinitions.has(prop)) {
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
const { caseSensitive } = opt;
|
|
256
248
|
val = prepareValue(val);
|
|
257
249
|
if (val === "" || hasVarFunc(val)) {
|
|
258
250
|
return val;
|
|
@@ -269,41 +261,18 @@ const parsePropertyValue = (prop, val, opt = {}) => {
|
|
|
269
261
|
const cachedValue = lruCache.get(cacheKey);
|
|
270
262
|
if (cachedValue === false) {
|
|
271
263
|
return;
|
|
272
|
-
} else if (
|
|
273
|
-
if (Array.isArray(cachedValue)) {
|
|
274
|
-
return cachedValue;
|
|
275
|
-
}
|
|
276
|
-
} else if (typeof cachedValue === "string") {
|
|
264
|
+
} else if (cachedValue !== undefined) {
|
|
277
265
|
return cachedValue;
|
|
278
266
|
}
|
|
279
267
|
let parsedValue;
|
|
280
268
|
const lowerCasedValue = asciiLowercase(val);
|
|
281
269
|
if (GLOBAL_KEYS.has(lowerCasedValue)) {
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
name: lowerCasedValue
|
|
287
|
-
}
|
|
288
|
-
];
|
|
289
|
-
} else {
|
|
290
|
-
parsedValue = lowerCasedValue;
|
|
291
|
-
}
|
|
292
|
-
} else if (SYS_COLORS.has(lowerCasedValue)) {
|
|
293
|
-
if (/^(?:(?:-webkit-)?(?:[a-z][a-z\d]*-)*color|border)$/i.test(prop)) {
|
|
294
|
-
if (inArray) {
|
|
295
|
-
parsedValue = [
|
|
296
|
-
{
|
|
297
|
-
type: AST_TYPES.IDENTIFIER,
|
|
298
|
-
name: lowerCasedValue
|
|
299
|
-
}
|
|
300
|
-
];
|
|
301
|
-
} else {
|
|
302
|
-
parsedValue = lowerCasedValue;
|
|
270
|
+
parsedValue = [
|
|
271
|
+
{
|
|
272
|
+
type: AST_TYPES.GLOBAL_KEYWORD,
|
|
273
|
+
name: lowerCasedValue
|
|
303
274
|
}
|
|
304
|
-
|
|
305
|
-
parsedValue = false;
|
|
306
|
-
}
|
|
275
|
+
];
|
|
307
276
|
} else {
|
|
308
277
|
try {
|
|
309
278
|
const ast = parseCSS(val, {
|
|
@@ -312,9 +281,9 @@ const parsePropertyValue = (prop, val, opt = {}) => {
|
|
|
312
281
|
const { error, matched } = cssTree.lexer.matchProperty(prop, ast);
|
|
313
282
|
if (error || !matched) {
|
|
314
283
|
parsedValue = false;
|
|
315
|
-
} else
|
|
316
|
-
const
|
|
317
|
-
const
|
|
284
|
+
} else {
|
|
285
|
+
const items = ast.children;
|
|
286
|
+
const itemCount = items.size;
|
|
318
287
|
const values = [];
|
|
319
288
|
for (const item of items) {
|
|
320
289
|
const { children, name, type, value, unit } = item;
|
|
@@ -328,48 +297,40 @@ const parsePropertyValue = (prop, val, opt = {}) => {
|
|
|
328
297
|
break;
|
|
329
298
|
}
|
|
330
299
|
case AST_TYPES.FUNCTION: {
|
|
331
|
-
const
|
|
332
|
-
.generate(item)
|
|
333
|
-
.replace(/\)(?!\)|\s|,)/g, ") ")
|
|
334
|
-
.trim();
|
|
335
|
-
const raw = items.length === 1 ? val : css;
|
|
300
|
+
const raw = itemCount === 1 ? val : cssTree.generate(item).replace(/\)(?!\)|\s|,)/g, ") ");
|
|
336
301
|
// Remove "${name}(" from the start and ")" from the end
|
|
337
|
-
const itemValue = raw.slice(name.length + 1, -1)
|
|
302
|
+
const itemValue = raw.trim().slice(name.length + 1, -1);
|
|
338
303
|
if (name === "calc") {
|
|
339
|
-
if (children.
|
|
340
|
-
const
|
|
304
|
+
if (children.size === 1) {
|
|
305
|
+
const child = children.first;
|
|
341
306
|
if (child.type === AST_TYPES.NUMBER) {
|
|
342
307
|
values.push({
|
|
343
308
|
type: AST_TYPES.CALC,
|
|
344
|
-
isNumber: true,
|
|
345
|
-
value: `${parseFloat(child.value)}`,
|
|
346
309
|
name,
|
|
347
|
-
|
|
310
|
+
isNumber: true,
|
|
311
|
+
value: `${parseFloat(child.value)}`
|
|
348
312
|
});
|
|
349
313
|
} else {
|
|
350
314
|
values.push({
|
|
351
315
|
type: AST_TYPES.CALC,
|
|
352
|
-
isNumber: false,
|
|
353
|
-
value: `${asciiLowercase(itemValue)}`,
|
|
354
316
|
name,
|
|
355
|
-
|
|
317
|
+
isNumber: false,
|
|
318
|
+
value: asciiLowercase(itemValue)
|
|
356
319
|
});
|
|
357
320
|
}
|
|
358
321
|
} else {
|
|
359
322
|
values.push({
|
|
360
323
|
type: AST_TYPES.CALC,
|
|
361
|
-
isNumber: false,
|
|
362
|
-
value: asciiLowercase(itemValue),
|
|
363
324
|
name,
|
|
364
|
-
|
|
325
|
+
isNumber: false,
|
|
326
|
+
value: asciiLowercase(itemValue)
|
|
365
327
|
});
|
|
366
328
|
}
|
|
367
329
|
} else {
|
|
368
330
|
values.push({
|
|
369
331
|
type,
|
|
370
332
|
name,
|
|
371
|
-
value: asciiLowercase(itemValue)
|
|
372
|
-
raw
|
|
333
|
+
value: caseSensitive ? itemValue : asciiLowercase(itemValue)
|
|
373
334
|
});
|
|
374
335
|
}
|
|
375
336
|
break;
|
|
@@ -391,8 +352,6 @@ const parsePropertyValue = (prop, val, opt = {}) => {
|
|
|
391
352
|
}
|
|
392
353
|
}
|
|
393
354
|
parsedValue = values;
|
|
394
|
-
} else {
|
|
395
|
-
parsedValue = val;
|
|
396
355
|
}
|
|
397
356
|
} catch {
|
|
398
357
|
parsedValue = false;
|
|
@@ -403,18 +362,18 @@ const parsePropertyValue = (prop, val, opt = {}) => {
|
|
|
403
362
|
return;
|
|
404
363
|
}
|
|
405
364
|
return parsedValue;
|
|
406
|
-
}
|
|
365
|
+
}
|
|
407
366
|
|
|
408
367
|
/**
|
|
409
368
|
* Parses a numeric value (number, dimension, percentage).
|
|
410
|
-
* Helper function for
|
|
369
|
+
* Helper function for serializeNumber, serializeLength, etc.
|
|
411
370
|
*
|
|
412
371
|
* @param {Array<object>} val - The AST value.
|
|
413
372
|
* @param {object} [opt={}] - The options for parsing.
|
|
414
373
|
* @param {Function} validateType - Function to validate the node type.
|
|
415
374
|
* @returns {object|undefined} The parsed result containing num and unit, or undefined.
|
|
416
375
|
*/
|
|
417
|
-
|
|
376
|
+
function parseNumericValue(val, opt, validateType) {
|
|
418
377
|
const [item] = val;
|
|
419
378
|
const { type, value, unit } = item ?? {};
|
|
420
379
|
if (!validateType(type, value, unit)) {
|
|
@@ -438,31 +397,31 @@ const parseNumericValue = (val, opt, validateType) => {
|
|
|
438
397
|
unit: unit ? asciiLowercase(unit) : null,
|
|
439
398
|
type
|
|
440
399
|
};
|
|
441
|
-
}
|
|
400
|
+
}
|
|
442
401
|
|
|
443
402
|
/**
|
|
444
|
-
*
|
|
403
|
+
* Serializes a <number> value.
|
|
445
404
|
*
|
|
446
405
|
* @param {Array<object>} val - The AST value.
|
|
447
406
|
* @param {object} [opt={}] - The options for parsing.
|
|
448
407
|
* @returns {string|undefined} The parsed number.
|
|
449
408
|
*/
|
|
450
|
-
|
|
409
|
+
function serializeNumber(val, opt = {}) {
|
|
451
410
|
const res = parseNumericValue(val, opt, (type) => type === AST_TYPES.NUMBER);
|
|
452
411
|
if (!res) {
|
|
453
412
|
return;
|
|
454
413
|
}
|
|
455
414
|
return `${res.num}`;
|
|
456
|
-
}
|
|
415
|
+
}
|
|
457
416
|
|
|
458
417
|
/**
|
|
459
|
-
*
|
|
418
|
+
* Serializes an <angle> value.
|
|
460
419
|
*
|
|
461
420
|
* @param {Array<object>} val - The AST value.
|
|
462
421
|
* @param {object} [opt={}] - The options for parsing.
|
|
463
|
-
* @returns {string|undefined} The
|
|
422
|
+
* @returns {string|undefined} The serialized angle.
|
|
464
423
|
*/
|
|
465
|
-
|
|
424
|
+
function serializeAngle(val, opt = {}) {
|
|
466
425
|
const res = parseNumericValue(
|
|
467
426
|
val,
|
|
468
427
|
opt,
|
|
@@ -472,67 +431,85 @@ const parseLength = (val, opt = {}) => {
|
|
|
472
431
|
return;
|
|
473
432
|
}
|
|
474
433
|
const { num, unit } = res;
|
|
475
|
-
if (
|
|
476
|
-
|
|
477
|
-
|
|
434
|
+
if (unit) {
|
|
435
|
+
if (!/^(?:deg|g?rad|turn)$/i.test(unit)) {
|
|
436
|
+
return;
|
|
437
|
+
}
|
|
478
438
|
return `${num}${unit}`;
|
|
439
|
+
} else if (num === 0) {
|
|
440
|
+
return `${num}deg`;
|
|
479
441
|
}
|
|
480
|
-
}
|
|
442
|
+
}
|
|
481
443
|
|
|
482
444
|
/**
|
|
483
|
-
*
|
|
445
|
+
* Serializes a <length> value.
|
|
484
446
|
*
|
|
485
447
|
* @param {Array<object>} val - The AST value.
|
|
486
448
|
* @param {object} [opt={}] - The options for parsing.
|
|
487
|
-
* @returns {string|undefined} The
|
|
449
|
+
* @returns {string|undefined} The serialized length.
|
|
488
450
|
*/
|
|
489
|
-
|
|
451
|
+
function serializeLength(val, opt = {}) {
|
|
490
452
|
const res = parseNumericValue(
|
|
491
453
|
val,
|
|
492
454
|
opt,
|
|
493
|
-
(type, value) => type === AST_TYPES.
|
|
455
|
+
(type, value) => type === AST_TYPES.DIMENSION || (type === AST_TYPES.NUMBER && value === "0")
|
|
494
456
|
);
|
|
495
457
|
if (!res) {
|
|
496
458
|
return;
|
|
497
459
|
}
|
|
498
|
-
const { num } = res;
|
|
499
|
-
|
|
500
|
-
}
|
|
460
|
+
const { num, unit } = res;
|
|
461
|
+
if (num === 0 && !unit) {
|
|
462
|
+
return `${num}px`;
|
|
463
|
+
} else if (unit) {
|
|
464
|
+
return `${num}${unit}`;
|
|
465
|
+
}
|
|
466
|
+
}
|
|
501
467
|
|
|
502
468
|
/**
|
|
503
|
-
*
|
|
469
|
+
* Serializes a <dimension> value, e.g. <frequency>, <time> and <resolution>.
|
|
504
470
|
*
|
|
505
471
|
* @param {Array<object>} val - The AST value.
|
|
506
472
|
* @param {object} [opt={}] - The options for parsing.
|
|
507
|
-
* @returns {string|undefined} The
|
|
473
|
+
* @returns {string|undefined} The serialized dimension.
|
|
508
474
|
*/
|
|
509
|
-
|
|
510
|
-
const res = parseNumericValue(
|
|
511
|
-
val,
|
|
512
|
-
opt,
|
|
513
|
-
(type, value) => type === AST_TYPES.DIMENSION || (type === AST_TYPES.NUMBER && value === "0")
|
|
514
|
-
);
|
|
475
|
+
function serializeDimension(val, opt = {}) {
|
|
476
|
+
const res = parseNumericValue(val, opt, (type) => type === AST_TYPES.DIMENSION);
|
|
515
477
|
if (!res) {
|
|
516
478
|
return;
|
|
517
479
|
}
|
|
518
480
|
const { num, unit } = res;
|
|
519
481
|
if (unit) {
|
|
520
|
-
if (!/^(?:deg|g?rad|turn)$/i.test(unit)) {
|
|
521
|
-
return;
|
|
522
|
-
}
|
|
523
482
|
return `${num}${unit}`;
|
|
524
|
-
} else if (num === 0) {
|
|
525
|
-
return `${num}deg`;
|
|
526
483
|
}
|
|
527
|
-
}
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
/**
|
|
487
|
+
* Serializes a <percentage> value.
|
|
488
|
+
*
|
|
489
|
+
* @param {Array<object>} val - The AST value.
|
|
490
|
+
* @param {object} [opt={}] - The options for parsing.
|
|
491
|
+
* @returns {string|undefined} The serialized percentage.
|
|
492
|
+
*/
|
|
493
|
+
function serializePercentage(val, opt = {}) {
|
|
494
|
+
const res = parseNumericValue(
|
|
495
|
+
val,
|
|
496
|
+
opt,
|
|
497
|
+
(type, value) => type === AST_TYPES.PERCENTAGE || (type === AST_TYPES.NUMBER && value === "0")
|
|
498
|
+
);
|
|
499
|
+
if (!res) {
|
|
500
|
+
return;
|
|
501
|
+
}
|
|
502
|
+
const { num } = res;
|
|
503
|
+
return `${num}%`;
|
|
504
|
+
}
|
|
528
505
|
|
|
529
506
|
/**
|
|
530
|
-
*
|
|
507
|
+
* Serializes a <url> value.
|
|
531
508
|
*
|
|
532
509
|
* @param {Array<object>} val - The AST value.
|
|
533
|
-
* @returns {string|undefined} The
|
|
510
|
+
* @returns {string|undefined} The serialized url.
|
|
534
511
|
*/
|
|
535
|
-
|
|
512
|
+
function serializeURL(val) {
|
|
536
513
|
const [item] = val;
|
|
537
514
|
const { type, value } = item ?? {};
|
|
538
515
|
if (type !== AST_TYPES.URL) {
|
|
@@ -540,15 +517,15 @@ const parseUrl = (val) => {
|
|
|
540
517
|
}
|
|
541
518
|
const str = value.replace(/\\\\/g, "\\").replaceAll('"', '\\"');
|
|
542
519
|
return `url("${str}")`;
|
|
543
|
-
}
|
|
520
|
+
}
|
|
544
521
|
|
|
545
522
|
/**
|
|
546
|
-
*
|
|
523
|
+
* Serializes a <string> value.
|
|
547
524
|
*
|
|
548
525
|
* @param {Array<object>} val - The AST value.
|
|
549
|
-
* @returns {string|undefined} The
|
|
526
|
+
* @returns {string|undefined} The serialized string.
|
|
550
527
|
*/
|
|
551
|
-
|
|
528
|
+
function serializeString(val) {
|
|
552
529
|
const [item] = val;
|
|
553
530
|
const { type, value } = item ?? {};
|
|
554
531
|
if (type !== AST_TYPES.STRING) {
|
|
@@ -556,15 +533,15 @@ const parseString = (val) => {
|
|
|
556
533
|
}
|
|
557
534
|
const str = value.replace(/\\\\/g, "\\").replaceAll('"', '\\"');
|
|
558
535
|
return `"${str}"`;
|
|
559
|
-
}
|
|
536
|
+
}
|
|
560
537
|
|
|
561
538
|
/**
|
|
562
|
-
*
|
|
539
|
+
* Serializes a <color> value.
|
|
563
540
|
*
|
|
564
541
|
* @param {Array<object>} val - The AST value.
|
|
565
|
-
* @returns {string|undefined} The
|
|
542
|
+
* @returns {string|undefined} The serialized color.
|
|
566
543
|
*/
|
|
567
|
-
|
|
544
|
+
function serializeColor(val) {
|
|
568
545
|
const [item] = val;
|
|
569
546
|
const { name, type, value } = item ?? {};
|
|
570
547
|
switch (type) {
|
|
@@ -600,15 +577,15 @@ const parseColor = (val) => {
|
|
|
600
577
|
}
|
|
601
578
|
default:
|
|
602
579
|
}
|
|
603
|
-
}
|
|
580
|
+
}
|
|
604
581
|
|
|
605
582
|
/**
|
|
606
|
-
*
|
|
583
|
+
* Serializes a <gradient> value.
|
|
607
584
|
*
|
|
608
585
|
* @param {Array<object>} val - The AST value.
|
|
609
|
-
* @returns {string|undefined} The
|
|
586
|
+
* @returns {string|undefined} The serialized gradient.
|
|
610
587
|
*/
|
|
611
|
-
|
|
588
|
+
function serializeGradient(val) {
|
|
612
589
|
const [item] = val;
|
|
613
590
|
const { name, type, value } = item ?? {};
|
|
614
591
|
if (type !== AST_TYPES.FUNCTION) {
|
|
@@ -620,7 +597,7 @@ const parseGradient = (val) => {
|
|
|
620
597
|
if (res) {
|
|
621
598
|
return res;
|
|
622
599
|
}
|
|
623
|
-
}
|
|
600
|
+
}
|
|
624
601
|
|
|
625
602
|
/**
|
|
626
603
|
* Resolves a keyword value.
|
|
@@ -629,7 +606,7 @@ const parseGradient = (val) => {
|
|
|
629
606
|
* @param {object} [opt={}] - The options for parsing.
|
|
630
607
|
* @returns {string|undefined} The resolved keyword or undefined.
|
|
631
608
|
*/
|
|
632
|
-
|
|
609
|
+
function resolveKeywordValue(value, opt = {}) {
|
|
633
610
|
const [{ name, type }] = value;
|
|
634
611
|
const { length } = opt;
|
|
635
612
|
switch (type) {
|
|
@@ -644,7 +621,7 @@ const resolveKeywordValue = (value, opt = {}) => {
|
|
|
644
621
|
}
|
|
645
622
|
default:
|
|
646
623
|
}
|
|
647
|
-
}
|
|
624
|
+
}
|
|
648
625
|
|
|
649
626
|
/**
|
|
650
627
|
* Resolves a function value.
|
|
@@ -653,7 +630,7 @@ const resolveKeywordValue = (value, opt = {}) => {
|
|
|
653
630
|
* @param {object} [opt={}] - The options for parsing.
|
|
654
631
|
* @returns {string|undefined} The resolved function or undefined.
|
|
655
632
|
*/
|
|
656
|
-
|
|
633
|
+
function resolveFunctionValue(value, opt = {}) {
|
|
657
634
|
const [{ name, type, value: itemValue }] = value;
|
|
658
635
|
const { length } = opt;
|
|
659
636
|
switch (type) {
|
|
@@ -671,16 +648,16 @@ const resolveFunctionValue = (value, opt = {}) => {
|
|
|
671
648
|
}
|
|
672
649
|
default:
|
|
673
650
|
}
|
|
674
|
-
}
|
|
651
|
+
}
|
|
675
652
|
|
|
676
653
|
/**
|
|
677
|
-
* Resolves a
|
|
654
|
+
* Resolves a numeric value.
|
|
678
655
|
*
|
|
679
|
-
* @param {Array<object>} value - The AST node array containing the value.
|
|
656
|
+
* @param {Array<object>} value - The AST node array containing the numeric value.
|
|
680
657
|
* @param {object} [opt={}] - The options for parsing.
|
|
681
658
|
* @returns {string|undefined} The resolved length/percentage/number or undefined.
|
|
682
659
|
*/
|
|
683
|
-
|
|
660
|
+
function resolveNumericValue(value, opt = {}) {
|
|
684
661
|
const [{ name, type: itemType, value: itemValue }] = value;
|
|
685
662
|
const { length, type } = opt;
|
|
686
663
|
switch (itemType) {
|
|
@@ -689,9 +666,11 @@ const resolveNumericValue = (value, opt = {}) => {
|
|
|
689
666
|
}
|
|
690
667
|
case AST_TYPES.DIMENSION: {
|
|
691
668
|
if (type === "angle") {
|
|
692
|
-
return
|
|
669
|
+
return serializeAngle(value, opt);
|
|
670
|
+
} else if (type === "length") {
|
|
671
|
+
return serializeLength(value, opt);
|
|
693
672
|
}
|
|
694
|
-
return
|
|
673
|
+
return serializeDimension(value, opt);
|
|
695
674
|
}
|
|
696
675
|
case AST_TYPES.GLOBAL_KEYWORD: {
|
|
697
676
|
if (length > 1) {
|
|
@@ -705,25 +684,25 @@ const resolveNumericValue = (value, opt = {}) => {
|
|
|
705
684
|
case AST_TYPES.NUMBER: {
|
|
706
685
|
switch (type) {
|
|
707
686
|
case "angle": {
|
|
708
|
-
return
|
|
687
|
+
return serializeAngle(value, opt);
|
|
709
688
|
}
|
|
710
689
|
case "length": {
|
|
711
|
-
return
|
|
690
|
+
return serializeLength(value, opt);
|
|
712
691
|
}
|
|
713
692
|
case "percentage": {
|
|
714
|
-
return
|
|
693
|
+
return serializePercentage(value, opt);
|
|
715
694
|
}
|
|
716
695
|
default: {
|
|
717
|
-
return
|
|
696
|
+
return serializeNumber(value, opt);
|
|
718
697
|
}
|
|
719
698
|
}
|
|
720
699
|
}
|
|
721
700
|
case AST_TYPES.PERCENTAGE: {
|
|
722
|
-
return
|
|
701
|
+
return serializePercentage(value, opt);
|
|
723
702
|
}
|
|
724
703
|
default:
|
|
725
704
|
}
|
|
726
|
-
}
|
|
705
|
+
}
|
|
727
706
|
|
|
728
707
|
/**
|
|
729
708
|
* Resolves a color value.
|
|
@@ -732,7 +711,7 @@ const resolveNumericValue = (value, opt = {}) => {
|
|
|
732
711
|
* @param {object} [opt={}] - The options for parsing.
|
|
733
712
|
* @returns {string|undefined} The resolved color or undefined.
|
|
734
713
|
*/
|
|
735
|
-
|
|
714
|
+
function resolveColorValue(value, opt = {}) {
|
|
736
715
|
const [{ name, type }] = value;
|
|
737
716
|
const { length } = opt;
|
|
738
717
|
switch (type) {
|
|
@@ -743,19 +722,19 @@ const resolveColorValue = (value, opt = {}) => {
|
|
|
743
722
|
return name;
|
|
744
723
|
}
|
|
745
724
|
default: {
|
|
746
|
-
return
|
|
725
|
+
return serializeColor(value, opt);
|
|
747
726
|
}
|
|
748
727
|
}
|
|
749
|
-
}
|
|
728
|
+
}
|
|
750
729
|
|
|
751
730
|
/**
|
|
752
|
-
* Resolves
|
|
731
|
+
* Resolves an image value.
|
|
753
732
|
*
|
|
754
|
-
* @param {Array<object>} value - The AST node array containing the
|
|
733
|
+
* @param {Array<object>} value - The AST node array containing the image value.
|
|
755
734
|
* @param {object} [opt={}] - The options for parsing.
|
|
756
735
|
* @returns {string|undefined} The resolved gradient/url or undefined.
|
|
757
736
|
*/
|
|
758
|
-
|
|
737
|
+
function resolveImageValue(value, opt = {}) {
|
|
759
738
|
const [{ name, type }] = value;
|
|
760
739
|
const { length } = opt;
|
|
761
740
|
switch (type) {
|
|
@@ -769,13 +748,13 @@ const resolveGradientUrlValue = (value, opt = {}) => {
|
|
|
769
748
|
return name;
|
|
770
749
|
}
|
|
771
750
|
case AST_TYPES.URL: {
|
|
772
|
-
return
|
|
751
|
+
return serializeURL(value, opt);
|
|
773
752
|
}
|
|
774
753
|
default: {
|
|
775
|
-
return
|
|
754
|
+
return serializeGradient(value, opt);
|
|
776
755
|
}
|
|
777
756
|
}
|
|
778
|
-
}
|
|
757
|
+
}
|
|
779
758
|
|
|
780
759
|
/**
|
|
781
760
|
* Resolves a border shorthand value.
|
|
@@ -785,7 +764,7 @@ const resolveGradientUrlValue = (value, opt = {}) => {
|
|
|
785
764
|
* @param {Map} parsedValues - The Map of parsed values.
|
|
786
765
|
* @returns {Array|string|undefined} - The resolved [prop, value] pair, keyword or undefined.
|
|
787
766
|
*/
|
|
788
|
-
|
|
767
|
+
function resolveBorderShorthandValue(value, subProps, parsedValues) {
|
|
789
768
|
const [{ isNumber, name, type, value: itemValue }] = value;
|
|
790
769
|
const { color: colorProp, style: styleProp, width: widthProp } = subProps;
|
|
791
770
|
switch (type) {
|
|
@@ -800,7 +779,7 @@ const resolveBorderShorthandValue = (value, subProps, parsedValues) => {
|
|
|
800
779
|
if (parsedValues.has(widthProp)) {
|
|
801
780
|
return;
|
|
802
781
|
}
|
|
803
|
-
const parsedValue =
|
|
782
|
+
const parsedValue = serializeLength(value, { min: 0 });
|
|
804
783
|
if (!parsedValue) {
|
|
805
784
|
return;
|
|
806
785
|
}
|
|
@@ -811,7 +790,7 @@ const resolveBorderShorthandValue = (value, subProps, parsedValues) => {
|
|
|
811
790
|
if (parsedValues.has(colorProp)) {
|
|
812
791
|
return;
|
|
813
792
|
}
|
|
814
|
-
const parsedValue =
|
|
793
|
+
const parsedValue = serializeColor(value);
|
|
815
794
|
if (!parsedValue) {
|
|
816
795
|
return;
|
|
817
796
|
}
|
|
@@ -841,7 +820,7 @@ const resolveBorderShorthandValue = (value, subProps, parsedValues) => {
|
|
|
841
820
|
}
|
|
842
821
|
default:
|
|
843
822
|
}
|
|
844
|
-
}
|
|
823
|
+
}
|
|
845
824
|
|
|
846
825
|
module.exports = {
|
|
847
826
|
AST_TYPES,
|
|
@@ -849,23 +828,24 @@ module.exports = {
|
|
|
849
828
|
hasVarFunc,
|
|
850
829
|
isGlobalKeyword,
|
|
851
830
|
isValidPropertyValue,
|
|
852
|
-
parseAngle,
|
|
853
831
|
parseCSS,
|
|
854
|
-
parseColor,
|
|
855
|
-
parseGradient,
|
|
856
|
-
parseLength,
|
|
857
|
-
parseNumber,
|
|
858
|
-
parsePercentage,
|
|
859
832
|
parsePropertyValue,
|
|
860
|
-
parseString,
|
|
861
|
-
parseUrl,
|
|
862
833
|
prepareValue,
|
|
863
834
|
resolveBorderShorthandValue,
|
|
864
835
|
resolveCalc,
|
|
865
836
|
resolveColorValue,
|
|
866
837
|
resolveFunctionValue,
|
|
867
|
-
|
|
838
|
+
resolveImageValue,
|
|
868
839
|
resolveKeywordValue,
|
|
869
840
|
resolveNumericValue,
|
|
841
|
+
serializeAngle,
|
|
842
|
+
serializeColor,
|
|
843
|
+
serializeDimension,
|
|
844
|
+
serializeGradient,
|
|
845
|
+
serializeLength,
|
|
846
|
+
serializeNumber,
|
|
847
|
+
serializePercentage,
|
|
848
|
+
serializeString,
|
|
849
|
+
serializeURL,
|
|
870
850
|
splitValue
|
|
871
851
|
};
|