cssstyle 4.3.1 → 4.4.0

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.
Files changed (94) hide show
  1. package/lib/CSSStyleDeclaration.js +545 -206
  2. package/lib/allExtraProperties.js +42 -60
  3. package/lib/allWebkitProperties.js +107 -187
  4. package/lib/generated/allProperties.js +615 -0
  5. package/lib/{implementedProperties.js → generated/implementedProperties.js} +11 -18
  6. package/lib/generated/properties.js +2574 -0
  7. package/lib/parsers.js +382 -547
  8. package/lib/properties/background.js +40 -13
  9. package/lib/properties/backgroundAttachment.js +23 -15
  10. package/lib/properties/backgroundColor.js +21 -19
  11. package/lib/properties/backgroundImage.js +19 -14
  12. package/lib/properties/backgroundPosition.js +35 -41
  13. package/lib/properties/backgroundRepeat.js +20 -20
  14. package/lib/properties/border.js +34 -25
  15. package/lib/properties/borderBottom.js +34 -11
  16. package/lib/properties/borderBottomColor.js +27 -8
  17. package/lib/properties/borderBottomStyle.js +42 -13
  18. package/lib/properties/borderBottomWidth.js +28 -8
  19. package/lib/properties/borderCollapse.js +16 -16
  20. package/lib/properties/borderColor.js +32 -18
  21. package/lib/properties/borderLeft.js +34 -11
  22. package/lib/properties/borderLeftColor.js +27 -8
  23. package/lib/properties/borderLeftStyle.js +42 -13
  24. package/lib/properties/borderLeftWidth.js +28 -8
  25. package/lib/properties/borderRight.js +34 -11
  26. package/lib/properties/borderRightColor.js +27 -8
  27. package/lib/properties/borderRightStyle.js +42 -13
  28. package/lib/properties/borderRightWidth.js +28 -8
  29. package/lib/properties/borderSpacing.js +31 -27
  30. package/lib/properties/borderStyle.js +43 -27
  31. package/lib/properties/borderTop.js +34 -11
  32. package/lib/properties/borderTopColor.js +27 -8
  33. package/lib/properties/borderTopStyle.js +42 -13
  34. package/lib/properties/borderTopWidth.js +28 -9
  35. package/lib/properties/borderWidth.js +32 -34
  36. package/lib/properties/bottom.js +23 -7
  37. package/lib/properties/clear.js +32 -8
  38. package/lib/properties/clip.js +33 -27
  39. package/lib/properties/color.js +23 -7
  40. package/lib/properties/flex.js +59 -29
  41. package/lib/properties/flexBasis.js +21 -16
  42. package/lib/properties/flexGrow.js +19 -10
  43. package/lib/properties/flexShrink.js +19 -10
  44. package/lib/properties/float.js +21 -6
  45. package/lib/properties/floodColor.js +23 -7
  46. package/lib/properties/font.js +120 -33
  47. package/lib/properties/fontFamily.js +59 -21
  48. package/lib/properties/fontSize.js +37 -28
  49. package/lib/properties/fontStyle.js +23 -9
  50. package/lib/properties/fontVariant.js +26 -8
  51. package/lib/properties/fontWeight.js +26 -23
  52. package/lib/properties/height.js +21 -14
  53. package/lib/properties/left.js +23 -7
  54. package/lib/properties/lightingColor.js +23 -7
  55. package/lib/properties/lineHeight.js +29 -16
  56. package/lib/properties/margin.js +42 -57
  57. package/lib/properties/marginBottom.js +34 -7
  58. package/lib/properties/marginLeft.js +34 -7
  59. package/lib/properties/marginRight.js +34 -7
  60. package/lib/properties/marginTop.js +34 -7
  61. package/lib/properties/opacity.js +39 -7
  62. package/lib/properties/outlineColor.js +23 -7
  63. package/lib/properties/padding.js +43 -51
  64. package/lib/properties/paddingBottom.js +36 -7
  65. package/lib/properties/paddingLeft.js +34 -7
  66. package/lib/properties/paddingRight.js +34 -7
  67. package/lib/properties/paddingTop.js +34 -7
  68. package/lib/properties/right.js +23 -7
  69. package/lib/properties/stopColor.js +23 -7
  70. package/lib/properties/top.js +23 -7
  71. package/lib/properties/webkitBorderAfterColor.js +23 -7
  72. package/lib/properties/webkitBorderBeforeColor.js +23 -7
  73. package/lib/properties/webkitBorderEndColor.js +23 -7
  74. package/lib/properties/webkitBorderStartColor.js +23 -7
  75. package/lib/properties/webkitColumnRuleColor.js +23 -7
  76. package/lib/properties/webkitTapHighlightColor.js +23 -7
  77. package/lib/properties/webkitTextEmphasisColor.js +23 -7
  78. package/lib/properties/webkitTextFillColor.js +23 -7
  79. package/lib/properties/webkitTextStrokeColor.js +23 -7
  80. package/lib/properties/width.js +21 -14
  81. package/lib/utils/camelize.js +35 -0
  82. package/lib/utils/propertyDescriptors.js +16 -0
  83. package/package.json +5 -4
  84. package/lib/allProperties.js +0 -529
  85. package/lib/constants.js +0 -6
  86. package/lib/named_colors.json +0 -152
  87. package/lib/properties/azimuth.js +0 -64
  88. package/lib/properties/cssFloat.js +0 -12
  89. package/lib/properties/textLineThroughColor.js +0 -14
  90. package/lib/properties/textOverlineColor.js +0 -14
  91. package/lib/properties/textUnderlineColor.js +0 -14
  92. package/lib/properties/webkitMatchNearestMailBlockquoteColor.js +0 -14
  93. package/lib/properties.js +0 -1672
  94. package/lib/utils/getBasicPropertyDescriptor.js +0 -14
@@ -1,272 +1,611 @@
1
- /*********************************************************************
1
+ /**
2
2
  * This is a fork from the CSS Style Declaration part of
3
3
  * https://github.com/NV/CSSOM
4
- ********************************************************************/
5
- 'use strict';
6
- var CSSOM = require('rrweb-cssom');
7
- var allProperties = require('./allProperties');
8
- var allExtraProperties = require('./allExtraProperties');
9
- var implementedProperties = require('./implementedProperties');
10
- var { dashedToCamelCase } = require('./parsers');
11
- var getBasicPropertyDescriptor = require('./utils/getBasicPropertyDescriptor');
4
+ */
5
+ "use strict";
6
+ const CSSOM = require("rrweb-cssom");
7
+ const allExtraProperties = require("./allExtraProperties");
8
+ const allProperties = require("./generated/allProperties");
9
+ const implementedProperties = require("./generated/implementedProperties");
10
+ const generatedProperties = require("./generated/properties");
11
+ const { hasVarFunc, parseKeyword, parseShorthand, prepareValue, splitValue } = require("./parsers");
12
+ const { dashedToCamelCase } = require("./utils/camelize");
13
+ const { getPropertyDescriptor } = require("./utils/propertyDescriptors");
12
14
 
13
15
  /**
14
- * @constructor
15
- * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleDeclaration
16
+ * @see https://drafts.csswg.org/cssom/#the-cssstyledeclaration-interface
16
17
  */
17
- var CSSStyleDeclaration = function CSSStyleDeclaration(onChangeCallback) {
18
- this._values = {};
19
- this._importants = {};
20
- this._length = 0;
21
- this._onChange = onChangeCallback;
22
- this._setInProgress = false;
23
- };
24
- CSSStyleDeclaration.prototype = {
25
- constructor: CSSStyleDeclaration,
26
-
18
+ class CSSStyleDeclaration {
27
19
  /**
28
- *
29
- * @param {string} name
30
- * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleDeclaration-getPropertyValue
31
- * @return {string} the value of the property if it has been explicitly set for this declaration block.
32
- * Returns the empty string if the property has not been set.
20
+ * @param {Function} onChangeCallback
21
+ * @param {object} [opt]
22
+ * @param {object} [opt.context] - Window, Element or CSSRule.
33
23
  */
34
- getPropertyValue: function (name) {
35
- if (!this._values.hasOwnProperty(name)) {
36
- return '';
37
- }
38
- return this._values[name].toString();
39
- },
24
+ constructor(onChangeCallback, opt = {}) {
25
+ // Make constructor and internals non-enumerable.
26
+ Object.defineProperties(this, {
27
+ constructor: {
28
+ enumerable: false,
29
+ writable: true
30
+ },
40
31
 
41
- /**
42
- *
43
- * @param {string} name
44
- * @param {string} value
45
- * @param {string} [priority=null] "important" or null
46
- * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleDeclaration-setProperty
47
- */
48
- setProperty: function (name, value, priority) {
49
- if (value === undefined) {
50
- return;
32
+ // Window
33
+ _global: {
34
+ value: globalThis,
35
+ enumerable: false,
36
+ writable: true
37
+ },
38
+
39
+ // Element
40
+ _ownerNode: {
41
+ value: null,
42
+ enumerable: false,
43
+ writable: true
44
+ },
45
+
46
+ // CSSRule
47
+ _parentNode: {
48
+ value: null,
49
+ enumerable: false,
50
+ writable: true
51
+ },
52
+
53
+ _onChange: {
54
+ value: null,
55
+ enumerable: false,
56
+ writable: true
57
+ },
58
+
59
+ _values: {
60
+ value: new Map(),
61
+ enumerable: false,
62
+ writable: true
63
+ },
64
+
65
+ _priorities: {
66
+ value: new Map(),
67
+ enumerable: false,
68
+ writable: true
69
+ },
70
+
71
+ _length: {
72
+ value: 0,
73
+ enumerable: false,
74
+ writable: true
75
+ },
76
+
77
+ _computed: {
78
+ value: false,
79
+ enumerable: false,
80
+ writable: true
81
+ },
82
+
83
+ _readonly: {
84
+ value: false,
85
+ enumerable: false,
86
+ writable: true
87
+ },
88
+
89
+ _setInProgress: {
90
+ value: false,
91
+ enumerable: false,
92
+ writable: true
93
+ }
94
+ });
95
+
96
+ const { context } = opt;
97
+ if (context) {
98
+ if (typeof context.getComputedStyle === "function") {
99
+ this._global = context;
100
+ this._computed = true;
101
+ this._readonly = true;
102
+ } else if (context.nodeType === 1 && Object.hasOwn(context, "style")) {
103
+ this._global = context.ownerDocument.defaultView;
104
+ this._ownerNode = context;
105
+ } else if (Object.hasOwn(context, "parentRule")) {
106
+ this._parentRule = context;
107
+ // Find Window from the owner node of the StyleSheet.
108
+ const window = context?.parentStyleSheet?.ownerNode?.ownerDocument?.defaultView;
109
+ if (window) {
110
+ this._global = window;
111
+ }
112
+ }
51
113
  }
52
- if (value === null || value === '') {
53
- this.removeProperty(name);
54
- return;
114
+ if (typeof onChangeCallback === "function") {
115
+ this._onChange = onChangeCallback;
55
116
  }
56
- var isCustomProperty =
57
- name.indexOf('--') === 0 ||
58
- (typeof value === 'string' && /^var\(--[-\w]+,?.*\)$/.test(value));
59
- if (isCustomProperty) {
60
- this._setProperty(name, value, priority);
61
- return;
117
+ }
118
+
119
+ get cssText() {
120
+ if (this._computed) {
121
+ return "";
62
122
  }
63
- var lowercaseName = name.toLowerCase();
64
- if (!allProperties.has(lowercaseName) && !allExtraProperties.has(lowercaseName)) {
65
- return;
123
+ const properties = [];
124
+ for (let i = 0; i < this._length; i++) {
125
+ const property = this[i];
126
+ const value = this.getPropertyValue(property);
127
+ const priority = this.getPropertyPriority(property);
128
+ if (priority === "important") {
129
+ properties.push(`${property}: ${value} !${priority};`);
130
+ } else {
131
+ properties.push(`${property}: ${value};`);
132
+ }
66
133
  }
134
+ return properties.join(" ");
135
+ }
67
136
 
68
- this[lowercaseName] = value;
69
- this._importants[lowercaseName] = priority;
70
- },
71
- _setProperty: function (name, value, priority) {
72
- if (value === undefined) {
73
- return;
137
+ set cssText(value) {
138
+ if (this._readonly) {
139
+ const msg = "cssText can not be modified.";
140
+ const name = "NoModificationAllowedError";
141
+ throw new this._global.DOMException(msg, name);
74
142
  }
75
- if (value === null || value === '') {
76
- this.removeProperty(name);
143
+ Array.prototype.splice.call(this, 0, this._length);
144
+ this._values.clear();
145
+ this._priorities.clear();
146
+ if (this._parentRule || (this._ownerNode && this._setInProgress)) {
77
147
  return;
78
148
  }
79
-
80
- var originalText;
81
- if (this._onChange) {
82
- originalText = this.cssText;
149
+ this._setInProgress = true;
150
+ let dummyRule;
151
+ try {
152
+ dummyRule = CSSOM.parse(`#bogus{${value}}`).cssRules[0].style;
153
+ } catch {
154
+ // Malformed css, just return.
155
+ return;
83
156
  }
84
-
85
- if (this._values[name]) {
86
- // Property already exist. Overwrite it.
87
- var index = Array.prototype.indexOf.call(this, name);
88
- if (index < 0) {
89
- this[this._length] = name;
90
- this._length++;
91
- }
92
- } else {
93
- // New property.
94
- this[this._length] = name;
95
- this._length++;
157
+ for (let i = 0; i < dummyRule.length; i++) {
158
+ const property = dummyRule[i];
159
+ this.setProperty(
160
+ property,
161
+ dummyRule.getPropertyValue(property),
162
+ dummyRule.getPropertyPriority(property)
163
+ );
96
164
  }
97
- this._values[name] = value;
98
- this._importants[name] = priority;
99
- if (this._onChange && this.cssText !== originalText && !this._setInProgress) {
165
+ this._setInProgress = false;
166
+ if (typeof this._onChange === "function") {
100
167
  this._onChange(this.cssText);
101
168
  }
102
- },
103
-
104
- /**
105
- *
106
- * @param {string} name
107
- * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleDeclaration-removeProperty
108
- * @return {string} the value of the property if it has been explicitly set for this declaration block.
109
- * Returns the empty string if the property has not been set or the property name does not correspond to a known CSS property.
110
- */
111
- removeProperty: function (name) {
112
- if (!this._values.hasOwnProperty(name)) {
113
- return '';
114
- }
169
+ }
115
170
 
116
- var prevValue = this._values[name];
117
- delete this._values[name];
118
- delete this._importants[name];
171
+ get length() {
172
+ return this._length;
173
+ }
119
174
 
120
- var index = Array.prototype.indexOf.call(this, name);
121
- if (index < 0) {
122
- return prevValue;
175
+ // This deletes indices if the new length is less then the current length.
176
+ // If the new length is more, it does nothing, the new indices will be
177
+ // undefined until set.
178
+ set length(len) {
179
+ for (let i = len; i < this._length; i++) {
180
+ delete this[i];
123
181
  }
182
+ this._length = len;
183
+ }
124
184
 
125
- // That's what WebKit and Opera do
126
- Array.prototype.splice.call(this, index, 1);
185
+ // Readonly
186
+ get parentRule() {
187
+ return this._parentRule;
188
+ }
127
189
 
128
- // That's what Firefox does
129
- //this[index] = ""
190
+ get cssFloat() {
191
+ return this.getPropertyValue("float");
192
+ }
130
193
 
131
- if (this._onChange) {
132
- this._onChange(this.cssText);
133
- }
134
- return prevValue;
135
- },
194
+ set cssFloat(value) {
195
+ this._setProperty("float", value);
196
+ }
136
197
 
137
198
  /**
138
- *
139
- * @param {String} name
199
+ * @param {string} property
140
200
  */
141
- getPropertyPriority: function (name) {
142
- return this._importants[name] || '';
143
- },
201
+ getPropertyPriority(property) {
202
+ return this._priorities.get(property) || "";
203
+ }
144
204
 
145
- getPropertyCSSValue: function () {
146
- //FIXME
147
- return;
148
- },
205
+ /**
206
+ * @param {string} property
207
+ */
208
+ getPropertyValue(property) {
209
+ if (this._values.has(property)) {
210
+ return this._values.get(property).toString();
211
+ }
212
+ return "";
213
+ }
149
214
 
150
215
  /**
151
- * element.style.overflow = "auto"
152
- * element.style.getPropertyShorthand("overflow-x")
153
- * -> "overflow"
216
+ * @param {...number} args
154
217
  */
155
- getPropertyShorthand: function () {
156
- //FIXME
157
- return;
158
- },
218
+ item(...args) {
219
+ if (!args.length) {
220
+ const msg = "1 argument required, but only 0 present.";
221
+ throw new this._global.TypeError(msg);
222
+ }
223
+ let [index] = args;
224
+ index = parseInt(index);
225
+ if (Number.isNaN(index) || index < 0 || index >= this._length) {
226
+ return "";
227
+ }
228
+ return this[index];
229
+ }
159
230
 
160
- isPropertyImplicit: function () {
161
- //FIXME
162
- return;
163
- },
231
+ /**
232
+ * @param {string} property
233
+ */
234
+ removeProperty(property) {
235
+ if (this._readonly) {
236
+ const msg = `Property ${property} can not be modified.`;
237
+ const name = "NoModificationAllowedError";
238
+ throw new this._global.DOMException(msg, name);
239
+ }
240
+ if (!this._values.has(property)) {
241
+ return "";
242
+ }
243
+ const prevValue = this._values.get(property);
244
+ this._values.delete(property);
245
+ this._priorities.delete(property);
246
+ const index = Array.prototype.indexOf.call(this, property);
247
+ if (index >= 0) {
248
+ Array.prototype.splice.call(this, index, 1);
249
+ if (typeof this._onChange === "function") {
250
+ this._onChange(this.cssText);
251
+ }
252
+ }
253
+ return prevValue;
254
+ }
164
255
 
165
256
  /**
166
- * http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleDeclaration-item
257
+ * @param {string} property
258
+ * @param {string} value
259
+ * @param {string?} [priority] - "important" or null
167
260
  */
168
- item: function (index) {
169
- index = parseInt(index, 10);
170
- if (index < 0 || index >= this._length) {
171
- return '';
261
+ setProperty(property, value, priority = null) {
262
+ if (this._readonly) {
263
+ const msg = `Property ${property} can not be modified.`;
264
+ const name = "NoModificationAllowedError";
265
+ throw new this._global.DOMException(msg, name);
172
266
  }
173
- return this[index];
174
- },
175
- };
267
+ value = prepareValue(value, this._global);
268
+ if (value === "") {
269
+ this[property] = "";
270
+ this.removeProperty(property);
271
+ return;
272
+ }
273
+ const isCustomProperty = property.startsWith("--");
274
+ if (isCustomProperty) {
275
+ this._setProperty(property, value);
276
+ return;
277
+ }
278
+ property = property.toLowerCase();
279
+ if (!allProperties.has(property) && !allExtraProperties.has(property)) {
280
+ return;
281
+ }
282
+ this[property] = value;
283
+ if (priority) {
284
+ this._priorities.set(property, priority);
285
+ } else {
286
+ this._priorities.delete(property);
287
+ }
288
+ }
289
+ }
176
290
 
291
+ // Internal methods
177
292
  Object.defineProperties(CSSStyleDeclaration.prototype, {
178
- cssText: {
179
- get: function () {
180
- var properties = [];
181
- var i;
182
- var name;
183
- var value;
184
- var priority;
185
- for (i = 0; i < this._length; i++) {
186
- name = this[i];
187
- value = this.getPropertyValue(name);
188
- priority = this.getPropertyPriority(name);
189
- if (priority !== '') {
190
- priority = ' !' + priority;
293
+ _shorthandGetter: {
294
+ /**
295
+ * @param {string} property
296
+ * @param {object} shorthandFor
297
+ */
298
+ value(property, shorthandFor) {
299
+ const parts = [];
300
+ for (const key of shorthandFor.keys()) {
301
+ const val = this.getPropertyValue(key);
302
+ if (hasVarFunc(val)) {
303
+ return "";
304
+ }
305
+ if (val !== "") {
306
+ parts.push(val);
191
307
  }
192
- properties.push([name, ': ', value, priority, ';'].join(''));
193
308
  }
194
- return properties.join(' ');
309
+ if (parts.length) {
310
+ return parts.join(" ");
311
+ }
312
+ if (this._values.has(property)) {
313
+ return this.getPropertyValue(property);
314
+ }
315
+ return "";
195
316
  },
196
- set: function (value) {
197
- var i;
198
- this._values = {};
199
- Array.prototype.splice.call(this, 0, this._length);
200
- this._importants = {};
201
- var dummyRule;
202
- try {
203
- dummyRule = CSSOM.parse('#bogus{' + value + '}').cssRules[0].style;
204
- } catch (err) {
205
- // malformed css, just return
317
+ enumerable: false
318
+ },
319
+
320
+ _implicitGetter: {
321
+ /**
322
+ * @param {string} property
323
+ * @param {Array.<string>} positions
324
+ */
325
+ value(property, positions = []) {
326
+ const parts = [];
327
+ for (const position of positions) {
328
+ const val = this.getPropertyValue(`${property}-${position}`);
329
+ if (val === "" || hasVarFunc(val)) {
330
+ return "";
331
+ }
332
+ parts.push(val);
333
+ }
334
+ if (!parts.length) {
335
+ return "";
336
+ }
337
+ switch (positions.length) {
338
+ case 4: {
339
+ const [top, right, bottom, left] = parts;
340
+ if (top === right && top === bottom && right === left) {
341
+ return top;
342
+ }
343
+ if (top !== right && top === bottom && right === left) {
344
+ return `${top} ${right}`;
345
+ }
346
+ if (top !== right && top !== bottom && right === left) {
347
+ return `${top} ${right} ${bottom}`;
348
+ }
349
+ return `${top} ${right} ${bottom} ${left}`;
350
+ }
351
+ case 2: {
352
+ const [x, y] = parts;
353
+ if (x === y) {
354
+ return x;
355
+ }
356
+ return `${x} ${y}`;
357
+ }
358
+ default:
359
+ return "";
360
+ }
361
+ },
362
+ enumerable: false
363
+ },
364
+
365
+ _setProperty: {
366
+ /**
367
+ * @param {string} property
368
+ * @param {string} val
369
+ * @param {string?} [priority]
370
+ */
371
+ value(property, val, priority = null) {
372
+ if (typeof val !== "string") {
206
373
  return;
207
374
  }
208
- this._setInProgress = true;
209
- var rule_length = dummyRule.length;
210
- var name;
211
- for (i = 0; i < rule_length; ++i) {
212
- name = dummyRule[i];
213
- this.setProperty(
214
- dummyRule[i],
215
- dummyRule.getPropertyValue(name),
216
- dummyRule.getPropertyPriority(name)
217
- );
375
+ if (val === "") {
376
+ this.removeProperty(property);
377
+ return;
218
378
  }
219
- this._setInProgress = false;
220
- if (this._onChange) {
379
+ let originalText = "";
380
+ if (typeof this._onChange === "function") {
381
+ originalText = this.cssText;
382
+ }
383
+ if (this._values.has(property)) {
384
+ const index = Array.prototype.indexOf.call(this, property);
385
+ // The property already exists but is not indexed into `this` so add it.
386
+ if (index < 0) {
387
+ this[this._length] = property;
388
+ this._length++;
389
+ }
390
+ } else {
391
+ // New property.
392
+ this[this._length] = property;
393
+ this._length++;
394
+ }
395
+ this._values.set(property, val);
396
+ if (priority) {
397
+ this._priorities.set(property, priority);
398
+ } else {
399
+ this._priorities.delete(property);
400
+ }
401
+ if (
402
+ typeof this._onChange === "function" &&
403
+ this.cssText !== originalText &&
404
+ !this._setInProgress
405
+ ) {
221
406
  this._onChange(this.cssText);
222
407
  }
223
408
  },
224
- enumerable: true,
225
- configurable: true,
409
+ enumerable: false
226
410
  },
227
- parentRule: {
228
- get: function () {
229
- return null;
411
+
412
+ _shorthandSetter: {
413
+ /**
414
+ * @param {string} property
415
+ * @param {string} val
416
+ * @param {object} shorthandFor
417
+ */
418
+ value(property, val, shorthandFor) {
419
+ val = prepareValue(val, this._global);
420
+ const obj = parseShorthand(val, shorthandFor);
421
+ if (!obj) {
422
+ return;
423
+ }
424
+ for (const subprop of Object.keys(obj)) {
425
+ // In case subprop is an implicit property, this will clear *its*
426
+ // subpropertiesX.
427
+ const camel = dashedToCamelCase(subprop);
428
+ this[camel] = obj[subprop];
429
+ // In case it gets translated into something else (0 -> 0px).
430
+ obj[subprop] = this[camel];
431
+ this.removeProperty(subprop);
432
+ // Don't add in empty properties.
433
+ if (obj[subprop] !== "") {
434
+ this._values.set(subprop, obj[subprop]);
435
+ }
436
+ }
437
+ for (const [subprop] of shorthandFor) {
438
+ if (!Object.hasOwn(obj, subprop)) {
439
+ this.removeProperty(subprop);
440
+ this._values.delete(subprop);
441
+ }
442
+ }
443
+ // In case the value is something like 'none' that removes all values,
444
+ // check that the generated one is not empty, first remove the property,
445
+ // if it already exists, then call the shorthandGetter, if it's an empty
446
+ // string, don't set the property.
447
+ this.removeProperty(property);
448
+ const calculated = this._shorthandGetter(property, shorthandFor);
449
+ if (calculated !== "") {
450
+ this._setProperty(property, calculated);
451
+ }
452
+ return obj;
230
453
  },
231
- enumerable: true,
232
- configurable: true,
454
+ enumerable: false
233
455
  },
234
- length: {
235
- get: function () {
236
- return this._length;
237
- },
456
+
457
+ // Companion to shorthandSetter, but for the individual parts which takes
458
+ // position value in the middle.
459
+ _midShorthandSetter: {
238
460
  /**
239
- * This deletes indices if the new length is less then the current
240
- * length. If the new length is more, it does nothing, the new indices
241
- * will be undefined until set.
242
- **/
243
- set: function (value) {
244
- var i;
245
- for (i = value; i < this._length; i++) {
246
- delete this[i];
461
+ * @param {string} property
462
+ * @param {string} val
463
+ * @param {object} shorthandFor
464
+ * @param {Array.<string>} positions
465
+ */
466
+ value(property, val, shorthandFor, positions = []) {
467
+ val = prepareValue(val, this._global);
468
+ const obj = this._shorthandSetter(property, val, shorthandFor);
469
+ if (!obj) {
470
+ return;
471
+ }
472
+ for (const position of positions) {
473
+ this.removeProperty(`${property}-${position}`);
474
+ this._values.set(`${property}-${position}`, val);
247
475
  }
248
- this._length = value;
249
476
  },
250
- enumerable: true,
251
- configurable: true,
477
+ enumerable: false
252
478
  },
253
- });
254
479
 
255
- require('./properties')(CSSStyleDeclaration.prototype);
480
+ _implicitSetter: {
481
+ /**
482
+ * @param {string} prefix
483
+ * @param {string} part
484
+ * @param {string} val
485
+ * @param {Function} isValid
486
+ * @param {Function} parser
487
+ * @param {Array.<string>} positions
488
+ */
489
+ value(prefix, part, val, isValid, parser, positions = []) {
490
+ val = prepareValue(val, this._global);
491
+ if (typeof val !== "string") {
492
+ return;
493
+ }
494
+ part ||= "";
495
+ if (part) {
496
+ part = `-${part}`;
497
+ }
498
+ let parts = [];
499
+ if (val === "") {
500
+ parts.push(val);
501
+ } else {
502
+ const key = parseKeyword(val);
503
+ if (key) {
504
+ parts.push(key);
505
+ } else {
506
+ parts.push(...splitValue(val));
507
+ }
508
+ }
509
+ if (!parts.length || parts.length > positions.length || !parts.every(isValid)) {
510
+ return;
511
+ }
512
+ parts = parts.map((p) => parser(p));
513
+ this._setProperty(`${prefix}${part}`, parts.join(" "));
514
+ switch (positions.length) {
515
+ case 4:
516
+ if (parts.length === 1) {
517
+ parts.push(parts[0], parts[0], parts[0]);
518
+ } else if (parts.length === 2) {
519
+ parts.push(parts[0], parts[1]);
520
+ } else if (parts.length === 3) {
521
+ parts.push(parts[1]);
522
+ }
523
+ break;
524
+ case 2:
525
+ if (parts.length === 1) {
526
+ parts.push(parts[0]);
527
+ }
528
+ break;
529
+ default:
530
+ }
531
+ for (let i = 0; i < positions.length; i++) {
532
+ const property = `${prefix}-${positions[i]}${part}`;
533
+ this.removeProperty(property);
534
+ this._values.set(property, parts[i]);
535
+ }
536
+ },
537
+ enumerable: false
538
+ },
256
539
 
257
- allProperties.forEach(function (property) {
258
- if (!implementedProperties.has(property)) {
259
- var declaration = getBasicPropertyDescriptor(property);
260
- Object.defineProperty(CSSStyleDeclaration.prototype, property, declaration);
261
- Object.defineProperty(CSSStyleDeclaration.prototype, dashedToCamelCase(property), declaration);
540
+ // Companion to implicitSetter, but for the individual parts.
541
+ // This sets the individual value, and checks to see if all sub-parts are
542
+ // set. If so, it sets the shorthand version and removes the individual parts
543
+ // from the cssText.
544
+ _subImplicitSetter: {
545
+ /**
546
+ * @param {string} prefix
547
+ * @param {string} part
548
+ * @param {string} val
549
+ * @param {Function} isValid
550
+ * @param {Function} parser
551
+ * @param {Array.<string>} positions
552
+ */
553
+ value(prefix, part, val, isValid, parser, positions = []) {
554
+ val = prepareValue(val, this._global);
555
+ if (typeof val !== "string" || !isValid(val)) {
556
+ return;
557
+ }
558
+ val = parser(val);
559
+ const property = `${prefix}-${part}`;
560
+ this._setProperty(property, val);
561
+ const combinedPriority = this.getPropertyPriority(prefix);
562
+ const subparts = [];
563
+ for (const position of positions) {
564
+ subparts.push(`${prefix}-${position}`);
565
+ }
566
+ const parts = subparts.map((subpart) => this._values.get(subpart));
567
+ const priorities = subparts.map((subpart) => this.getPropertyPriority(subpart));
568
+ const [priority] = priorities;
569
+ // Combine into a single property if all values are set and have the same
570
+ // priority.
571
+ if (
572
+ priority === combinedPriority &&
573
+ parts.every((p) => p) &&
574
+ priorities.every((p) => p === priority)
575
+ ) {
576
+ for (let i = 0; i < subparts.length; i++) {
577
+ this.removeProperty(subparts[i]);
578
+ this._values.set(subparts[i], parts[i]);
579
+ }
580
+ this._setProperty(prefix, parts.join(" "), priority);
581
+ } else {
582
+ this.removeProperty(prefix);
583
+ for (let i = 0; i < subparts.length; i++) {
584
+ // The property we're setting won't be important, the rest will either
585
+ // keep their priority or inherit it from the combined property
586
+ const subPriority = subparts[i] === property ? "" : priorities[i] || combinedPriority;
587
+ this._setProperty(subparts[i], parts[i], subPriority);
588
+ }
589
+ }
590
+ },
591
+ enumerable: false
262
592
  }
263
593
  });
264
594
 
265
- allExtraProperties.forEach(function (property) {
595
+ // Properties
596
+ Object.defineProperties(CSSStyleDeclaration.prototype, generatedProperties);
597
+
598
+ // Additional properties
599
+ [...allProperties, ...allExtraProperties].forEach(function (property) {
266
600
  if (!implementedProperties.has(property)) {
267
- var declaration = getBasicPropertyDescriptor(property);
601
+ const declaration = getPropertyDescriptor(property);
268
602
  Object.defineProperty(CSSStyleDeclaration.prototype, property, declaration);
269
- Object.defineProperty(CSSStyleDeclaration.prototype, dashedToCamelCase(property), declaration);
603
+ const camel = dashedToCamelCase(property);
604
+ Object.defineProperty(CSSStyleDeclaration.prototype, camel, declaration);
605
+ if (/^webkit[A-Z]/.test(camel)) {
606
+ const pascal = camel.replace(/^webkit/, "Webkit");
607
+ Object.defineProperty(CSSStyleDeclaration.prototype, pascal, declaration);
608
+ }
270
609
  }
271
610
  });
272
611