diff --git a/nativescript-core/ui/core/properties/properties.ts b/nativescript-core/ui/core/properties/properties.ts index 24cea4c99..8ecaeaab9 100644 --- a/nativescript-core/ui/core/properties/properties.ts +++ b/nativescript-core/ui/core/properties/properties.ts @@ -58,19 +58,16 @@ export function _getStyleProperties(): CssProperty[] { return getPropertiesFromMap(cssSymbolPropertyMap) as CssProperty[]; } -const cssVariableExpressionRegexp = /\bvar\(\s*(--[^,\s]+?)(?:\s*,\s*(.+))?\s*\)/; -const cssVariableAllExpressionsRegexp = /\bvar\(\s*(--[^,\s]+?)(?:\s*,\s*(.+))?\s*\)/g; - export function isCssVariable(property: string) { return /^--[^,\s]+?$/.test(property); } export function isCssCalcExpression(value: string) { - return /\bcalc\(/.test(value); + return value.includes("calc("); } export function isCssVariableExpression(value: string) { - return cssVariableExpressionRegexp.test(value); + return value.includes("var(--"); } export function _evaluateCssVariableExpression(view: ViewBase, cssName: string, value: string): string { @@ -90,26 +87,28 @@ export function _evaluateCssVariableExpression(view: ViewBase, cssName: string, while (lastValue !== output) { lastValue = output; - output = output.replace(cssVariableAllExpressionsRegexp, (matchStr, cssVariableName: string, fallbackStr: string) => { - const cssVariableValue = view.style.getCssVariable(cssVariableName); - if (cssVariableValue !== null) { - return cssVariableValue; - } + const idx = output.lastIndexOf("var("); + if (idx === -1) { + continue; + } - if (fallbackStr) { - // css-variable not found, using fallback-string. - const fallbackOutput = _evaluateCssVariableExpression(view, cssName, fallbackStr); - if (fallbackOutput) { - // If the fallback have multiple values, return the first of them. - return fallbackOutput.split(",")[0]; - } - } + const endIdx = output.indexOf(")", idx); + if (endIdx === -1) { + continue; + } - // Couldn't find a value for the css-variable or the fallback, return "unset" - traceWrite(`Failed to get value for css-variable "${cssVariableName}" used in "${cssName}"=[${value}] to ${view}`, traceCategories.Style, traceMessageType.error); + const matched = output.substring(idx + 4, endIdx).split(",").map((v) => v.trim()).filter((v) => !!v); + const cssVariableName = matched.shift(); + let cssVariableValue = view.style.getCssVariable(cssVariableName); + if (cssVariableValue === null && matched.length) { + cssVariableValue = _evaluateCssVariableExpression(view, cssName, matched.join(", ")).split(",")[0]; + } - return "unset"; - }); + if (!cssVariableValue) { + cssVariableValue = "unset"; + } + + output = `${output.substring(0, idx)}${cssVariableValue}${output.substring(endIdx + 1)}`; } return output; diff --git a/tests/app/ui/styling/style-tests.ts b/tests/app/ui/styling/style-tests.ts index 0eb398cdc..37835cbb4 100644 --- a/tests/app/ui/styling/style-tests.ts +++ b/tests/app/ui/styling/style-tests.ts @@ -1789,6 +1789,7 @@ export function test_nested_css_calc_and_variables() { const cssVarName = `--my-width-factor-base-${Date.now()}`; const cssVarName2 = `--my-width-factor-${Date.now()}`; + const undefinedCssVarName = `--my-undefined-variable-${Date.now()}`; const stack = new stackModule.StackLayout(); stack.css = ` @@ -1809,6 +1810,10 @@ export function test_nested_css_calc_and_variables() { StackLayout.nested { ${cssVarName2}: calc(var(${cssVarName}) * 2); } + + StackLayout.nested-fallback { + width: calc(calc(var(${undefinedCssVarName}, 16) / 2) * 2)); + } `; const label = new labelModule.Label(); @@ -1841,6 +1846,9 @@ export function test_nested_css_calc_and_variables() { stack.className = "nested"; TKUnit.assertDeepEqual(stack.width, { unit: "%", value: 1 }, "Stack - width === 100%"); + + stack.className = "nested-fallback"; + TKUnit.assertDeepEqual(stack.width, 16, "Stack - width === 16"); } export function test_css_variable_is_applied_to_normal_properties() {