mirror of
https://github.com/webstudio-is/webstudio.git
synced 2026-11-08 13:05:08 +09:00
add tests for parsing css value input
This commit is contained in:
1 parent
49187a07c4
commit
8748d93eb6
3 files changed
+134
-20
No files matched your search
@@ -0,0 +1,120 @@
|
||||
import { parseCssValue } from "./parse-css-value";
|
||||
|
||||
describe("Parse CSS value", () => {
|
||||
describe("number value", () => {
|
||||
test("unitless", () => {
|
||||
expect(parseCssValue("lineHeight", "10")).toEqual({
|
||||
type: "unit",
|
||||
unit: "number",
|
||||
value: 10,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("unit value", () => {
|
||||
test("with unit", () => {
|
||||
expect(parseCssValue("width", "10px")).toEqual({
|
||||
type: "unit",
|
||||
unit: "px",
|
||||
value: 10,
|
||||
});
|
||||
});
|
||||
|
||||
test("with default unit", () => {
|
||||
expect(parseCssValue("width", "10", "px")).toEqual({
|
||||
type: "unit",
|
||||
unit: "px",
|
||||
value: 10,
|
||||
});
|
||||
});
|
||||
|
||||
test("with unit and default unit", () => {
|
||||
expect(parseCssValue("width", "10px", "rem")).toEqual({
|
||||
type: "unit",
|
||||
unit: "px",
|
||||
value: 10,
|
||||
});
|
||||
});
|
||||
|
||||
test("empty input", () => {
|
||||
expect(parseCssValue("width", "")).toEqual({
|
||||
type: "invalid",
|
||||
value: "",
|
||||
});
|
||||
});
|
||||
|
||||
test("empty input with default unit", () => {
|
||||
expect(parseCssValue("width", "", "px")).toEqual({
|
||||
type: "invalid",
|
||||
value: "",
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("keyword value", () => {
|
||||
test("keyword", () => {
|
||||
expect(parseCssValue("width", "auto")).toEqual({
|
||||
type: "keyword",
|
||||
value: "auto",
|
||||
});
|
||||
});
|
||||
|
||||
test("keyword with unit", () => {
|
||||
expect(parseCssValue("width", "autopx")).toEqual({
|
||||
type: "keyword",
|
||||
value: "autopx",
|
||||
});
|
||||
});
|
||||
|
||||
test("incomplete", () => {
|
||||
// This will return invalid unit when `CSSStyleValue.parse` is available
|
||||
expect(parseCssValue("width", "10p")).toEqual({
|
||||
type: "unit",
|
||||
unit: "number",
|
||||
value: 10,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("math expression", () => {
|
||||
test("addition with unit", () => {
|
||||
expect(parseCssValue("width", "10+1px")).toEqual({
|
||||
type: "unit",
|
||||
unit: "px",
|
||||
value: 11,
|
||||
});
|
||||
});
|
||||
|
||||
test("addition without unit", () => {
|
||||
expect(parseCssValue("width", "10+1", "px")).toEqual({
|
||||
type: "unit",
|
||||
unit: "px",
|
||||
value: 11,
|
||||
});
|
||||
});
|
||||
|
||||
test("subtraction with unit", () => {
|
||||
expect(parseCssValue("width", "10-1px")).toEqual({
|
||||
type: "unit",
|
||||
unit: "px",
|
||||
value: 9,
|
||||
});
|
||||
});
|
||||
|
||||
test("multiplication with unit", () => {
|
||||
expect(parseCssValue("width", "2*2px")).toEqual({
|
||||
type: "unit",
|
||||
unit: "px",
|
||||
value: 4,
|
||||
});
|
||||
});
|
||||
|
||||
test("division with unit", () => {
|
||||
expect(parseCssValue("width", "4/2px")).toEqual({
|
||||
type: "unit",
|
||||
unit: "px",
|
||||
value: 2,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
+6
-15
@@ -1,6 +1,6 @@
|
||||
import hyphenate from "hyphenate-style-name";
|
||||
import { units } from "@webstudio-is/sdk";
|
||||
import type { Style, StyleProperty, StyleValue, Unit } from "@webstudio-is/sdk";
|
||||
import type { StyleProperty, StyleValue, Unit } from "@webstudio-is/sdk";
|
||||
|
||||
const unitRegex = new RegExp(`${units.join("|")}`);
|
||||
|
||||
@@ -55,10 +55,10 @@ const evaluate = (input: string, parsedUnit: [Unit] | null) => {
|
||||
// - 10px > px as unit
|
||||
// - empty string
|
||||
// - a keyword
|
||||
export const parseValue = (
|
||||
export const parseCssValue = (
|
||||
property: StyleProperty,
|
||||
input: string,
|
||||
style: Style
|
||||
defaultUnit?: Unit
|
||||
): StyleValue => {
|
||||
const invalidValue = {
|
||||
type: "invalid",
|
||||
@@ -84,20 +84,11 @@ export const parseValue = (
|
||||
return invalidValue;
|
||||
}
|
||||
|
||||
const previousValue = style[property];
|
||||
// If user didn't enter a unit, use the previous known unit otherwise fallback to px.
|
||||
const defaultUnit: Unit =
|
||||
previousValue !== undefined && "unit" in previousValue
|
||||
? previousValue.unit
|
||||
: "number";
|
||||
const [unit] = parsedUnit || [defaultUnit];
|
||||
const fallbackUnit: Unit = defaultUnit ?? "number";
|
||||
const [unit] = parsedUnit || [fallbackUnit];
|
||||
|
||||
if (
|
||||
isValid(property, input) ||
|
||||
isValid(property, input + unit) ||
|
||||
isValid(property, number) ||
|
||||
isValid(property, number + unit)
|
||||
) {
|
||||
if (isValid(property, number) || isValid(property, number + unit)) {
|
||||
return {
|
||||
type: "unit",
|
||||
unit,
|
||||
@@ -3,7 +3,7 @@ import type { SelectedInstanceData, StyleUpdates } from "~/shared/component";
|
||||
import { type Style, type StyleProperty } from "@webstudio-is/sdk";
|
||||
import { type Publish } from "~/designer/features/canvas-iframe";
|
||||
import { useRootInstance } from "../../shared/nano-values";
|
||||
import { parseValue } from "./parse-value";
|
||||
import { parseCssValue } from "./parse-css-value";
|
||||
import { getInheritedStyle, type InheritedStyle } from "./get-inherited-style";
|
||||
|
||||
type UseStyleData = {
|
||||
@@ -64,13 +64,16 @@ export const useStyleData = ({
|
||||
const setProperty: SetProperty = (property) => {
|
||||
return (input, options = { isEphemeral: false }) => {
|
||||
if (currentStyle === undefined) return;
|
||||
const value = parseValue(property, input, currentStyle);
|
||||
if (value.type !== "invalid") {
|
||||
const updates = [{ property, value }];
|
||||
const currentValue = currentStyle[property];
|
||||
const defaultUnit =
|
||||
currentValue?.type === "unit" ? currentValue?.unit : undefined;
|
||||
const nextValue = parseCssValue(property, input, defaultUnit);
|
||||
if (nextValue.type !== "invalid") {
|
||||
const updates = [{ property, value: nextValue }];
|
||||
const type = options.isEphemeral ? "preview" : "update";
|
||||
publishUpdates(type, updates);
|
||||
}
|
||||
setCurrentStyle({ ...currentStyle, [property]: value });
|
||||
setCurrentStyle({ ...currentStyle, [property]: nextValue });
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
Reference in new issue
Block a user