clone

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

fix renderer examples and document shell

Dami committed 3d73b73
commit
3d73b73f677f95d08c37c76d04306582efda7876
parent
4dcd287f40acdf6b92b44682f60e0d0c71e60ef4
author
Dami <dami.etoile@gmail.com>
41 files changed, +1684 -58
Mdiagramzip-client-units/tikz/scripts/check.mjs2+-
Mdiagramzip-client-units/tikz/src/frame.js48++++-
Mdiagramzip-client-units/tikz/unit/worker.js4+-
Mdiagramzip-render/src/adapters/edge/d2.ts29++-
Mdiagramzip-render/src/catalog.ts2+-
Mdiagramzip-render/src/units/d2.ts2+-
Mdiagramzip-render/test/d2.test.ts5+-
Mdiagramzip-render/wrangler.units/d2.jsonc2+-
Mdiagramzip-shell/test/index.test.ts2+-
Adiagramzip/examples/bpmn.bpmn82+++++++
Adiagramzip/examples/bytefield.bf6+
Adiagramzip/examples/d2.d29+
Adiagramzip/examples/dbml.dbml23++
Adiagramzip/examples/diagramsnet.drawio1+
Adiagramzip/examples/erd.erd13+
Adiagramzip/examples/excalidraw.excalidraw357++++++++++++++++++++++++++++++
Adiagramzip/examples/goat.goat24++
Adiagramzip/examples/nomnoml.nomnoml13+
Adiagramzip/examples/nwdiag.diag16+
Adiagramzip/examples/packetdiag.diag22++
Adiagramzip/examples/pikchr.pikchr5+
Adiagramzip/examples/rackdiag.diag10+
Adiagramzip/examples/svgbob.bob9+
Adiagramzip/examples/symbolator.sv16+
Adiagramzip/examples/tikz.tex276+++++++++++++++++++++++
Adiagramzip/examples/umlet.uxf353++++++++++++++++++++++++++++++
Adiagramzip/examples/vega.json95++++++++
Adiagramzip/examples/vegalite.json129+++++++++++
Adiagramzip/examples/wavedrom.json57+
Adiagramzip/examples/wireviz.yaml26++
Mdiagramzip/index.html2+-
Mdiagramzip/src/client-renderers.js2+-
Mdiagramzip/src/example-variants.js4+-
Mdiagramzip/src/examples.js44++--
Mdiagramzip/src/main.js14+-
Mdiagramzip/src/state.js4+
Mdiagramzip/src/style.css48+++-
Mdiagramzip/test/client-renderers.test.js2+-
Mdiagramzip/test/example-variants.test.js6+-
Adiagramzip/test/examples.test.js20++
Mdiagramzip/test/state.test.js8+-
M diagramzip-client-units/tikz/scripts/check.mjs +1 -1
M diagramzip-client-units/tikz/src/frame.js +45 -3
@@ -1,7 +1,7 @@
11 const CHANNEL = 'diagram.zip:renderer:v1'22 const ENGINE = 'tikz'33 const VERSION = '@planktimerr/tikzjax@1.0.63'4-const BUILD = 'tikzjax-1.0.63-client-unit-3'4+const BUILD = 'tikzjax-1.0.63-client-unit-4'55 const MAX_SOURCE_LENGTH = 262_14466 const MAX_OUTPUT_LENGTH = 4_194_30477 const RENDER_TIMEOUT = 60_000
@@ -27,7 +27,48 @@ function normalizedSource(source) {
2727 return { body: source.slice(begin + beginMatch[0].length, end), preamble }2828 }2929 30-function safeSvg(svg) {30+function fontFamilyNames(documentSvg) {31+ const names = new Set()32+ for (const element of documentSvg.querySelectorAll('[font-family], [style*="font-family"]')) {33+ const value = element.getAttribute('font-family') || element.style.fontFamily34+ for (const family of value.split(',')) {35+ const name = family.trim().replace(/^(['"])(.*)\1$/, '$2')36+ if (/^[a-z0-9_-]{1,64}$/i.test(name)) names.add(name)37+ }38+ }39+ return [...names]40+}41+42+function base64(bytes) {43+ let binary = ''44+ const chunkSize = 0x800045+ for (let offset = 0; offset < bytes.length; offset += chunkSize) {46+ binary += String.fromCharCode(...bytes.subarray(offset, offset + chunkSize))47+ }48+ return btoa(binary)49+}50+51+async function embedUsedFonts(documentSvg) {52+ const rules = []53+ for (const family of fontFamilyNames(documentSvg)) {54+ const response = await fetch(`/fonts/${encodeURIComponent(family)}.woff2`)55+ if (!response.ok) continue56+ const encoded = base64(new Uint8Array(await response.arrayBuffer()))57+ rules.push(`@font-face{font-family:"${family}";src:url("data:font/woff2;base64,${encoded}") format("woff2");font-display:block}`)58+ }59+ if (rules.length === 0) return60+ const namespace = 'http://www.w3.org/2000/svg'61+ let defs = documentSvg.querySelector(':scope > defs')62+ if (!defs) {63+ defs = document.createElementNS(namespace, 'defs')64+ documentSvg.prepend(defs)65+ }66+ const style = document.createElementNS(namespace, 'style')67+ style.textContent = rules.join('')68+ defs.prepend(style)69+}70+71+async function safeSvg(svg) {3172 if (typeof svg === 'string') {3273 const start = svg.indexOf('<svg')3374 const end = svg.lastIndexOf('</svg>')
@@ -44,6 +85,7 @@ function safeSvg(svg) {
4485 if (/^(href|src|xlink:href)$/i.test(attribute.name) && !attribute.value.startsWith('#') && !attribute.value.startsWith('data:')) element.removeAttribute(attribute.name)4586 }4687 }88+ await embedUsedFonts(documentSvg)4789 return new XMLSerializer().serializeToString(documentSvg)4890 }4991
@@ -82,7 +124,7 @@ async function renderMessage(message, origin, sequence) {
82124 try {83125 const svg = await finished84126 if (sequence !== latest) return85- const output = safeSvg(svg.outerHTML)127+ const output = await safeSvg(svg.outerHTML)86128 if (output.length > MAX_OUTPUT_LENGTH) throw new Error('TikZ SVG output is too large.')87129 reply(origin, { type: 'result', requestId: message.requestId, ok: true, svg: output, version: VERSION, build: BUILD, pipeline: [ENGINE] })88130 } finally {
M diagramzip-client-units/tikz/unit/worker.js +2 -2
M diagramzip-render/src/adapters/edge/d2.ts +28 -1
@@ -15,6 +15,33 @@ type D2Response = { svg?: string; error?: string }
1515 let initPromise: Promise<void> | undefined1616 let renderTail: Promise<void> = Promise.resolve()1717 18+function styleDeclaration(style: string, name: string): string | null {19+ for (const declaration of style.split(';')) {20+ const separator = declaration.indexOf(':')21+ if (separator < 0 || declaration.slice(0, separator).trim().toLowerCase() !== name) continue22+ return declaration.slice(separator + 1).trim()23+ }24+ return null25+}26+27+export function imageCompatibleAnimations(svg: string): string {28+ return svg.replace(/<path\b(?=[^>]*\bclass="[^"]*\banimated-connection\b[^"]*")(?=[^>]*\bstyle="([^"]*)")[^>]*>/g, (tag, style: string) => {29+ const offset = styleDeclaration(style, 'stroke-dashoffset')30+ const animation = styleDeclaration(style, 'animation')31+ const duration = animation?.match(/^dashdraw\s+(\d+(?:\.\d+)?)s\s+linear\s+infinite$/)?.[1]32+ if (!offset || !/^-?\d+(?:\.\d+)?(?:px)?$/.test(offset) || !duration) return tag33+ const withoutCssAnimation = style34+ .split(';')35+ .filter(declaration => declaration.trim() && !/^\s*animation\s*:/i.test(declaration))36+ .join(';')37+ const normalizedTag = tag.replace(/\bstyle="[^"]*"/, `style="${withoutCssAnimation};"`)38+ const animate = `<animate attributeName="stroke-dashoffset" from="0" to="${offset}" dur="${duration}s" calcMode="linear" repeatCount="indefinite"></animate>`39+ return /\/\s*>$/.test(normalizedTag)40+ ? `${normalizedTag.replace(/\/\s*>$/, '>')}${animate}</path>`41+ : `${normalizedTag}${animate}`42+ })43+}44+1845 async function init(): Promise<void> {1946 if (initPromise) return initPromise2047 initPromise = (async () => {
@@ -70,7 +97,7 @@ export const d2Adapter: RendererAdapter = {
7097 }7198 if (result.error) throw new RenderError(422, 'render_failed', result.error.slice(0, 500))7299 if (!result.svg || result.svg.trim() === '') throw new RenderError(422, 'empty_render', 'D2 returned no SVG.')73- return edgeResult('d2', VERSION, result.svg, 'edge-wasm')100+ return edgeResult('d2', VERSION, imageCompatibleAnimations(result.svg), 'edge-wasm')74101 })75102 },76103 }
M diagramzip-render/src/catalog.ts +1 -1
M diagramzip-render/src/units/d2.ts +1 -1
M diagramzip-render/test/d2.test.ts +4 -1
M diagramzip-render/wrangler.units/d2.jsonc +1 -1
M diagramzip-shell/test/index.test.ts +1 -1
A diagramzip/examples/bpmn.bpmn +82 -0
@@ -0,0 +1,82 @@
1+<?xml version="1.0" encoding="UTF-8"?>2+<bpmn2:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:qa="http://some-company/schema/bpmn/qa" id="_RdgBELNaEeSYkoSLDs6j-w" targetNamespace="http://activiti.org/bpmn">3+ <bpmn2:process id="Process_1">4+ <bpmn2:task id="Task_1" name="Examine Situation" qa:suitable="0.7">5+ <bpmn2:outgoing>SequenceFlow_1</bpmn2:outgoing>6+ <bpmn2:extensionElements>7+ <qa:analysisDetails lastChecked="2015-01-20" nextCheck="2015-07-15">8+ <qa:comment author="Klaus">9+ Our operators always have a hard time to figure out, what they need to do here.10+ </qa:comment>11+ <qa:comment author="Walter">12+ I believe this can be split up in a number of activities and partly automated.13+ </qa:comment>14+ </qa:analysisDetails>15+ </bpmn2:extensionElements>16+ </bpmn2:task>17+ <bpmn2:sequenceFlow id="SequenceFlow_1" name="" sourceRef="Task_1" targetRef="ExclusiveGateway_1"/>18+ <bpmn2:exclusiveGateway id="ExclusiveGateway_1" name="Things OK?">19+ <bpmn2:incoming>SequenceFlow_1</bpmn2:incoming>20+ <bpmn2:outgoing>SequenceFlow_2</bpmn2:outgoing>21+ <bpmn2:outgoing>SequenceFlow_5</bpmn2:outgoing>22+ </bpmn2:exclusiveGateway>23+ <bpmn2:sequenceFlow id="SequenceFlow_2" name="" sourceRef="ExclusiveGateway_1" targetRef="EndEvent_1"/>24+ <bpmn2:sequenceFlow id="SequenceFlow_5" name="" sourceRef="ExclusiveGateway_1" targetRef="EndEvent_2"/>25+ <bpmn2:endEvent id="EndEvent_1" name="Notification Sent">26+ <bpmn2:incoming>SequenceFlow_2</bpmn2:incoming>27+ <bpmn2:messageEventDefinition id="MessageEventDefinition_1"/>28+ </bpmn2:endEvent>29+ <bpmn2:endEvent id="EndEvent_2" name="Error Propagated">30+ <bpmn2:incoming>SequenceFlow_5</bpmn2:incoming>31+ <bpmn2:errorEventDefinition id="ErrorEventDefinition_1"/>32+ </bpmn2:endEvent>33+ </bpmn2:process>34+ <bpmndi:BPMNDiagram id="BPMNDiagram_1">35+ <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1">36+ <bpmndi:BPMNShape id="_BPMNShape_Task_2" bpmnElement="Task_1">37+ <dc:Bounds height="80.0" width="100.0" x="96.0" y="196.0"/>38+ </bpmndi:BPMNShape>39+ <bpmndi:BPMNShape id="_BPMNShape_EndEvent_2" bpmnElement="EndEvent_1">40+ <dc:Bounds height="36.0" width="36.0" x="396.0" y="300.0"/>41+ <bpmndi:BPMNLabel>42+ <dc:Bounds height="0.0" width="0.0" x="414.0" y="341.0"/>43+ </bpmndi:BPMNLabel>44+ </bpmndi:BPMNShape>45+ <bpmndi:BPMNShape id="_BPMNShape_ExclusiveGateway_2" bpmnElement="ExclusiveGateway_1" isMarkerVisible="true">46+ <dc:Bounds height="50.0" width="50.0" x="276.0" y="210.0"/>47+ <bpmndi:BPMNLabel>48+ <dc:Bounds height="21.0" width="74.0" x="333.0" y="226.0"/>49+ </bpmndi:BPMNLabel>50+ </bpmndi:BPMNShape>51+ <bpmndi:BPMNEdge id="BPMNEdge_SequenceFlow_1" bpmnElement="SequenceFlow_1" sourceElement="_BPMNShape_Task_2" targetElement="_BPMNShape_ExclusiveGateway_2">52+ <di:waypoint xsi:type="dc:Point" x="196.0" y="236.0"/>53+ <di:waypoint xsi:type="dc:Point" x="276.0" y="235.0"/>54+ <bpmndi:BPMNLabel>55+ <dc:Bounds height="6.0" width="6.0" x="214.0" y="236.0"/>56+ </bpmndi:BPMNLabel>57+ </bpmndi:BPMNEdge>58+ <bpmndi:BPMNEdge id="BPMNEdge_SequenceFlow_2" bpmnElement="SequenceFlow_2" sourceElement="_BPMNShape_ExclusiveGateway_2" targetElement="_BPMNShape_EndEvent_2">59+ <di:waypoint xsi:type="dc:Point" x="301.0" y="260.0"/>60+ <di:waypoint xsi:type="dc:Point" x="301.0" y="318.0"/>61+ <di:waypoint xsi:type="dc:Point" x="396.0" y="318.0"/>62+ <bpmndi:BPMNLabel>63+ <dc:Bounds height="6.0" width="6.0" x="298.0" y="301.0"/>64+ </bpmndi:BPMNLabel>65+ </bpmndi:BPMNEdge>66+ <bpmndi:BPMNShape id="_BPMNShape_EndEvent_3" bpmnElement="EndEvent_2">67+ <dc:Bounds height="36.0" width="36.0" x="396.0" y="132.0"/>68+ <bpmndi:BPMNLabel>69+ <dc:Bounds height="0.0" width="0.0" x="414.0" y="173.0"/>70+ </bpmndi:BPMNLabel>71+ </bpmndi:BPMNShape>72+ <bpmndi:BPMNEdge id="BPMNEdge_SequenceFlow_5" bpmnElement="SequenceFlow_5" sourceElement="_BPMNShape_ExclusiveGateway_2" targetElement="_BPMNShape_EndEvent_3">73+ <di:waypoint xsi:type="dc:Point" x="301.0" y="210.0"/>74+ <di:waypoint xsi:type="dc:Point" x="301.0" y="150.0"/>75+ <di:waypoint xsi:type="dc:Point" x="396.0" y="150.0"/>76+ <bpmndi:BPMNLabel>77+ <dc:Bounds height="6.0" width="6.0" x="333.0" y="150.0"/>78+ </bpmndi:BPMNLabel>79+ </bpmndi:BPMNEdge>80+ </bpmndi:BPMNPlane>81+ </bpmndi:BPMNDiagram>82+</bpmn2:definitions>
A diagramzip/examples/bytefield.bf +6 -0
A diagramzip/examples/d2.d2 +9 -0
A diagramzip/examples/dbml.dbml +23 -0
A diagramzip/examples/diagramsnet.drawio +1 -0
@@ -0,0 +1 @@
1+<mxfile host="localhost" modified="2021-05-13T15:13:49.065Z" agent="5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36" etag="wSTZ0NLKJqQDPf-wjMNB" version="@DRAWIO-VERSION@" type="device"><diagram id="3228e29e-7158-1315-38df-8450db1d8a1d" name="Page-1">3VpdU+s4DP01PK5HtiTLfmwL3H3ZJ3Zmn0Mb2s4tTSeEBfbXr0LT2wbncvkI7WYDMzSy3CTnyEeSwxlObh+/ldlm8Ucxy1dnDmaPZ3h+5pwlCPqntjxtLUKNYV4uZ43T3nC1/CdvjNBY75ez/K7lWBXFqlpu2sZpsV7n06ply8qyeGi73RSr9lU32TxPDFfTbJVa/1rOqkVjtT7uB37Pl/NFc+ngZDtwnU2/z8vift1cb12s8+3Ibbb7muYZ7xbZrHg4MOHFGU7Koqi2n24fJ/mqhnWH2Hbe5U9Gf9xyma+rt0xwlqmZ9He2um+evLm36mkHhU5S1PVk/LBYVvnVJpvWIw9KvNrKosqqZbFWy28IarhZrlaTYlWUz7PxEoIAq73QecuqDgdfu91VZfE93zk+o4TjRXW70jOrH9OH2d1qXlb544GpebhveXGbV+WTujSj6MAgWYsueI8hNAw1EenYG+/QEgs7jLaJz4c92zrFQAAOzlvhgNFvXRYHvFv9FhSOFAOCOAqNT9bE3/zHXe2J0A8NFz/nxfXIi0VOebkI7PUqp+DFW2fIO6+/7NFjygt7G0J0IZLeJSbE2MgmgKOamaAnMeXFARknMQrqohUl0fbDC36Wlxc0uEsey+QkNDBYDd0YrUdG8YDU5gHZOOuDJ3ZgrfPp+hDoWBAE/SBNPSNt3Wg0fqsQHa4e7h15wmgsB+s9K7awg/ZpB6s1KkkcKIJlQKAEeRetcQREEFXYkEQ6iHA9EcF9pgjqSBGCfjIKJ1kDpBIfiFBCtFFUcNpMeDQYFGjkCACRO4hgQ6A5RKcCk0TqIALEuEBWPFJEiNH1w4tPeBklxCgMVY1kDex6/mexqTl4zgbFurpq/GB3vq3CLLVhrocOE/rz0RP84gy3IbdBARUBDwGDIHfITofq9BXrkmA6HhqmwvACUw1Qzaiq7xIFNBKjHBXTkGA6GRqmAYLRYkUlNWrVwbEt2FpenjJmY4Lv+dDw9ULtUqQdvwLGa65UB4xoO2T4C+FlSOC9GBq8TIkkxHaN4Y4qCZx2naPBaQIzGZF6wQNq+xjbpYPKrDlunKYd43hwmIrnpB44pbZy2u6Nhoeqd+EVdXXxpAinbd54MjiB1S75FYQRgxGwQThErjeLjgpw2r6N/2/4hlPWt5z2YePhFWBRO12P2gVLBPL2RbWApF2yDb7eM6r37Y6Kb0dPdj68CE67MutMjBEic0Br/XGrhbQpGw0uaElrLF37pFAK2wD+Remgw0E1g2zUoCXXscH/hQB3dGWDC1ptD14pcYlOKbs+7cvS7a8370t27ErefPDF1bzMZst8z0njccggfy1tCrFhODhebFcwGl06on21hQAdyyLWwrQ/OvY0lfrgg3gR0gN3+eKznKZ9Ybr99hlO8w++9Do2eW0dg1/wRR2rTEtOiFrb67L1tfpRPwSlTWbaDb3v/dcNX8t0aIywN6CwkmZuAXkrJWLIqVoGbbL0x0o/lKQtaprI3/miLMuuPyB8J6WEgA1GrVRBIvlgO7rYIy6TtKlNc/9ndEzQT7MPvDH77yQhYjIuIEBg9BARO8rfX6chdXFgRbkTFUfaFV3voE9P9/9w8zx28A9NePEv</diagram></mxfile>\ No newline at end of file
A diagramzip/examples/erd.erd +13 -0
A diagramzip/examples/excalidraw.excalidraw +357 -0
@@ -0,0 +1,357 @@
1+{2+ "type": "excalidraw",3+ "version": 2,4+ "source": "https://excalidraw.com",5+ "elements": [6+ {7+ "id": "vWrqOAfkind2qcm7LDAGZ",8+ "type": "ellipse",9+ "x": 414,10+ "y": 237,11+ "width": 214,12+ "height": 214,13+ "angle": 0,14+ "strokeColor": "#000000",15+ "backgroundColor": "#15aabf",16+ "fillStyle": "hachure",17+ "strokeWidth": 1,18+ "strokeStyle": "solid",19+ "roughness": 1,20+ "opacity": 100,21+ "groupIds": [],22+ "strokeSharpness": "sharp",23+ "seed": 1041657908,24+ "version": 120,25+ "versionNonce": 1188004276,26+ "isDeleted": false,27+ "boundElementIds": null28+ },29+ {30+ "id": "rC-02l026X3SWaucOxDw9",31+ "type": "ellipse",32+ "x": 563,33+ "y": 236,34+ "width": 214,35+ "height": 214,36+ "angle": 0,37+ "strokeColor": "#000000",38+ "backgroundColor": "#40c057",39+ "fillStyle": "hachure",40+ "strokeWidth": 1,41+ "strokeStyle": "solid",42+ "roughness": 1,43+ "opacity": 100,44+ "groupIds": [],45+ "strokeSharpness": "sharp",46+ "seed": 476355980,47+ "version": 169,48+ "versionNonce": 830055604,49+ "isDeleted": false,50+ "boundElementIds": null51+ },52+ {53+ "id": "DrhW4ZSEpniMojuzsiqvi",54+ "type": "ellipse",55+ "x": 476,56+ "y": 358,57+ "width": 214,58+ "height": 214,59+ "angle": 0,60+ "strokeColor": "#000000",61+ "backgroundColor": "#7950f2",62+ "fillStyle": "hachure",63+ "strokeWidth": 1,64+ "strokeStyle": "solid",65+ "roughness": 1,66+ "opacity": 100,67+ "groupIds": [],68+ "strokeSharpness": "sharp",69+ "seed": 1966042508,70+ "version": 119,71+ "versionNonce": 1553878324,72+ "isDeleted": false,73+ "boundElementIds": null74+ },75+ {76+ "id": "NMI4ix1W7sQ6z9EDdYwc7",77+ "type": "arrow",78+ "x": 384.12748830144295,79+ "y": 207.60779895196669,80+ "width": 119.87251169855705,81+ "height": 100.39220104803331,82+ "angle": 0,83+ "strokeColor": "#000000",84+ "backgroundColor": "#7950f2",85+ "fillStyle": "hachure",86+ "strokeWidth": 1,87+ "strokeStyle": "solid",88+ "roughness": 1,89+ "opacity": 100,90+ "groupIds": [],91+ "strokeSharpness": "round",92+ "seed": 1656470796,93+ "version": 69,94+ "versionNonce": 1460943500,95+ "isDeleted": false,96+ "boundElementIds": null,97+ "points": [98+ [99+ 0,100+ 0101+ ],102+ [103+ 119.87251169855705,104+ 100.39220104803331105+ ]106+ ],107+ "lastCommittedPoint": null,108+ "startBinding": {109+ "elementId": "3J8-URSbMsKSvZ2TvCc3K",110+ "focus": 0.2594107757283838,111+ "gap": 7.607798951966686112+ },113+ "endBinding": null114+ },115+ {116+ "id": "QixLrxvPLw7TbG6VJJ9dj",117+ "type": "arrow",118+ "x": 652.9917772874236,119+ "y": 609.5185939229559,120+ "width": 61.74239993095398,121+ "height": 105.02421977738851,122+ "angle": 0,123+ "strokeColor": "#000000",124+ "backgroundColor": "#40c057",125+ "fillStyle": "hachure",126+ "strokeWidth": 1,127+ "strokeStyle": "solid",128+ "roughness": 1,129+ "opacity": 100,130+ "groupIds": [],131+ "strokeSharpness": "round",132+ "seed": 738941452,133+ "version": 107,134+ "versionNonce": 1655140148,135+ "isDeleted": false,136+ "boundElementIds": null,137+ "points": [138+ [139+ 0,140+ 0141+ ],142+ [143+ -61.74239993095398,144+ -105.02421977738851145+ ]146+ ],147+ "lastCommittedPoint": null,148+ "startBinding": {149+ "elementId": "dhyExWoj7pia0unVwtXeL",150+ "focus": 0.1480924722475781,151+ "gap": 8.481406077044085152+ },153+ "endBinding": null154+ },155+ {156+ "id": "LBRnTRdXKmkt5IwhKJLDC",157+ "type": "arrow",158+ "x": 806.9784146802895,159+ "y": 212.38825479040858,160+ "width": 104.97841468028946,161+ "height": 96.61174520959142,162+ "angle": 0,163+ "strokeColor": "#000000",164+ "backgroundColor": "#40c057",165+ "fillStyle": "hachure",166+ "strokeWidth": 1,167+ "strokeStyle": "solid",168+ "roughness": 1,169+ "opacity": 100,170+ "groupIds": [],171+ "strokeSharpness": "round",172+ "seed": 751503500,173+ "version": 69,174+ "versionNonce": 1180701708,175+ "isDeleted": false,176+ "boundElementIds": null,177+ "points": [178+ [179+ 0,180+ 0181+ ],182+ [183+ -104.97841468028946,184+ 96.61174520959142185+ ]186+ ],187+ "lastCommittedPoint": null,188+ "startBinding": {189+ "elementId": "7fiPETvGUweaqK1VIn2zu",190+ "focus": -0.07338204068894764,191+ "gap": 9.388254790408553192+ },193+ "endBinding": null194+ },195+ {196+ "id": "VFSwfD_HsZyf5SBKdiFDz",197+ "type": "arrow",198+ "x": 599.140263160093,199+ "y": 191.4445904184276,200+ "width": 3.62529516014456,201+ "height": 206.31238589940077,202+ "angle": 0.13471642395161876,203+ "strokeColor": "#000000",204+ "backgroundColor": "#40c057",205+ "fillStyle": "hachure",206+ "strokeWidth": 1,207+ "strokeStyle": "solid",208+ "roughness": 1,209+ "opacity": 100,210+ "groupIds": [],211+ "strokeSharpness": "round",212+ "seed": 1721266612,213+ "version": 192,214+ "versionNonce": 1388066444,215+ "isDeleted": false,216+ "boundElementIds": null,217+ "points": [218+ [219+ 0,220+ 0221+ ],222+ [223+ 3.62529516014456,224+ 206.31238589940077225+ ]226+ ],227+ "lastCommittedPoint": null,228+ "startBinding": null,229+ "endBinding": null230+ },231+ {232+ "id": "3J8-URSbMsKSvZ2TvCc3K",233+ "type": "text",234+ "x": 314,235+ "y": 175,236+ "width": 135,237+ "height": 25,238+ "angle": 0,239+ "strokeColor": "#000000",240+ "backgroundColor": "#40c057",241+ "fillStyle": "hachure",242+ "strokeWidth": 1,243+ "strokeStyle": "solid",244+ "roughness": 1,245+ "opacity": 100,246+ "groupIds": [],247+ "strokeSharpness": "sharp",248+ "seed": 1793099060,249+ "version": 43,250+ "versionNonce": 2135655476,251+ "isDeleted": false,252+ "boundElementIds": [253+ "NMI4ix1W7sQ6z9EDdYwc7"254+ ],255+ "text": "want to draw",256+ "fontSize": 20,257+ "fontFamily": 1,258+ "textAlign": "left",259+ "verticalAlign": "top",260+ "baseline": 18261+ },262+ {263+ "id": "7fiPETvGUweaqK1VIn2zu",264+ "type": "text",265+ "x": 782,266+ "y": 178,267+ "width": 89,268+ "height": 25,269+ "angle": 0,270+ "strokeColor": "#000000",271+ "backgroundColor": "#40c057",272+ "fillStyle": "hachure",273+ "strokeWidth": 1,274+ "strokeStyle": "solid",275+ "roughness": 1,276+ "opacity": 100,277+ "groupIds": [],278+ "strokeSharpness": "sharp",279+ "seed": 1750780940,280+ "version": 38,281+ "versionNonce": 1584702860,282+ "isDeleted": false,283+ "boundElementIds": [284+ "LBRnTRdXKmkt5IwhKJLDC"285+ ],286+ "text": "can draw",287+ "fontSize": 20,288+ "fontFamily": 1,289+ "textAlign": "left",290+ "verticalAlign": "top",291+ "baseline": 18292+ },293+ {294+ "id": "dhyExWoj7pia0unVwtXeL",295+ "type": "text",296+ "x": 612,297+ "y": 618,298+ "width": 91,299+ "height": 25,300+ "angle": 0,301+ "strokeColor": "#000000",302+ "backgroundColor": "#40c057",303+ "fillStyle": "hachure",304+ "strokeWidth": 1,305+ "strokeStyle": "solid",306+ "roughness": 1,307+ "opacity": 100,308+ "groupIds": [],309+ "strokeSharpness": "sharp",310+ "seed": 1228201396,311+ "version": 105,312+ "versionNonce": 288443916,313+ "isDeleted": false,314+ "boundElementIds": [315+ "QixLrxvPLw7TbG6VJJ9dj"316+ ],317+ "text": "have time",318+ "fontSize": 20,319+ "fontFamily": 1,320+ "textAlign": "left",321+ "verticalAlign": "top",322+ "baseline": 18323+ },324+ {325+ "id": "PKjjaNpqiOpZQ7kml-d18",326+ "type": "text",327+ "x": 567,328+ "y": 148,329+ "width": 88,330+ "height": 25,331+ "angle": 0,332+ "strokeColor": "#000000",333+ "backgroundColor": "#40c057",334+ "fillStyle": "hachure",335+ "strokeWidth": 1,336+ "strokeStyle": "solid",337+ "roughness": 1,338+ "opacity": 100,339+ "groupIds": [],340+ "strokeSharpness": "sharp",341+ "seed": 152899636,342+ "version": 105,343+ "versionNonce": 1333089972,344+ "isDeleted": false,345+ "boundElementIds": [],346+ "text": "NOT ME!",347+ "fontSize": 20,348+ "fontFamily": 1,349+ "textAlign": "left",350+ "verticalAlign": "top",351+ "baseline": 18352+ }353+ ],354+ "appState": {355+ "gridSize": null356+ }357+}
A diagramzip/examples/goat.goat +24 -0
A diagramzip/examples/nomnoml.nomnoml +13 -0
A diagramzip/examples/nwdiag.diag +16 -0
A diagramzip/examples/packetdiag.diag +22 -0
A diagramzip/examples/pikchr.pikchr +5 -0
A diagramzip/examples/rackdiag.diag +10 -0
A diagramzip/examples/svgbob.bob +9 -0
A diagramzip/examples/symbolator.sv +16 -0
A diagramzip/examples/tikz.tex +276 -0
@@ -0,0 +1,276 @@
1+% From: https://tikz.net/periodic-table/2+3+% Adapted from https://texample.net/tikz/examples/periodic-table-of-chemical-elements.4+% All Credit to Ivan Griffin.5+6+\documentclass[tikz]{standalone}7+\usetikzlibrary{shapes,calc}8+9+\begin{document}10+11+\newcommand{\ElemLabel}[4]{12+ \begin{minipage}{2.2cm}13+ \centering14+ {\textbf{#1} \hfill #2}%15+ \linebreak \linebreak16+ {\textbf{#3}}%17+ \linebreak \linebreak18+ {{#4}}19+ \end{minipage}20+}21+22+\newcommand{\NaturalElem}[4]{\ElemLabel{#1}{#2}{\huge {#3}}{#4}}23+24+\newcommand{\SyntheticElem}[4]{\ElemLabel{#1}{#2}{\color{gray}{\huge #3}}{#4}}25+26+\begin{tikzpicture}[font=\sffamily]27+28+ % Fill Color Styles29+ \tikzstyle{ElementFill} = [fill=yellow!15]30+ \tikzstyle{AlkaliMetalFill} = [fill=blue!55]31+ \tikzstyle{AlkalineEarthMetalFill} = [fill=blue!40]32+ \tikzstyle{MetalFill} = [fill=blue!25]33+ \tikzstyle{MetalloidFill} = [fill=orange!40]34+ \tikzstyle{NonmetalFill} = [fill=teal!40]35+ \tikzstyle{HalogenFill} = [fill=yellow!40]36+ \tikzstyle{NobleGasFill} = [fill=green!55]37+ \tikzstyle{LanthanideActinideFill} = [fill=red!40]38+39+ % Element Styles40+ \tikzstyle{Element} = [ElementFill,41+ minimum width=2.5cm, minimum height=2.5cm, node distance=2.75cm]42+ \tikzstyle{AlkaliMetal} = [Element, AlkaliMetalFill]43+ \tikzstyle{AlkalineEarthMetal} = [Element, AlkalineEarthMetalFill]44+ \tikzstyle{Metal} = [Element, MetalFill]45+ \tikzstyle{Metalloid} = [Element, MetalloidFill]46+ \tikzstyle{Nonmetal} = [Element, NonmetalFill]47+ \tikzstyle{Halogen} = [Element, HalogenFill]48+ \tikzstyle{NobleGas} = [Element, NobleGasFill]49+ \tikzstyle{LanthanideActinide} = [Element, LanthanideActinideFill]50+ \tikzstyle{PeriodLabel} = [font={\sffamily\LARGE}, node distance=2.0cm]51+ \tikzstyle{GroupLabel} = [font={\sffamily\LARGE}, minimum width=2.75cm, node distance=2.0cm]52+53+ % Group 1 - IA54+ \node[Element] (H) {\NaturalElem{1} {1.0079}{H}{Hydrogen}};55+ \node[below of=H, AlkaliMetal] (Li) {\NaturalElem{3}{6.941}{Li}{Lithium}};56+ \node[below of=Li, AlkaliMetal] (Na) {\NaturalElem{11}{22.990}{Na}{Sodium}};57+ \node[below of=Na, AlkaliMetal] (K) {\NaturalElem{19}{39.098}{K}{Potassium}};58+ \node[below of=K, AlkaliMetal] (Rb) {\NaturalElem{37}{85.468}{Rb}{Rubidium}};59+ \node[below of=Rb, AlkaliMetal] (Cs) {\NaturalElem{55}{132.91}{Cs}{Caesium}};60+ \node[below of=Cs, AlkaliMetal] (Fr) {\NaturalElem{87}{223}{Fr}{Francium}};61+62+ % Group 2 - IIA63+ \node[right of=Li, AlkalineEarthMetal] (Be) {\NaturalElem{4}{9.0122}{Be}{Beryllium}};64+ \node[below of=Be, AlkalineEarthMetal] (Mg) {\NaturalElem{12}{24.305}{Mg}{Magnesium}};65+ \node[below of=Mg, AlkalineEarthMetal] (Ca) {\NaturalElem{20}{40.078}{Ca}{Calcium}};66+ \node[below of=Ca, AlkalineEarthMetal] (Sr) {\NaturalElem{38}{87.62}{Sr}{Strontium}};67+ \node[below of=Sr, AlkalineEarthMetal] (Ba) {\NaturalElem{56}{137.33}{Ba}{Barium}};68+ \node[below of=Ba, AlkalineEarthMetal] (Ra) {\NaturalElem{88}{226}{Ra}{Radium}};69+70+ % Group 3 - IIIB71+ \node[right of=Ca, Metal] (Sc) {\NaturalElem{21}{44.956}{Sc}{Scandium}};72+ \node[below of=Sc, Metal] (Y) {\NaturalElem{39}{88.906}{Y}{Yttrium}};73+ \node[below of=Y, LanthanideActinide] (LaLu) {\NaturalElem{57-71}{}{La-Lu}{Lanthanide}};74+ \node[below of=LaLu, LanthanideActinide] (AcLr) {\NaturalElem{89-103}{}{Ac-Lr}{Actinide}};75+76+ % Group 4 - IVB77+ \node[right of=Sc, Metal] (Ti) {\NaturalElem{22}{47.867}{Ti}{Titanium}};78+ \node[below of=Ti, Metal] (Zr) {\NaturalElem{40}{91.224}{Zr}{Zirconium}};79+ \node[below of=Zr, Metal] (Hf) {\NaturalElem{72}{178.49}{Hf}{Hafnium}};80+ \node[below of=Hf, Metal] (Rf) {\SyntheticElem{104}{261}{Rf}{Rutherfordium}};81+82+ % Group 5 - VB83+ \node[right of=Ti, Metal] (V) {\NaturalElem{23}{50.942}{V}{Vanadium}};84+ \node[below of=V, Metal] (Nb) {\NaturalElem{41}{92.906}{Nb}{Niobium}};85+ \node[below of=Nb, Metal] (Ta) {\NaturalElem{73}{180.95}{Ta}{Tantalum}};86+ \node[below of=Ta, Metal] (Db) {\SyntheticElem{105}{262}{Db}{Dubnium}};87+88+ % Group 6 - VIB89+ \node[right of=V, Metal] (Cr) {\NaturalElem{24}{51.996}{Cr}{Chromium}};90+ \node[below of=Cr, Metal] (Mo) {\NaturalElem{42}{95.94}{Mo}{Molybdenum}};91+ \node[below of=Mo, Metal] (W) {\NaturalElem{74}{183.84}{W}{Tungsten}};92+ \node[below of=W, Metal] (Sg) {\SyntheticElem{106}{266}{Sg}{Seaborgium}};93+94+ % Group 7 - VIIB95+ \node[right of=Cr, Metal] (Mn) {\NaturalElem{25}{54.938}{Mn}{Manganese}};96+ \node[below of=Mn, Metal] (Tc) {\NaturalElem{43}{96}{Tc}{Technetium}};97+ \node[below of=Tc, Metal] (Re) {\NaturalElem{75}{186.21}{Re}{Rhenium}};98+ \node[below of=Re, Metal] (Bh) {\SyntheticElem{107}{264}{Bh}{Bohrium}};99+100+ % Group 8 - VIIIB101+ \node[right of=Mn, Metal] (Fe) {\NaturalElem{26}{55.845}{Fe}{Iron}};102+ \node[below of=Fe, Metal] (Ru) {\NaturalElem{44}{101.07}{Ru}{Ruthenium}};103+ \node[below of=Ru, Metal] (Os) {\NaturalElem{76}{190.23}{Os}{Osmium}};104+ \node[below of=Os, Metal] (Hs) {\SyntheticElem{108}{277}{Hs}{Hassium}};105+106+ % Group 9 - VIIIB107+ \node[right of=Fe, Metal] (Co) {\NaturalElem{27}{58.933}{Co}{Cobalt}};108+ \node[below of=Co, Metal] (Rh) {\NaturalElem{45}{102.91}{Rh}{Rhodium}};109+ \node[below of=Rh, Metal] (Ir) {\NaturalElem{77}{192.22}{Ir}{Iridium}};110+ \node[below of=Ir, Metal] (Mt) {\SyntheticElem{109}{268}{Mt}{Meitnerium}};111+112+ % Group 10 - VIIIB113+ \node[right of=Co, Metal] (Ni) {\NaturalElem{28}{58.693}{Ni}{Nickel}};114+ \node[below of=Ni, Metal] (Pd) {\NaturalElem{46}{106.42}{Pd}{Palladium}};115+ \node[below of=Pd, Metal] (Pt) {\NaturalElem{78}{195.08}{Pt}{Platinum}};116+ \node[below of=Pt, Metal] (Ds) {\SyntheticElem{110}{281}{Ds}{Darmstadtium}};117+118+ % Group 11 - IB119+ \node[right of=Ni, Metal] (Cu) {\NaturalElem{29}{63.546}{Cu}{Copper}};120+ \node[below of=Cu, Metal] (Ag) {\NaturalElem{47}{107.87}{Ag}{Silver}};121+ \node[below of=Ag, Metal] (Au) {\NaturalElem{79}{196.97}{Au}{Gold}};122+ \node[below of=Au, Metal] (Rg) {\SyntheticElem{111}{280}{Rg}{Roentgenium}};123+124+ % Group 12 - IIB125+ \node[right of=Cu, Metal] (Zn) {\NaturalElem{30}{65.39}{Zn}{Zinc}};126+ \node[below of=Zn, Metal] (Cd) {\NaturalElem{48}{112.41}{Cd}{Cadmium}};127+ \node[below of=Cd, Metal] (Hg) {\NaturalElem{80}{200.59}{Hg}{Mercury}};128+ \node[below of=Hg, Metal] (Uub) {\SyntheticElem{112}{285}{Uub}{Ununbium}};129+130+ % Group 13 - IIIA131+ \node[right of=Zn, Metal] (Ga) {\NaturalElem{31}{69.723}{Ga}{Gallium}};132+ \node[above of=Ga, Metal] (Al) {\NaturalElem{13}{26.982}{Al}{Aluminium}};133+ \node[above of=Al, Metalloid] (B) {\NaturalElem{5}{10.811}{B}{Boron}};134+ \node[below of=Ga, Metal] (In) {\NaturalElem{49}{114.82}{In}{Indium}};135+ \node[below of=In, Metal] (Tl) {\NaturalElem{81}{204.38}{Tl}{Thallium}};136+ \node[below of=Tl, Metal] (Uut) {\SyntheticElem{113}{284}{Uut}{Ununtrium}};137+138+ % Group 14 - IVA139+ \node[right of=B, Nonmetal] (C) {\NaturalElem{6}{12.011}{C}{Carbon}};140+ \node[below of=C, Metalloid] (Si) {\NaturalElem{14}{28.086}{Si}{Silicon}};141+ \node[below of=Si, Metalloid] (Ge) {\NaturalElem{32}{72.64}{Ge}{Germanium}};142+ \node[below of=Ge, Metal] (Sn) {\NaturalElem{50}{118.71}{Sn}{Tin}};143+ \node[below of=Sn, Metal] (Pb) {\NaturalElem{82}{207.2}{Pb}{Lead}};144+ \node[below of=Pb, Metal] (Uuq) {\SyntheticElem{114}{289}{Uuq}{Ununquadium}};145+146+ % Group 15 - VA147+ \node[right of=C, Nonmetal] (N) {\NaturalElem{7}{14.007}{N}{Nitrogen}};148+ \node[below of=N, Nonmetal] (P) {\NaturalElem{15}{30.974}{P}{Phosphorus}};149+ \node[below of=P, Metalloid] (As) {\NaturalElem{33}{74.922}{As}{Arsenic}};150+ \node[below of=As, Metalloid] (Sb) {\NaturalElem{51}{121.76}{Sb}{Antimony}};151+ \node[below of=Sb, Metal] (Bi) {\NaturalElem{83}{208.98}{Bi}{Bismuth}};152+ \node[below of=Bi, Metal] (Uup) {\SyntheticElem{115}{288}{Uup}{Ununpentium}};153+154+ % Group 16 - VIA155+ \node[right of=N, Nonmetal] (O) {\NaturalElem{8}{15.999}{O}{Oxygen}};156+ \node[below of=O, Nonmetal] (S) {\NaturalElem{16}{32.065}{S}{Sulphur}};157+ \node[below of=S, Nonmetal] (Se) {\NaturalElem{34}{78.96}{Se}{Selenium}};158+ \node[below of=Se, Metalloid] (Te) {\NaturalElem{52}{127.6}{Te}{Tellurium}};159+ \node[below of=Te, Metalloid] (Po) {\NaturalElem{84}{209}{Po}{Polonium}};160+ \node[below of=Po, Metal] (Uuh) {\SyntheticElem{116}{293}{Uuh}{Ununhexium}};161+162+ % Group 17 - VIIA163+ \node[right of=O, Halogen] (F) {\NaturalElem{9}{18.998}{F}{Fluorine}};164+ \node[below of=F, Halogen] (Cl) {\NaturalElem{17}{35.453}{Cl}{Chlorine}};165+ \node[below of=Cl, Halogen] (Br) {\NaturalElem{35}{79.904}{Br}{Bromine}};166+ \node[below of=Br, Halogen] (I) {\NaturalElem{53}{126.9}{I}{Iodine}};167+ \node[below of=I, Halogen] (At) {\NaturalElem{85}{210}{At}{Astatine}};168+ \node[below of=At, Element] (Uus) {\SyntheticElem{117}{292}{Uus}{Ununseptium}};169+170+ % Group 18 - VIIIA171+ \node[right of=F, NobleGas] (Ne) {\NaturalElem{10}{20.180}{Ne}{Neon}};172+ \node[above of=Ne, NobleGas] (He) {\NaturalElem{2}{4.0025}{He}{Helium}};173+ \node[below of=Ne, NobleGas] (Ar) {\NaturalElem{18}{39.948}{Ar}{Argon}};174+ \node[below of=Ar, NobleGas] (Kr) {\NaturalElem{36}{83.8}{Kr}{Krypton}};175+ \node[below of=Kr, NobleGas] (Xe) {\NaturalElem{54}{131.29}{Xe}{Xenon}};176+ \node[below of=Xe, NobleGas] (Rn) {\NaturalElem{86}{222}{Rn}{Radon}};177+ \node[below of=Rn, Nonmetal] (Uuo) {\SyntheticElem{118}{294}{Uuo}{Ununoctium}};178+179+ % Period180+ \node[left of=H, PeriodLabel] (Period1) {1};181+ \node[left of=Li, PeriodLabel] (Period2) {2};182+ \node[left of=Na, PeriodLabel] (Period3) {3};183+ \node[left of=K, PeriodLabel] (Period4) {4};184+ \node[left of=Rb, PeriodLabel] (Period5) {5};185+ \node[left of=Cs, PeriodLabel] (Period6) {6};186+ \node[left of=Fr, PeriodLabel] (Period7) {7};187+188+ % Group189+ \node[above of=H, GroupLabel] (Group1) {1 \hfill IA};190+ \node[above of=Be, GroupLabel] (Group2) {2 \hfill IIA};191+ \node[above of=Sc, GroupLabel] (Group3) {3 \hfill IIIA};192+ \node[above of=Ti, GroupLabel] (Group4) {4 \hfill IVB};193+ \node[above of=V, GroupLabel] (Group5) {5 \hfill VB};194+ \node[above of=Cr, GroupLabel] (Group6) {6 \hfill VIB};195+ \node[above of=Mn, GroupLabel] (Group7) {7 \hfill VIIB};196+ \node[above of=Fe, GroupLabel] (Group8) {8 \hfill VIIIB};197+ \node[above of=Co, GroupLabel] (Group9) {9 \hfill VIIIB};198+ \node[above of=Ni, GroupLabel] (Group10) {10 \hfill VIIIB};199+ \node[above of=Cu, GroupLabel] (Group11) {11 \hfill IB};200+ \node[above of=Zn, GroupLabel] (Group12) {12 \hfill IIB};201+ \node[above of=B, GroupLabel] (Group13) {13 \hfill IIIA};202+ \node[above of=C, GroupLabel] (Group14) {14 \hfill IVA};203+ \node[above of=N, GroupLabel] (Group15) {15 \hfill VA};204+ \node[above of=O, GroupLabel] (Group16) {16 \hfill VIA};205+ \node[above of=F, GroupLabel] (Group17) {17 \hfill VIIA};206+ \node[above of=He, GroupLabel] (Group18) {18 \hfill VIIIA};207+208+ % Lanthanide209+ \node[below of=Rf, LanthanideActinide, yshift=-1cm] (La) {\NaturalElem{57}{138.91}{La}{Lanthanum}};210+ \node[right of=La, LanthanideActinide] (Ce) {\NaturalElem{58}{140.12}{Ce}{Cerium}};211+ \node[right of=Ce, LanthanideActinide] (Pr) {\NaturalElem{59}{140.91}{Pr}{Praseodymium}};212+ \node[right of=Pr, LanthanideActinide] (Nd) {\NaturalElem{60}{144.24}{Nd}{Neodymium}};213+ \node[right of=Nd, LanthanideActinide] (Pm) {\NaturalElem{61}{145}{Pm}{Promethium}};214+ \node[right of=Pm, LanthanideActinide] (Sm) {\NaturalElem{62}{150.36}{Sm}{Samarium}};215+ \node[right of=Sm, LanthanideActinide] (Eu) {\NaturalElem{63}{151.96}{Eu}{Europium}};216+ \node[right of=Eu, LanthanideActinide] (Gd) {\NaturalElem{64}{157.25}{Gd}{Gadolinium}};217+ \node[right of=Gd, LanthanideActinide] (Tb) {\NaturalElem{65}{158.93}{Tb}{Terbium}};218+ \node[right of=Tb, LanthanideActinide] (Dy) {\NaturalElem{66}{162.50}{Dy}{Dysprosium}};219+ \node[right of=Dy, LanthanideActinide] (Ho) {\NaturalElem{67}{164.93}{Ho}{Holmium}};220+ \node[right of=Ho, LanthanideActinide] (Er) {\NaturalElem{68}{167.26}{Er}{Erbium}};221+ \node[right of=Er, LanthanideActinide] (Tm) {\NaturalElem{69}{168.93}{Tm}{Thulium}};222+ \node[right of=Tm, LanthanideActinide] (Yb) {\NaturalElem{70}{173.04}{Yb}{Ytterbium}};223+ \node[right of=Yb, LanthanideActinide] (Lu) {\NaturalElem{71}{174.97}{Lu}{Lutetium}};224+225+ % Actinide226+ \node[below of=La, LanthanideActinide, yshift=-1cm] (Ac) {\NaturalElem{89}{227}{Ac}{Actinium}};227+ \node[right of=Ac, LanthanideActinide] (Th) {\NaturalElem{90}{232.04}{Th}{Thorium}};228+ \node[right of=Th, LanthanideActinide] (Pa) {\NaturalElem{91}{231.04}{Pa}{Protactinium}};229+ \node[right of=Pa, LanthanideActinide] (U) {\NaturalElem{92}{238.03}{U}{Uranium}};230+ \node[right of=U, LanthanideActinide] (Np) {\SyntheticElem{93}{237}{Np}{Neptunium}};231+ \node[right of=Np, LanthanideActinide] (Pu) {\SyntheticElem{94}{244}{Pu}{Plutonium}};232+ \node[right of=Pu, LanthanideActinide] (Am) {\SyntheticElem{95}{243}{Am}{Americium}};233+ \node[right of=Am, LanthanideActinide] (Cm) {\SyntheticElem{96}{247}{Cm}{Curium}};234+ \node[right of=Cm, LanthanideActinide] (Bk) {\SyntheticElem{97}{247}{Bk}{Berkelium}};235+ \node[right of=Bk, LanthanideActinide] (Cf) {\SyntheticElem{98}{251}{Cf}{Californium}};236+ \node[right of=Cf, LanthanideActinide] (Es) {\SyntheticElem{99}{252}{Es}{Einsteinium}};237+ \node[right of=Es, LanthanideActinide] (Fm) {\SyntheticElem{100}{257}{Fm}{Fermium}};238+ \node[right of=Fm, LanthanideActinide] (Md) {\SyntheticElem{101}{258}{Md}{Mendelevium}};239+ \node[right of=Md, LanthanideActinide] (No) {\SyntheticElem{102}{259}{No}{Nobelium}};240+ \node[right of=No, LanthanideActinide] (Lr) {\SyntheticElem{103}{262}{Lr}{Lawrencium}};241+242+ % Draw dotted lines connecting Lanthanide breakout to main table243+ \draw[thick,dotted] (LaLu.north west) -- (La.north west)244+ (LaLu.south west) -- (La.south west);245+ % Draw dotted lines connecting Actinide breakout to main table246+ \draw[thick,dotted] (AcLr.north west) -- (Ac.north west)247+ (AcLr.south west) -- (Ac.south west);248+249+ % Legend250+ \fill[AlkaliMetalFill] ($(La.north -| Fr.west) + (0,1em)$)251+ rectangle +(1em, 1em) node[right, yshift=-1.2ex] (AlkaliMetal) {Alkali Metal};252+ \fill[AlkalineEarthMetalFill] ($(AlkaliMetal.west) - (1em,2em)$)253+ rectangle +(1em, 1em) node[right, yshift=-1.2ex] (AlkalineEarthMetal) {Alkaline Earth Metal};254+ \fill[MetalFill] ($(AlkalineEarthMetal.west) - (1em,2em)$)255+ rectangle +(1em, 1em) node[right, yshift=-1.2ex] (Metal) {Metal};256+ \fill[MetalloidFill] ($(Metal.west) - (1em,2em)$)257+ rectangle +(1em, 1em) node[right, yshift=-1.2ex] (Metalloid) {Metalloid};258+ \fill[NonmetalFill] ($(Metalloid.west) - (1em,2em)$)259+ rectangle +(1em, 1em) node[right, yshift=-1.2ex] (Non-metal) {Non-metal};260+ \fill[HalogenFill] ($(Non-metal.west) - (1em,2em)$)261+ rectangle +(1em, 1em) node[right, yshift=-1.2ex] (Halogen) {Halogen};262+ \fill[NobleGasFill] ($(Halogen.west) - (1em,2em)$)263+ rectangle +(1em, 1em) node[right, yshift=-1.2ex] (NobleGas) {Noble Gas};264+ \fill[LanthanideActinideFill] ($(NobleGas.west) - (1em,2em)$)265+ rectangle +(1em, 1em) node[right, yshift=-1.2ex] (Lanthanide/Actinide) {Lanthanide/Actinide};266+267+ \node at (Ac -| Fr) [draw, Element, fill=white] (legend) {\NaturalElem{Z}{mass}{\LARGE Symbol}{Name}};268+ \node[align=left] at (Ac -| Ra) {black: natural\\\color{gray}gray: man-made};269+270+ % Diagram Title271+ \node at (H.west -| Fe.north) [scale=2, font={\sffamily\Huge\bfseries}]272+ {Periodic Table of Elements};273+274+\end{tikzpicture}275+276+\end{document}
A diagramzip/examples/umlet.uxf +353 -0
@@ -0,0 +1,353 @@
1+<?xml version="1.0" encoding="UTF-8"?>2+<umlet_diagram>3+ <element>4+ <type>com.umlet.element.base.Relation</type>5+ <coordinates>6+ <x>739</x>7+ <y>16</y>8+ <w>232</w>9+ <h>264</h>10+ </coordinates>11+ <panel_attributes>lt=&lt;-12+ when(spidersensor="rotate")13+ /block spider14+ </panel_attributes>15+ <additional_attributes>161;244;161;34;71;34;71;74</additional_attributes>16+ </element>17+ <element>18+ <type>com.umlet.element.custom.FinalState</type>19+ <coordinates>20+ <x>890</x>21+ <y>260</y>22+ <w>20</w>23+ <h>20</h>24+ </coordinates>25+ <panel_attributes></panel_attributes>26+ <additional_attributes>transparentSelection=false</additional_attributes>27+ </element>28+ <element>29+ <type>com.umlet.element.base.Relation</type>30+ <coordinates>31+ <x>750</x>32+ <y>170</y>33+ <w>160</w>34+ <h>137</h>35+ </coordinates>36+ <panel_attributes>lt=&lt;-37+ after (10s)38+ / block spider39+ </panel_attributes>40+ <additional_attributes>140;100;66;100;66;20</additional_attributes>41+ </element>42+ <element>43+ <type>com.umlet.element.custom.State</type>44+ <coordinates>45+ <x>340</x>46+ <y>420</y>47+ <w>100</w>48+ <h>40</h>49+ </coordinates>50+ <panel_attributes>wait</panel_attributes>51+ <additional_attributes>transparentSelection=false</additional_attributes>52+ </element>53+ <element>54+ <type>com.umlet.element.custom.HistoryState</type>55+ <coordinates>56+ <x>230</x>57+ <y>440</y>58+ <w>20</w>59+ <h>20</h>60+ </coordinates>61+ <panel_attributes></panel_attributes>62+ <additional_attributes>transparentSelection=false</additional_attributes>63+ </element>64+ <element>65+ <type>com.umlet.element.base.Relation</type>66+ <coordinates>67+ <x>230</x>68+ <y>416</y>69+ <w>130</w>70+ <h>54</h>71+ </coordinates>72+ <panel_attributes>lt=&lt;-73+ restart74+ </panel_attributes>75+ <additional_attributes>20;34;110;34</additional_attributes>76+ </element>77+ <element>78+ <type>com.umlet.element.base.Relation</type>79+ <coordinates>80+ <x>270</x>81+ <y>396</y>82+ <w>90</w>83+ <h>54</h>84+ </coordinates>85+ <panel_attributes>lt=&lt;-86+ pause87+ </panel_attributes>88+ <additional_attributes>70;34;20;34</additional_attributes>89+ </element>90+ <element>91+ <type>com.umlet.element.custom.FinalState</type>92+ <coordinates>93+ <x>90</x>94+ <y>400</y>95+ <w>20</w>96+ <h>20</h>97+ </coordinates>98+ <panel_attributes></panel_attributes>99+ <additional_attributes>transparentSelection=false</additional_attributes>100+ </element>101+ <element>102+ <type>com.umlet.element.base.Relation</type>103+ <coordinates>104+ <x>46</x>105+ <y>256</y>106+ <w>114</w>107+ <h>164</h>108+ </coordinates>109+ <panel_attributes>lt=&lt;-110+ after (10s)111+ /timeout112+ </panel_attributes>113+ <additional_attributes>54;144;54;34;94;34</additional_attributes>114+ </element>115+ <element>116+ <type>com.umlet.element.base.Relation</type>117+ <coordinates>118+ <x>230</x>119+ <y>110</y>120+ <w>190</w>121+ <h>170</h>122+ </coordinates>123+ <panel_attributes>lt=&lt;-124+ timeout125+ </panel_attributes>126+ <additional_attributes>20;150;110;150;110;20;170;20</additional_attributes>127+ </element>128+ <element>129+ <type>com.umlet.element.custom.State</type>130+ <coordinates>131+ <x>700</x>132+ <y>90</y>133+ <w>180</w>134+ <h>100</h>135+ </coordinates>136+ <panel_attributes>accept137+ boarding pass138+ --139+ entry/ release card140+ do/release spider141+ </panel_attributes>142+ <additional_attributes>transparentSelection=true</additional_attributes>143+ </element>144+ <element>145+ <type>com.umlet.element.base.Relation</type>146+ <coordinates>147+ <x>540</x>148+ <y>140</y>149+ <w>205</w>150+ <h>100</h>151+ </coordinates>152+ <panel_attributes>lt=&lt;-153+ [passenger booked]154+ </panel_attributes>155+ <additional_attributes>160;20;120;80;20;80</additional_attributes>156+ </element>157+ <element>158+ <type>com.umlet.element.base.Relation</type>159+ <coordinates>160+ <x>450</x>161+ <y>210</y>162+ <w>239</w>163+ <h>190</h>164+ </coordinates>165+ <panel_attributes>lt=&lt;-166+ [passenger not booked]167+ </panel_attributes>168+ <additional_attributes>219;170;99;170;99;20</additional_attributes>169+ </element>170+ <element>171+ <type>com.umlet.element.custom.State</type>172+ <coordinates>173+ <x>670</x>174+ <y>350</y>175+ <w>120</w>176+ <h>50</h>177+ </coordinates>178+ <panel_attributes>reject179+ boarding pass180+ </panel_attributes>181+ <additional_attributes>transparentSelection=false</additional_attributes>182+ </element>183+ <element>184+ <type>com.umlet.element.base.Relation</type>185+ <coordinates>186+ <x>480</x>187+ <y>130</y>188+ <w>142</w>189+ <h>100</h>190+ </coordinates>191+ <panel_attributes>lt=&lt;-192+ result of search193+ </panel_attributes>194+ <additional_attributes>71;80;71;20</additional_attributes>195+ </element>196+ <element>197+ <type>com.umlet.element.base.Relation</type>198+ <coordinates>199+ <x>270</x>200+ <y>70</y>201+ <w>150</w>202+ <h>40</h>203+ </coordinates>204+ <panel_attributes>lt=&lt;-</panel_attributes>205+ <additional_attributes>130;20;20;20</additional_attributes>206+ </element>207+ <element>208+ <type>com.umlet.element.custom.ThreeWayRelation</type>209+ <coordinates>210+ <x>540</x>211+ <y>210</y>212+ <w>20</w>213+ <h>20</h>214+ </coordinates>215+ <panel_attributes></panel_attributes>216+ <additional_attributes>transparentSelection=false</additional_attributes>217+ </element>218+ <element>219+ <type>com.umlet.element.custom.State</type>220+ <coordinates>221+ <x>140</x>222+ <y>60</y>223+ <w>150</w>224+ <h>420</h>225+ </coordinates>226+ <panel_attributes>read boarding pass227+ --228+ </panel_attributes>229+ <additional_attributes>transparentSelection=true</additional_attributes>230+ </element>231+ <element>232+ <type>com.umlet.element.custom.State</type>233+ <coordinates>234+ <x>400</x>235+ <y>60</y>236+ <w>180</w>237+ <h>90</h>238+ </coordinates>239+ <panel_attributes>check passenger240+ --241+ entry/start search242+ do/blink lamp243+ </panel_attributes>244+ <additional_attributes>transparentSelection=true</additional_attributes>245+ </element>246+ <element>247+ <type>com.umlet.element.custom.FinalState</type>248+ <coordinates>249+ <x>170</x>250+ <y>410</y>251+ <w>20</w>252+ <h>20</h>253+ </coordinates>254+ <panel_attributes></panel_attributes>255+ <additional_attributes>transparentSelection=false</additional_attributes>256+ </element>257+ <element>258+ <type>com.umlet.element.custom.State</type>259+ <coordinates>260+ <x>150</x>261+ <y>240</y>262+ <w>100</w>263+ <h>40</h>264+ </coordinates>265+ <panel_attributes>read266+ passenger ID267+ </panel_attributes>268+ <additional_attributes>transparentSelection=false</additional_attributes>269+ </element>270+ <element>271+ <type>com.umlet.element.custom.State</type>272+ <coordinates>273+ <x>150</x>274+ <y>330</y>275+ <w>100</w>276+ <h>40</h>277+ </coordinates>278+ <panel_attributes>identify279+ passenger280+ </panel_attributes>281+ <additional_attributes>transparentSelection=false</additional_attributes>282+ </element>283+ <element>284+ <type>com.umlet.element.base.Relation</type>285+ <coordinates>286+ <x>160</x>287+ <y>260</y>288+ <w>40</w>289+ <h>90</h>290+ </coordinates>291+ <panel_attributes>lt=&lt;-</panel_attributes>292+ <additional_attributes>20;70;20;20</additional_attributes>293+ </element>294+ <element>295+ <type>com.umlet.element.base.Relation</type>296+ <coordinates>297+ <x>160</x>298+ <y>100</y>299+ <w>40</w>300+ <h>70</h>301+ </coordinates>302+ <panel_attributes>lt=&lt;-</panel_attributes>303+ <additional_attributes>20;50;20;20</additional_attributes>304+ </element>305+ <element>306+ <type>com.umlet.element.base.Relation</type>307+ <coordinates>308+ <x>160</x>309+ <y>350</y>310+ <w>40</w>311+ <h>80</h>312+ </coordinates>313+ <panel_attributes>lt=&lt;-</panel_attributes>314+ <additional_attributes>20;60;20;20</additional_attributes>315+ </element>316+ <element>317+ <type>com.umlet.element.base.Relation</type>318+ <coordinates>319+ <x>140</x>320+ <y>170</y>321+ <w>78</w>322+ <h>90</h>323+ </coordinates>324+ <panel_attributes>lt=&lt;-325+ [valid]326+ </panel_attributes>327+ <additional_attributes>39;70;39;20</additional_attributes>328+ </element>329+ <element>330+ <type>com.umlet.element.custom.State</type>331+ <coordinates>332+ <x>150</x>333+ <y>150</y>334+ <w>100</w>335+ <h>40</h>336+ </coordinates>337+ <panel_attributes>check338+ validity339+ </panel_attributes>340+ <additional_attributes>transparentSelection=false</additional_attributes>341+ </element>342+ <element>343+ <type>com.umlet.element.custom.InitialState</type>344+ <coordinates>345+ <x>170</x>346+ <y>100</y>347+ <w>20</w>348+ <h>20</h>349+ </coordinates>350+ <panel_attributes></panel_attributes>351+ <additional_attributes>transparentSelection=false</additional_attributes>352+ </element>353+</umlet_diagram>
A diagramzip/examples/vega.json +95 -0
@@ -0,0 +1,95 @@
1+{2+ "$schema": "https://vega.github.io/schema/vega/v5.json",3+ "width": 400,4+ "height": 200,5+ "padding": 5,6+7+ "data": [8+ {9+ "name": "table",10+ "values": [11+ {"category": "A", "amount": 28},12+ {"category": "B", "amount": 55},13+ {"category": "C", "amount": 43},14+ {"category": "D", "amount": 91},15+ {"category": "E", "amount": 81},16+ {"category": "F", "amount": 53},17+ {"category": "G", "amount": 19},18+ {"category": "H", "amount": 87}19+ ]20+ }21+ ],22+23+ "signals": [24+ {25+ "name": "tooltip",26+ "value": {},27+ "on": [28+ {"events": "rect:mouseover", "update": "datum"},29+ {"events": "rect:mouseout", "update": "{}"}30+ ]31+ }32+ ],33+34+ "scales": [35+ {36+ "name": "xscale",37+ "type": "band",38+ "domain": {"data": "table", "field": "category"},39+ "range": "width",40+ "padding": 0.05,41+ "round": true42+ },43+ {44+ "name": "yscale",45+ "domain": {"data": "table", "field": "amount"},46+ "nice": true,47+ "range": "height"48+ }49+ ],50+51+ "axes": [52+ { "orient": "bottom", "scale": "xscale" },53+ { "orient": "left", "scale": "yscale" }54+ ],55+56+ "marks": [57+ {58+ "type": "rect",59+ "from": {"data":"table"},60+ "encode": {61+ "enter": {62+ "x": {"scale": "xscale", "field": "category"},63+ "width": {"scale": "xscale", "band": 1},64+ "y": {"scale": "yscale", "field": "amount"},65+ "y2": {"scale": "yscale", "value": 0}66+ },67+ "update": {68+ "fill": {"value": "steelblue"}69+ },70+ "hover": {71+ "fill": {"value": "red"}72+ }73+ }74+ },75+ {76+ "type": "text",77+ "encode": {78+ "enter": {79+ "align": {"value": "center"},80+ "baseline": {"value": "bottom"},81+ "fill": {"value": "#333"}82+ },83+ "update": {84+ "x": {"scale": "xscale", "signal": "tooltip.category", "band": 0.5},85+ "y": {"scale": "yscale", "signal": "tooltip.amount", "offset": -2},86+ "text": {"signal": "tooltip.amount"},87+ "fillOpacity": [88+ {"test": "datum === tooltip", "value": 0},89+ {"value": 1}90+ ]91+ }92+ }93+ }94+ ]95+}
A diagramzip/examples/vegalite.json +129 -0
@@ -0,0 +1,129 @@
1+{2+ "$schema": "https://vega.github.io/schema/vega-lite/v4.json",3+ "description": "Horizontally concatenated charts that show different types of discretizing scales.",4+ "data": {5+ "values": [6+ {"a": "A", "b": 28},7+ {"a": "B", "b": 55},8+ {"a": "C", "b": 43},9+ {"a": "D", "b": 91},10+ {"a": "E", "b": 81},11+ {"a": "F", "b": 53},12+ {"a": "G", "b": 19},13+ {"a": "H", "b": 87},14+ {"a": "I", "b": 52}15+ ]16+ },17+ "hconcat": [18+ {19+ "mark": "circle",20+ "encoding": {21+ "y": {22+ "field": "b",23+ "type": "nominal",24+ "sort": null,25+ "axis": {26+ "ticks": false,27+ "domain": false,28+ "title": null29+ }30+ },31+ "size": {32+ "field": "b",33+ "type": "quantitative",34+ "scale": {35+ "type": "quantize"36+ }37+ },38+ "color": {39+ "field": "b",40+ "type": "quantitative",41+ "scale": {42+ "type": "quantize",43+ "zero": true44+ },45+ "legend": {46+ "title": "Quantize"47+ }48+ }49+ }50+ },51+ {52+ "mark": "circle",53+ "encoding": {54+ "y": {55+ "field": "b",56+ "type": "nominal",57+ "sort": null,58+ "axis": {59+ "ticks": false,60+ "domain": false,61+ "title": null62+ }63+ },64+ "size": {65+ "field": "b",66+ "type": "quantitative",67+ "scale": {68+ "type": "quantile",69+ "range": [80, 160, 240, 320, 400]70+ }71+ },72+ "color": {73+ "field": "b",74+ "type": "quantitative",75+ "scale": {76+ "type": "quantile",77+ "scheme": "magma"78+ },79+ "legend": {80+ "format": "d",81+ "title": "Quantile"82+ }83+ }84+ }85+ },86+ {87+ "mark": "circle",88+ "encoding": {89+ "y": {90+ "field": "b",91+ "type": "nominal",92+ "sort": null,93+ "axis": {94+ "ticks": false,95+ "domain": false,96+ "title": null97+ }98+ },99+ "size": {100+ "field": "b",101+ "type": "quantitative",102+ "scale": {103+ "type": "threshold",104+ "domain": [30, 70],105+ "range": [80, 200, 320]106+ }107+ },108+ "color": {109+ "field": "b",110+ "type": "quantitative",111+ "scale": {112+ "type": "threshold",113+ "domain": [30, 70],114+ "scheme": "viridis"115+ },116+ "legend": {117+ "title": "Threshold"118+ }119+ }120+ }121+ }122+ ],123+ "resolve": {124+ "scale": {125+ "color": "independent",126+ "size": "independent"127+ }128+ }129+}
A diagramzip/examples/wavedrom.json5 +7 -0
A diagramzip/examples/wireviz.yaml +26 -0
M diagramzip/index.html +1 -1
M diagramzip/src/client-renderers.js +1 -1
M diagramzip/src/example-variants.js +2 -2
M diagramzip/src/examples.js +22 -22
@@ -1,24 +1,24 @@
1-import bpmn from '../../ci/tests/diagrams/example.bpmn?raw'2-import bytefield from '../../ci/tests/diagrams/bytefield.bf?raw'3-import d2 from '../../ci/tests/diagrams/connections.d2?raw'4-import dbml from '../../ci/tests/diagrams/dbml.dbml?raw'5-import diagramsnet from '../../ci/tests/diagrams/diagramsnet-venn.xml?raw'6-import erd from '../../ci/tests/diagrams/schema.erd?raw'7-import excalidraw from '../../ci/tests/diagrams/venn.excalidraw?raw'8-import goat from '../../ci/tests/diagrams/components.goat?raw'9-import nomnoml from '../../ci/tests/diagrams/pirate.nomnoml?raw'10-import nwdiag from '../../ci/tests/diagrams/network.diag?raw'11-import packetdiag from '../../ci/tests/diagrams/packet.diag?raw'12-import pikchr from '../../ci/tests/diagrams/diamond.pikchr?raw'13-import rackdiag from '../../ci/tests/diagrams/rack.diag?raw'14-import svgbob from '../../ci/tests/diagrams/cloud.bob?raw'15-import symbolator from '../../ci/tests/diagrams/component.sv?raw'16-import tikz from '../../ci/tests/diagrams/periodic-table.tex?raw'17-import umlet from '../../ci/tests/diagrams/umlet.xml?raw'18-import vega from '../../ci/tests/diagrams/bar-chart.vega?raw'19-import vegalite from '../../ci/tests/diagrams/discretizing-scale.vlite?raw'20-import wavedrom from '../../ci/tests/diagrams/wavedrom.json5?raw'21-import wireviz from '../../ci/tests/diagrams/wireviz.yaml?raw'1+import bpmn from '../examples/bpmn.bpmn?raw'2+import bytefield from '../examples/bytefield.bf?raw'3+import d2 from '../examples/d2.d2?raw'4+import dbml from '../examples/dbml.dbml?raw'5+import diagramsnet from '../examples/diagramsnet.drawio?raw'6+import erd from '../examples/erd.erd?raw'7+import excalidraw from '../examples/excalidraw.excalidraw?raw'8+import goat from '../examples/goat.goat?raw'9+import nomnoml from '../examples/nomnoml.nomnoml?raw'10+import nwdiag from '../examples/nwdiag.diag?raw'11+import packetdiag from '../examples/packetdiag.diag?raw'12+import pikchr from '../examples/pikchr.pikchr?raw'13+import rackdiag from '../examples/rackdiag.diag?raw'14+import svgbob from '../examples/svgbob.bob?raw'15+import symbolator from '../examples/symbolator.sv?raw'16+import tikz from '../examples/tikz.tex?raw'17+import umlet from '../examples/umlet.uxf?raw'18+import vega from '../examples/vega.json?raw'19+import vegalite from '../examples/vegalite.json?raw'20+import wavedrom from '../examples/wavedrom.json5?raw'21+import wireviz from '../examples/wireviz.yaml?raw'2222 import { diagramTypes } from './diagram-types.js'2323 import { exampleVariant } from './example-variants.js'2424 import { DEFAULT_SOURCE } from './state.js'
@@ -152,7 +152,7 @@ Rel(bob, tandem, "Completes tasks")
152152 v153153 +--------+--------+154154 | Shared Tasks |155- | {s} |155+ | |156156 +-----------------+`,157157 158158 // Domain-specific examples stay intact so they remain useful references for
M diagramzip/src/main.js +7 -7
@@ -4,6 +4,7 @@ import { createSourceEditor } from './source-editor.js'
44 import { stateForTypeChange } from './type-drafts.js'55 import {66 DEFAULT_DIAGRAM_TYPE,7+ documentTitle,78 normalizeMetadata,89 normalizePresentation,910 } from './state.js'
@@ -58,7 +59,10 @@ const typeDrafts = new Map()
5859 document.querySelector('#app').innerHTML = `5960 <main class="app-shell">6061 <header class="app-header">61- <a class="brand" href="/" aria-label="New diagram"><img class="brand-mark" src="/icon.svg?v=2" alt=""><span>diagram.zip</span></a>62+ <div class="document-identity">63+ <a class="brand" href="/" aria-label="New diagram" title="New diagram"><img class="brand-mark" src="/icon.svg?v=2" alt=""></a>64+ <input class="document-title" id="diagram-title" maxlength="200" placeholder="Untitled diagram" aria-label="Diagram title">65+ </div>6266 <div class="header-meta">6367 <span class="render-status" data-state="idle" role="status">Ready</span>6468 <label class="type-picker">
@@ -120,10 +124,6 @@ document.querySelector('#app').innerHTML = `
120124 <button class="icon-button" value="cancel" aria-label="Close">×</button>121125 </div>122126 <div class="details-fields">123- <label>124- <span>Title</span>125- <input id="diagram-title" maxlength="200" placeholder="Untitled diagram">126- </label>127127 <label>128128 <span>Description</span>129129 <textarea id="diagram-description" maxlength="2000" rows="4" placeholder="What does this diagram show?"></textarea>
@@ -265,7 +265,7 @@ typePicker.addEventListener('change', () => {
265265 266266 document.querySelector('#details').addEventListener('click', () => {267267 document.querySelector('#details-dialog').showModal()268- titleInput.focus()268+ descriptionInput.focus()269269 })270270 for (const input of [titleInput, descriptionInput, backgroundInput, paddingInput, frameInput]) {271271 input.addEventListener('input', () => {
@@ -994,7 +994,7 @@ function startNewDiagram() {
994994 function updateDocumentMetadata() {995995 const title = titleInput.value.trim()996996 const description = descriptionInput.value.trim()997- document.title = title ? `${title} — diagram.zip` : 'diagram.zip'997+ document.title = documentTitle(title)998998 document.querySelector('meta[name="description"]').content = description || 'Create diagrams from text and share them as a link.'999999 }10001000
M diagramzip/src/state.js +4 -0
M diagramzip/src/style.css +40 -8
@@ -49,6 +49,7 @@ dialog,
4949 .monaco-editor,5050 .monaco-editor .view-lines,5151 .source-editor-textarea,52+.document-title,5253 .share-options input,5354 .details-fields input,5455 .details-fields textarea,
@@ -76,7 +77,7 @@ button { cursor: pointer; }
7677 7778 .app-shell {7879 display: grid;79- grid-template-rows: 58px auto minmax(0, 1fr);80+ grid-template-rows: 64px auto minmax(0, 1fr);8081 height: 100%;8182 }8283
@@ -96,19 +97,46 @@ button { cursor: pointer; }
9697 .brand {9798 display: inline-flex;9899 align-items: center;99- gap: 10px;100100 color: var(--ink);101- font-weight: 780;102- letter-spacing: -.025em;103101 text-decoration: none;104102 }105103 106104 .brand-mark {107- width: 24px;108- height: 24px;105+ width: 40px;106+ height: 40px;109107 display: block;110108 }111109 110+.document-identity {111+ display: flex;112+ align-items: center;113+ flex: 1 1 320px;114+ gap: 12px;115+ min-width: 0;116+}117+118+.document-title {119+ width: min(38vw, 420px);120+ min-width: 90px;121+ padding: 4px 7px;122+ border: 1px solid transparent;123+ border-radius: 6px;124+ background: transparent;125+ color: var(--ink);126+ font-size: 22px;127+ font-weight: 440;128+ letter-spacing: -.025em;129+ outline: none;130+ text-overflow: ellipsis;131+}132+133+.document-title:hover { border-color: var(--line); }134+.document-title:focus {135+ border-color: var(--ink);136+ background: var(--surface);137+ box-shadow: 0 0 0 1px var(--ink);138+}139+112140 .header-meta {113141 display: flex;114142 align-items: center;
@@ -501,7 +529,7 @@ dialog::backdrop {
501529 :focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }502530 503531 @media (max-width: 760px) {504- .app-shell { grid-template-rows: 58px auto 42px minmax(0, 1fr); }532+ .app-shell { grid-template-rows: 64px auto 42px minmax(0, 1fr); }505533 .render-status { display: none; }506534 .render-status[data-state="error"] {507535 position: fixed;
@@ -521,7 +549,9 @@ dialog::backdrop {
521549 white-space: normal;522550 }523551 .app-header { padding-left: 14px; }524- .brand span:last-child { display: none; }552+ .brand-mark { width: 36px; height: 36px; }553+ .document-identity { flex-basis: 140px; gap: 8px; }554+ .document-title { width: 100%; font-size: 18px; }525555 .header-meta { flex: 1; justify-content: flex-end; gap: 6px; }526556 .draft-bar { align-items: stretch; flex-direction: column; gap: 7px; padding: 9px 14px; }527557 .draft-bar div { display: grid; grid-template-columns: 1fr 1fr; }
@@ -568,6 +598,8 @@ dialog::backdrop {
568598 .header-meta { gap: 6px; }569599 .type-picker { flex-basis: 108px; }570600 .type-picker select { max-width: 108px; }601+ .document-identity { flex-basis: 76px; }602+ .document-title { min-width: 40px; padding-inline: 4px; font-size: 16px; }571603 #details {572604 width: 36px;573605 padding-inline: 0;
M diagramzip/test/client-renderers.test.js +1 -1
M diagramzip/test/example-variants.test.js +3 -3
A diagramzip/test/examples.test.js +20 -0
M diagramzip/test/state.test.js +7 -1