clone

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

nit: remove custom styles on examples

Dami committed cbaf57e
commit
cbaf57eaf2ffabc7392d4108fb375e61a2f7e851
parent
711c0b669fd94d904540b0d2a1a8e4e5307ef666
author
Dami <dami.etoile@gmail.com>
6 files changed, +115 -143
Aapps/editor/src/example-defaults.js59+++++++++++++++++++++++++++++
Dapps/editor/src/example-variants.js37------------------
Mapps/editor/src/examples.js45+---------------------
Mapps/editor/src/main.js2+-
Aapps/editor/test/example-defaults.test.js53++++++++++++++++++++++++++
Dapps/editor/test/example-variants.test.js62------------------------------
A apps/editor/src/example-defaults.js +59 -0
@@ -0,0 +1,59 @@
1+const EXAMPLE_NAMES = {2+ plantuml: 'Tandem task sync',3+ mermaid: 'Shared task flow',4+ graphviz: 'Tandem collaboration graph',5+ d2: 'Connection styles',6+ c4plantuml: 'Tandem system context',7+ blockdiag: 'Tandem block flow',8+ seqdiag: 'Tandem task sequence',9+ actdiag: 'Tandem delivery activities',10+ nwdiag: 'Network layout',11+ packetdiag: 'TCP packet structure',12+ rackdiag: 'Rack layout',13+ bpmn: 'Agent-assisted review',14+ bytefield: 'Byte field layout',15+ dbml: 'Database schema',16+ diagramsnet: 'Venn diagram',17+ ditaa: 'Tandem ASCII architecture',18+ erd: 'Data model',19+ excalidraw: 'Venn sketch',20+ goat: 'Component shapes',21+ nomnoml: 'Pirate class diagram',22+ pikchr: 'Cardinal points',23+ structurizr: 'Tandem landscape',24+ svgbob: 'Cloud network',25+ symbolator: 'Hardware component',26+ tikz: 'Periodic table',27+ umlet: 'UML example',28+ vega: 'Bar chart',29+ vegalite: 'Discretizing scale',30+ wavedrom: 'Timing diagram',31+ wireviz: 'Wiring harness',32+}33+34+export function namedExample(type) {35+ return {36+ meta: {37+ title: EXAMPLE_NAMES[type] ?? 'Diagram example',38+ description: '',39+ },40+ presentation: {41+ background: '',42+ padding: 0,43+ frame: false,44+ appearance: 'raw',45+ },46+ }47+}48+49+export function refreshMatchingExampleMetadata(state, exampleState) {50+ if (state?.source !== exampleState?.source || state?.meta?.title?.trim()) return state51+52+ return {53+ ...state,54+ meta: {55+ ...state.meta,56+ title: exampleState.meta.title,57+ },58+ }59+}
D apps/editor/src/example-variants.js +0 -37
M apps/editor/src/examples.js +2 -43
@@ -19,8 +19,7 @@ import vega from '../../../examples/diagrams/bar-chart.vega?raw'
1919 import vegalite from '../../../examples/diagrams/discretizing-scale.vlite?raw'2020 import wavedrom from '../../../examples/diagrams/wavedrom.json5?raw'2121 import wireviz from '../../../examples/diagrams/wireviz.yaml?raw'22-import { diagramTypes } from './diagram-types.js'23-import { defaultExampleAppearance, exampleVariant } from './example-variants.js'22+import { namedExample } from './example-defaults.js'2423 import { DEFAULT_SOURCE } from './state.js'2524 2625 const EXAMPLES = {
@@ -186,55 +185,15 @@ Rel(bob, tandem, "Completes tasks")
186185 wireviz,187186 }188187 189-const EXAMPLE_CONTEXT = {190- plantuml: ['Tandem task sync', 'Alice and Bob coordinate shared tasks through their agents.'],191- mermaid: ['Shared task flow', 'A compact view of ideas moving through the Tandem team.'],192- graphviz: ['Tandem collaboration graph', 'People and agents converge on one synchronized task list.'],193- d2: ['Connection styles', 'D2 connection, arrowhead, shape, and animation syntax.'],194- c4plantuml: ['Tandem system context', 'The people and software systems surrounding Tandem.'],195- blockdiag: ['Tandem block flow', 'A block-oriented view of the shared task workflow.'],196- seqdiag: ['Tandem task sequence', 'A task moves from Alice to Bob and back through Tandem.'],197- actdiag: ['Tandem delivery activities', 'Work crosses Alice, Alice Agent, and Bob Agent lanes.'],198- nwdiag: ['Network layout', 'A sample network topology and its connected address ranges.'],199- packetdiag: ['TCP packet structure', 'The bit-level layout of a TCP packet header.'],200- rackdiag: ['Rack layout', 'A sample equipment rack rendered from rackdiag syntax.'],201- bpmn: ['Agent-assisted review', 'A BPMN review flow that branches on test results.'],202- bytefield: ['Byte field layout', 'A compact byte-oriented protocol field example.'],203- dbml: ['Database schema', 'Tables and relationships expressed with DBML.'],204- diagramsnet: ['Venn diagram', 'An overlapping-set example imported from diagrams.net.'],205- ditaa: ['Tandem ASCII architecture', 'An ASCII sketch becomes a rendered system diagram.'],206- erd: ['Data model', 'Entities and relationships in a small relational schema.'],207- excalidraw: ['Venn sketch', 'A hand-drawn overlapping-set diagram.'],208- goat: ['Component shapes', 'GoAT exercises boxes, connectors, curves, and symbols.'],209- nomnoml: ['Pirate class diagram', 'A playful class diagram demonstrating Nomnoml syntax.'],210- pikchr: ['Cardinal points', 'A diamond marks north, east, south, and west.'],211- structurizr: ['Tandem landscape', 'A software landscape linking people, agents, and Tandem.'],212- svgbob: ['Cloud network', 'An ASCII cloud connects clients and services.'],213- symbolator: ['Hardware component', 'A component symbol generated from interface declarations.'],214- tikz: ['Periodic table', 'A color-coded periodic table rendered with TikZ.'],215- umlet: ['UML example', 'A UMLet document rendered directly from its XML form.'],216- vega: ['Bar chart', 'A declarative bar chart expressed with Vega.'],217- vegalite: ['Discretizing scale', 'A Vega-Lite example comparing discretized values.'],218- wavedrom: ['Timing diagram', 'Digital signals and timing relationships rendered by WaveDrom.'],219- wireviz: ['Wiring harness', 'Connections, cables, and pins described with WireViz.'],220-}221-222188 export function exampleFor(type) {223189 return EXAMPLES[type] ?? DEFAULT_SOURCE224190 }225191 226192 export function exampleStateFor(type) {227- const index = diagramTypes.findIndex(diagramType => diagramType.id === type)228- const [title, description] = EXAMPLE_CONTEXT[type] ?? ['Diagram example', 'A diagram.zip catalog example.']229- const variant = exampleVariant(Math.max(index, 0), { title, description })230193 return {231194 type,232195 source: exampleFor(type),233196 options: {},234- ...variant,235- presentation: {236- ...variant.presentation,237- appearance: defaultExampleAppearance(type),238- },197+ ...namedExample(type),239198 }240199 }
M apps/editor/src/main.js +1 -1
A apps/editor/test/example-defaults.test.js +53 -0
@@ -0,0 +1,53 @@
1+import assert from 'node:assert/strict'2+import test from 'node:test'3+import { diagramTypes } from '../src/diagram-types.js'4+import {5+ namedExample,6+ refreshMatchingExampleMetadata,7+} from '../src/example-defaults.js'8+9+test('names every example without adding description or presentation styling', () => {10+ for (const { id } of diagramTypes) {11+ const example = namedExample(id)12+ assert.ok(example.meta.title)13+ assert.equal(example.meta.title, example.meta.title.trim())14+ assert.equal(example.meta.description, '')15+ assert.deepEqual(example.presentation, {16+ background: '',17+ padding: 0,18+ frame: false,19+ appearance: 'raw',20+ })21+ }22+})23+24+test('names an untitled draft matching its bundled example', () => {25+ const state = {26+ type: 'd2',27+ source: 'a -> b',28+ meta: { title: '', description: '' },29+ presentation: { padding: 24 },30+ }31+ const example = {32+ type: 'd2',33+ source: 'a -> b',34+ meta: { title: 'Connection styles', description: '' },35+ }36+37+ assert.deepEqual(refreshMatchingExampleMetadata(state, example), {38+ ...state,39+ meta: { title: 'Connection styles', description: '' },40+ })41+})42+43+test('preserves named and edited drafts', () => {44+ const example = {45+ source: 'a -> b',46+ meta: { title: 'Connection styles', description: '' },47+ }48+ const named = { source: example.source, meta: { title: 'Mine', description: '' } }49+ const edited = { source: 'a -> b: edited', meta: { title: '', description: '' } }50+51+ assert.equal(refreshMatchingExampleMetadata(named, example), named)52+ assert.equal(refreshMatchingExampleMetadata(edited, example), edited)53+})
D apps/editor/test/example-variants.test.js +0 -62
@@ -1,62 +0,0 @@
1-import assert from 'node:assert/strict'2-import test from 'node:test'3-import {4- defaultExampleAppearance,5- exampleVariant,6- grayCode,7- refreshMatchingExampleMetadata,8-} from '../src/example-variants.js'9-10-test('uses adaptive normalized appearances for catalog examples', () => {11- assert.equal(defaultExampleAppearance('d2'), 'auto-transparent')12- assert.equal(defaultExampleAppearance('diagramsnet'), 'auto-framed')13-})14-15-test('changes one example axis at a time across the catalog', () => {16- for (let index = 1; index < 30; index++) {17- const changedBits = grayCode(index) ^ grayCode(index - 1)18- assert.equal(changedBits > 0 && (changedBits & (changedBits - 1)) === 0, true)19- }20-})21-22-test('names every example while varying descriptions and padding', () => {23- const context = { title: 'Title', description: 'Description' }24- const variants = Array.from({ length: 30 }, (_, index) => exampleVariant(index, context))25- assert.ok(variants.every(variant => variant.meta.title === context.title))26- assert.ok(variants.some(variant => variant.meta.description))27- assert.ok(variants.some(variant => !variant.meta.description))28- assert.ok(variants.some(variant => variant.presentation.padding))29- assert.ok(variants.every(variant => variant.presentation.background === ''))30- assert.ok(variants.every(variant => variant.presentation.frame === false))31-})32-33-test('refreshes metadata for an untitled draft matching its bundled example', () => {34- const state = {35- type: 'd2',36- source: 'a -> b',37- meta: { title: '', description: '' },38- presentation: { padding: 24 },39- }40- const example = {41- type: 'd2',42- source: 'a -> b',43- meta: { title: 'Connection styles', description: 'D2 syntax.' },44- }45-46- assert.deepEqual(refreshMatchingExampleMetadata(state, example), {47- ...state,48- meta: { title: 'Connection styles', description: 'D2 syntax.' },49- })50-})51-52-test('preserves named and edited drafts', () => {53- const example = {54- source: 'a -> b',55- meta: { title: 'Connection styles', description: 'D2 syntax.' },56- }57- const named = { source: example.source, meta: { title: 'Mine', description: '' } }58- const edited = { source: 'a -> b: edited', meta: { title: '', description: '' } }59-60- assert.equal(refreshMatchingExampleMetadata(named, example), named)61- assert.equal(refreshMatchingExampleMetadata(edited, example), edited)62-})