diff --git a/src/context/stylesheets.ts b/src/context/stylesheets.ts index 84e70dfe..eea79173 100644 --- a/src/context/stylesheets.ts +++ b/src/context/stylesheets.ts @@ -5,7 +5,6 @@ export class StyleSheets { private rootSvg: Element private readonly loadExternalSheets: boolean private readonly styleSheets: CSSStyleSheet[] - constructor(rootSvg: Element, loadExtSheets: boolean) { this.rootSvg = rootSvg this.loadExternalSheets = loadExtSheets @@ -184,6 +183,62 @@ export class StyleSheets { const mostSpecificRule = matchingRules.reduce((previousValue, currentValue) => compare(previousValue, currentValue) === 1 ? previousValue : currentValue ) - return mostSpecificRule.style.getPropertyValue(propertyCss) || undefined + const getPropertyCssValue = (propertyCss: string): string => { + //Screening fallback + let propertyValue = + propertyCss.indexOf('var(') == -1 + ? mostSpecificRule.style.getPropertyValue(propertyCss.trim()) + : propertyCss + const cssVariables: { + text: string //Varlables text + fallback: string // Varlables fallback + key: string //Varlables key + }[] = [] + for ( + let index = propertyValue.indexOf('var('), left = index + 4, bracketsLevels = 0; + index < propertyValue.length; + + ) { + // not found + if (index < 0) { + break + } + if (propertyValue.charAt(index) === ')') bracketsLevels-- + else if (propertyValue.charAt(index) === '(') bracketsLevels++ + if (bracketsLevels == 0 && index > left) { + const text = propertyValue.substring(left - 4, index + 1) + const inner = text.substring(4, text.length - 1) + const separator = inner.indexOf(',') + const length = inner.length + const sp = separator < 0 ? length : separator + cssVariables.push({ + text, //var(--one,var(--two,rgb(1,1,1))) + fallback: inner.substring(sp + 1), //var(--two,rgb(1,1,1)) + key: inner.substring(0, sp).trim() //--one + }) + //Process the next css Varlables + index = propertyValue.indexOf('var(', index) + left = index + 4 + continue + } + index++ + } + if (cssVariables.length === 0) { + //propertyCss is a normal cssValue return itself + //propertyCss is a cssVariable key return getPropertyValue() + return propertyValue || propertyCss.startsWith('--') ? propertyValue : propertyCss + } + cssVariables.map(v => { + const value = getPropertyCssValue(v.key) + // Detect the need for fallback + propertyValue = propertyValue.replace( + v.text, + value ? value : getPropertyCssValue(v.fallback) + ) + }) + return propertyValue + } + + return getPropertyCssValue(propertyCss) || undefined } } diff --git a/test/common/tests.js b/test/common/tests.js index fa42728b..e28eb96c 100644 --- a/test/common/tests.js +++ b/test/common/tests.js @@ -15,6 +15,7 @@ window.tests = [ 'complete-organization-chart', 'complete-organization-chart-new', 'complete-social-network', + 'css-variables', 'custom-fonts', 'display-none-and-visibility-inheritance', 'duplicate-ids', diff --git a/test/specs/css-variables/reference.pdf b/test/specs/css-variables/reference.pdf new file mode 100644 index 00000000..3617ded5 Binary files /dev/null and b/test/specs/css-variables/reference.pdf differ diff --git a/test/specs/css-variables/spec.svg b/test/specs/css-variables/spec.svg new file mode 100644 index 00000000..5b29d616 --- /dev/null +++ b/test/specs/css-variables/spec.svg @@ -0,0 +1,32 @@ + + + Test Get variables globally + + + Test RGB Color + + + Test normal use + + + + + Test Value With Space + + + + + Test Var With Space + + + + Test Value fallback + + + + Test Multiple variables + + + Test error value + + \ No newline at end of file