feat: introduce local-first SVG workbench
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { parseSvgSource } from "../../src/document/source-parser";
|
||||
import {
|
||||
createSelectedSvgSource,
|
||||
createSymbolSpriteSource,
|
||||
} from "../../src/export/derived-svg-export";
|
||||
|
||||
function semantic(source: string) {
|
||||
const parsed = parseSvgSource(source, 1);
|
||||
if (!parsed.semantic) throw new Error("Fixture did not parse");
|
||||
return parsed.semantic;
|
||||
}
|
||||
|
||||
describe("derived SVG exports", () => {
|
||||
it("retains selected ancestry and definitions while using a safe projection", () => {
|
||||
const document = semantic(`
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
|
||||
<defs><linearGradient id="paint"><stop offset="1"/></linearGradient></defs>
|
||||
<g transform="translate(2 3)"><path id="keep" d="M0 0L1 1" fill="url(#paint)"/></g>
|
||||
<circle id="remove" r="4"/>
|
||||
<script>alert(1)</script>
|
||||
</svg>`);
|
||||
const selected = document.order.find(
|
||||
(key) => document.nodes.get(key)?.id === "keep",
|
||||
)!;
|
||||
const result = createSelectedSvgSource(document, [selected]);
|
||||
|
||||
expect(result.source).toContain("translate(2 3)");
|
||||
expect(result.source).toContain("linearGradient");
|
||||
expect(result.source).toContain('id="keep"');
|
||||
expect(result.source).not.toContain('id="remove"');
|
||||
expect(result.source).not.toContain("script");
|
||||
expect(result.source).not.toContain("data-svg-tools-node");
|
||||
});
|
||||
|
||||
it("exports existing symbols and shared definitions as a sprite", () => {
|
||||
const document = semantic(`
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
|
||||
<defs>
|
||||
<linearGradient id="paint"><stop offset="1"/></linearGradient>
|
||||
<symbol id="mark" viewBox="0 0 4 4"><path d="M0 0L4 4"/></symbol>
|
||||
</defs>
|
||||
</svg>`);
|
||||
const result = createSymbolSpriteSource(document, []);
|
||||
|
||||
expect(result.source).toContain('<symbol id="mark"');
|
||||
expect(result.source).toContain("linearGradient");
|
||||
expect(result.source.match(/<symbol/gu)).toHaveLength(1);
|
||||
expect(result.source).not.toContain("data-svg-tools-node");
|
||||
});
|
||||
|
||||
it("wraps a selection in a symbol when the source has no symbols", () => {
|
||||
const document = semantic(`
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 10">
|
||||
<path id="arrow" d="M0 5L10 5"/>
|
||||
</svg>`);
|
||||
const selected = document.order.find(
|
||||
(key) => document.nodes.get(key)?.id === "arrow",
|
||||
)!;
|
||||
const result = createSymbolSpriteSource(document, [selected]);
|
||||
|
||||
expect(result.source).toContain('id="symbol-arrow"');
|
||||
expect(result.source).toContain('id="arrow"');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user