sketchmark 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +748 -0
  3. package/dist/animation/index.d.ts +56 -0
  4. package/dist/animation/index.d.ts.map +1 -0
  5. package/dist/ast/index.d.ts +2 -0
  6. package/dist/ast/index.d.ts.map +1 -0
  7. package/dist/ast/types.d.ts +159 -0
  8. package/dist/ast/types.d.ts.map +1 -0
  9. package/dist/export/index.d.ts +21 -0
  10. package/dist/export/index.d.ts.map +1 -0
  11. package/dist/index.cjs +4706 -0
  12. package/dist/index.cjs.map +1 -0
  13. package/dist/index.d.ts +51 -0
  14. package/dist/index.d.ts.map +1 -0
  15. package/dist/index.js +4669 -0
  16. package/dist/index.js.map +1 -0
  17. package/dist/layout/index.d.ts +4 -0
  18. package/dist/layout/index.d.ts.map +1 -0
  19. package/dist/parser/index.d.ts +9 -0
  20. package/dist/parser/index.d.ts.map +1 -0
  21. package/dist/parser/tokenizer.d.ts +10 -0
  22. package/dist/parser/tokenizer.d.ts.map +1 -0
  23. package/dist/renderer/canvas/index.d.ts +14 -0
  24. package/dist/renderer/canvas/index.d.ts.map +1 -0
  25. package/dist/renderer/canvas/roughChartCanvas.d.ts +16 -0
  26. package/dist/renderer/canvas/roughChartCanvas.d.ts.map +1 -0
  27. package/dist/renderer/roughChart.d.ts +57 -0
  28. package/dist/renderer/roughChart.d.ts.map +1 -0
  29. package/dist/renderer/svg/index.d.ts +13 -0
  30. package/dist/renderer/svg/index.d.ts.map +1 -0
  31. package/dist/renderer/svg/roughChartSVG.d.ts +12 -0
  32. package/dist/renderer/svg/roughChartSVG.d.ts.map +1 -0
  33. package/dist/scene/index.d.ts +118 -0
  34. package/dist/scene/index.d.ts.map +1 -0
  35. package/dist/sketchmark.iife.js +4710 -0
  36. package/dist/theme/index.d.ts +35 -0
  37. package/dist/theme/index.d.ts.map +1 -0
  38. package/dist/utils/index.d.ts +14 -0
  39. package/dist/utils/index.d.ts.map +1 -0
  40. package/package.json +66 -0
package/README.md ADDED
@@ -0,0 +1,748 @@
1
+ # sketchmark
2
+
3
+ A text-based diagram DSL that renders hand-drawn SVG and Canvas diagrams using [rough.js](https://roughjs.com). Write diagrams as plain text, get sketchy, expressive visuals with a full animation system.
4
+
5
+ ```
6
+ diagram
7
+ title label="System Architecture"
8
+
9
+ box client label="Client App" theme=primary
10
+ box gateway label="API Gateway" theme=warning
11
+ box db label="PostgreSQL" theme=success
12
+
13
+ client --> gateway label="HTTPS"
14
+ gateway --> db label="SQL"
15
+
16
+ step highlight client
17
+ step draw client-->gateway
18
+ step highlight gateway
19
+ step draw gateway-->db
20
+ end
21
+ ```
22
+
23
+ ---
24
+
25
+ ## Table of Contents
26
+
27
+ - [Installation](#installation)
28
+ - [Quick Start](#quick-start)
29
+ - [DSL Reference](#dsl-reference)
30
+ - [Diagram Header](#diagram-header)
31
+ - [Node Shapes](#node-shapes)
32
+ - [Edges](#edges)
33
+ - [Groups](#groups)
34
+ - [Tables](#tables)
35
+ - [Notes](#notes)
36
+ - [Charts](#charts)
37
+ - [Themes](#themes)
38
+ - [Animation Steps](#animation-steps)
39
+ - [Layout System](#layout-system)
40
+ - [Animation System](#animation-system)
41
+ - [Theme Palettes](#theme-palettes)
42
+ - [API Reference](#api-reference)
43
+ - [Export](#export)
44
+ - [Examples](#examples)
45
+
46
+ ---
47
+
48
+ ## Installation
49
+
50
+ ```bash
51
+ npm install sketchmark roughjs
52
+ ```
53
+
54
+ rough.js is a peer dependency — it must be available at runtime.
55
+
56
+ ---
57
+
58
+ ## Quick Start
59
+
60
+ **With a bundler (Vite, webpack, Next.js):**
61
+
62
+ ```typescript
63
+ import { render } from 'sketchmark';
64
+
65
+ const instance = render({
66
+ container: document.getElementById('diagram'),
67
+ dsl: `
68
+ diagram
69
+ box a label="Hello"
70
+ box b label="World"
71
+ a --> b label="connects"
72
+ `,
73
+ renderer: 'svg',
74
+ svgOptions: { showTitle: true, interactive: true,transparent: true },
75
+ });
76
+
77
+ // Step through animation
78
+ instance.anim.next();
79
+ instance.anim.play(800);
80
+ ```
81
+
82
+ **CDN / no bundler:**
83
+
84
+ ```html
85
+ <script src="https://unpkg.com/roughjs@4.6.6/bundled/rough.js"></script>
86
+ <script type="module">
87
+ import { render } from 'https://unpkg.com/sketchmark/dist/index.js';
88
+
89
+ render({
90
+ container: document.getElementById('diagram'),
91
+ dsl: `diagram\nbox a label="Hello"\nbox b label="World"\na --> b`,
92
+ });
93
+ </script>
94
+ ```
95
+
96
+ **CommonJS:**
97
+
98
+ ```javascript
99
+ const { parse, buildSceneGraph, layout } = require('sketchmark');
100
+ ```
101
+
102
+ ---
103
+
104
+ ## DSL Reference
105
+
106
+ Every diagram starts with `diagram` and ends with `end`.
107
+
108
+ ```
109
+ diagram
110
+ title label="My Diagram"
111
+ layout row
112
+ config gap=60
113
+
114
+ ... nodes, edges, groups, steps ...
115
+
116
+ end
117
+ ```
118
+
119
+ ### Diagram Header
120
+
121
+ | Keyword | Example | Description |
122
+ |---|---|---|
123
+ | `title` | `title label="My Diagram"` | Title shown above the diagram |
124
+ | `layout` | `layout row` | Root layout direction: `row`, `column`, `grid` |
125
+ | `config gap` | `config gap=60` | Gap between root-level items (default: 80) |
126
+ | `config margin` | `config margin=40` | Outer canvas margin (default: 60) |
127
+ | `config theme` | `config theme=ocean` | Global palette (see [Theme Palettes](#theme-palettes)) |
128
+
129
+ ---
130
+
131
+ ### Node Shapes
132
+
133
+ ```
134
+ box id label="..." [theme=X] [width=N] [height=N]
135
+ circle id label="..."
136
+ diamond id label="..."
137
+ hexagon id label="..."
138
+ triangle id label="..."
139
+ cylinder id label="..."
140
+ parallelogram id label="..."
141
+ text id label="..."
142
+ image id label="..." url="https://..."
143
+ ```
144
+
145
+ **Common properties:**
146
+
147
+ | Property | Example | Description |
148
+ |---|---|---|
149
+ | `label` | `label="API Gateway"` | Display text |
150
+ | `theme` | `theme=primary` | Named theme (defined with `theme` keyword) |
151
+ | `width` | `width=140` | Override auto-width in px |
152
+ | `height` | `height=55` | Override auto-height in px |
153
+ | `fill` | `fill="#e8f4ff"` | Background fill color |
154
+ | `stroke` | `stroke="#0044cc"` | Border color |
155
+ | `color` | `color="#003399"` | Text color |
156
+ | `font-size` | `font-size=12` | Label font size |
157
+
158
+ **Example:**
159
+ ```
160
+ box gateway label="API Gateway" theme=warning width=150 height=55
161
+ circle user label="User" fill="#e8f4ff" stroke="#0044cc" color="#003399"
162
+ cylinder db label="PostgreSQL" theme=success width=140 height=65
163
+ ```
164
+
165
+ ---
166
+
167
+ ### Edges
168
+
169
+ ```
170
+ fromId connector toId [label="..."]
171
+ ```
172
+
173
+ **Connectors:**
174
+
175
+ | Connector | Arrow | Line |
176
+ |---|---|---|
177
+ | `->` | end | solid |
178
+ | `<-` | start | solid |
179
+ | `<->` | both | solid |
180
+ | `-->` | end | dashed |
181
+ | `<-->` | both | dashed |
182
+ | `--` | none | solid |
183
+ | `---` | none | dashed |
184
+
185
+ **Example:**
186
+ ```
187
+ client --> gateway label="HTTPS"
188
+ gateway <-> auth label="verify"
189
+ db --- replica label="sync"
190
+ a --- b
191
+ ```
192
+
193
+ ---
194
+
195
+ ### Groups
196
+
197
+ Groups are containers that arrange children using a flexbox-style layout.
198
+
199
+ ```
200
+ group id [label="..."] [layout=row|column|grid] [gap=N] [padding=N]
201
+ [justify=start|center|end|space-between|space-around]
202
+ [align=start|center|end]
203
+ [columns=N]
204
+ [width=N] [height=N]
205
+ [theme=X]
206
+ {
207
+ box child1 label="..."
208
+ box child2 label="..."
209
+ group nested { ... }
210
+ }
211
+ ```
212
+
213
+ **Properties:**
214
+
215
+ | Property | Default | Description |
216
+ |---|---|---|
217
+ | `layout` | `column` | `row`, `column`, or `grid` |
218
+ | `gap` | `10` | Space between children in px |
219
+ | `padding` | `26` | Inner padding in px |
220
+ | `justify` | `start` | Main-axis distribution of children |
221
+ | `align` | `start` | Cross-axis alignment of children |
222
+ | `columns` | `1` | Number of columns when `layout=grid` |
223
+ | `width` | auto | Minimum width — enables `justify` distribution |
224
+ | `height` | auto | Minimum height |
225
+ | `theme` | — | Named theme for border/background |
226
+
227
+ > **Note on `justify`:** Requires an explicit `width` larger than the children's total width to have visible effect. Without extra space, all five values look identical.
228
+
229
+ **Example:**
230
+ ```
231
+ group services label="Microservices" layout=column gap=16 padding=30 theme=muted
232
+ {
233
+ box auth label="Auth Service" theme=primary width=140 height=55
234
+ box billing label="Billing Service" theme=primary width=140 height=55
235
+ }
236
+ ```
237
+
238
+ **Grid layout:**
239
+ ```
240
+ group icons layout=grid columns=3 gap=20 padding=24 width=400
241
+ {
242
+ box a label="A" width=100 height=60
243
+ box b label="B" width=100 height=60
244
+ box c label="C" width=100 height=60
245
+ box d label="D" width=100 height=60
246
+ }
247
+ ```
248
+
249
+ **Justify example:**
250
+ ```
251
+ group nav layout=row justify=space-between width=500 padding=20 gap=10
252
+ {
253
+ box home label="Home" width=80 height=40
254
+ box about label="About" width=80 height=40
255
+ box contact label="Contact" width=80 height=40
256
+ }
257
+ ```
258
+
259
+ ---
260
+
261
+ ### Tables
262
+
263
+ ```
264
+ table id [label="..."] [theme=X]
265
+ {
266
+ header Col1 Col2 Col3
267
+ row val1 val2 val3
268
+ row val4 val5 val6
269
+ }
270
+ ```
271
+
272
+ **Example:**
273
+ ```
274
+ table pricing label="Pricing Plans"
275
+ {
276
+ header Plan Price Requests
277
+ row Free $0 1k/day
278
+ row Pro $29 100k/day
279
+ row Enterprise $299 Unlimited
280
+ }
281
+ ```
282
+
283
+ ---
284
+
285
+ ### Notes
286
+
287
+ Single or multiline sticky notes.
288
+
289
+ ```
290
+ note id label="Single line note" [theme=X]
291
+ note id label="Line one\nLine two\nLine three"
292
+ ```
293
+
294
+ ---
295
+
296
+ ### Charts
297
+
298
+ ```
299
+ bar-chart id [title="..."] [width=N] [height=N] [theme=X]
300
+ line-chart id ...
301
+ area-chart id ...
302
+ pie-chart id ...
303
+ donut-chart id ...
304
+ scatter-chart id ...
305
+
306
+ data
307
+ [
308
+ ["Label", "Series1", "Series2"],
309
+ ["Jan", 120, 80 ],
310
+ ["Feb", 150, 95 ],
311
+ ["Mar", 130, 110 ]
312
+ ]
313
+ ```
314
+
315
+ **Pie / donut data format:**
316
+ ```
317
+ pie-chart revenue title="Revenue Split"
318
+ data
319
+ [
320
+ ["Product", 45],
321
+ ["Services", 30],
322
+ ["Support", 25]
323
+ ]
324
+ ```
325
+
326
+ **Scatter data format:**
327
+ ```
328
+ scatter-chart perf title="Performance"
329
+ data
330
+ [
331
+ ["headers", "x", "y"],
332
+ ["Server A", 10, 95],
333
+ ["Server B", 20, 87]
334
+ ]
335
+ ```
336
+
337
+ ---
338
+
339
+ ### Themes
340
+
341
+ Define reusable style presets with `theme`, then apply them to any node or group.
342
+
343
+ ```
344
+ theme primary fill="#e8f4ff" stroke="#0044cc" color="#003399"
345
+ theme success fill="#e8ffe8" stroke="#007700" color="#004400"
346
+ theme warning fill="#fff9e6" stroke="#f0a500" color="#7a5000"
347
+ theme danger fill="#ffe8e8" stroke="#cc0000" color="#900000"
348
+ theme muted fill="#f5f5f5" stroke="#999999" color="#444444"
349
+ ```
350
+
351
+ Apply: `box myNode label="..." theme=primary`
352
+
353
+ ---
354
+
355
+ ### Animation Steps
356
+
357
+ ```
358
+ step action target [options]
359
+ ```
360
+
361
+ **Actions:**
362
+
363
+ | Action | Syntax | Description |
364
+ |---|---|---|
365
+ | `highlight` | `step highlight nodeId` | Pulsing glow on a node |
366
+ | `fade` | `step fade nodeId` | Fade node to 22% opacity |
367
+ | `unfade` | `step unfade nodeId` | Restore full opacity |
368
+ | `draw` | `step draw nodeId` | Animate node appearing (stroke-draw) |
369
+ | `draw` | `step draw a-->b` | Animate edge appearing |
370
+ | `erase` | `step erase nodeId` | Fade element to invisible |
371
+ | `show` | `step show nodeId` | Make hidden element visible |
372
+ | `hide` | `step hide nodeId` | Hide element |
373
+ | `pulse` | `step pulse nodeId` | Single brightness flash |
374
+ | `color` | `step color nodeId #ff0000` | Change fill color |
375
+ | `move` | `step move nodeId dx=50 dy=0` | Translate by dx/dy px |
376
+ | `scale` | `step scale nodeId factor=1.5` | Scale (absolute, 1.0 = normal) |
377
+ | `rotate` | `step rotate nodeId deg=45` | Rotate (cumulative degrees) |
378
+
379
+ **Options:**
380
+
381
+ | Option | Example | Description |
382
+ |---|---|---|
383
+ | `duration` | `duration=600` | Animation duration in ms |
384
+ | `dx` | `dx=100` | X offset for `move` |
385
+ | `dy` | `dy=-80` | Y offset for `move` |
386
+ | `factor` | `factor=1.5` | Scale multiplier for `scale` |
387
+ | `deg` | `deg=45` | Degrees for `rotate` (cumulative) |
388
+
389
+ **Notes on `move` / `scale` / `rotate`:**
390
+ - `move` is cumulative — `dx=50` twice = 100px total
391
+ - `scale` is absolute — `factor=1.5` always means 1.5×, `factor=1.0` resets to normal
392
+ - `rotate` is cumulative — `deg=45` twice = 90° total, `deg=-45` rotates back
393
+
394
+ ---
395
+
396
+ ## Layout System
397
+
398
+ ### Root layout
399
+
400
+ Controls how top-level items (groups, standalone nodes) are arranged:
401
+
402
+ ```
403
+ layout row # left to right (default)
404
+ layout column # top to bottom
405
+ layout grid # grid, use config columns=N
406
+ ```
407
+
408
+ ### Group layout
409
+
410
+ Each group is an independent flex container:
411
+
412
+ ```
413
+ group g layout=row justify=space-between width=500 gap=16 padding=20
414
+ ```
415
+
416
+ ### `justify` values
417
+
418
+ | Value | Effect |
419
+ |---|---|
420
+ | `start` | Pack children to the start (default) |
421
+ | `center` | Center children in the container |
422
+ | `end` | Pack children to the end |
423
+ | `space-between` | First at start, last at end, equal gaps between |
424
+ | `space-around` | Equal space around each child |
425
+
426
+ > Requires `width` wider than total child width to be visible.
427
+
428
+ ### `align` values
429
+
430
+ | Value | Effect |
431
+ |---|---|
432
+ | `start` | Align to the start of the cross-axis (default) |
433
+ | `center` | Center on the cross-axis |
434
+ | `end` | Align to the end of the cross-axis |
435
+
436
+ ---
437
+
438
+ ## Animation System
439
+
440
+ The `AnimationController` is returned as `instance.anim` from `render()`.
441
+
442
+ ```typescript
443
+ const instance = render({ container, dsl });
444
+ const { anim } = instance;
445
+
446
+ anim.next(); // advance one step
447
+ anim.prev(); // go back one step
448
+ anim.reset(); // return to initial state
449
+ anim.goTo(3); // jump to specific step index
450
+ await anim.play(800); // auto-play, 800ms per step
451
+
452
+ anim.currentStep // current step index (-1 = not started)
453
+ anim.total // total number of steps
454
+ anim.canNext // boolean
455
+ anim.canPrev // boolean
456
+
457
+ // listen to events
458
+ anim.on((event) => {
459
+ // event.type: 'step-change' | 'animation-reset' |
460
+ // 'animation-start' | 'animation-end' | 'step-complete'
461
+ console.log(event.stepIndex, event.step);
462
+ });
463
+ ```
464
+
465
+ **Slide-in entrance pattern:**
466
+ ```
467
+ step move nodeId dx=0 dy=80 # push below final position
468
+ step draw nodeId # reveal at offset
469
+ step move nodeId dx=0 dy=-80 # animate into final position
470
+ ```
471
+
472
+ **Wobble then fail pattern:**
473
+ ```
474
+ step rotate nodeId deg=8
475
+ step rotate nodeId deg=-8
476
+ step rotate nodeId deg=8
477
+ step rotate nodeId deg=25 # cumulative = 33°, looks like toppling
478
+ step fade nodeId
479
+ ```
480
+
481
+ ---
482
+
483
+ ## Theme Palettes
484
+
485
+ Set a global palette with `config theme=NAME`. Available palettes:
486
+
487
+ | Name | Description |
488
+ |---|---|
489
+ | `light` | Warm parchment (default) |
490
+ | `dark` | Dark warm background |
491
+ | `ocean` | Cool blues |
492
+ | `forest` | Greens |
493
+ | `sunset` | Warm oranges and reds |
494
+ | `slate` | Cool grays |
495
+ | `rose` | Pinks and magentas |
496
+ | `midnight` | GitHub-dark style blues |
497
+
498
+ ```
499
+ config theme=ocean
500
+ ```
501
+
502
+ ---
503
+
504
+ ## API Reference
505
+
506
+ ### `render(options): DiagramInstance`
507
+
508
+ One-call API. Parses DSL, builds scene, lays out, renders, and returns a controller.
509
+
510
+ ```typescript
511
+ import { render } from 'sketchmark';
512
+
513
+ const instance = render({
514
+ container: '#my-div', // CSS selector, HTMLElement, or SVGSVGElement
515
+ dsl: '...', // DSL source text
516
+ renderer: 'svg', // 'svg' (default) | 'canvas'
517
+ injectCSS: true, // inject animation CSS into <head>
518
+ svgOptions: {
519
+ showTitle: true,
520
+ interactive: true, // hover effects + click handlers
521
+ roughness: 1.3,
522
+ bowing: 0.7,
523
+ theme: 'light', // 'light' | 'dark'
524
+ onNodeClick: (nodeId) => {},
525
+ },
526
+ canvasOptions: {
527
+ scale: 2, // pixel density
528
+ roughness: 1.3,
529
+ },
530
+ onNodeClick: (nodeId) => {},
531
+ onReady: (anim, svg) => {},
532
+ });
533
+ ```
534
+
535
+ **`DiagramInstance`:**
536
+
537
+ ```typescript
538
+ instance.scene // SceneGraph — all positioned nodes, edges, groups
539
+ instance.anim // AnimationController
540
+ instance.svg // SVGSVGElement (if renderer='svg')
541
+ instance.canvas // HTMLCanvasElement (if renderer='canvas')
542
+ instance.update(dsl) // re-render with new DSL
543
+ instance.exportSVG() // download as SVG file
544
+ instance.exportPNG() // download as PNG file
545
+ ```
546
+
547
+ ---
548
+
549
+ ### Pipeline API (low-level)
550
+
551
+ Use these if you need to control each step manually:
552
+
553
+ ```typescript
554
+ import { parse, buildSceneGraph, layout, renderToSVG } from 'sketchmark';
555
+
556
+ const ast = parse(dslString); // DSL → AST
557
+ const scene = buildSceneGraph(ast); // AST → SceneGraph
558
+ layout(scene); // compute x/y positions
559
+ const svg = renderToSVG(scene, containerEl, options);
560
+ ```
561
+
562
+ ---
563
+
564
+ ### `parse(dsl: string): DiagramAST`
565
+
566
+ Tokenizes and parses DSL source into an AST.
567
+ Throws `ParseError` with line/col information on invalid syntax.
568
+
569
+ ```typescript
570
+ import { parse, ParseError } from 'sketchmark';
571
+
572
+ try {
573
+ const ast = parse(dsl);
574
+ } catch (e) {
575
+ if (e instanceof ParseError) {
576
+ console.error(`Line ${e.line}, Col ${e.col}: ${e.message}`);
577
+ }
578
+ }
579
+ ```
580
+
581
+ ---
582
+
583
+ ### `buildSceneGraph(ast): SceneGraph`
584
+
585
+ Converts AST to a SceneGraph with unpositioned nodes and groups.
586
+
587
+ ---
588
+
589
+ ### `layout(scene): SceneGraph`
590
+
591
+ Computes x/y positions for all elements. Mutates and returns the SceneGraph.
592
+
593
+ ---
594
+
595
+ ### `renderToSVG(scene, container, options?): SVGSVGElement`
596
+
597
+ Renders scene to SVG using rough.js.
598
+
599
+ ---
600
+
601
+ ### `renderToCanvas(scene, canvas, options?): void`
602
+
603
+ Renders scene to an HTML Canvas element using rough.js.
604
+
605
+ ---
606
+
607
+ ## Export
608
+
609
+ ```typescript
610
+ import { exportSVG, exportPNG, exportHTML, getSVGBlob } from 'sketchmark';
611
+
612
+ exportSVG(svgElement, { filename: 'diagram.svg' });
613
+ await exportPNG(svgElement, { filename: 'diagram.png', scale: 2 });
614
+ exportHTML(svgElement, dslSource, { filename: 'diagram.html' });
615
+
616
+ // Get blob without downloading
617
+ const blob = getSVGBlob(svgElement);
618
+ ```
619
+
620
+ Or via the instance:
621
+ ```typescript
622
+ instance.exportSVG('my-diagram.svg');
623
+ await instance.exportPNG('my-diagram.png');
624
+ ```
625
+
626
+ ---
627
+
628
+ ## Examples
629
+
630
+ ### Basic architecture diagram
631
+
632
+ ```
633
+ diagram
634
+ title label="System Architecture"
635
+ layout row
636
+ config gap=60
637
+
638
+ theme primary fill="#e8f4ff" stroke="#0044cc" color="#003399"
639
+ theme success fill="#e8ffe8" stroke="#007700" color="#004400"
640
+ theme muted fill="#f5f5f5" stroke="#999999" color="#444444"
641
+
642
+ box client label="Client App" theme=primary width=140 height=55
643
+ box gateway label="API Gateway" theme=muted width=140 height=55
644
+
645
+ group services label="Services" layout=column gap=16 padding=30 theme=muted
646
+ {
647
+ box auth label="Auth Service" theme=primary width=130 height=50
648
+ box data label="Data Service" theme=primary width=130 height=50
649
+ }
650
+
651
+ cylinder db label="PostgreSQL" theme=success width=140 height=65
652
+
653
+ client --> gateway label="HTTPS"
654
+ gateway --> auth
655
+ gateway --> data
656
+ auth --> db label="SQL"
657
+ data --> db label="SQL"
658
+
659
+ end
660
+ ```
661
+
662
+ ---
663
+
664
+ ### Animated deployment
665
+
666
+ ```
667
+ diagram
668
+ title label="Blue-Green Deployment"
669
+ layout row
670
+ config gap=50
671
+
672
+ theme primary fill="#e8f4ff" stroke="#0044cc" color="#003399"
673
+ theme success fill="#e8ffe8" stroke="#007700" color="#004400"
674
+ theme muted fill="#f5f5f5" stroke="#999999" color="#444444"
675
+
676
+ box lb label="Load Balancer" theme=muted width=150 height=55
677
+
678
+ group blue label="Blue (live)" layout=column gap=16 padding=26 theme=primary
679
+ {
680
+ box b1 label="API v1" theme=primary width=120 height=50
681
+ box b2 label="Worker v1" theme=primary width=120 height=50
682
+ }
683
+
684
+ group green label="Green (new)" layout=column gap=16 padding=26 theme=success
685
+ {
686
+ box g1 label="API v2" theme=success width=120 height=50
687
+ box g2 label="Worker v2" theme=success width=120 height=50
688
+ }
689
+
690
+ lb --> b1 label="100%"
691
+ lb --> g1 label="0%"
692
+
693
+ step highlight lb
694
+ step draw lb-->b1
695
+ step highlight b1
696
+
697
+ # green slides in from below
698
+ step move g1 dx=0 dy=60
699
+ step move g2 dx=0 dy=60
700
+ step draw g1
701
+ step move g1 dx=0 dy=-60 duration=500
702
+ step draw g2
703
+ step move g2 dx=0 dy=-60 duration=500
704
+
705
+ # traffic shifts
706
+ step fade b1
707
+ step fade b2
708
+ step draw lb-->g1
709
+ step highlight g1
710
+
711
+ end
712
+ ```
713
+
714
+ ---
715
+
716
+ ### Charts
717
+
718
+ ```
719
+ diagram
720
+ layout row
721
+ config gap=40
722
+
723
+ bar-chart revenue title="Monthly Revenue" width=340 height=240
724
+ data
725
+ [
726
+ ["Month", "2023", "2024"],
727
+ ["Jan", 42000, 58000 ],
728
+ ["Feb", 38000, 61000 ],
729
+ ["Mar", 51000, 67000 ],
730
+ ["Apr", 46000, 72000 ]
731
+ ]
732
+
733
+ pie-chart share title="Market Share" width=280 height=240
734
+ data
735
+ [
736
+ ["Product A", 42],
737
+ ["Product B", 31],
738
+ ["Product C", 27]
739
+ ]
740
+
741
+ end
742
+ ```
743
+
744
+ ---
745
+
746
+ ## License
747
+
748
+ MIT