forked from jsdom/cssstyle
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpropertyDescriptors.js
More file actions
149 lines (145 loc) · 6.15 KB
/
propertyDescriptors.js
File metadata and controls
149 lines (145 loc) · 6.15 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
"use strict";
const parsers = require("../parsers");
// Constants
const { AST_TYPES } = parsers;
/**
* Creates a generic property descriptor for a given property. Such descriptors are used whenever we don't have a
* specific handler in `./properties/*.js`. They perform some basic logic that works as a fallback, and is correct for
* simple properties, but properties with more complex grammars will need their own handlers.
*
* @param {string} property - The canonical CSS property name (e.g. "backdrop-filter", not "backdropFilter").
* @param {object} opts - The options object.
* @param {boolean} opts.caseSensitive - True if value is case-sensitive, false otherwise.
* @param {object} [opts.dimensionTypes={}] - An object containing information about the dimension types used by this
* property, if any. Keys are a type of dimension, which determines which serializer to use, and values are the
* information used by the serializer to serialize a parsed value.
* @param {object} [opts.functionTypes={}] - An object containing information about the function types used by this
* property, if any. Keys are a type of function, which determines which function to use; values are ignored.
* @returns {object} The property descriptor object.
*/
function createGenericPropertyDescriptor(property, { caseSensitive, dimensionTypes = {}, functionTypes = {} }) {
return {
set(v) {
const value = parsers.prepareValue(v);
if (parsers.hasVarFunc(value)) {
this._setProperty(property, value);
} else {
const parsedValue = parsers.parsePropertyValue(property, v, {
caseSensitive
});
const priority = this._priorities.get(property) ?? "";
if (Array.isArray(parsedValue)) {
if (parsedValue.length === 1) {
const {
angle: angleType,
dimension: dimensionType,
length: lengthType,
number: numberType,
percentage: percentageType
} = dimensionTypes;
const { color: colorType, image: imageType, paint: paintType } = functionTypes;
const [{ name, type, value: itemValue }] = parsedValue;
switch (type) {
case AST_TYPES.CALC: {
this._setProperty(property, `${name}(${itemValue})`, priority);
break;
}
case AST_TYPES.DIMENSION: {
let val;
if (dimensionType && lengthType) {
val = parsers.serializeLength(parsedValue, lengthType);
if (!val) {
val = parsers.serializeDimension(parsedValue, dimensionType);
}
} else if (lengthType) {
val = parsers.serializeLength(parsedValue, lengthType);
} else {
val = parsers.serializeDimension(parsedValue, dimensionType);
}
this._setProperty(property, val, priority);
break;
}
case AST_TYPES.HASH: {
this._setProperty(property, parsers.serializeColor(parsedValue), priority);
break;
}
case AST_TYPES.NUMBER: {
let val;
if (numberType) {
val = parsers.serializeNumber(parsedValue, numberType);
} else if (angleType) {
val = parsers.serializeAngle(parsedValue, angleType);
} else if (lengthType) {
val = parsers.serializeLength(parsedValue, lengthType);
} else if (percentageType) {
val = parsers.serializePercentage(parsedValue, percentageType);
}
this._setProperty(property, val, priority);
break;
}
case AST_TYPES.GLOBAL_KEYWORD: {
this._setProperty(property, name, priority);
break;
}
case AST_TYPES.IDENTIFIER: {
if ((colorType || paintType) && parsers.isColorIdentifier(value)) {
this._setProperty(property, parsers.serializeColor(parsedValue), priority);
} else {
this._setProperty(property, name, priority);
}
break;
}
case AST_TYPES.PERCENTAGE: {
let numericType;
if (percentageType) {
numericType = percentageType;
} else if (dimensionType) {
numericType = dimensionType;
} else if (angleType) {
numericType = angleType;
} else if (lengthType) {
numericType = lengthType;
}
if (numericType) {
this._setProperty(property, parsers.resolveNumericValue(parsedValue, numericType), priority);
}
break;
}
case AST_TYPES.STRING: {
this._setProperty(property, parsers.serializeString(parsedValue), priority);
break;
}
case AST_TYPES.URL: {
this._setProperty(property, parsers.serializeURL(parsedValue), priority);
break;
}
case AST_TYPES.FUNCTION:
default: {
if (colorType || paintType) {
this._setProperty(property, parsers.serializeColor(parsedValue), priority);
} else if (imageType) {
this._setProperty(property, parsers.serializeGradient(parsedValue), priority);
} else {
this._setProperty(property, value, priority);
}
}
}
} else {
// Set the prepared value for lists containing multiple values.
this._setProperty(property, value, priority);
}
} else if (typeof parsedValue === "string") {
this._setProperty(property, parsedValue, priority);
}
}
},
get() {
return this.getPropertyValue(property);
},
enumerable: true,
configurable: true
};
}
module.exports = {
createGenericPropertyDescriptor
};