From 59d01b6e2f7ac4c7697074ae8a7da5e75fea8644 Mon Sep 17 00:00:00 2001 From: David Ortner Date: Sat, 13 Jan 2024 01:22:38 +0100 Subject: [PATCH] #1192@patch: Adds support for fallback values when declaring a CSS variable (e.g. "var(--my-var, #FFF)"). --- .../CSSStyleDeclarationElementStyle.ts | 9 ++++- .../test/window/BrowserWindow.test.ts | 39 +++++++++++++++++++ 2 files changed, 46 insertions(+), 2 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 e27e06da5..322763fa3 100644 --- a/packages/happy-dom/src/css/declaration/element-style/CSSStyleDeclarationElementStyle.ts +++ b/packages/happy-dom/src/css/declaration/element-style/CSSStyleDeclarationElementStyle.ts @@ -19,7 +19,7 @@ import CSSMeasurementConverter from '../measurement-converter/CSSMeasurementConv import MediaQueryList from '../../../match-media/MediaQueryList.js'; import WindowBrowserSettingsReader from '../../../window/WindowBrowserSettingsReader.js'; -const CSS_VARIABLE_REGEXP = /var\( *(--[^) ]+)\)/g; +const CSS_VARIABLE_REGEXP = /var\( *(--[^), ]+)\)|var\( *(--[^), ]+), *([^), ]+)\)/g; const CSS_MEASUREMENT_REGEXP = /[0-9.]+(px|rem|em|vw|vh|%|vmin|vmax|cm|mm|in|pt|pc|Q)/g; type IStyleAndElement = { @@ -333,7 +333,12 @@ export default class CSSStyleDeclarationElementStyle { let match; while ((match = regexp.exec(value)) !== null) { - newValue = newValue.replace(match[0], cssVariables[match[1]] || ''); + // Fallback value - E.g. var(--my-var, #FFFFFF) + if (match[2] !== undefined) { + newValue = newValue.replace(match[0], cssVariables[match[2]] || match[3]); + } else { + newValue = newValue.replace(match[0], cssVariables[match[1]] || ''); + } } return newValue; diff --git a/packages/happy-dom/test/window/BrowserWindow.test.ts b/packages/happy-dom/test/window/BrowserWindow.test.ts index bce9597dd..cd77b1a3d 100644 --- a/packages/happy-dom/test/window/BrowserWindow.test.ts +++ b/packages/happy-dom/test/window/BrowserWindow.test.ts @@ -487,6 +487,45 @@ describe('BrowserWindow', () => { expect(computedStyle.color).toBe(''); }); + it('Returns values defined by a CSS variables when a fallback is used.', () => { + const parent = document.createElement('div'); + const element = document.createElement('span'); + const computedStyle = window.getComputedStyle(element); + const parentStyle = document.createElement('style'); + const elementStyle = document.createElement('style'); + + browserFrame.page.setViewport({ width: 1024 }); + + parentStyle.innerHTML = ` + html { + font: 14px "Times New Roman"; + } + + div { + --border-variable: 1px solid var(--color-variable, #000); + --font-variable: 1rem "Tahoma"; + } + `; + + elementStyle.innerHTML = ` + span { + border: var(--border-variable); + font: var(--font-variable); + color: var(--invalid-variable); + } + `; + + parent.appendChild(elementStyle); + parent.appendChild(element); + + document.body.appendChild(parentStyle); + document.body.appendChild(parent); + + expect(computedStyle.border).toBe('1px solid #000'); + expect(computedStyle.font).toBe('14px "Tahoma"'); + expect(computedStyle.color).toBe(''); + }); + it('Returns a CSSStyleDeclaration object with computed styles containing "rem" and "em" measurement values converted to pixels.', () => { const parent = document.createElement('div'); const element = document.createElement('span');