cssstyle 5.3.7 → 6.0.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 (93) hide show
  1. package/lib/CSSStyleDeclaration.js +359 -395
  2. package/lib/generated/.gitkeep +0 -0
  3. package/lib/generated/propertyDefinitions.js +3685 -1498
  4. package/lib/generated/propertyDescriptors.js +1705 -0
  5. package/lib/index.js +9 -0
  6. package/lib/normalize.js +127 -253
  7. package/lib/parsers.js +152 -164
  8. package/lib/properties/background.js +201 -202
  9. package/lib/properties/backgroundAttachment.js +35 -33
  10. package/lib/properties/backgroundClip.js +35 -33
  11. package/lib/properties/backgroundColor.js +26 -24
  12. package/lib/properties/backgroundImage.js +36 -34
  13. package/lib/properties/backgroundOrigin.js +35 -33
  14. package/lib/properties/backgroundPosition.js +57 -57
  15. package/lib/properties/backgroundRepeat.js +40 -37
  16. package/lib/properties/backgroundSize.js +38 -34
  17. package/lib/properties/border.js +41 -34
  18. package/lib/properties/{webkitBorderEndColor.js → borderBlockEndColor.js} +26 -22
  19. package/lib/properties/{webkitBorderAfterColor.js → borderBlockStartColor.js} +26 -22
  20. package/lib/properties/borderBottom.js +40 -36
  21. package/lib/properties/borderBottomColor.js +25 -21
  22. package/lib/properties/borderBottomStyle.js +25 -21
  23. package/lib/properties/borderBottomWidth.js +28 -24
  24. package/lib/properties/borderCollapse.js +25 -21
  25. package/lib/properties/borderColor.js +36 -33
  26. package/lib/properties/{webkitBorderStartColor.js → borderInlineEndColor.js} +26 -22
  27. package/lib/properties/borderInlineStartColor.js +49 -0
  28. package/lib/properties/borderLeft.js +40 -36
  29. package/lib/properties/borderLeftColor.js +25 -21
  30. package/lib/properties/borderLeftStyle.js +25 -21
  31. package/lib/properties/borderLeftWidth.js +28 -24
  32. package/lib/properties/borderRight.js +40 -36
  33. package/lib/properties/borderRightColor.js +25 -21
  34. package/lib/properties/borderRightStyle.js +25 -21
  35. package/lib/properties/borderRightWidth.js +28 -24
  36. package/lib/properties/borderSpacing.js +33 -29
  37. package/lib/properties/borderStyle.js +36 -33
  38. package/lib/properties/borderTop.js +40 -36
  39. package/lib/properties/borderTopColor.js +25 -21
  40. package/lib/properties/borderTopStyle.js +25 -21
  41. package/lib/properties/borderTopWidth.js +28 -24
  42. package/lib/properties/borderWidth.js +36 -33
  43. package/lib/properties/bottom.js +27 -23
  44. package/lib/properties/clear.js +25 -21
  45. package/lib/properties/clip.js +37 -31
  46. package/lib/properties/color.js +25 -21
  47. package/lib/properties/display.js +36 -30
  48. package/lib/properties/flex.js +53 -45
  49. package/lib/properties/flexBasis.js +28 -26
  50. package/lib/properties/flexGrow.js +28 -26
  51. package/lib/properties/flexShrink.js +28 -26
  52. package/lib/properties/float.js +25 -21
  53. package/lib/properties/floodColor.js +25 -21
  54. package/lib/properties/font.js +89 -118
  55. package/lib/properties/fontFamily.js +38 -33
  56. package/lib/properties/fontSize.js +29 -27
  57. package/lib/properties/fontStyle.js +38 -34
  58. package/lib/properties/fontVariant.js +35 -33
  59. package/lib/properties/fontWeight.js +33 -31
  60. package/lib/properties/height.js +28 -24
  61. package/lib/properties/left.js +27 -23
  62. package/lib/properties/lightingColor.js +25 -21
  63. package/lib/properties/lineHeight.js +28 -26
  64. package/lib/properties/margin.js +40 -34
  65. package/lib/properties/marginBottom.js +30 -27
  66. package/lib/properties/marginLeft.js +30 -27
  67. package/lib/properties/marginRight.js +30 -27
  68. package/lib/properties/marginTop.js +30 -27
  69. package/lib/properties/opacity.js +27 -23
  70. package/lib/properties/outlineColor.js +25 -21
  71. package/lib/properties/padding.js +40 -34
  72. package/lib/properties/paddingBottom.js +31 -28
  73. package/lib/properties/paddingLeft.js +31 -28
  74. package/lib/properties/paddingRight.js +31 -28
  75. package/lib/properties/paddingTop.js +31 -28
  76. package/lib/properties/right.js +27 -23
  77. package/lib/properties/stopColor.js +25 -21
  78. package/lib/properties/{webkitBorderBeforeColor.js → textEmphasisColor.js} +26 -22
  79. package/lib/properties/top.js +27 -23
  80. package/lib/properties/webkitTextFillColor.js +25 -21
  81. package/lib/properties/webkitTextStrokeColor.js +25 -21
  82. package/lib/properties/width.js +28 -24
  83. package/lib/utils/propertyDescriptors.js +129 -42
  84. package/lib/utils/strings.js +11 -156
  85. package/package.json +11 -21
  86. package/lib/generated/allProperties.js +0 -653
  87. package/lib/generated/implementedProperties.js +0 -1466
  88. package/lib/generated/properties.js +0 -6637
  89. package/lib/properties/webkitColumnRuleColor.js +0 -45
  90. package/lib/properties/webkitTapHighlightColor.js +0 -45
  91. package/lib/properties/webkitTextEmphasisColor.js +0 -45
  92. package/lib/utils/allExtraProperties.js +0 -155
  93. package/lib/utils/camelize.js +0 -37
@@ -2,54 +2,141 @@
2
2
 
3
3
  const parsers = require("../parsers");
4
4
 
5
+ // Constants
5
6
  const { AST_TYPES } = parsers;
6
7
 
7
- const getPropertyDescriptor = (property) => ({
8
- set(v) {
9
- const value = parsers.prepareValue(v);
10
- if (parsers.hasVarFunc(value)) {
11
- this._setProperty(property, value);
12
- } else {
13
- const parsedValue = parsers.parsePropertyValue(property, v, {
14
- globalObject: this._global,
15
- inArray: true
16
- });
17
- if (Array.isArray(parsedValue)) {
18
- if (parsedValue.length === 1) {
19
- const [{ name, type, value: itemValue }] = parsedValue;
20
- switch (type) {
21
- case AST_TYPES.CALC: {
22
- this._setProperty(property, `${name}(${itemValue})`);
23
- break;
24
- }
25
- case AST_TYPES.GLOBAL_KEYWORD:
26
- case AST_TYPES.IDENTIFIER: {
27
- // Set the normalized name for keywords or identifiers.
28
- this._setProperty(property, name);
29
- break;
30
- }
31
- default: {
32
- // Set the prepared value for Dimension, Function, etc.
33
- this._setProperty(property, value);
8
+ /**
9
+ * Creates a generic property descriptor for a given property. Such descriptors are used whenever we don't have a
10
+ * specific handler in `./properties/*.js`. They perform some basic logic that works as a fallback, and is correct for
11
+ * simple properties, but properties with more complex grammars will need their own handlers.
12
+ *
13
+ * @param {string} property - The canonical CSS property name (e.g. "backdrop-filter", not "backdropFilter").
14
+ * @param {object} opts - The options object.
15
+ * @param {boolean} opts.caseSensitive - True if value is case-sensitive, false otherwise.
16
+ * @param {object} [opts.dimensionTypes={}] - An object containing information about the dimension types used by this
17
+ * property, if any. Keys are a type of dimension, which determines which serializer to use, and values are the
18
+ * information used by the serializer to serialize a parsed value.
19
+ * @param {object} [opts.functionTypes={}] - An object containing information about the function types used by this
20
+ * property, if any. Keys are a type of function, which determines which function to use; values are ignored.
21
+ * @returns {object} The property descriptor object.
22
+ */
23
+ function createGenericPropertyDescriptor(property, { caseSensitive, dimensionTypes = {}, functionTypes = {} }) {
24
+ return {
25
+ set(v) {
26
+ const value = parsers.prepareValue(v);
27
+ if (parsers.hasVarFunc(value)) {
28
+ this._setProperty(property, value);
29
+ } else {
30
+ const parsedValue = parsers.parsePropertyValue(property, v, {
31
+ caseSensitive
32
+ });
33
+ if (Array.isArray(parsedValue)) {
34
+ if (parsedValue.length === 1) {
35
+ const {
36
+ angle: angleType,
37
+ dimension: dimensionType,
38
+ length: lengthType,
39
+ number: numberType,
40
+ percentage: percentageType
41
+ } = dimensionTypes;
42
+ const { color: colorType, image: imageType } = functionTypes;
43
+ const [{ name, type, value: itemValue }] = parsedValue;
44
+ switch (type) {
45
+ case AST_TYPES.CALC: {
46
+ this._setProperty(property, `${name}(${itemValue})`);
47
+ break;
48
+ }
49
+ case AST_TYPES.DIMENSION: {
50
+ let val;
51
+ if (dimensionType && lengthType) {
52
+ val = parsers.serializeLength(parsedValue, lengthType);
53
+ if (!val) {
54
+ val = parsers.serializeDimension(parsedValue, dimensionType);
55
+ }
56
+ } else if (lengthType) {
57
+ val = parsers.serializeLength(parsedValue, lengthType);
58
+ } else {
59
+ val = parsers.serializeDimension(parsedValue, dimensionType);
60
+ }
61
+ this._setProperty(property, val);
62
+ break;
63
+ }
64
+ case AST_TYPES.HASH: {
65
+ this._setProperty(property, parsers.serializeColor(parsedValue));
66
+ break;
67
+ }
68
+ case AST_TYPES.NUMBER: {
69
+ let val;
70
+ if (numberType) {
71
+ val = parsers.serializeNumber(parsedValue, numberType);
72
+ } else if (angleType) {
73
+ val = parsers.serializeAngle(parsedValue, angleType);
74
+ } else if (lengthType) {
75
+ val = parsers.serializeLength(parsedValue, lengthType);
76
+ } else if (percentageType) {
77
+ val = parsers.serializePercentage(parsedValue, percentageType);
78
+ }
79
+ this._setProperty(property, val);
80
+ break;
81
+ }
82
+ case AST_TYPES.GLOBAL_KEYWORD:
83
+ case AST_TYPES.IDENTIFIER: {
84
+ this._setProperty(property, name);
85
+ break;
86
+ }
87
+ case AST_TYPES.PERCENTAGE: {
88
+ let numericType;
89
+ if (percentageType) {
90
+ numericType = percentageType;
91
+ } else if (dimensionType) {
92
+ numericType = dimensionType;
93
+ } else if (angleType) {
94
+ numericType = angleType;
95
+ } else if (lengthType) {
96
+ numericType = lengthType;
97
+ }
98
+ if (numericType) {
99
+ this._setProperty(property, parsers.resolveNumericValue(parsedValue, numericType));
100
+ }
101
+ break;
102
+ }
103
+ case AST_TYPES.STRING: {
104
+ this._setProperty(property, parsers.serializeString(parsedValue));
105
+ break;
106
+ }
107
+ case AST_TYPES.URL: {
108
+ this._setProperty(property, parsers.serializeURL(parsedValue));
109
+ break;
110
+ }
111
+ case AST_TYPES.FUNCTION:
112
+ default: {
113
+ if (colorType) {
114
+ this._setProperty(property, parsers.serializeColor(parsedValue));
115
+ } else if (imageType) {
116
+ this._setProperty(property, parsers.serializeGradient(parsedValue));
117
+ } else {
118
+ this._setProperty(property, value);
119
+ }
120
+ }
34
121
  }
122
+ } else {
123
+ // Set the prepared value for lists containing multiple values.
124
+ this._setProperty(property, value);
35
125
  }
36
- } else {
37
- // Set the prepared value for lists containing multiple values.
38
- this._setProperty(property, value);
126
+ } else if (typeof parsedValue === "string") {
127
+ // Empty string.
128
+ this._setProperty(property, parsedValue);
39
129
  }
40
- } else if (typeof parsedValue === "string") {
41
- // Empty string.
42
- this._setProperty(property, parsedValue);
43
130
  }
44
- }
45
- },
46
- get() {
47
- return this.getPropertyValue(property);
48
- },
49
- enumerable: true,
50
- configurable: true
51
- });
131
+ },
132
+ get() {
133
+ return this.getPropertyValue(property);
134
+ },
135
+ enumerable: true,
136
+ configurable: true
137
+ };
138
+ }
52
139
 
53
140
  module.exports = {
54
- getPropertyDescriptor
141
+ createGenericPropertyDescriptor
55
142
  };
@@ -2,12 +2,14 @@
2
2
 
3
3
  "use strict";
4
4
 
5
- // https://infra.spec.whatwg.org/#ascii-whitespace
6
- const asciiWhitespaceRe = /^[\t\n\f\r ]$/;
7
- exports.asciiWhitespaceRe = asciiWhitespaceRe;
8
-
9
- // https://infra.spec.whatwg.org/#ascii-lowercase
10
- exports.asciiLowercase = (s) => {
5
+ /**
6
+ * Converts a string to ASCII lowercase.
7
+ *
8
+ * @see https://infra.spec.whatwg.org/#ascii-lowercase
9
+ * @param {string} s - The string to convert.
10
+ * @returns {string} The converted string.
11
+ */
12
+ function asciiLowercase(s) {
11
13
  if (!/[^\x00-\x7f]/.test(s)) {
12
14
  return s.toLowerCase();
13
15
  }
@@ -19,155 +21,8 @@ exports.asciiLowercase = (s) => {
19
21
  out[i] = code >= 65 && code <= 90 ? String.fromCharCode(code | 32) : s[i];
20
22
  }
21
23
  return out.join("");
22
- };
23
-
24
- // https://infra.spec.whatwg.org/#ascii-uppercase
25
- exports.asciiUppercase = (s) => {
26
- if (!/[^\x00-\x7f]/.test(s)) {
27
- return s.toUpperCase();
28
- }
29
- const len = s.length;
30
- const out = new Array(len);
31
- for (let i = 0; i < len; i++) {
32
- const code = s.charCodeAt(i);
33
- // If the character is between 'a' (97) and 'z' (122), convert using bitwise AND with ~32
34
- out[i] = code >= 97 && code <= 122 ? String.fromCharCode(code & ~32) : s[i];
35
- }
36
- return out.join("");
37
- };
38
-
39
- // https://infra.spec.whatwg.org/#strip-newlines
40
- exports.stripNewlines = (s) => {
41
- return s.replace(/[\n\r]+/g, "");
42
- };
43
-
44
- // https://infra.spec.whatwg.org/#strip-leading-and-trailing-ascii-whitespace
45
- exports.stripLeadingAndTrailingASCIIWhitespace = (s) => {
46
- return s.replace(/^[ \t\n\f\r]+/, "").replace(/[ \t\n\f\r]+$/, "");
47
- };
48
-
49
- // https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace
50
- exports.stripAndCollapseASCIIWhitespace = (s) => {
51
- return s
52
- .replace(/[ \t\n\f\r]+/g, " ")
53
- .replace(/^[ \t\n\f\r]+/, "")
54
- .replace(/[ \t\n\f\r]+$/, "");
55
- };
56
-
57
- // https://html.spec.whatwg.org/multipage/infrastructure.html#valid-simple-colour
58
- exports.isValidSimpleColor = (s) => {
59
- return /^#[a-fA-F\d]{6}$/.test(s);
60
- };
61
-
62
- // https://infra.spec.whatwg.org/#ascii-case-insensitive
63
- exports.asciiCaseInsensitiveMatch = (a, b) => {
64
- if (a.length !== b.length) {
65
- return false;
66
- }
24
+ }
67
25
 
68
- for (let i = 0; i < a.length; ++i) {
69
- if ((a.charCodeAt(i) | 32) !== (b.charCodeAt(i) | 32)) {
70
- return false;
71
- }
72
- }
73
-
74
- return true;
75
- };
76
-
77
- // https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#rules-for-parsing-integers
78
- // Error is represented as null.
79
- const parseInteger = (exports.parseInteger = (input) => {
80
- // The implementation here is slightly different from the spec's. We want to use parseInt(), but parseInt() trims
81
- // Unicode whitespace in addition to just ASCII ones, so we make sure that the trimmed prefix contains only ASCII
82
- // whitespace ourselves.
83
- const numWhitespace = input.length - input.trimStart().length;
84
- if (/[^\t\n\f\r ]/.test(input.slice(0, numWhitespace))) {
85
- return null;
86
- }
87
- // We don't allow hexadecimal numbers here.
88
- // eslint-disable-next-line radix
89
- const value = parseInt(input, 10);
90
- if (Number.isNaN(value)) {
91
- return null;
92
- }
93
- // parseInt() returns -0 for "-0". Normalize that here.
94
- return value === 0 ? 0 : value;
95
- });
96
-
97
- // https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#rules-for-parsing-non-negative-integers
98
- // Error is represented as null.
99
- exports.parseNonNegativeInteger = (input) => {
100
- const value = parseInteger(input);
101
- if (value === null) {
102
- return null;
103
- }
104
- if (value < 0) {
105
- return null;
106
- }
107
- return value;
108
- };
109
-
110
- // https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-floating-point-number
111
- const floatingPointNumRe = /^-?(?:\d+|\d*\.\d+)(?:[eE][-+]?\d+)?$/;
112
- exports.isValidFloatingPointNumber = (str) => floatingPointNumRe.test(str);
113
-
114
- // https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#rules-for-parsing-floating-point-number-values
115
- // Error is represented as null.
116
- exports.parseFloatingPointNumber = (str) => {
117
- // The implementation here is slightly different from the spec's. We need to use parseFloat() in order to retain
118
- // accuracy, but parseFloat() trims Unicode whitespace in addition to just ASCII ones, so we make sure that the
119
- // trimmed prefix contains only ASCII whitespace ourselves.
120
- const numWhitespace = str.length - str.trimStart().length;
121
- if (/[^\t\n\f\r ]/.test(str.slice(0, numWhitespace))) {
122
- return null;
123
- }
124
- const parsed = parseFloat(str);
125
- return isFinite(parsed) ? parsed : null;
126
- };
127
-
128
- // https://infra.spec.whatwg.org/#split-on-ascii-whitespace
129
- exports.splitOnASCIIWhitespace = (str) => {
130
- let position = 0;
131
- const tokens = [];
132
- while (position < str.length && asciiWhitespaceRe.test(str[position])) {
133
- position++;
134
- }
135
- if (position === str.length) {
136
- return tokens;
137
- }
138
- while (position < str.length) {
139
- const start = position;
140
- while (position < str.length && !asciiWhitespaceRe.test(str[position])) {
141
- position++;
142
- }
143
- tokens.push(str.slice(start, position));
144
- while (position < str.length && asciiWhitespaceRe.test(str[position])) {
145
- position++;
146
- }
147
- }
148
- return tokens;
149
- };
150
-
151
- // https://infra.spec.whatwg.org/#split-on-commas
152
- exports.splitOnCommas = (str) => {
153
- let position = 0;
154
- const tokens = [];
155
- while (position < str.length) {
156
- let start = position;
157
- while (position < str.length && str[position] !== ",") {
158
- position++;
159
- }
160
- let end = position;
161
- while (start < str.length && asciiWhitespaceRe.test(str[start])) {
162
- start++;
163
- }
164
- while (end > start && asciiWhitespaceRe.test(str[end - 1])) {
165
- end--;
166
- }
167
- tokens.push(str.slice(start, end));
168
- if (position < str.length) {
169
- position++;
170
- }
171
- }
172
- return tokens;
26
+ module.exports = {
27
+ asciiLowercase
173
28
  };
package/package.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "CSSStyleDeclaration",
7
7
  "StyleSheet"
8
8
  ],
9
- "version": "5.3.7",
9
+ "version": "6.0.0",
10
10
  "repository": {
11
11
  "type": "git",
12
12
  "url": "git+https://github.com/jsdom/cssstyle.git"
@@ -14,36 +14,26 @@
14
14
  "files": [
15
15
  "lib/"
16
16
  ],
17
- "main": "./lib/CSSStyleDeclaration.js",
17
+ "main": "./lib/index.js",
18
18
  "dependencies": {
19
19
  "@asamuzakjp/css-color": "^4.1.1",
20
- "@csstools/css-syntax-patches-for-csstree": "^1.0.21",
20
+ "@csstools/css-syntax-patches-for-csstree": "^1.0.26",
21
21
  "css-tree": "^3.1.0",
22
- "lru-cache": "^11.2.4"
22
+ "lru-cache": "^11.2.5"
23
23
  },
24
24
  "devDependencies": {
25
- "@babel/generator": "^7.28.5",
26
- "@babel/parser": "^7.28.5",
27
- "@babel/traverse": "^7.28.5",
28
- "@babel/types": "^7.28.5",
29
- "@domenic/eslint-config": "^4.0.1",
30
- "@webref/css": "^8.1.1",
31
- "eslint": "^9.39.1",
25
+ "@domenic/eslint-config": "^4.1.0",
26
+ "@webref/css": "^8.2.3",
27
+ "eslint": "^9.39.2",
32
28
  "eslint-config-prettier": "^10.1.8",
33
- "eslint-plugin-prettier": "^5.5.4",
34
- "globals": "^16.5.0",
35
- "npm-run-all": "^4.1.5",
36
- "prettier": "^3.7.4",
37
- "resolve": "^1.22.11"
29
+ "eslint-plugin-prettier": "^5.5.5",
30
+ "globals": "^17.3.0",
31
+ "prettier": "^3.8.1"
38
32
  },
39
33
  "scripts": {
40
- "download": "node ./scripts/downloadLatestProperties.mjs",
41
34
  "lint": "eslint --max-warnings 0",
42
35
  "lint:fix": "eslint --fix --max-warnings 0",
43
- "prepare": "run-p prepare:*",
44
- "prepare:implemented_properties": "node ./scripts/generateImplementedProperties.mjs",
45
- "prepare:properties": "node ./scripts/generateProperties.js",
46
- "prepare:propertyDefinitions": "node ./scripts/generatePropertyDefinitions.mjs",
36
+ "prepare": "node ./scripts/prepare.mjs",
47
37
  "test": "node --test"
48
38
  },
49
39
  "license": "MIT",