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.
- package/lib/CSSStyleDeclaration.js +16 -6
- package/lib/generated/implementedProperties.js +13 -10
- package/lib/generated/properties.js +822 -94
- package/lib/parsers.js +59 -42
- package/lib/properties/background.js +350 -13
- package/lib/properties/backgroundAttachment.js +18 -1
- package/lib/properties/backgroundClip.js +49 -0
- package/lib/properties/backgroundImage.js +19 -2
- package/lib/properties/backgroundOrigin.js +49 -0
- package/lib/properties/backgroundPosition.js +142 -18
- package/lib/properties/backgroundRepeat.js +52 -2
- package/lib/properties/backgroundSize.js +80 -0
- package/lib/properties/border.js +10 -5
- package/lib/properties/borderBottom.js +4 -4
- package/lib/properties/borderLeft.js +4 -4
- package/lib/properties/borderRight.js +4 -4
- package/lib/properties/borderStyle.js +1 -1
- package/lib/properties/borderTop.js +4 -4
- package/lib/properties/clip.js +2 -1
- package/lib/properties/flex.js +5 -5
- package/lib/properties/font.js +8 -15
- package/lib/properties/fontFamily.js +10 -0
- package/lib/properties/margin.js +1 -1
- package/lib/properties/marginBottom.js +1 -1
- package/lib/properties/marginLeft.js +1 -1
- package/lib/properties/marginRight.js +1 -1
- package/lib/properties/marginTop.js +1 -1
- package/lib/shorthandProperties.js +21 -0
- package/lib/utils/camelize.js +3 -1
- package/lib/utils/strings.js +167 -0
- package/package.json +2 -2
package/lib/properties/font.js
CHANGED
|
@@ -8,7 +8,7 @@ const fontSize = require("./fontSize");
|
|
|
8
8
|
const lineHeight = require("./lineHeight");
|
|
9
9
|
const fontFamily = require("./fontFamily");
|
|
10
10
|
|
|
11
|
-
|
|
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
|
-
|
|
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.
|
package/lib/properties/margin.js
CHANGED
|
@@ -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
|
|
8
|
+
const val = parsers.parseMeasurement(v);
|
|
9
9
|
if (val) {
|
|
10
10
|
return val;
|
|
11
11
|
}
|
|
@@ -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
|
+
]);
|
package/lib/utils/camelize.js
CHANGED
|
@@ -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, "-$&")
|
|
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": "
|
|
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": ">=
|
|
70
|
+
"node": ">=20"
|
|
71
71
|
}
|
|
72
72
|
}
|