clone

a browser-first diagram editor with live svg previews, local drafts and encrypted, accountless sharing

docs: document SVG normalization contracts

Dami committed e4d5143
Add the public normalization, appearance, metadata, and versioning guide. Link it from style navigation and generated renderer references, and align the engineering contract with current capabilities.
commit
e4d514384f74d4d04eb89111910b79e9fb453212
parent
8d2ee70386f6690e1f1c0bb9de7392b79705a695
author
Dami <dami.etoile@gmail.com>
38 files changed, +243 -11
Mapps/docs/docs/style/presentation.md6+-
Aapps/docs/docs/style/svg-normalization.md163++++++++++++++++++++++++++++++
Mapps/docs/docs/style/types/actdiag.md1+
Mapps/docs/docs/style/types/blockdiag.md1+
Mapps/docs/docs/style/types/bpmn.md1+
Mapps/docs/docs/style/types/bytefield.md1+
Mapps/docs/docs/style/types/c4plantuml.md1+
Mapps/docs/docs/style/types/d2.md1+
Mapps/docs/docs/style/types/dbml.md1+
Mapps/docs/docs/style/types/diagramsnet.md1+
Mapps/docs/docs/style/types/ditaa.md1+
Mapps/docs/docs/style/types/erd.md1+
Mapps/docs/docs/style/types/excalidraw.md1+
Mapps/docs/docs/style/types/goat.md1+
Mapps/docs/docs/style/types/graphviz.md1+
Mapps/docs/docs/style/types/mermaid.md1+
Mapps/docs/docs/style/types/nomnoml.md1+
Mapps/docs/docs/style/types/nwdiag.md1+
Mapps/docs/docs/style/types/packetdiag.md1+
Mapps/docs/docs/style/types/pikchr.md1+
Mapps/docs/docs/style/types/plantuml.md1+
Mapps/docs/docs/style/types/rackdiag.md1+
Mapps/docs/docs/style/types/seqdiag.md1+
Mapps/docs/docs/style/types/structurizr.md1+
Mapps/docs/docs/style/types/svgbob.md1+
Mapps/docs/docs/style/types/symbolator.md1+
Mapps/docs/docs/style/types/tikz.md1+
Mapps/docs/docs/style/types/umlet.md1+
Mapps/docs/docs/style/types/vega.md1+
Mapps/docs/docs/style/types/vegalite.md1+
Mapps/docs/docs/style/types/wavedrom.md1+
Mapps/docs/docs/style/types/wireviz.md1+
Mapps/docs/scripts/check-docs.mjs1+
Mapps/docs/scripts/generate-docs.mjs4+-
Mapps/docs/sidebars.js5+-
Mapps/docs/static/llms-full.txt30++++++
Mapps/docs/static/llms.txt1+
Mdocs/svg-normalization.md14+-
M apps/docs/docs/style/presentation.md +5 -1
A apps/docs/docs/style/svg-normalization.md +163 -0
@@ -0,0 +1,163 @@
1+---2+id: svg-normalization3+title: SVG normalization and version contracts4+description: Understand normalized SVG, renderer version selection, capability metadata, and consumer guarantees.5+sidebar_position: 26+---7+8+# SVG normalization and version contracts9+10+Diagram.zip accepts SVG from renderers with different structures, palettes, and release cycles. A shared pipeline turns that output into safe, predictable artifacts.11+12+```text13+renderer SVG14+ -> sanitization15+ -> canonical normalization16+ -> appearance materialization17+ -> final SVG18+```19+20+The renderer owns source interpretation and layout. Later stages preserve diagram geometry while adding safety, semantic paint roles, and optional presentation bounds.21+22+## Artifact stages23+24+| Stage | Contract |25+| --- | --- |26+| Renderer SVG | Output from one identified renderer build. |27+| Canonical SVG | Sanitized SVG with normalized metadata, bounds, and supported semantic roles. |28+| Materialized SVG | Canonical geometry combined with one explicit appearance, palette, and optional frame. |29+30+Materialization does not run the renderer again. Light, dark, transparent, and framed artifacts reuse the same canonical geometry.31+32+Framed appearances may expand the outer view box for standard padding and the frame. They do not reroute connectors or reflow labels.33+34+## Appearance contract35+36+The appearance name is a closed enum:37+38+```text39+raw40+auto-transparent41+light-transparent42+dark-transparent43+auto-framed44+light-framed45+dark-framed46+```47+48+`raw` preserves the safe renderer appearance. It does not promise byte-for-byte preservation because sanitization and deterministic serialization still apply.49+50+Automatic appearances embed both palettes and select one with `prefers-color-scheme`. They do not depend on styles from the embedding page.51+52+Transparent appearances omit the outer canvas. Diagram objects may retain opaque surfaces when those surfaces are required for readable labels.53+54+Framed appearances add a matching canvas, standard padding, and a border. They remain readable independently of the embedding page.55+56+The editor offers only appearances advertised by the active profile. `raw` is always available.57+58+## Capability levels59+60+| Conformance | Meaning | Expected appearance support |61+| --- | --- | --- |62+| `semantic` | Stable renderer meaning maps directly to shared visual roles. | All audited appearances. |63+| `adaptive` | Known structure and neutral paint adapt while authored color remains intact. | All audited appearances. |64+| `presentation-only` | The authored drawing stays unchanged while Diagram.zip owns the outer presentation. | Raw and audited framed appearances. |65+| `raw` | The SVG is safe, but no themed adaptation is claimed. | Raw only. |66+67+An authored non-neutral color may remain unchanged in a semantic or adaptive profile. Normalization does not erase meaningful source styling.68+69+## How renderer versions select a profile70+71+Each engine catalog entry pins a renderer version and an audited normalization profile. Compatibility belongs to that tested pair, not only to the engine name.72+73+HTTP renderers identify their output with these response headers:74+75+| Header | Purpose |76+| --- | --- |77+| `X-Diagram-Engine-Version` | Identifies the underlying engine release. |78+| `X-Renderer-Build` | Identifies the Diagram.zip renderer build. |79+80+Browser renderers provide the same version identity from their catalog entry. Diagram.zip uses this identity before it assigns semantic roles.81+82+An unknown or upgraded renderer build does not inherit an older profile automatically. It falls back to `safe-raw-1`, which supports only `raw`.83+84+This fail-closed behavior prevents rules for one renderer structure from changing unrelated elements in another structure.85+86+Version identifiers are opaque contract values. Consumers should compare complete values and must not infer compatibility from embedded numbers.87+88+The [renderer catalog](https://diagram.zip/render/v1/catalog) reports every engine version, known loss, and active normalization capability.89+90+## Independently versioned contracts91+92+| Contract | Example identifier | Changes when |93+| --- | --- | --- |94+| Canonical schema | `1` | The canonical SVG structure changes incompatibly. |95+| Normalizer | `svg-normalizer-2` | Sanitization, annotation, or serialization behavior changes. |96+| Profile | `neutral-svg-semantic-2` | Renderer recognition or role assignment changes. |97+| Palette | `diagramzip-palette-1` | Materialized role colors change. |98+| Materializer | `svg-materializer-2` | Appearance rules, padding, frame, or output assembly changes. |99+| Renderer | Catalog version and build | Engine output or its integration changes. |100+101+These versions advance independently. A renderer upgrade does not require a schema change, and a palette update does not require new geometry.102+103+Any component that changes pixels or bounds must change the relevant build identifier. Cache identity must include every component that affected the artifact.104+105+## Root SVG metadata106+107+Canonical and materialized SVG expose their active contract through `data-dz-*` attributes on the root element.108+109+| Attribute | Meaning |110+| --- | --- |111+| `data-dz-schema` | Canonical SVG schema. |112+| `data-dz-normalizer` | Normalizer build. |113+| `data-dz-engine` | Renderer engine identifier. |114+| `data-dz-profile` | Selected normalization profile. |115+| `data-dz-palette` | `renderer` for raw SVG, or the selected Diagram.zip palette build. |116+| `data-dz-appearance` | Materialized appearance. |117+| `data-dz-conformance` | Active capability level. |118+| `data-dz-appearances` | Supported non-raw appearances, separated by spaces. |119+| `data-dz-bounds` | Canonical diagram bounds as `x y width height`. |120+| `data-dz-materializer` | Materializer build, present after non-raw materialization. |121+122+Normalized elements may also use `data-dz-fill`, `data-dz-stroke`, and `data-dz-role`. These attributes separate semantic intent from concrete palette values.123+124+```xml125+<svg126+ data-dz-schema="1"127+ data-dz-normalizer="svg-normalizer-2"128+ data-dz-engine="mermaid"129+ data-dz-profile="neutral-svg-semantic-2"130+ data-dz-palette="renderer"131+ data-dz-appearance="raw"132+ data-dz-conformance="adaptive"133+ data-dz-appearances="auto-transparent light-transparent dark-transparent auto-framed light-framed dark-framed"134+ data-dz-bounds="0 0 320 180">135+</svg>136+```137+138+The identifiers above are examples. Inspect the artifact or catalog instead of hard-coding them.139+140+Consumers should treat `data-dz-appearances` as an allowlist. Adding an unsupported value by hand does not create a supported artifact.141+142+## Consumer guarantees143+144+A normalized SVG has these guarantees:145+146+- It is valid, sanitized, deterministic SVG with no unapproved network dependency.147+- It is self-contained after materialization and does not require embedding-page CSS.148+- It preserves renderer geometry, except for presentation bounds added by a frame.149+- It applies palette rules only to elements assigned a supported semantic role.150+- It preserves authored paint when the profile cannot adapt that paint honestly.151+- It rejects unsupported appearance materialization instead of applying heuristic theming.152+153+Cache keys must include source identity, renderer options, renderer builds, schema, normalizer, profile, palette, materializer, and appearance.154+155+Do not key a cache only by source and engine name. That can return artifacts created under an incompatible renderer or presentation contract.156+157+## Upgrade expectations158+159+A renderer upgrade is a new output contract until the representative test corpus passes. The existing profile may then add compatibility, or a new profile may replace it.160+161+Tests cover safety, determinism, raw fidelity, geometry stability, contrast, transparent canvases, frames, authored colors, and hostile resource attempts.162+163+See the [full engineering contract](https://github.com/FelineStateMachine/diagramzip/blob/main/docs/svg-normalization.md) for profile design, semantic roles, validation rules, and caching details.
M apps/docs/docs/style/types/actdiag.md +1 -0
M apps/docs/docs/style/types/blockdiag.md +1 -0
M apps/docs/docs/style/types/bpmn.md +1 -0
M apps/docs/docs/style/types/bytefield.md +1 -0
M apps/docs/docs/style/types/c4plantuml.md +1 -0
M apps/docs/docs/style/types/d2.md +1 -0
M apps/docs/docs/style/types/dbml.md +1 -0
M apps/docs/docs/style/types/diagramsnet.md +1 -0
M apps/docs/docs/style/types/ditaa.md +1 -0
M apps/docs/docs/style/types/erd.md +1 -0
M apps/docs/docs/style/types/excalidraw.md +1 -0
M apps/docs/docs/style/types/goat.md +1 -0
M apps/docs/docs/style/types/graphviz.md +1 -0
M apps/docs/docs/style/types/mermaid.md +1 -0
M apps/docs/docs/style/types/nomnoml.md +1 -0
M apps/docs/docs/style/types/nwdiag.md +1 -0
M apps/docs/docs/style/types/packetdiag.md +1 -0
M apps/docs/docs/style/types/pikchr.md +1 -0
M apps/docs/docs/style/types/plantuml.md +1 -0
M apps/docs/docs/style/types/rackdiag.md +1 -0
M apps/docs/docs/style/types/seqdiag.md +1 -0
M apps/docs/docs/style/types/structurizr.md +1 -0
M apps/docs/docs/style/types/svgbob.md +1 -0
M apps/docs/docs/style/types/symbolator.md +1 -0
M apps/docs/docs/style/types/tikz.md +1 -0
M apps/docs/docs/style/types/umlet.md +1 -0
M apps/docs/docs/style/types/vega.md +1 -0
M apps/docs/docs/style/types/vegalite.md +1 -0
M apps/docs/docs/style/types/wavedrom.md +1 -0
M apps/docs/docs/style/types/wireviz.md +1 -0
M apps/docs/scripts/check-docs.mjs +1 -0
M apps/docs/scripts/generate-docs.mjs +2 -2
@@ -111,7 +111,7 @@ function stylePage(type) {
111111 return frontmatter(type, 'style', `Style a ${type.label} diagram in diagram.zip.`) +112112 `# Style ${type.label}\n\n${type.styleSummary}\n\nStart with the [general presentation settings](/style/presentation). Choose a shared appearance, or use the renderer defaults with custom canvas controls.\n\n## Source controls\n\n${lines(type.sourceStyle).map((item) => `- ${item}`).join('\n')}\n${rendererOptions}` +113113 (limitations.length ? `## Limitations\n\n${limitations.map((item) => `- ${item}`).join('\n')}\n\n` : '') +114-`## Related pages\n\n- [Create ${article} ${type.label} diagram](${syntaxPath(type.id)})\n- [General presentation settings](/style/presentation)\n- [Open ${type.label} in the editor](${editorLink(type.id)})\n`114+`## Related pages\n\n- [Create ${article} ${type.label} diagram](${syntaxPath(type.id)})\n- [General presentation settings](/style/presentation)\n- [SVG normalization and version contracts](/style/svg-normalization)\n- [Open ${type.label} in the editor](${editorLink(type.id)})\n`115115 }116116 117117 const catalog = diagramTypes.map((type) => ({
@@ -146,7 +146,7 @@ await Promise.all(diagramTypes.flatMap((type) => [
146146 await Promise.all(diagramSkills.map(({ id }) => cp(join(skillsDir, id), join(publicSkillsDir, id), { recursive: true })))147147 await writeFile(join(staticDir, 'diagram-types.json'), `${JSON.stringify({ version: 1, diagramTypes: catalog }, null, 2)}\n`)148148 await writeFile(join(staticDir, 'diagram-skills.json'), `${JSON.stringify({ version: 1, groups: skillGroups, skills: skillCatalog, standards: standardsSupport }, null, 2)}\n`)149-await writeFile(join(staticDir, 'llms.txt'), `# diagram.zip documentation\n\n> Choose the semantic story first, then choose a renderer and source format.\n\n- [Diagram routing skill](https://docs.diagram.zip/skills/diagramming/SKILL.md): Select a diagram family from the reader's question.\n- [Machine-readable semantic catalog](https://docs.diagram.zip/diagram-skills.json): Inspect every skill, use case, exclusion, role, and invocation constraint.\n\n${skillIndex()}\n\n## Renderer and source formats\n\n${diagramTypes.map((type) => `- [${type.label} syntax](https://docs.diagram.zip${syntaxPath(type.id)}/): Create ${articleFor(type.label)} ${type.label} diagram. [Style](https://docs.diagram.zip${stylePath(type.id)}/).`).join('\n')}\n\n## General pages\n\n- [General presentation](https://docs.diagram.zip/style/presentation/)\n- [Share a diagram](https://docs.diagram.zip/collaboration/sharing/)\n- [Password encryption](https://docs.diagram.zip/collaboration/encryption/)\n- [Working state and saved state](https://docs.diagram.zip/collaboration/working-and-saved-state/)\n\n## Structured catalogs\n\n- [diagram-skills.json](https://docs.diagram.zip/diagram-skills.json)\n- [diagram-types.json](https://docs.diagram.zip/diagram-types.json)\n- [Full renderer text reference](https://docs.diagram.zip/llms-full.txt)\n- [Source repository](https://github.com/FelineStateMachine/diagramzip)\n`)149+await writeFile(join(staticDir, 'llms.txt'), `# diagram.zip documentation\n\n> Choose the semantic story first, then choose a renderer and source format.\n\n- [Diagram routing skill](https://docs.diagram.zip/skills/diagramming/SKILL.md): Select a diagram family from the reader's question.\n- [Machine-readable semantic catalog](https://docs.diagram.zip/diagram-skills.json): Inspect every skill, use case, exclusion, role, and invocation constraint.\n\n${skillIndex()}\n\n## Renderer and source formats\n\n${diagramTypes.map((type) => `- [${type.label} syntax](https://docs.diagram.zip${syntaxPath(type.id)}/): Create ${articleFor(type.label)} ${type.label} diagram. [Style](https://docs.diagram.zip${stylePath(type.id)}/).`).join('\n')}\n\n## General pages\n\n- [General presentation](https://docs.diagram.zip/style/presentation/)\n- [SVG normalization and version contracts](https://docs.diagram.zip/style/svg-normalization/)\n- [Share a diagram](https://docs.diagram.zip/collaboration/sharing/)\n- [Password encryption](https://docs.diagram.zip/collaboration/encryption/)\n- [Working state and saved state](https://docs.diagram.zip/collaboration/working-and-saved-state/)\n\n## Structured catalogs\n\n- [diagram-skills.json](https://docs.diagram.zip/diagram-skills.json)\n- [diagram-types.json](https://docs.diagram.zip/diagram-types.json)\n- [Full renderer text reference](https://docs.diagram.zip/llms-full.txt)\n- [Source repository](https://github.com/FelineStateMachine/diagramzip)\n`)150150 await writeFile(join(staticDir, 'llms-full.txt'), `# diagram.zip documentation\n\n${fullText()}`)151151 152152 console.log(`Generated ${diagramTypes.length} renderer guides, ${diagramSkills.length} semantic skill packages, and machine-readable indexes.`)
M apps/docs/sidebars.js +4 -1
M apps/docs/static/llms-full.txt +30 -0
@@ -79,6 +79,7 @@ Start with the [general presentation settings](/style/presentation). Choose a sh
7979 8080 - [Create a PlantUML diagram](/create/types/plantuml)8181 - [General presentation settings](/style/presentation)82+- [SVG normalization and version contracts](/style/svg-normalization)8283 - [Open PlantUML in the editor](https://diagram.zip/?type=plantuml)8384 8485 ---
@@ -169,6 +170,7 @@ Start with the [general presentation settings](/style/presentation). Choose a sh
169170 170171 - [Create a Mermaid diagram](/create/types/mermaid)171172 - [General presentation settings](/style/presentation)173+- [SVG normalization and version contracts](/style/svg-normalization)172174 - [Open Mermaid in the editor](https://diagram.zip/?type=mermaid)173175 174176 ---
@@ -255,6 +257,7 @@ Start with the [general presentation settings](/style/presentation). Choose a sh
255257 256258 - [Create a Graphviz diagram](/create/types/graphviz)257259 - [General presentation settings](/style/presentation)260+- [SVG normalization and version contracts](/style/svg-normalization)258261 - [Open Graphviz in the editor](https://diagram.zip/?type=graphviz)259262 260263 ---
@@ -338,6 +341,7 @@ Start with the [general presentation settings](/style/presentation). Choose a sh
338341 339342 - [Create a D2 diagram](/create/types/d2)340343 - [General presentation settings](/style/presentation)344+- [SVG normalization and version contracts](/style/svg-normalization)341345 - [Open D2 in the editor](https://diagram.zip/?type=d2)342346 343347 ---
@@ -421,6 +425,7 @@ Start with the [general presentation settings](/style/presentation). Choose a sh
421425 422426 - [Create a C4 PlantUML diagram](/create/types/c4plantuml)423427 - [General presentation settings](/style/presentation)428+- [SVG normalization and version contracts](/style/svg-normalization)424429 - [Open C4 PlantUML in the editor](https://diagram.zip/?type=c4plantuml)425430 426431 ---
@@ -503,6 +508,7 @@ Start with the [general presentation settings](/style/presentation). Choose a sh
503508 504509 - [Create a BlockDiag diagram](/create/types/blockdiag)505510 - [General presentation settings](/style/presentation)511+- [SVG normalization and version contracts](/style/svg-normalization)506512 - [Open BlockDiag in the editor](https://diagram.zip/?type=blockdiag)507513 508514 ---
@@ -585,6 +591,7 @@ Start with the [general presentation settings](/style/presentation). Choose a sh
585591 586592 - [Create a SeqDiag diagram](/create/types/seqdiag)587593 - [General presentation settings](/style/presentation)594+- [SVG normalization and version contracts](/style/svg-normalization)588595 - [Open SeqDiag in the editor](https://diagram.zip/?type=seqdiag)589596 590597 ---
@@ -672,6 +679,7 @@ Start with the [general presentation settings](/style/presentation). Choose a sh
672679 673680 - [Create an ActDiag diagram](/create/types/actdiag)674681 - [General presentation settings](/style/presentation)682+- [SVG normalization and version contracts](/style/svg-normalization)675683 - [Open ActDiag in the editor](https://diagram.zip/?type=actdiag)676684 677685 ---
@@ -756,6 +764,7 @@ Start with the [general presentation settings](/style/presentation). Choose a sh
756764 757765 - [Create a NwDiag diagram](/create/types/nwdiag)758766 - [General presentation settings](/style/presentation)767+- [SVG normalization and version contracts](/style/svg-normalization)759768 - [Open NwDiag in the editor](https://diagram.zip/?type=nwdiag)760769 761770 ---
@@ -839,6 +848,7 @@ Start with the [general presentation settings](/style/presentation). Choose a sh
839848 840849 - [Create a PacketDiag diagram](/create/types/packetdiag)841850 - [General presentation settings](/style/presentation)851+- [SVG normalization and version contracts](/style/svg-normalization)842852 - [Open PacketDiag in the editor](https://diagram.zip/?type=packetdiag)843853 844854 ---
@@ -922,6 +932,7 @@ Start with the [general presentation settings](/style/presentation). Choose a sh
922932 923933 - [Create a RackDiag diagram](/create/types/rackdiag)924934 - [General presentation settings](/style/presentation)935+- [SVG normalization and version contracts](/style/svg-normalization)925936 - [Open RackDiag in the editor](https://diagram.zip/?type=rackdiag)926937 927938 ---
@@ -1000,6 +1011,7 @@ Start with the [general presentation settings](/style/presentation). Choose a sh
10001011 10011012 - [Create a BPMN diagram](/create/types/bpmn)10021013 - [General presentation settings](/style/presentation)1014+- [SVG normalization and version contracts](/style/svg-normalization)10031015 - [Open BPMN in the editor](https://diagram.zip/?type=bpmn)10041016 10051017 ---
@@ -1082,6 +1094,7 @@ Start with the [general presentation settings](/style/presentation). Choose a sh
10821094 10831095 - [Create a Bytefield diagram](/create/types/bytefield)10841096 - [General presentation settings](/style/presentation)1097+- [SVG normalization and version contracts](/style/svg-normalization)10851098 - [Open Bytefield in the editor](https://diagram.zip/?type=bytefield)10861099 10871100 ---
@@ -1162,6 +1175,7 @@ Start with the [general presentation settings](/style/presentation). Choose a sh
11621175 11631176 - [Create a DBML diagram](/create/types/dbml)11641177 - [General presentation settings](/style/presentation)1178+- [SVG normalization and version contracts](/style/svg-normalization)11651179 - [Open DBML in the editor](https://diagram.zip/?type=dbml)11661180 11671181 ---
@@ -1243,6 +1257,7 @@ Start with the [general presentation settings](/style/presentation). Choose a sh
12431257 12441258 - [Create a Diagrams.net diagram](/create/types/diagramsnet)12451259 - [General presentation settings](/style/presentation)1260+- [SVG normalization and version contracts](/style/svg-normalization)12461261 - [Open Diagrams.net in the editor](https://diagram.zip/?type=diagramsnet)12471262 12481263 ---
@@ -1329,6 +1344,7 @@ Start with the [general presentation settings](/style/presentation). Choose a sh
13291344 13301345 - [Create a Ditaa diagram](/create/types/ditaa)13311346 - [General presentation settings](/style/presentation)1347+- [SVG normalization and version contracts](/style/svg-normalization)13321348 - [Open Ditaa in the editor](https://diagram.zip/?type=ditaa)13331349 13341350 ---
@@ -1407,6 +1423,7 @@ Start with the [general presentation settings](/style/presentation). Choose a sh
14071423 14081424 - [Create an ERD diagram](/create/types/erd)14091425 - [General presentation settings](/style/presentation)1426+- [SVG normalization and version contracts](/style/svg-normalization)14101427 - [Open ERD in the editor](https://diagram.zip/?type=erd)14111428 14121429 ---
@@ -1486,6 +1503,7 @@ Start with the [general presentation settings](/style/presentation). Choose a sh
14861503 14871504 - [Create an Excalidraw diagram](/create/types/excalidraw)14881505 - [General presentation settings](/style/presentation)1506+- [SVG normalization and version contracts](/style/svg-normalization)14891507 - [Open Excalidraw in the editor](https://diagram.zip/?type=excalidraw)14901508 14911509 ---
@@ -1588,6 +1606,7 @@ Start with the [general presentation settings](/style/presentation). Choose a sh
15881606 15891607 - [Create a GoAT diagram](/create/types/goat)15901608 - [General presentation settings](/style/presentation)1609+- [SVG normalization and version contracts](/style/svg-normalization)15911610 - [Open GoAT in the editor](https://diagram.zip/?type=goat)15921611 15931612 ---
@@ -1668,6 +1687,7 @@ Start with the [general presentation settings](/style/presentation). Choose a sh
16681687 16691688 - [Create a Nomnoml diagram](/create/types/nomnoml)16701689 - [General presentation settings](/style/presentation)1690+- [SVG normalization and version contracts](/style/svg-normalization)16711691 - [Open Nomnoml in the editor](https://diagram.zip/?type=nomnoml)16721692 16731693 ---
@@ -1740,6 +1760,7 @@ Start with the [general presentation settings](/style/presentation). Choose a sh
17401760 17411761 - [Create a Pikchr diagram](/create/types/pikchr)17421762 - [General presentation settings](/style/presentation)1763+- [SVG normalization and version contracts](/style/svg-normalization)17431764 - [Open Pikchr in the editor](https://diagram.zip/?type=pikchr)17441765 17451766 ---
@@ -1828,6 +1849,7 @@ Start with the [general presentation settings](/style/presentation). Choose a sh
18281849 18291850 - [Create a Structurizr diagram](/create/types/structurizr)18301851 - [General presentation settings](/style/presentation)1852+- [SVG normalization and version contracts](/style/svg-normalization)18311853 - [Open Structurizr in the editor](https://diagram.zip/?type=structurizr)18321854 18331855 ---
@@ -1912,6 +1934,7 @@ Start with the [general presentation settings](/style/presentation). Choose a sh
19121934 19131935 - [Create a Svgbob diagram](/create/types/svgbob)19141936 - [General presentation settings](/style/presentation)1937+- [SVG normalization and version contracts](/style/svg-normalization)19151938 - [Open Svgbob in the editor](https://diagram.zip/?type=svgbob)19161939 19171940 ---
@@ -1999,6 +2022,7 @@ Start with the [general presentation settings](/style/presentation). Choose a sh
19992022 20002023 - [Create a Symbolator diagram](/create/types/symbolator)20012024 - [General presentation settings](/style/presentation)2025+- [SVG normalization and version contracts](/style/svg-normalization)20022026 - [Open Symbolator in the editor](https://diagram.zip/?type=symbolator)20032027 20042028 ---
@@ -2074,6 +2098,7 @@ Start with the [general presentation settings](/style/presentation). Choose a sh
20742098 20752099 - [Create a TikZ diagram](/create/types/tikz)20762100 - [General presentation settings](/style/presentation)2101+- [SVG normalization and version contracts](/style/svg-normalization)20772102 - [Open TikZ in the editor](https://diagram.zip/?type=tikz)20782103 20792104 ---
@@ -2152,6 +2177,7 @@ Start with the [general presentation settings](/style/presentation). Choose a sh
21522177 21532178 - [Create an UMLet diagram](/create/types/umlet)21542179 - [General presentation settings](/style/presentation)2180+- [SVG normalization and version contracts](/style/svg-normalization)21552181 - [Open UMLet in the editor](https://diagram.zip/?type=umlet)21562182 21572183 ---
@@ -2265,6 +2291,7 @@ Start with the [general presentation settings](/style/presentation). Choose a sh
22652291 22662292 - [Create a Vega diagram](/create/types/vega)22672293 - [General presentation settings](/style/presentation)2294+- [SVG normalization and version contracts](/style/svg-normalization)22682295 - [Open Vega in the editor](https://diagram.zip/?type=vega)22692296 22702297 ---
@@ -2354,6 +2381,7 @@ Start with the [general presentation settings](/style/presentation). Choose a sh
23542381 23552382 - [Create a Vega-Lite diagram](/create/types/vegalite)23562383 - [General presentation settings](/style/presentation)2384+- [SVG normalization and version contracts](/style/svg-normalization)23572385 - [Open Vega-Lite in the editor](https://diagram.zip/?type=vegalite)23582386 23592387 ---
@@ -2437,6 +2465,7 @@ Start with the [general presentation settings](/style/presentation). Choose a sh
24372465 24382466 - [Create a WaveDrom diagram](/create/types/wavedrom)24392467 - [General presentation settings](/style/presentation)2468+- [SVG normalization and version contracts](/style/svg-normalization)24402469 - [Open WaveDrom in the editor](https://diagram.zip/?type=wavedrom)24412470 24422471 ---
@@ -2517,4 +2546,5 @@ Start with the [general presentation settings](/style/presentation). Choose a sh
25172546 25182547 - [Create a WireViz diagram](/create/types/wireviz)25192548 - [General presentation settings](/style/presentation)2549+- [SVG normalization and version contracts](/style/svg-normalization)25202550 - [Open WireViz in the editor](https://diagram.zip/?type=wireviz)
M apps/docs/static/llms.txt +1 -0
M docs/svg-normalization.md +7 -7
@@ -466,11 +466,11 @@ invariants. Capability reporting should distinguish:
466466 - `presentation-only`: only the canvas and frame are normalized;467467 - `unsupported`: the appearance cannot be produced honestly.468468 469-The four themed appearances require `semantic` or `adaptive` conformance.470-`presentation-only` output may be useful for experimentation, but it must not471-be presented as a normalized dark or light diagram. A production engine472-upgrade should remain on its last conforming renderer/profile pair until the473-new output contract passes normalization tests.469+Palette adaptation requires `semantic` or `adaptive` conformance.470+`presentation-only` output may support framed appearances, but only the outer471+canvas and frame adapt. The authored drawing remains unchanged. A production472+engine upgrade should remain on its last conforming renderer/profile pair473+until the new output contract passes normalization tests.474474 475475 If a profile selector does not recognize a renderer build or structural476476 signature, it fails closed. It must not silently apply rules written for a
@@ -610,5 +610,5 @@ frame. Materialization combines one canonical geometry with one explicit
610610 appearance to produce a deterministic, self-contained SVG.611611 612612 Engines and their versions may change normalization patterns freely. Consumers613-continue to receive the same five appearance names and the same semantic visual614-contract.613+continue to receive the same seven appearance names and the same semantic614+visual contract.