Files
Bogdan Chadkin 3b8c58b435 refactor: use content model to detect rich text (#5109)
Ref https://github.com/webstudio-is/webstudio/issues/3632

Here I finally got rid from "rich-text-child" necessity. With html
elements in the tree it will no longer work so we need a new way to work
with rich text.

Added a few new utilities to content model which detect rich text by
text inside or any textual tags. Span and links can still be detected as
containers rather than children when not surrounded by text and other
textual elements.
2025-04-10 14:16:34 +07:00

126 lines
3.2 KiB
TypeScript

import { test, expect } from "vitest";
import type {
Instance,
StyleDecl,
Styles,
StyleSource,
StyleSourceSelection,
} from "@webstudio-is/sdk";
import { getStyleDeclKey } from "@webstudio-is/sdk";
import {
cloneStyles,
findLocalStyleSourcesWithinInstances,
isDescendantOrSelf,
} from "./tree-utils";
const createStyleSource = (
type: StyleSource["type"],
id: StyleSource["id"]
): StyleSource => {
if (type === "token") {
return {
type,
id,
name: id,
};
}
return {
type,
id,
};
};
const createStyleSourceSelection = (
instanceId: Instance["id"],
values: StyleSource["id"][]
): StyleSourceSelection => {
return {
instanceId,
values,
};
};
const createStyleDecl = (
styleSourceId: string,
breakpointId: string,
value?: string
): StyleDecl => {
return {
styleSourceId,
breakpointId,
property: "width",
value: {
type: "keyword",
value: value ?? "value",
},
};
};
const createStyleDeclPair = (
styleSourceId: string,
breakpointId: string,
state?: string,
value?: string
) => {
return [
getStyleDeclKey({
styleSourceId,
breakpointId,
state,
property: "width",
}),
createStyleDecl(styleSourceId, breakpointId, value),
] as const;
};
test("clone styles with appled new style source ids", () => {
const styles: Styles = new Map([
createStyleDeclPair("styleSource1", "bp1"),
createStyleDeclPair("styleSource2", "bp2"),
createStyleDeclPair("styleSource1", "bp3"),
createStyleDeclPair("styleSource3", "bp4"),
createStyleDeclPair("styleSource1", "bp5"),
createStyleDeclPair("styleSource3", "bp6"),
]);
const clonedStyleSourceIds = new Map<StyleSource["id"], StyleSource["id"]>();
clonedStyleSourceIds.set("styleSource2", "newStyleSource2");
clonedStyleSourceIds.set("styleSource3", "newStyleSource3");
expect(cloneStyles(styles, clonedStyleSourceIds)).toEqual([
createStyleDecl("newStyleSource2", "bp2"),
createStyleDecl("newStyleSource3", "bp4"),
createStyleDecl("newStyleSource3", "bp6"),
]);
});
test("find local style sources within instances", () => {
const instanceIds = new Set(["instance2", "instance4"]);
const styleSources = [
createStyleSource("local", "local1"),
createStyleSource("local", "local2"),
createStyleSource("token", "token3"),
createStyleSource("local", "local4"),
createStyleSource("token", "token5"),
createStyleSource("local", "local6"),
];
const styleSourceSelections = [
createStyleSourceSelection("instance1", ["local1"]),
createStyleSourceSelection("instance2", ["local2"]),
createStyleSourceSelection("instance3", ["token3"]),
createStyleSourceSelection("instance4", ["local4", "token5"]),
createStyleSourceSelection("instance5", ["local6"]),
];
expect(
findLocalStyleSourcesWithinInstances(
styleSources,
styleSourceSelections,
instanceIds
)
).toEqual(new Set(["local2", "local4"]));
});
test("is descendant or self", () => {
expect(isDescendantOrSelf(["1", "2", "3"], ["1", "2", "3"])).toBe(true);
expect(isDescendantOrSelf(["0", "1", "2", "3"], ["1", "2", "3"])).toBe(true);
expect(isDescendantOrSelf(["1", "2", "3"], ["0", "1", "2", "3"])).toBe(false);
});