From c0e1b4837bfbea9d8e78dd5d9558a3de0eb97505 Mon Sep 17 00:00:00 2001 From: David Ortner Date: Wed, 27 Mar 2024 01:09:21 +0100 Subject: [PATCH 1/4] chore: [#1364] Adds unit tests --- .../test/window/BrowserWindow.test.ts | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/packages/happy-dom/test/window/BrowserWindow.test.ts b/packages/happy-dom/test/window/BrowserWindow.test.ts index 2fe889f0..d9f29c8b 100644 --- a/packages/happy-dom/test/window/BrowserWindow.test.ts +++ b/packages/happy-dom/test/window/BrowserWindow.test.ts @@ -748,6 +748,42 @@ describe('BrowserWindow', () => { expect(computedStyle.color).toBe('green'); }); + it('Handles variables in style attributes.', () => { + const div = document.createElement('div'); + div.setAttribute('style', '--my-color1: pink;'); + + const style = document.createElement('style'); + + style.textContent = ` + div { + border-color: var(--my-color1); + } + `; + + document.head.appendChild(style); + document.body.appendChild(div); + + expect(window.getComputedStyle(div).getPropertyValue('border-color')).toBe('pink'); + }); + + it('Handles variables in root of style.', () => { + const div = document.createElement('div'); + const style = document.createElement('style'); + + style.textContent = ` + div { + border-color: var(--my-color1); + } + + --my-color1: pink; + `; + + document.head.appendChild(style); + document.body.appendChild(div); + + expect(window.getComputedStyle(div).getPropertyValue('border-color')).toBe('pink'); + }); + it('Ingores invalid selectors in parsed CSS.', () => { const parent = document.createElement('div'); const element = document.createElement('span'); From afbf758775c785f1eeae43e140a8b1de238da0f0 Mon Sep 17 00:00:00 2001 From: David Ortner Date: Tue, 2 Apr 2024 00:26:07 +0200 Subject: [PATCH 2/4] fix: [#1364] Fixes problem related to CSS properties not being used when defined after the CSS value --- packages/happy-dom/src/PropertySymbol.ts | 1 + .../CSSStyleDeclarationCSSParser.ts | 39 +++++--- .../CSSStyleDeclarationElementStyle.ts | 92 ++++++++++++------- .../CSSStyleDeclarationPropertyManager.ts | 9 +- .../HTMLLinkElementStyleSheetLoader.ts | 10 +- .../html-style-element/HTMLStyleElement.ts | 57 ++++++++++-- .../test/window/BrowserWindow.test.ts | 8 +- 7 files changed, 151 insertions(+), 65 deletions(-) diff --git a/packages/happy-dom/src/PropertySymbol.ts b/packages/happy-dom/src/PropertySymbol.ts index c13aebf1..f711ee4f 100644 --- a/packages/happy-dom/src/PropertySymbol.ts +++ b/packages/happy-dom/src/PropertySymbol.ts @@ -158,3 +158,4 @@ export const navigator = Symbol('navigator'); export const screen = Symbol('screen'); export const sessionStorage = Symbol('sessionStorage'); export const localStorage = Symbol('localStorage'); +export const cssProperties = Symbol('cssProperties'); diff --git a/packages/happy-dom/src/css/declaration/css-parser/CSSStyleDeclarationCSSParser.ts b/packages/happy-dom/src/css/declaration/css-parser/CSSStyleDeclarationCSSParser.ts index 34cce2a3..7298b785 100644 --- a/packages/happy-dom/src/css/declaration/css-parser/CSSStyleDeclarationCSSParser.ts +++ b/packages/happy-dom/src/css/declaration/css-parser/CSSStyleDeclarationCSSParser.ts @@ -1,7 +1,8 @@ -// PropName => \s*([^:;]+?)\s*: -// PropValue => \s*((?:[^(;]*?(?:\([^)]*\))?)*?) <- will match any non ';' char except inside (), nested parentheses are not supported -// !important => \s*(!important)? -// EndOfRule => \s*(?:$|;) +// Groups: +// Property name => \s*([^:;]+?)\s*: +// Property value => \s*((?:[^(;]*?(?:\([^)]*\))?)*?) <- will match any non ';' char except inside (), nested parentheses are not supported +// Important ("!important") => \s*(!important)? +// End of rule => \s*(?:$|;) const SPLIT_RULES_REGEXP = /\s*([^:;]+?)\s*:\s*((?:[^(;]*?(?:\([^)]*\))?)*?)\s*(!important)?\s*(?:$|;)/g; @@ -15,15 +16,29 @@ export default class CSSStyleDeclarationCSSParser { * @param cssText CSS string. * @param callback Callback. */ - public static parse( - cssText: string, - callback: (name: string, value: string, important: boolean) => void - ): void { - const rules = Array.from(cssText.matchAll(SPLIT_RULES_REGEXP)); - for (const [, key, value, important] of rules) { - if (key && value) { - callback(key.trim(), value.trim(), !!important); + public static parse(cssText: string): { + rules: Array<{ name: string; value: string; important: boolean }>; + properties: { [name: string]: string }; + } { + const properties: { [name: string]: string } = {}; + const rules: Array<{ name: string; value: string; important: boolean }> = []; + const regexp = new RegExp(SPLIT_RULES_REGEXP); + let match; + + while ((match = regexp.exec(cssText))) { + const name = (match[1] ?? '').trim(); + const value = (match[2] ?? '').trim(); + const important = match[3] ? true : false; + + if (name && value) { + if (name.startsWith('--')) { + properties[name] = value; + } + + rules.push({ name, value, important }); } } + + return { rules, properties }; } } diff --git a/packages/happy-dom/src/css/declaration/element-style/CSSStyleDeclarationElementStyle.ts b/packages/happy-dom/src/css/declaration/element-style/CSSStyleDeclarationElementStyle.ts index 9bd3080f..858592c4 100644 --- a/packages/happy-dom/src/css/declaration/element-style/CSSStyleDeclarationElementStyle.ts +++ b/packages/happy-dom/src/css/declaration/element-style/CSSStyleDeclarationElementStyle.ts @@ -1,6 +1,6 @@ import ShadowRoot from '../../../nodes/shadow-root/ShadowRoot.js'; import * as PropertySymbol from '../../../PropertySymbol.js'; -import Element from '../../../nodes/element/Element.js'; +import HTMLElement from '../../../nodes/html-element/HTMLElement.js'; import Document from '../../../nodes/document/Document.js'; import HTMLStyleElement from '../../../nodes/html-style-element/HTMLStyleElement.js'; import NodeList from '../../../nodes/node/NodeList.js'; @@ -19,11 +19,19 @@ import CSSMeasurementConverter from '../measurement-converter/CSSMeasurementConv import MediaQueryList from '../../../match-media/MediaQueryList.js'; import WindowBrowserSettingsReader from '../../../window/WindowBrowserSettingsReader.js'; +// Groups: +// Property name => \s*([^:;]+?)\s*: +// Property value => \s*((?:[^(;]*?(?:\([^)]*\))?)*?) <- will match any non ';' char except inside (), nested parentheses are not supported +// Important ("!important") => \s*(!important)? +// End of rule => \s*(?:$|;) +const SPLIT_RULES_REGEXP = + /\s*([^:;]+?)\s*:\s*((?:[^(;]*?(?:\([^)]*\))?)*?)\s*(!important)?\s*(?:$|;)/g; + const CSS_VARIABLE_REGEXP = /var\( *(--[^), ]+)\)|var\( *(--[^), ]+), *([^), ]+)\)/; const CSS_MEASUREMENT_REGEXP = /[0-9.]+(px|rem|em|vw|vh|%|vmin|vmax|cm|mm|in|pt|pc|Q)/g; type IStyleAndElement = { - element: Element | ShadowRoot | Document; + element: HTMLElement | ShadowRoot | Document; cssTexts: Array<{ cssText: string; priorityWeight: number }>; }; @@ -41,7 +49,7 @@ export default class CSSStyleDeclarationElementStyle { documentCacheID: null }; - private element: Element; + private element: HTMLElement; private computed: boolean; /** @@ -50,7 +58,7 @@ export default class CSSStyleDeclarationElementStyle { * @param element Element. * @param [computed] Computed. */ - constructor(element: Element, computed = false) { + constructor(element: HTMLElement, computed = false) { this.element = element; this.computed = computed; } @@ -89,7 +97,7 @@ export default class CSSStyleDeclarationElementStyle { const documentElements: Array = []; const parentElements: Array = []; let styleAndElement: IStyleAndElement = { - element: this.element, + element: this.element, cssTexts: [] }; let shadowRootElements: Array = []; @@ -132,15 +140,23 @@ export default class CSSStyleDeclarationElementStyle { if (sheet) { this.parseCSSRules({ elements: documentElements, + rootElement: + documentElements[0].element[PropertySymbol.tagName] === 'HTML' + ? documentElements[0] + : null, cssRules: sheet.cssRules }); } } - for (const styleSheet of this.element[PropertySymbol.ownerDocument].adoptedStyleSheets) { + for (const sheet of this.element[PropertySymbol.ownerDocument].adoptedStyleSheets) { this.parseCSSRules({ elements: documentElements, - cssRules: styleSheet.cssRules + rootElement: + documentElements[0].element[PropertySymbol.tagName] === 'HTML' + ? documentElements[0] + : null, + cssRules: sheet.cssRules }); } @@ -155,7 +171,7 @@ export default class CSSStyleDeclarationElementStyle { ); styleAndElement = { - element: shadowRoot.host, + element: shadowRoot.host, cssTexts: [] }; @@ -170,10 +186,10 @@ export default class CSSStyleDeclarationElementStyle { } } - for (const styleSheet of shadowRoot.adoptedStyleSheets) { + for (const sheet of shadowRoot.adoptedStyleSheets) { this.parseCSSRules({ elements: shadowRootElements, - cssRules: styleSheet.cssRules, + cssRules: sheet.cssRules, hostElement: styleAndElement }); } @@ -181,7 +197,7 @@ export default class CSSStyleDeclarationElementStyle { shadowRootElements = []; } else { styleAndElement = { - element: styleAndElement.element[PropertySymbol.parentNode], + element: styleAndElement.element[PropertySymbol.parentNode], cssTexts: [] }; } @@ -190,7 +206,7 @@ export default class CSSStyleDeclarationElementStyle { // Concatenates all parent element CSS to one string. const targetElement = parentElements[parentElements.length - 1]; const propertyManager = new CSSStyleDeclarationPropertyManager(); - const cssVariables: { [k: string]: string } = {}; + const cssProperties: { [k: string]: string } = {}; let rootFontSize: string | number = 16; let parentFontSize: string | number = 16; @@ -200,35 +216,35 @@ export default class CSSStyleDeclarationElementStyle { let elementCSSText = ''; if ( CSSStyleDeclarationElementDefaultCSS[ - (parentElement.element)[PropertySymbol.tagName] + (parentElement.element)[PropertySymbol.tagName] ] ) { if ( typeof CSSStyleDeclarationElementDefaultCSS[ - (parentElement.element)[PropertySymbol.tagName] + (parentElement.element)[PropertySymbol.tagName] ] === 'string' ) { elementCSSText += CSSStyleDeclarationElementDefaultCSS[ - (parentElement.element)[PropertySymbol.tagName] + (parentElement.element)[PropertySymbol.tagName] ]; } else { for (const key of Object.keys( CSSStyleDeclarationElementDefaultCSS[ - (parentElement.element)[PropertySymbol.tagName] + (parentElement.element)[PropertySymbol.tagName] ] )) { if (key === 'default' || !!parentElement.element[key]) { elementCSSText += CSSStyleDeclarationElementDefaultCSS[ - (parentElement.element)[PropertySymbol.tagName] + (parentElement.element)[PropertySymbol.tagName] ][key]; } } } elementCSSText += CSSStyleDeclarationElementDefaultCSS[ - (parentElement.element)[PropertySymbol.tagName] + (parentElement.element)[PropertySymbol.tagName] ]; } @@ -236,27 +252,30 @@ export default class CSSStyleDeclarationElementStyle { elementCSSText += cssText.cssText; } - const elementStyleAttribute = (parentElement.element)[PropertySymbol.attributes][ + const elementStyleAttribute = (parentElement.element)[PropertySymbol.attributes][ 'style' ]; + if (elementStyleAttribute) { elementCSSText += elementStyleAttribute[PropertySymbol.value]; } - CSSStyleDeclarationCSSParser.parse(elementCSSText, (name, value, important) => { - const isCSSVariable = name.startsWith('--'); + const rulesAndProperties = CSSStyleDeclarationCSSParser.parse(elementCSSText); + const rules = rulesAndProperties.rules; + + Object.assign(cssProperties, rulesAndProperties.properties); + + for (const { name, value, important } of rules) { if ( - isCSSVariable || CSSStyleDeclarationElementInheritedProperties[name] || parentElement === targetElement ) { - const cssValue = this.parseCSSVariablesInValue(value, cssVariables); - if (cssValue && (!propertyManager.get(name)?.important || important)) { - propertyManager.set(name, cssValue, important); + const parsedValue = this.parseCSSVariablesInValue(value.trim(), cssProperties); + + if (parsedValue && (!propertyManager.get(name)?.important || important)) { + propertyManager.set(name, parsedValue, important); - if (isCSSVariable) { - cssVariables[name] = cssValue; - } else if (name === 'font' || name === 'font-size') { + if (name === 'font' || name === 'font-size') { const fontSize = propertyManager.properties['font-size']; if (fontSize !== null) { const parsedValue = this.parseMeasurementsInValue({ @@ -265,7 +284,7 @@ export default class CSSStyleDeclarationElementStyle { parentFontSize, parentSize: parentFontSize }); - if ((parentElement.element)[PropertySymbol.tagName] === 'HTML') { + if ((parentElement.element)[PropertySymbol.tagName] === 'HTML') { rootFontSize = parsedValue; } else if (parentElement !== targetElement) { parentFontSize = parsedValue; @@ -274,7 +293,7 @@ export default class CSSStyleDeclarationElementStyle { } } } - }); + } } for (const name of CSSStyleDeclarationElementMeasurementProperties) { @@ -302,11 +321,13 @@ export default class CSSStyleDeclarationElementStyle { * @param options Options. * @param options.elements Elements. * @param options.cssRules CSS rules. + * @param options.rootElement Root element. * @param [options.hostElement] Host element. */ private parseCSSRules(options: { cssRules: CSSRule[]; - elements: Array; + elements: IStyleAndElement[]; + rootElement?: IStyleAndElement; hostElement?: IStyleAndElement; }): void { if (!options.elements.length) { @@ -326,9 +347,16 @@ export default class CSSStyleDeclarationElementStyle { priorityWeight: 0 }); } + } else if (selectorText.startsWith(':root')) { + if (options.rootElement) { + options.rootElement.cssTexts.push({ + cssText: (rule)[PropertySymbol.cssText], + priorityWeight: 0 + }); + } } else { for (const element of options.elements) { - const match = QuerySelector.matches(element.element, selectorText, { + const match = QuerySelector.matches(element.element, selectorText, { ignoreErrors: true }); if (match) { diff --git a/packages/happy-dom/src/css/declaration/property-manager/CSSStyleDeclarationPropertyManager.ts b/packages/happy-dom/src/css/declaration/property-manager/CSSStyleDeclarationPropertyManager.ts index de060af2..ce1a969c 100644 --- a/packages/happy-dom/src/css/declaration/property-manager/CSSStyleDeclarationPropertyManager.ts +++ b/packages/happy-dom/src/css/declaration/property-manager/CSSStyleDeclarationPropertyManager.ts @@ -30,11 +30,12 @@ export default class CSSStyleDeclarationPropertyManager { */ constructor(options?: { cssText?: string }) { if (options?.cssText) { - CSSStyleDeclarationCSSParser.parse(options.cssText, (name, value, important) => { - if (important || !this.get(name)?.important) { - this.set(name, value, important); + const { rules } = CSSStyleDeclarationCSSParser.parse(options.cssText); + for (const rule of rules) { + if (rule.important || !this.get(rule.name)?.important) { + this.set(rule.name, rule.value, rule.important); } - }); + } } } diff --git a/packages/happy-dom/src/nodes/html-link-element/HTMLLinkElementStyleSheetLoader.ts b/packages/happy-dom/src/nodes/html-link-element/HTMLLinkElementStyleSheetLoader.ts index 69f9de8a..d74bb704 100644 --- a/packages/happy-dom/src/nodes/html-link-element/HTMLLinkElementStyleSheetLoader.ts +++ b/packages/happy-dom/src/nodes/html-link-element/HTMLLinkElementStyleSheetLoader.ts @@ -38,6 +38,7 @@ export default class HTMLLinkElementStyleSheetLoader { public async loadStyleSheet(url: string | null, rel: string | null): Promise { const element = this.#element; const browserSettings = this.#browserFrame.page.context.browser.settings; + const window = element[PropertySymbol.ownerDocument][PropertySymbol.ownerWindow]; if ( !url || @@ -50,10 +51,7 @@ export default class HTMLLinkElementStyleSheetLoader { let absoluteURL: string; try { - absoluteURL = new URL( - url, - element[PropertySymbol.ownerDocument][PropertySymbol.ownerWindow].location.href - ).href; + absoluteURL = new URL(url, window.location.href).href; } catch (error) { return; } @@ -79,10 +77,10 @@ export default class HTMLLinkElementStyleSheetLoader { const resourceFetch = new ResourceFetch({ browserFrame: this.#browserFrame, - window: element[PropertySymbol.ownerDocument][PropertySymbol.ownerWindow] + window: window }); const readyStateManager = (<{ [PropertySymbol.readyStateManager]: DocumentReadyStateManager }>( - (element[PropertySymbol.ownerDocument][PropertySymbol.ownerWindow]) + (window) ))[PropertySymbol.readyStateManager]; this.#loadedStyleSheetURL = absoluteURL; diff --git a/packages/happy-dom/src/nodes/html-style-element/HTMLStyleElement.ts b/packages/happy-dom/src/nodes/html-style-element/HTMLStyleElement.ts index 9bb37028..6cdbe958 100644 --- a/packages/happy-dom/src/nodes/html-style-element/HTMLStyleElement.ts +++ b/packages/happy-dom/src/nodes/html-style-element/HTMLStyleElement.ts @@ -1,6 +1,7 @@ import CSSStyleSheet from '../../css/CSSStyleSheet.js'; import * as PropertySymbol from '../../PropertySymbol.js'; import HTMLElement from '../html-element/HTMLElement.js'; +import Node from '../node/Node.js'; /** * HTML Style Element. @@ -17,14 +18,7 @@ export default class HTMLStyleElement extends HTMLElement { * @returns CSS style sheet. */ public get sheet(): CSSStyleSheet { - if (!this[PropertySymbol.isConnected]) { - return null; - } - if (!this[PropertySymbol.sheet]) { - this[PropertySymbol.sheet] = new CSSStyleSheet(); - } - this[PropertySymbol.sheet].replaceSync(this.textContent); - return this[PropertySymbol.sheet]; + return this[PropertySymbol.sheet] ? this[PropertySymbol.sheet] : null; } /** @@ -84,4 +78,51 @@ export default class HTMLStyleElement extends HTMLElement { this.setAttribute('disabled', ''); } } + + /** + * @override + */ + public override appendChild(node: Node): Node { + const returnValue = super.appendChild(node); + if (this[PropertySymbol.sheet]) { + this[PropertySymbol.sheet].replaceSync(this.textContent); + } + return returnValue; + } + + /** + * @override + */ + public override removeChild(node: Node): Node { + const returnValue = super.removeChild(node); + if (this[PropertySymbol.sheet]) { + this[PropertySymbol.sheet].replaceSync(this.textContent); + } + return returnValue; + } + + /** + * @override + */ + public override insertBefore(newNode: Node, referenceNode: Node | null): Node { + const returnValue = super.insertBefore(newNode, referenceNode); + if (this[PropertySymbol.sheet]) { + this[PropertySymbol.sheet].replaceSync(this.textContent); + } + return returnValue; + } + + /** + * @override + */ + public override [PropertySymbol.connectToNode](parentNode: Node = null): void { + super[PropertySymbol.connectToNode](parentNode); + + if (parentNode) { + this[PropertySymbol.sheet] = new CSSStyleSheet(); + this[PropertySymbol.sheet].replaceSync(this.textContent); + } else { + this[PropertySymbol.sheet] = null; + } + } } diff --git a/packages/happy-dom/test/window/BrowserWindow.test.ts b/packages/happy-dom/test/window/BrowserWindow.test.ts index d9f29c8b..00a41b0f 100644 --- a/packages/happy-dom/test/window/BrowserWindow.test.ts +++ b/packages/happy-dom/test/window/BrowserWindow.test.ts @@ -750,6 +750,7 @@ describe('BrowserWindow', () => { it('Handles variables in style attributes.', () => { const div = document.createElement('div'); + div.setAttribute('style', '--my-color1: pink;'); const style = document.createElement('style'); @@ -766,16 +767,17 @@ describe('BrowserWindow', () => { expect(window.getComputedStyle(div).getPropertyValue('border-color')).toBe('pink'); }); - it('Handles variables in root of style.', () => { + it('Handles variables in root pseudo element (:root).', () => { const div = document.createElement('div'); const style = document.createElement('style'); style.textContent = ` + :root { + --my-color1: pink; + } div { border-color: var(--my-color1); } - - --my-color1: pink; `; document.head.appendChild(style); From bd0205f2f20984a08155b3345e0f907a1d8f6690 Mon Sep 17 00:00:00 2001 From: David Ortner Date: Tue, 2 Apr 2024 00:28:30 +0200 Subject: [PATCH 3/4] chore: [#1364] Removes unused constants --- packages/happy-dom/src/PropertySymbol.ts | 1 - .../element-style/CSSStyleDeclarationElementStyle.ts | 8 -------- 2 files changed, 9 deletions(-) diff --git a/packages/happy-dom/src/PropertySymbol.ts b/packages/happy-dom/src/PropertySymbol.ts index f711ee4f..c13aebf1 100644 --- a/packages/happy-dom/src/PropertySymbol.ts +++ b/packages/happy-dom/src/PropertySymbol.ts @@ -158,4 +158,3 @@ export const navigator = Symbol('navigator'); export const screen = Symbol('screen'); export const sessionStorage = Symbol('sessionStorage'); export const localStorage = Symbol('localStorage'); -export const cssProperties = Symbol('cssProperties'); diff --git a/packages/happy-dom/src/css/declaration/element-style/CSSStyleDeclarationElementStyle.ts b/packages/happy-dom/src/css/declaration/element-style/CSSStyleDeclarationElementStyle.ts index 858592c4..cec29b73 100644 --- a/packages/happy-dom/src/css/declaration/element-style/CSSStyleDeclarationElementStyle.ts +++ b/packages/happy-dom/src/css/declaration/element-style/CSSStyleDeclarationElementStyle.ts @@ -19,14 +19,6 @@ import CSSMeasurementConverter from '../measurement-converter/CSSMeasurementConv import MediaQueryList from '../../../match-media/MediaQueryList.js'; import WindowBrowserSettingsReader from '../../../window/WindowBrowserSettingsReader.js'; -// Groups: -// Property name => \s*([^:;]+?)\s*: -// Property value => \s*((?:[^(;]*?(?:\([^)]*\))?)*?) <- will match any non ';' char except inside (), nested parentheses are not supported -// Important ("!important") => \s*(!important)? -// End of rule => \s*(?:$|;) -const SPLIT_RULES_REGEXP = - /\s*([^:;]+?)\s*:\s*((?:[^(;]*?(?:\([^)]*\))?)*?)\s*(!important)?\s*(?:$|;)/g; - const CSS_VARIABLE_REGEXP = /var\( *(--[^), ]+)\)|var\( *(--[^), ]+), *([^), ]+)\)/; const CSS_MEASUREMENT_REGEXP = /[0-9.]+(px|rem|em|vw|vh|%|vmin|vmax|cm|mm|in|pt|pc|Q)/g; From 9155ec1fc1a257847db2a17da6173b67908cafd9 Mon Sep 17 00:00:00 2001 From: David Ortner Date: Tue, 2 Apr 2024 00:32:36 +0200 Subject: [PATCH 4/4] chore: [#1364] Removes unused constants --- .../CSSStyleDeclarationElementStyle.ts | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/packages/happy-dom/src/css/declaration/element-style/CSSStyleDeclarationElementStyle.ts b/packages/happy-dom/src/css/declaration/element-style/CSSStyleDeclarationElementStyle.ts index cec29b73..c77fb160 100644 --- a/packages/happy-dom/src/css/declaration/element-style/CSSStyleDeclarationElementStyle.ts +++ b/packages/happy-dom/src/css/declaration/element-style/CSSStyleDeclarationElementStyle.ts @@ -1,6 +1,6 @@ import ShadowRoot from '../../../nodes/shadow-root/ShadowRoot.js'; import * as PropertySymbol from '../../../PropertySymbol.js'; -import HTMLElement from '../../../nodes/html-element/HTMLElement.js'; +import Element from '../../../nodes/element/Element.js'; import Document from '../../../nodes/document/Document.js'; import HTMLStyleElement from '../../../nodes/html-style-element/HTMLStyleElement.js'; import NodeList from '../../../nodes/node/NodeList.js'; @@ -23,7 +23,7 @@ const CSS_VARIABLE_REGEXP = /var\( *(--[^), ]+)\)|var\( *(--[^), ]+), *([^), ]+) const CSS_MEASUREMENT_REGEXP = /[0-9.]+(px|rem|em|vw|vh|%|vmin|vmax|cm|mm|in|pt|pc|Q)/g; type IStyleAndElement = { - element: HTMLElement | ShadowRoot | Document; + element: Element | ShadowRoot | Document; cssTexts: Array<{ cssText: string; priorityWeight: number }>; }; @@ -41,7 +41,7 @@ export default class CSSStyleDeclarationElementStyle { documentCacheID: null }; - private element: HTMLElement; + private element: Element; private computed: boolean; /** @@ -50,7 +50,7 @@ export default class CSSStyleDeclarationElementStyle { * @param element Element. * @param [computed] Computed. */ - constructor(element: HTMLElement, computed = false) { + constructor(element: Element, computed = false) { this.element = element; this.computed = computed; } @@ -89,7 +89,7 @@ export default class CSSStyleDeclarationElementStyle { const documentElements: Array = []; const parentElements: Array = []; let styleAndElement: IStyleAndElement = { - element: this.element, + element: this.element, cssTexts: [] }; let shadowRootElements: Array = []; @@ -163,7 +163,7 @@ export default class CSSStyleDeclarationElementStyle { ); styleAndElement = { - element: shadowRoot.host, + element: shadowRoot.host, cssTexts: [] }; @@ -189,7 +189,7 @@ export default class CSSStyleDeclarationElementStyle { shadowRootElements = []; } else { styleAndElement = { - element: styleAndElement.element[PropertySymbol.parentNode], + element: styleAndElement.element[PropertySymbol.parentNode], cssTexts: [] }; } @@ -208,35 +208,35 @@ export default class CSSStyleDeclarationElementStyle { let elementCSSText = ''; if ( CSSStyleDeclarationElementDefaultCSS[ - (parentElement.element)[PropertySymbol.tagName] + (parentElement.element)[PropertySymbol.tagName] ] ) { if ( typeof CSSStyleDeclarationElementDefaultCSS[ - (parentElement.element)[PropertySymbol.tagName] + (parentElement.element)[PropertySymbol.tagName] ] === 'string' ) { elementCSSText += CSSStyleDeclarationElementDefaultCSS[ - (parentElement.element)[PropertySymbol.tagName] + (parentElement.element)[PropertySymbol.tagName] ]; } else { for (const key of Object.keys( CSSStyleDeclarationElementDefaultCSS[ - (parentElement.element)[PropertySymbol.tagName] + (parentElement.element)[PropertySymbol.tagName] ] )) { if (key === 'default' || !!parentElement.element[key]) { elementCSSText += CSSStyleDeclarationElementDefaultCSS[ - (parentElement.element)[PropertySymbol.tagName] + (parentElement.element)[PropertySymbol.tagName] ][key]; } } } elementCSSText += CSSStyleDeclarationElementDefaultCSS[ - (parentElement.element)[PropertySymbol.tagName] + (parentElement.element)[PropertySymbol.tagName] ]; } @@ -244,7 +244,7 @@ export default class CSSStyleDeclarationElementStyle { elementCSSText += cssText.cssText; } - const elementStyleAttribute = (parentElement.element)[PropertySymbol.attributes][ + const elementStyleAttribute = (parentElement.element)[PropertySymbol.attributes][ 'style' ]; @@ -276,7 +276,7 @@ export default class CSSStyleDeclarationElementStyle { parentFontSize, parentSize: parentFontSize }); - if ((parentElement.element)[PropertySymbol.tagName] === 'HTML') { + if ((parentElement.element)[PropertySymbol.tagName] === 'HTML') { rootFontSize = parsedValue; } else if (parentElement !== targetElement) { parentFontSize = parsedValue; @@ -348,7 +348,7 @@ export default class CSSStyleDeclarationElementStyle { } } else { for (const element of options.elements) { - const match = QuerySelector.matches(element.element, selectorText, { + const match = QuerySelector.matches(element.element, selectorText, { ignoreErrors: true }); if (match) {