feat: introduce local-first SVG workbench
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { parseSvgSource } from "../../src/document/source-parser";
|
||||
import { applyToPoint } from "../../src/domain/affine";
|
||||
import { resolveTransformChain } from "../../src/domain/transform-chain";
|
||||
|
||||
function semantic(source: string) {
|
||||
const result = parseSvgSource(source, 1);
|
||||
expect(result.semantic).not.toBeNull();
|
||||
return result.semantic!;
|
||||
}
|
||||
|
||||
describe("ancestor transform chains", () => {
|
||||
it("composes root, ancestor and local transforms in SVG order", () => {
|
||||
const document = semantic(
|
||||
'<svg xmlns="http://www.w3.org/2000/svg" transform="translate(2 3)"><g id="parent" transform="rotate(90)"><path id="child" transform="scale(2 3)" d="M0 0L1 1"/></g></svg>',
|
||||
);
|
||||
const child = [...document.nodes.values()].find(
|
||||
(node) => node.id === "child",
|
||||
)!;
|
||||
const chain = resolveTransformChain(document, child.key);
|
||||
expect(chain.entries).toHaveLength(3);
|
||||
expect(applyToPoint(chain.matrix, { x: 1, y: 1 })).toMatchObject({
|
||||
x: -1,
|
||||
y: 5,
|
||||
});
|
||||
const restored = applyToPoint(
|
||||
chain.inverse!,
|
||||
applyToPoint(chain.matrix, { x: 7, y: -4 }),
|
||||
);
|
||||
expect(restored.x).toBeCloseTo(7);
|
||||
expect(restored.y).toBeCloseTo(-4);
|
||||
});
|
||||
|
||||
it("refuses deterministic coordinate editing through singular or CSS transforms", () => {
|
||||
const document = semantic(
|
||||
'<svg xmlns="http://www.w3.org/2000/svg"><g transform="scale(1 0)"><path id="p" style="transform: rotate(2deg)" d="M0 0L1 1"/></g></svg>',
|
||||
);
|
||||
const path = [...document.nodes.values()].find((node) => node.id === "p")!;
|
||||
const chain = resolveTransformChain(document, path.key);
|
||||
expect(chain.inverse).toBeNull();
|
||||
expect(chain.diagnostics).toContainEqual(
|
||||
expect.stringContaining("CSS transforms"),
|
||||
);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user