From 916d59f1ab8b67f63faceea7d4e57fa565b7be20 Mon Sep 17 00:00:00 2001 From: Ivan Starkov Date: Mon, 16 Dec 2024 21:46:20 +0700 Subject: [PATCH] fix: Pasting gradient into color field breaks CSS parser (#4593) ## Description closes #4578 ## Steps for reproduction 1. click button 2. expect xyz ## Code Review - [ ] hi @kof, I need you to do - conceptual review (architecture, feature-correctness) - detailed review (read every line) - test it on preview ## Before requesting a review - [ ] made a self-review - [ ] added inline comments where things may be not obvious (the "why", not "what") ## Before merging - [ ] tested locally and on preview environment (preview dev login: 0000) - [ ] updated [test cases](https://github.com/webstudio-is/webstudio/blob/main/apps/builder/docs/test-cases.md) document - [ ] added tests - [ ] if any new env variables are added, added them to `.env` file --- .../parse-intermediate-or-invalid-value.ts | 30 +++++++++++++------ ...e-intermediate-or-invalid-value.ts.test.ts | 13 ++++++++ 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/apps/builder/app/builder/features/style-panel/shared/css-value-input/parse-intermediate-or-invalid-value.ts b/apps/builder/app/builder/features/style-panel/shared/css-value-input/parse-intermediate-or-invalid-value.ts index 99c6ee35510b..23e0c7f37db4 100644 --- a/apps/builder/app/builder/features/style-panel/shared/css-value-input/parse-intermediate-or-invalid-value.ts +++ b/apps/builder/app/builder/features/style-panel/shared/css-value-input/parse-intermediate-or-invalid-value.ts @@ -1,10 +1,9 @@ -import { parse } from "css-tree"; import type { StyleProperty, StyleValue, InvalidValue, } from "@webstudio-is/css-engine"; -import { units, parseCssValue } from "@webstudio-is/css-data"; +import { units, parseCssValue, cssTryParseValue } from "@webstudio-is/css-data"; import type { IntermediateStyleValue } from "./css-value-input"; import { evaluateMath } from "./evaluate-math"; import { toKebabCase } from "../keyword-utils"; @@ -13,7 +12,8 @@ const unitsList = Object.values(units).flat(); export const parseIntermediateOrInvalidValue = ( property: StyleProperty, - styleValue: IntermediateStyleValue | InvalidValue + styleValue: IntermediateStyleValue | InvalidValue, + originalValue?: string ): StyleValue => { let value = styleValue.value.trim(); if (value.endsWith(";")) { @@ -22,7 +22,15 @@ export const parseIntermediateOrInvalidValue = ( // When user enters a number, we don't know if its a valid unit value, // so we are going to parse it with a unit and if its not invalid - we take it. - const ast = parse(value, { context: "value" }); + const ast = cssTryParseValue(value); + + if (ast === undefined) { + return { + type: "invalid", + value: originalValue ?? value, + }; + } + const node = "children" in ast && ast.children?.size === 1 ? ast.children.first @@ -119,16 +127,20 @@ export const parseIntermediateOrInvalidValue = ( // Users often mistype comma instead of dot and we want to be tolerant to that. // We need to try replace comma with dot and then try all parsing options again. if (value.includes(",")) { - return parseIntermediateOrInvalidValue(property, { - ...styleValue, - value: value.replace(/,/g, "."), - }); + return parseIntermediateOrInvalidValue( + property, + { + ...styleValue, + value: value.replace(/,/g, "."), + }, + originalValue ?? value + ); } // If we are here it means that value can be Valid but our parseCssValue can't handle it // or value is invalid return { type: "invalid", - value: value, + value: originalValue ?? value, }; }; diff --git a/apps/builder/app/builder/features/style-panel/shared/css-value-input/parse-intermediate-or-invalid-value.ts.test.ts b/apps/builder/app/builder/features/style-panel/shared/css-value-input/parse-intermediate-or-invalid-value.ts.test.ts index c789862c2049..ab3e225918a0 100644 --- a/apps/builder/app/builder/features/style-panel/shared/css-value-input/parse-intermediate-or-invalid-value.ts.test.ts +++ b/apps/builder/app/builder/features/style-panel/shared/css-value-input/parse-intermediate-or-invalid-value.ts.test.ts @@ -638,3 +638,16 @@ test("parse z-index", () => { unit: "number", }); }); + +test("parse color", () => { + expect( + parseIntermediateOrInvalidValue("color", { + type: "intermediate", + value: "linear-gradient(red, blue)", + unit: undefined, + }) + ).toEqual({ + type: "invalid", + value: "linear-gradient(red, blue)", + }); +});