happy-dom 14.3.8 → 14.3.10
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.
Potentially problematic release.
This version of happy-dom might be problematic. Click here for more details.
- package/cjs/css/declaration/css-parser/CSSStyleDeclarationCSSParser.cjs +20 -9
- package/cjs/css/declaration/css-parser/CSSStyleDeclarationCSSParser.cjs.map +1 -1
- package/cjs/css/declaration/css-parser/CSSStyleDeclarationCSSParser.d.ts +10 -1
- package/cjs/css/declaration/css-parser/CSSStyleDeclarationCSSParser.d.ts.map +1 -1
- package/cjs/css/declaration/element-style/CSSStyleDeclarationElementStyle.cjs +30 -17
- package/cjs/css/declaration/element-style/CSSStyleDeclarationElementStyle.cjs.map +1 -1
- package/cjs/css/declaration/element-style/CSSStyleDeclarationElementStyle.d.ts +1 -0
- package/cjs/css/declaration/element-style/CSSStyleDeclarationElementStyle.d.ts.map +1 -1
- package/cjs/css/declaration/property-manager/CSSStyleDeclarationPropertyManager.cjs +5 -4
- package/cjs/css/declaration/property-manager/CSSStyleDeclarationPropertyManager.cjs.map +1 -1
- package/cjs/css/declaration/property-manager/CSSStyleDeclarationPropertyManager.d.ts.map +1 -1
- package/cjs/nodes/html-link-element/HTMLLinkElementStyleSheetLoader.cjs +4 -3
- package/cjs/nodes/html-link-element/HTMLLinkElementStyleSheetLoader.cjs.map +1 -1
- package/cjs/nodes/html-link-element/HTMLLinkElementStyleSheetLoader.d.ts.map +1 -1
- package/cjs/nodes/html-style-element/HTMLStyleElement.cjs +44 -9
- package/cjs/nodes/html-style-element/HTMLStyleElement.cjs.map +1 -1
- package/cjs/nodes/html-style-element/HTMLStyleElement.d.ts +17 -0
- package/cjs/nodes/html-style-element/HTMLStyleElement.d.ts.map +1 -1
- package/cjs/storage/StorageFactory.cjs +19 -1
- package/cjs/storage/StorageFactory.cjs.map +1 -1
- package/cjs/storage/StorageFactory.d.ts.map +1 -1
- package/lib/css/declaration/css-parser/CSSStyleDeclarationCSSParser.d.ts +10 -1
- package/lib/css/declaration/css-parser/CSSStyleDeclarationCSSParser.d.ts.map +1 -1
- package/lib/css/declaration/css-parser/CSSStyleDeclarationCSSParser.js +20 -9
- package/lib/css/declaration/css-parser/CSSStyleDeclarationCSSParser.js.map +1 -1
- package/lib/css/declaration/element-style/CSSStyleDeclarationElementStyle.d.ts +1 -0
- package/lib/css/declaration/element-style/CSSStyleDeclarationElementStyle.d.ts.map +1 -1
- package/lib/css/declaration/element-style/CSSStyleDeclarationElementStyle.js +30 -17
- package/lib/css/declaration/element-style/CSSStyleDeclarationElementStyle.js.map +1 -1
- package/lib/css/declaration/property-manager/CSSStyleDeclarationPropertyManager.d.ts.map +1 -1
- package/lib/css/declaration/property-manager/CSSStyleDeclarationPropertyManager.js +5 -4
- package/lib/css/declaration/property-manager/CSSStyleDeclarationPropertyManager.js.map +1 -1
- package/lib/nodes/html-link-element/HTMLLinkElementStyleSheetLoader.d.ts.map +1 -1
- package/lib/nodes/html-link-element/HTMLLinkElementStyleSheetLoader.js +4 -3
- package/lib/nodes/html-link-element/HTMLLinkElementStyleSheetLoader.js.map +1 -1
- package/lib/nodes/html-style-element/HTMLStyleElement.d.ts +17 -0
- package/lib/nodes/html-style-element/HTMLStyleElement.d.ts.map +1 -1
- package/lib/nodes/html-style-element/HTMLStyleElement.js +45 -11
- package/lib/nodes/html-style-element/HTMLStyleElement.js.map +1 -1
- package/lib/storage/StorageFactory.d.ts.map +1 -1
- package/lib/storage/StorageFactory.js +19 -1
- package/lib/storage/StorageFactory.js.map +1 -1
- package/package.json +1 -1
- package/src/css/declaration/css-parser/CSSStyleDeclarationCSSParser.ts +27 -12
- package/src/css/declaration/element-style/CSSStyleDeclarationElementStyle.ts +36 -16
- package/src/css/declaration/property-manager/CSSStyleDeclarationPropertyManager.ts +5 -4
- package/src/nodes/html-link-element/HTMLLinkElementStyleSheetLoader.ts +4 -6
- package/src/nodes/html-style-element/HTMLStyleElement.ts +49 -8
- package/src/storage/StorageFactory.ts +19 -1
@@ -1,7 +1,8 @@
|
|
1
|
-
//
|
2
|
-
//
|
3
|
-
//
|
4
|
-
//
|
1
|
+
// Groups:
|
2
|
+
// Property name => \s*([^:;]+?)\s*:
|
3
|
+
// Property value => \s*((?:[^(;]*?(?:\([^)]*\))?)*?) <- will match any non ';' char except inside (), nested parentheses are not supported
|
4
|
+
// Important ("!important") => \s*(!important)?
|
5
|
+
// End of rule => \s*(?:$|;)
|
5
6
|
const SPLIT_RULES_REGEXP =
|
6
7
|
/\s*([^:;]+?)\s*:\s*((?:[^(;]*?(?:\([^)]*\))?)*?)\s*(!important)?\s*(?:$|;)/g;
|
7
8
|
|
@@ -15,15 +16,29 @@ export default class CSSStyleDeclarationCSSParser {
|
|
15
16
|
* @param cssText CSS string.
|
16
17
|
* @param callback Callback.
|
17
18
|
*/
|
18
|
-
public static parse(
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
const
|
23
|
-
|
24
|
-
|
25
|
-
|
19
|
+
public static parse(cssText: string): {
|
20
|
+
rules: Array<{ name: string; value: string; important: boolean }>;
|
21
|
+
properties: { [name: string]: string };
|
22
|
+
} {
|
23
|
+
const properties: { [name: string]: string } = {};
|
24
|
+
const rules: Array<{ name: string; value: string; important: boolean }> = [];
|
25
|
+
const regexp = new RegExp(SPLIT_RULES_REGEXP);
|
26
|
+
let match;
|
27
|
+
|
28
|
+
while ((match = regexp.exec(cssText))) {
|
29
|
+
const name = (match[1] ?? '').trim();
|
30
|
+
const value = (match[2] ?? '').trim();
|
31
|
+
const important = match[3] ? true : false;
|
32
|
+
|
33
|
+
if (name && value) {
|
34
|
+
if (name.startsWith('--')) {
|
35
|
+
properties[name] = value;
|
36
|
+
}
|
37
|
+
|
38
|
+
rules.push({ name, value, important });
|
26
39
|
}
|
27
40
|
}
|
41
|
+
|
42
|
+
return { rules, properties };
|
28
43
|
}
|
29
44
|
}
|
@@ -132,15 +132,23 @@ export default class CSSStyleDeclarationElementStyle {
|
|
132
132
|
if (sheet) {
|
133
133
|
this.parseCSSRules({
|
134
134
|
elements: documentElements,
|
135
|
+
rootElement:
|
136
|
+
documentElements[0].element[PropertySymbol.tagName] === 'HTML'
|
137
|
+
? documentElements[0]
|
138
|
+
: null,
|
135
139
|
cssRules: sheet.cssRules
|
136
140
|
});
|
137
141
|
}
|
138
142
|
}
|
139
143
|
|
140
|
-
for (const
|
144
|
+
for (const sheet of this.element[PropertySymbol.ownerDocument].adoptedStyleSheets) {
|
141
145
|
this.parseCSSRules({
|
142
146
|
elements: documentElements,
|
143
|
-
|
147
|
+
rootElement:
|
148
|
+
documentElements[0].element[PropertySymbol.tagName] === 'HTML'
|
149
|
+
? documentElements[0]
|
150
|
+
: null,
|
151
|
+
cssRules: sheet.cssRules
|
144
152
|
});
|
145
153
|
}
|
146
154
|
|
@@ -170,10 +178,10 @@ export default class CSSStyleDeclarationElementStyle {
|
|
170
178
|
}
|
171
179
|
}
|
172
180
|
|
173
|
-
for (const
|
181
|
+
for (const sheet of shadowRoot.adoptedStyleSheets) {
|
174
182
|
this.parseCSSRules({
|
175
183
|
elements: shadowRootElements,
|
176
|
-
cssRules:
|
184
|
+
cssRules: sheet.cssRules,
|
177
185
|
hostElement: styleAndElement
|
178
186
|
});
|
179
187
|
}
|
@@ -190,7 +198,7 @@ export default class CSSStyleDeclarationElementStyle {
|
|
190
198
|
// Concatenates all parent element CSS to one string.
|
191
199
|
const targetElement = parentElements[parentElements.length - 1];
|
192
200
|
const propertyManager = new CSSStyleDeclarationPropertyManager();
|
193
|
-
const
|
201
|
+
const cssProperties: { [k: string]: string } = {};
|
194
202
|
let rootFontSize: string | number = 16;
|
195
203
|
let parentFontSize: string | number = 16;
|
196
204
|
|
@@ -239,24 +247,27 @@ export default class CSSStyleDeclarationElementStyle {
|
|
239
247
|
const elementStyleAttribute = (<Element>parentElement.element)[PropertySymbol.attributes][
|
240
248
|
'style'
|
241
249
|
];
|
250
|
+
|
242
251
|
if (elementStyleAttribute) {
|
243
252
|
elementCSSText += elementStyleAttribute[PropertySymbol.value];
|
244
253
|
}
|
245
254
|
|
246
|
-
CSSStyleDeclarationCSSParser.parse(elementCSSText
|
247
|
-
|
255
|
+
const rulesAndProperties = CSSStyleDeclarationCSSParser.parse(elementCSSText);
|
256
|
+
const rules = rulesAndProperties.rules;
|
257
|
+
|
258
|
+
Object.assign(cssProperties, rulesAndProperties.properties);
|
259
|
+
|
260
|
+
for (const { name, value, important } of rules) {
|
248
261
|
if (
|
249
|
-
isCSSVariable ||
|
250
262
|
CSSStyleDeclarationElementInheritedProperties[name] ||
|
251
263
|
parentElement === targetElement
|
252
264
|
) {
|
253
|
-
const
|
254
|
-
if (cssValue && (!propertyManager.get(name)?.important || important)) {
|
255
|
-
propertyManager.set(name, cssValue, important);
|
265
|
+
const parsedValue = this.parseCSSVariablesInValue(value.trim(), cssProperties);
|
256
266
|
|
257
|
-
|
258
|
-
|
259
|
-
|
267
|
+
if (parsedValue && (!propertyManager.get(name)?.important || important)) {
|
268
|
+
propertyManager.set(name, parsedValue, important);
|
269
|
+
|
270
|
+
if (name === 'font' || name === 'font-size') {
|
260
271
|
const fontSize = propertyManager.properties['font-size'];
|
261
272
|
if (fontSize !== null) {
|
262
273
|
const parsedValue = this.parseMeasurementsInValue({
|
@@ -274,7 +285,7 @@ export default class CSSStyleDeclarationElementStyle {
|
|
274
285
|
}
|
275
286
|
}
|
276
287
|
}
|
277
|
-
}
|
288
|
+
}
|
278
289
|
}
|
279
290
|
|
280
291
|
for (const name of CSSStyleDeclarationElementMeasurementProperties) {
|
@@ -302,11 +313,13 @@ export default class CSSStyleDeclarationElementStyle {
|
|
302
313
|
* @param options Options.
|
303
314
|
* @param options.elements Elements.
|
304
315
|
* @param options.cssRules CSS rules.
|
316
|
+
* @param options.rootElement Root element.
|
305
317
|
* @param [options.hostElement] Host element.
|
306
318
|
*/
|
307
319
|
private parseCSSRules(options: {
|
308
320
|
cssRules: CSSRule[];
|
309
|
-
elements:
|
321
|
+
elements: IStyleAndElement[];
|
322
|
+
rootElement?: IStyleAndElement;
|
310
323
|
hostElement?: IStyleAndElement;
|
311
324
|
}): void {
|
312
325
|
if (!options.elements.length) {
|
@@ -326,6 +339,13 @@ export default class CSSStyleDeclarationElementStyle {
|
|
326
339
|
priorityWeight: 0
|
327
340
|
});
|
328
341
|
}
|
342
|
+
} else if (selectorText.startsWith(':root')) {
|
343
|
+
if (options.rootElement) {
|
344
|
+
options.rootElement.cssTexts.push({
|
345
|
+
cssText: (<CSSStyleRule>rule)[PropertySymbol.cssText],
|
346
|
+
priorityWeight: 0
|
347
|
+
});
|
348
|
+
}
|
329
349
|
} else {
|
330
350
|
for (const element of options.elements) {
|
331
351
|
const match = QuerySelector.matches(<Element>element.element, selectorText, {
|
@@ -30,11 +30,12 @@ export default class CSSStyleDeclarationPropertyManager {
|
|
30
30
|
*/
|
31
31
|
constructor(options?: { cssText?: string }) {
|
32
32
|
if (options?.cssText) {
|
33
|
-
CSSStyleDeclarationCSSParser.parse(options.cssText
|
34
|
-
|
35
|
-
|
33
|
+
const { rules } = CSSStyleDeclarationCSSParser.parse(options.cssText);
|
34
|
+
for (const rule of rules) {
|
35
|
+
if (rule.important || !this.get(rule.name)?.important) {
|
36
|
+
this.set(rule.name, rule.value, rule.important);
|
36
37
|
}
|
37
|
-
}
|
38
|
+
}
|
38
39
|
}
|
39
40
|
}
|
40
41
|
|
@@ -38,6 +38,7 @@ export default class HTMLLinkElementStyleSheetLoader {
|
|
38
38
|
public async loadStyleSheet(url: string | null, rel: string | null): Promise<void> {
|
39
39
|
const element = this.#element;
|
40
40
|
const browserSettings = this.#browserFrame.page.context.browser.settings;
|
41
|
+
const window = element[PropertySymbol.ownerDocument][PropertySymbol.ownerWindow];
|
41
42
|
|
42
43
|
if (
|
43
44
|
!url ||
|
@@ -50,10 +51,7 @@ export default class HTMLLinkElementStyleSheetLoader {
|
|
50
51
|
|
51
52
|
let absoluteURL: string;
|
52
53
|
try {
|
53
|
-
absoluteURL = new URL(
|
54
|
-
url,
|
55
|
-
element[PropertySymbol.ownerDocument][PropertySymbol.ownerWindow].location.href
|
56
|
-
).href;
|
54
|
+
absoluteURL = new URL(url, window.location.href).href;
|
57
55
|
} catch (error) {
|
58
56
|
return;
|
59
57
|
}
|
@@ -79,10 +77,10 @@ export default class HTMLLinkElementStyleSheetLoader {
|
|
79
77
|
|
80
78
|
const resourceFetch = new ResourceFetch({
|
81
79
|
browserFrame: this.#browserFrame,
|
82
|
-
window:
|
80
|
+
window: window
|
83
81
|
});
|
84
82
|
const readyStateManager = (<{ [PropertySymbol.readyStateManager]: DocumentReadyStateManager }>(
|
85
|
-
(<unknown>
|
83
|
+
(<unknown>window)
|
86
84
|
))[PropertySymbol.readyStateManager];
|
87
85
|
|
88
86
|
this.#loadedStyleSheetURL = absoluteURL;
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import CSSStyleSheet from '../../css/CSSStyleSheet.js';
|
2
2
|
import * as PropertySymbol from '../../PropertySymbol.js';
|
3
3
|
import HTMLElement from '../html-element/HTMLElement.js';
|
4
|
+
import Node from '../node/Node.js';
|
4
5
|
|
5
6
|
/**
|
6
7
|
* HTML Style Element.
|
@@ -17,14 +18,7 @@ export default class HTMLStyleElement extends HTMLElement {
|
|
17
18
|
* @returns CSS style sheet.
|
18
19
|
*/
|
19
20
|
public get sheet(): CSSStyleSheet {
|
20
|
-
|
21
|
-
return null;
|
22
|
-
}
|
23
|
-
if (!this[PropertySymbol.sheet]) {
|
24
|
-
this[PropertySymbol.sheet] = new CSSStyleSheet();
|
25
|
-
}
|
26
|
-
this[PropertySymbol.sheet].replaceSync(this.textContent);
|
27
|
-
return this[PropertySymbol.sheet];
|
21
|
+
return this[PropertySymbol.sheet] ? this[PropertySymbol.sheet] : null;
|
28
22
|
}
|
29
23
|
|
30
24
|
/**
|
@@ -84,4 +78,51 @@ export default class HTMLStyleElement extends HTMLElement {
|
|
84
78
|
this.setAttribute('disabled', '');
|
85
79
|
}
|
86
80
|
}
|
81
|
+
|
82
|
+
/**
|
83
|
+
* @override
|
84
|
+
*/
|
85
|
+
public override appendChild(node: Node): Node {
|
86
|
+
const returnValue = super.appendChild(node);
|
87
|
+
if (this[PropertySymbol.sheet]) {
|
88
|
+
this[PropertySymbol.sheet].replaceSync(this.textContent);
|
89
|
+
}
|
90
|
+
return returnValue;
|
91
|
+
}
|
92
|
+
|
93
|
+
/**
|
94
|
+
* @override
|
95
|
+
*/
|
96
|
+
public override removeChild(node: Node): Node {
|
97
|
+
const returnValue = super.removeChild(node);
|
98
|
+
if (this[PropertySymbol.sheet]) {
|
99
|
+
this[PropertySymbol.sheet].replaceSync(this.textContent);
|
100
|
+
}
|
101
|
+
return returnValue;
|
102
|
+
}
|
103
|
+
|
104
|
+
/**
|
105
|
+
* @override
|
106
|
+
*/
|
107
|
+
public override insertBefore(newNode: Node, referenceNode: Node | null): Node {
|
108
|
+
const returnValue = super.insertBefore(newNode, referenceNode);
|
109
|
+
if (this[PropertySymbol.sheet]) {
|
110
|
+
this[PropertySymbol.sheet].replaceSync(this.textContent);
|
111
|
+
}
|
112
|
+
return returnValue;
|
113
|
+
}
|
114
|
+
|
115
|
+
/**
|
116
|
+
* @override
|
117
|
+
*/
|
118
|
+
public override [PropertySymbol.connectToNode](parentNode: Node = null): void {
|
119
|
+
super[PropertySymbol.connectToNode](parentNode);
|
120
|
+
|
121
|
+
if (parentNode) {
|
122
|
+
this[PropertySymbol.sheet] = new CSSStyleSheet();
|
123
|
+
this[PropertySymbol.sheet].replaceSync(this.textContent);
|
124
|
+
} else {
|
125
|
+
this[PropertySymbol.sheet] = null;
|
126
|
+
}
|
127
|
+
}
|
87
128
|
}
|
@@ -41,7 +41,25 @@ export default class StorageFactory {
|
|
41
41
|
return storage[PropertySymbol.data][key] !== undefined;
|
42
42
|
},
|
43
43
|
defineProperty(storage: Storage, key: string, descriptor: PropertyDescriptor): boolean {
|
44
|
-
if (Storage.prototype.hasOwnProperty(key)
|
44
|
+
if (Storage.prototype.hasOwnProperty(key)) {
|
45
|
+
if (descriptor.get || descriptor.set) {
|
46
|
+
Object.defineProperty(storage, key, {
|
47
|
+
...descriptor,
|
48
|
+
get: descriptor.get ? descriptor.get.bind(storage) : undefined,
|
49
|
+
set: descriptor.set ? descriptor.set.bind(storage) : undefined
|
50
|
+
});
|
51
|
+
} else {
|
52
|
+
Object.defineProperty(storage, key, {
|
53
|
+
...descriptor,
|
54
|
+
value:
|
55
|
+
typeof descriptor.value === 'function'
|
56
|
+
? descriptor.value.bind(storage)
|
57
|
+
: descriptor.value
|
58
|
+
});
|
59
|
+
}
|
60
|
+
return true;
|
61
|
+
}
|
62
|
+
if (descriptor.value === undefined) {
|
45
63
|
return false;
|
46
64
|
}
|
47
65
|
storage[PropertySymbol.data][key] = String(descriptor.value);
|