cssstyle 4.5.0 → 5.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.
@@ -8,7 +8,7 @@ const fontSize = require("./fontSize");
8
8
  const lineHeight = require("./lineHeight");
9
9
  const fontFamily = require("./fontFamily");
10
10
 
11
- const shorthandFor = new Map([
11
+ module.exports.shorthandFor = new Map([
12
12
  ["font-style", fontStyle],
13
13
  ["font-variant", fontVariant],
14
14
  ["font-weight", fontWeight],
@@ -57,15 +57,9 @@ module.exports.parse = function parse(v) {
57
57
  switch (property) {
58
58
  case "font-style":
59
59
  case "font-variant":
60
- case "font-weight": {
61
- const value = shorthandFor.get(property);
62
- if (value.isValid(part)) {
63
- font[property] = value.parse(part);
64
- }
65
- break;
66
- }
60
+ case "font-weight":
67
61
  case "font-size": {
68
- const value = shorthandFor.get(property);
62
+ const value = module.exports.shorthandFor.get(property);
69
63
  if (value.isValid(part)) {
70
64
  font[property] = value.parse(part);
71
65
  }
@@ -82,8 +76,7 @@ module.exports.parse = function parse(v) {
82
76
  return;
83
77
  }
84
78
  } else {
85
- // FIXME: Switch to toReversed() when we can drop Node.js 18 support.
86
- const revParts = [...parsers.splitValue(fontBlockA.trim())].reverse();
79
+ const revParts = parsers.splitValue(fontBlockA.trim()).toReversed();
87
80
  const revFontFamily = [];
88
81
  const properties = ["font-style", "font-variant", "font-weight", "line-height"];
89
82
  font["font-style"] = "normal";
@@ -102,7 +95,7 @@ module.exports.parse = function parse(v) {
102
95
  case "font-variant":
103
96
  case "font-weight":
104
97
  case "line-height": {
105
- const value = shorthandFor.get(property);
98
+ const value = module.exports.shorthandFor.get(property);
106
99
  if (value.isValid(part)) {
107
100
  font[property] = value.parse(part);
108
101
  }
@@ -143,7 +136,7 @@ module.exports.definition = {
143
136
  set(v) {
144
137
  v = parsers.prepareValue(v, this._global);
145
138
  if (v === "" || parsers.hasVarFunc(v)) {
146
- for (const [key] of shorthandFor) {
139
+ for (const [key] of module.exports.shorthandFor) {
147
140
  this._setProperty(key, "");
148
141
  }
149
142
  this._setProperty("font", v);
@@ -153,7 +146,7 @@ module.exports.definition = {
153
146
  return;
154
147
  }
155
148
  const str = new Set();
156
- for (const [key] of shorthandFor) {
149
+ for (const [key] of module.exports.shorthandFor) {
157
150
  const val = obj[key];
158
151
  if (typeof val === "string") {
159
152
  this._setProperty(key, val);
@@ -175,7 +168,7 @@ module.exports.definition = {
175
168
  return val;
176
169
  }
177
170
  const str = new Set();
178
- for (const [key] of shorthandFor) {
171
+ for (const [key] of module.exports.shorthandFor) {
179
172
  const v = this.getPropertyValue(key);
180
173
  if (parsers.hasVarFunc(v)) {
181
174
  return "";
@@ -19,6 +19,7 @@ module.exports.parse = function parse(v) {
19
19
  "ui-monospace",
20
20
  "ui-rounded"
21
21
  ];
22
+ const genericValues = ["fangsong", "kai", "khmer-mul", "nastaliq"];
22
23
  const val = parsers.splitValue(v, {
23
24
  delimiter: ","
24
25
  });
@@ -37,6 +38,15 @@ module.exports.parse = function parse(v) {
37
38
  valid = true;
38
39
  continue;
39
40
  }
41
+ const obj = parsers.parseFunction(i);
42
+ if (obj) {
43
+ const { name, value } = obj;
44
+ if (name === "generic" && genericValues.includes(value)) {
45
+ font.push(`${name}(${value})`);
46
+ valid = true;
47
+ continue;
48
+ }
49
+ }
40
50
  // This implementation does not strictly follow the specification.
41
51
  // The spec does not require the first letter of the font-family to be
42
52
  // capitalized, and unquoted font-family names are not restricted to ASCII.
@@ -5,7 +5,7 @@ const parsers = require("../parsers");
5
5
  const positions = ["top", "right", "bottom", "left"];
6
6
 
7
7
  module.exports.parse = function parse(v) {
8
- const val = parsers.parseMeasurement(v, true);
8
+ const val = parsers.parseMeasurement(v);
9
9
  if (val) {
10
10
  return val;
11
11
  }
@@ -3,7 +3,7 @@
3
3
  const parsers = require("../parsers");
4
4
 
5
5
  module.exports.parse = function parse(v) {
6
- const val = parsers.parseMeasurement(v, true);
6
+ const val = parsers.parseMeasurement(v);
7
7
  if (val) {
8
8
  return val;
9
9
  }
@@ -3,7 +3,7 @@
3
3
  const parsers = require("../parsers");
4
4
 
5
5
  module.exports.parse = function parse(v) {
6
- const val = parsers.parseMeasurement(v, true);
6
+ const val = parsers.parseMeasurement(v);
7
7
  if (val) {
8
8
  return val;
9
9
  }
@@ -3,7 +3,7 @@
3
3
  const parsers = require("../parsers");
4
4
 
5
5
  module.exports.parse = function parse(v) {
6
- const val = parsers.parseMeasurement(v, true);
6
+ const val = parsers.parseMeasurement(v);
7
7
  if (val) {
8
8
  return val;
9
9
  }
@@ -3,7 +3,7 @@
3
3
  const parsers = require("../parsers");
4
4
 
5
5
  module.exports.parse = function parse(v) {
6
- const val = parsers.parseMeasurement(v, true);
6
+ const val = parsers.parseMeasurement(v);
7
7
  if (val) {
8
8
  return val;
9
9
  }
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+
3
+ const background = require("./properties/background");
4
+ const border = require("./properties/border");
5
+ const borderTop = require("./properties/borderTop");
6
+ const borderRight = require("./properties/borderRight");
7
+ const borderBottom = require("./properties/borderBottom");
8
+ const borderLeft = require("./properties/borderLeft");
9
+ const flex = require("./properties/flex");
10
+ const font = require("./properties/font");
11
+
12
+ module.exports.shorthandProperties = new Map([
13
+ ["background", background.shorthandFor],
14
+ ["border", border.shorthandFor],
15
+ ["border-top", borderTop.shorthandFor],
16
+ ["border-right", borderRight.shorthandFor],
17
+ ["border-bottom", borderBottom.shorthandFor],
18
+ ["border-left", borderLeft.shorthandFor],
19
+ ["flex", flex.shorthandFor],
20
+ ["font", font.shorthandFor]
21
+ ]);
@@ -1,5 +1,7 @@
1
1
  "use strict";
2
2
 
3
+ const { asciiLowercase } = require("./strings");
4
+
3
5
  // Utility to translate from `border-width` to `borderWidth`.
4
6
  // NOTE: For values prefixed with webkit, e.g. `-webkit-foo`, we need to provide
5
7
  // both `webkitFoo` and `WebkitFoo`. Here we only return `webkitFoo`.
@@ -27,7 +29,7 @@ exports.camelCaseToDashed = function (camelCase) {
27
29
  if (camelCase.startsWith("--")) {
28
30
  return camelCase;
29
31
  }
30
- const dashed = camelCase.replace(/(?<=[a-z])[A-Z]/g, "-$&").toLowerCase();
32
+ const dashed = asciiLowercase(camelCase.replace(/(?<=[a-z])[A-Z]/g, "-$&"));
31
33
  if (/^webkit-/.test(dashed)) {
32
34
  return `-${dashed}`;
33
35
  }
@@ -0,0 +1,167 @@
1
+ // Forked from https://github.com/jsdom/jsdom/blob/main/lib/jsdom/living/helpers/strings.js
2
+
3
+ "use strict";
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) => {
11
+ const len = s.length;
12
+ const out = new Array(len);
13
+ for (let i = 0; i < len; i++) {
14
+ const code = s.charCodeAt(i);
15
+ // If the character is between 'A' (65) and 'Z' (90), convert using bitwise OR with 32
16
+ out[i] = code >= 65 && code <= 90 ? String.fromCharCode(code | 32) : s[i];
17
+ }
18
+ return out.join("");
19
+ };
20
+
21
+ // https://infra.spec.whatwg.org/#ascii-uppercase
22
+ exports.asciiUppercase = (s) => {
23
+ const len = s.length;
24
+ const out = new Array(len);
25
+ for (let i = 0; i < len; i++) {
26
+ const code = s.charCodeAt(i);
27
+ // If the character is between 'a' (97) and 'z' (122), convert using bitwise AND with ~32
28
+ out[i] = code >= 97 && code <= 122 ? String.fromCharCode(code & ~32) : s[i];
29
+ }
30
+ return out.join("");
31
+ };
32
+
33
+ // https://infra.spec.whatwg.org/#strip-newlines
34
+ exports.stripNewlines = (s) => {
35
+ return s.replace(/[\n\r]+/g, "");
36
+ };
37
+
38
+ // https://infra.spec.whatwg.org/#strip-leading-and-trailing-ascii-whitespace
39
+ exports.stripLeadingAndTrailingASCIIWhitespace = (s) => {
40
+ return s.replace(/^[ \t\n\f\r]+/, "").replace(/[ \t\n\f\r]+$/, "");
41
+ };
42
+
43
+ // https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace
44
+ exports.stripAndCollapseASCIIWhitespace = (s) => {
45
+ return s
46
+ .replace(/[ \t\n\f\r]+/g, " ")
47
+ .replace(/^[ \t\n\f\r]+/, "")
48
+ .replace(/[ \t\n\f\r]+$/, "");
49
+ };
50
+
51
+ // https://html.spec.whatwg.org/multipage/infrastructure.html#valid-simple-colour
52
+ exports.isValidSimpleColor = (s) => {
53
+ return /^#[a-fA-F\d]{6}$/.test(s);
54
+ };
55
+
56
+ // https://infra.spec.whatwg.org/#ascii-case-insensitive
57
+ exports.asciiCaseInsensitiveMatch = (a, b) => {
58
+ if (a.length !== b.length) {
59
+ return false;
60
+ }
61
+
62
+ for (let i = 0; i < a.length; ++i) {
63
+ if ((a.charCodeAt(i) | 32) !== (b.charCodeAt(i) | 32)) {
64
+ return false;
65
+ }
66
+ }
67
+
68
+ return true;
69
+ };
70
+
71
+ // https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#rules-for-parsing-integers
72
+ // Error is represented as null.
73
+ const parseInteger = (exports.parseInteger = (input) => {
74
+ // The implementation here is slightly different from the spec's. We want to use parseInt(), but parseInt() trims
75
+ // Unicode whitespace in addition to just ASCII ones, so we make sure that the trimmed prefix contains only ASCII
76
+ // whitespace ourselves.
77
+ const numWhitespace = input.length - input.trimStart().length;
78
+ if (/[^\t\n\f\r ]/.test(input.slice(0, numWhitespace))) {
79
+ return null;
80
+ }
81
+ // We don't allow hexadecimal numbers here.
82
+ // eslint-disable-next-line radix
83
+ const value = parseInt(input, 10);
84
+ if (Number.isNaN(value)) {
85
+ return null;
86
+ }
87
+ // parseInt() returns -0 for "-0". Normalize that here.
88
+ return value === 0 ? 0 : value;
89
+ });
90
+
91
+ // https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#rules-for-parsing-non-negative-integers
92
+ // Error is represented as null.
93
+ exports.parseNonNegativeInteger = (input) => {
94
+ const value = parseInteger(input);
95
+ if (value === null) {
96
+ return null;
97
+ }
98
+ if (value < 0) {
99
+ return null;
100
+ }
101
+ return value;
102
+ };
103
+
104
+ // https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-floating-point-number
105
+ const floatingPointNumRe = /^-?(?:\d+|\d*\.\d+)(?:[eE][-+]?\d+)?$/;
106
+ exports.isValidFloatingPointNumber = (str) => floatingPointNumRe.test(str);
107
+
108
+ // https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#rules-for-parsing-floating-point-number-values
109
+ // Error is represented as null.
110
+ exports.parseFloatingPointNumber = (str) => {
111
+ // The implementation here is slightly different from the spec's. We need to use parseFloat() in order to retain
112
+ // accuracy, but parseFloat() trims Unicode whitespace in addition to just ASCII ones, so we make sure that the
113
+ // trimmed prefix contains only ASCII whitespace ourselves.
114
+ const numWhitespace = str.length - str.trimStart().length;
115
+ if (/[^\t\n\f\r ]/.test(str.slice(0, numWhitespace))) {
116
+ return null;
117
+ }
118
+ const parsed = parseFloat(str);
119
+ return isFinite(parsed) ? parsed : null;
120
+ };
121
+
122
+ // https://infra.spec.whatwg.org/#split-on-ascii-whitespace
123
+ exports.splitOnASCIIWhitespace = (str) => {
124
+ let position = 0;
125
+ const tokens = [];
126
+ while (position < str.length && asciiWhitespaceRe.test(str[position])) {
127
+ position++;
128
+ }
129
+ if (position === str.length) {
130
+ return tokens;
131
+ }
132
+ while (position < str.length) {
133
+ const start = position;
134
+ while (position < str.length && !asciiWhitespaceRe.test(str[position])) {
135
+ position++;
136
+ }
137
+ tokens.push(str.slice(start, position));
138
+ while (position < str.length && asciiWhitespaceRe.test(str[position])) {
139
+ position++;
140
+ }
141
+ }
142
+ return tokens;
143
+ };
144
+
145
+ // https://infra.spec.whatwg.org/#split-on-commas
146
+ exports.splitOnCommas = (str) => {
147
+ let position = 0;
148
+ const tokens = [];
149
+ while (position < str.length) {
150
+ let start = position;
151
+ while (position < str.length && str[position] !== ",") {
152
+ position++;
153
+ }
154
+ let end = position;
155
+ while (start < str.length && asciiWhitespaceRe.test(str[start])) {
156
+ start++;
157
+ }
158
+ while (end > start && asciiWhitespaceRe.test(str[end - 1])) {
159
+ end--;
160
+ }
161
+ tokens.push(str.slice(start, end));
162
+ if (position < str.length) {
163
+ position++;
164
+ }
165
+ }
166
+ return tokens;
167
+ };
package/package.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "CSSStyleDeclaration",
7
7
  "StyleSheet"
8
8
  ],
9
- "version": "4.5.0",
9
+ "version": "5.0.0",
10
10
  "homepage": "https://github.com/jsdom/cssstyle",
11
11
  "maintainers": [
12
12
  {
@@ -67,6 +67,6 @@
67
67
  },
68
68
  "license": "MIT",
69
69
  "engines": {
70
- "node": ">=18"
70
+ "node": ">=20"
71
71
  }
72
72
  }