sketchmark 0.2.6 → 0.2.8
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.
- package/README.md +1041 -1066
- package/dist/animation/index.d.ts +6 -1
- package/dist/animation/index.d.ts.map +1 -1
- package/dist/ast/types.d.ts +6 -17
- package/dist/ast/types.d.ts.map +1 -1
- package/dist/config.d.ts +150 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/export/index.d.ts.map +1 -1
- package/dist/index.cjs +1562 -1325
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1562 -1325
- package/dist/index.js.map +1 -1
- package/dist/layout/entity-rect.d.ts +9 -0
- package/dist/layout/entity-rect.d.ts.map +1 -0
- package/dist/layout/index.d.ts.map +1 -1
- package/dist/markdown/parser.d.ts.map +1 -1
- package/dist/parser/index.d.ts.map +1 -1
- package/dist/parser/tokenizer.d.ts.map +1 -1
- package/dist/renderer/canvas/index.d.ts.map +1 -1
- package/dist/renderer/roughChart.d.ts.map +1 -1
- package/dist/renderer/shapes/box.d.ts +3 -0
- package/dist/renderer/shapes/box.d.ts.map +1 -0
- package/dist/renderer/shapes/circle.d.ts +3 -0
- package/dist/renderer/shapes/circle.d.ts.map +1 -0
- package/dist/renderer/shapes/cylinder.d.ts +3 -0
- package/dist/renderer/shapes/cylinder.d.ts.map +1 -0
- package/dist/renderer/shapes/diamond.d.ts +3 -0
- package/dist/renderer/shapes/diamond.d.ts.map +1 -0
- package/dist/renderer/shapes/hexagon.d.ts +3 -0
- package/dist/renderer/shapes/hexagon.d.ts.map +1 -0
- package/dist/renderer/shapes/icon.d.ts +3 -0
- package/dist/renderer/shapes/icon.d.ts.map +1 -0
- package/dist/renderer/shapes/image.d.ts +3 -0
- package/dist/renderer/shapes/image.d.ts.map +1 -0
- package/dist/renderer/shapes/index.d.ts +4 -0
- package/dist/renderer/shapes/index.d.ts.map +1 -0
- package/dist/renderer/shapes/line.d.ts +3 -0
- package/dist/renderer/shapes/line.d.ts.map +1 -0
- package/dist/renderer/shapes/note.d.ts +3 -0
- package/dist/renderer/shapes/note.d.ts.map +1 -0
- package/dist/renderer/shapes/parallelogram.d.ts +3 -0
- package/dist/renderer/shapes/parallelogram.d.ts.map +1 -0
- package/dist/renderer/shapes/path.d.ts +3 -0
- package/dist/renderer/shapes/path.d.ts.map +1 -0
- package/dist/renderer/shapes/registry.d.ts +5 -0
- package/dist/renderer/shapes/registry.d.ts.map +1 -0
- package/dist/renderer/shapes/text-shape.d.ts +3 -0
- package/dist/renderer/shapes/text-shape.d.ts.map +1 -0
- package/dist/renderer/shapes/triangle.d.ts +3 -0
- package/dist/renderer/shapes/triangle.d.ts.map +1 -0
- package/dist/renderer/shapes/types.d.ts +50 -0
- package/dist/renderer/shapes/types.d.ts.map +1 -0
- package/dist/renderer/shared.d.ts +26 -0
- package/dist/renderer/shared.d.ts.map +1 -0
- package/dist/renderer/svg/index.d.ts.map +1 -1
- package/dist/renderer/svg/roughChartSVG.d.ts.map +1 -1
- package/dist/renderer/typography.d.ts +27 -0
- package/dist/renderer/typography.d.ts.map +1 -0
- package/dist/scene/index.d.ts +5 -13
- package/dist/scene/index.d.ts.map +1 -1
- package/dist/sketchmark.iife.js +1564 -1327
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,1066 +1,1041 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
|
250
|
-
|
|
251
|
-
| `
|
|
252
|
-
| `
|
|
253
|
-
| `
|
|
254
|
-
| `
|
|
255
|
-
| `
|
|
256
|
-
| `
|
|
257
|
-
| `
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
|
288
|
-
|
|
289
|
-
| `
|
|
290
|
-
| `
|
|
291
|
-
| `
|
|
292
|
-
| `
|
|
293
|
-
| `
|
|
294
|
-
| `
|
|
295
|
-
| `
|
|
296
|
-
| `
|
|
297
|
-
| `
|
|
298
|
-
| `
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
```
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
```
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
["
|
|
433
|
-
]
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
]
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
#
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
```
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
```
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
theme
|
|
522
|
-
|
|
523
|
-
```
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
```
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
|
547
|
-
|
|
548
|
-
| `
|
|
549
|
-
| `
|
|
550
|
-
| `
|
|
551
|
-
| `
|
|
552
|
-
| `
|
|
553
|
-
| `
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
box
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
---
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
```
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
|
582
|
-
|
|
583
|
-
| `
|
|
584
|
-
| `draw` |
|
|
585
|
-
| `
|
|
586
|
-
| `
|
|
587
|
-
| `
|
|
588
|
-
| `
|
|
589
|
-
| `
|
|
590
|
-
| `
|
|
591
|
-
| `
|
|
592
|
-
| `
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
|
599
|
-
|
|
600
|
-
| `
|
|
601
|
-
| `
|
|
602
|
-
| `
|
|
603
|
-
| `
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
step
|
|
614
|
-
step
|
|
615
|
-
step
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
step
|
|
623
|
-
step
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
step
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
step
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
|
739
|
-
|
|
740
|
-
| `
|
|
741
|
-
| `
|
|
742
|
-
| `
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
###
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
diagram
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
theme
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
---
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
```
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
box client label="Client App" width=140 height=55
|
|
1043
|
-
box gateway label="API Gateway" width=140 height=55
|
|
1044
|
-
|
|
1045
|
-
group services layout=column gap=16 padding=30
|
|
1046
|
-
{
|
|
1047
|
-
box auth label="Auth Service" width=140 height=55
|
|
1048
|
-
box billing label="Billing Service" width=140 height=55
|
|
1049
|
-
}
|
|
1050
|
-
|
|
1051
|
-
cylinder db label="PostgreSQL" width=140 height=65
|
|
1052
|
-
}
|
|
1053
|
-
|
|
1054
|
-
client --> gateway label="HTTPS"
|
|
1055
|
-
gateway --> auth
|
|
1056
|
-
gateway --> billing
|
|
1057
|
-
auth --> db label="SQL"
|
|
1058
|
-
billing --> db label="SQL"
|
|
1059
|
-
end
|
|
1060
|
-
```
|
|
1061
|
-
|
|
1062
|
-
---
|
|
1063
|
-
|
|
1064
|
-
## License
|
|
1065
|
-
|
|
1066
|
-
MIT
|
|
1
|
+
# Sketchmark
|
|
2
|
+
|
|
3
|
+
> Hand-drawn, rough-style diagrams from a plain-text DSL.
|
|
4
|
+
> Live examples: **https://sketchmark.dev/examples**
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Table of Contents
|
|
9
|
+
|
|
10
|
+
1. [Installation](#installation)
|
|
11
|
+
2. [Quick Start](#quick-start)
|
|
12
|
+
3. [Framework Setup](#framework-setup)
|
|
13
|
+
- [Plain HTML (CDN)](#plain-html-cdn)
|
|
14
|
+
- [Vite / Vanilla TS](#vite--vanilla-ts)
|
|
15
|
+
- [Next.js (App Router)](#nextjs-app-router)
|
|
16
|
+
4. [DSL Syntax Overview](#dsl-syntax-overview)
|
|
17
|
+
5. [Nodes](#nodes)
|
|
18
|
+
- [Shapes](#shapes)
|
|
19
|
+
- [Node Properties](#node-properties)
|
|
20
|
+
6. [Edges (Connectors)](#edges-connectors)
|
|
21
|
+
7. [Groups](#groups)
|
|
22
|
+
8. [Tables](#tables)
|
|
23
|
+
9. [Charts](#charts)
|
|
24
|
+
10. [Markdown Blocks](#markdown-blocks)
|
|
25
|
+
11. [Themes](#themes)
|
|
26
|
+
12. [Fonts](#fonts)
|
|
27
|
+
13. [Animation System](#animation-system)
|
|
28
|
+
14. [Config Options](#config-options)
|
|
29
|
+
15. [Export](#export)
|
|
30
|
+
16. [Supported vs Unsupported Features](#supported-vs-unsupported-features)
|
|
31
|
+
17. [Full DSL Reference Table](#full-dsl-reference-table)
|
|
32
|
+
18. [Complete Example](#complete-example)
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Installation
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
npm install sketchmark
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Quick Start
|
|
45
|
+
|
|
46
|
+
```javascript
|
|
47
|
+
import { render } from 'sketchmark';
|
|
48
|
+
|
|
49
|
+
const dsl = `
|
|
50
|
+
diagram
|
|
51
|
+
box a label="Hello"
|
|
52
|
+
box b label="World"
|
|
53
|
+
a --> b label="greets"
|
|
54
|
+
end
|
|
55
|
+
`.trim();
|
|
56
|
+
|
|
57
|
+
const instance = render({
|
|
58
|
+
container: document.getElementById('diagram'),
|
|
59
|
+
dsl,
|
|
60
|
+
renderer: 'svg',
|
|
61
|
+
svgOptions: { showTitle: true, theme: 'light', transparent: true },
|
|
62
|
+
});
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Framework Setup
|
|
68
|
+
|
|
69
|
+
### Plain HTML (CDN)
|
|
70
|
+
|
|
71
|
+
```html
|
|
72
|
+
<!DOCTYPE html>
|
|
73
|
+
<html>
|
|
74
|
+
<head>
|
|
75
|
+
<!-- rough.js MUST load before sketchmark -->
|
|
76
|
+
<script src="https://unpkg.com/roughjs@4.6.6/bundled/rough.js"></script>
|
|
77
|
+
</head>
|
|
78
|
+
<body>
|
|
79
|
+
<div id="diagram"></div>
|
|
80
|
+
|
|
81
|
+
<script type="module">
|
|
82
|
+
import { render } from 'https://unpkg.com/sketchmark/dist/index.js';
|
|
83
|
+
|
|
84
|
+
const dsl = `
|
|
85
|
+
diagram
|
|
86
|
+
box a label="Client"
|
|
87
|
+
box b label="Server"
|
|
88
|
+
a --> b label="HTTP"
|
|
89
|
+
end
|
|
90
|
+
`.trim();
|
|
91
|
+
|
|
92
|
+
const instance = render({
|
|
93
|
+
container: document.getElementById('diagram'),
|
|
94
|
+
dsl,
|
|
95
|
+
renderer: 'svg',
|
|
96
|
+
svgOptions: { showTitle: true, interactive: true, theme: 'light', transparent: true },
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
// Animation controls
|
|
100
|
+
const { anim } = instance;
|
|
101
|
+
document.getElementById('btn-next').addEventListener('click', () => anim.next());
|
|
102
|
+
document.getElementById('btn-play').addEventListener('click', () => anim.play(700));
|
|
103
|
+
</script>
|
|
104
|
+
</body>
|
|
105
|
+
</html>
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
### Vite / Vanilla TS
|
|
111
|
+
|
|
112
|
+
**`src/main.ts`**:
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
import { render } from 'sketchmark';
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
const dsl = `
|
|
119
|
+
diagram
|
|
120
|
+
title label="My Architecture"
|
|
121
|
+
layout row
|
|
122
|
+
config gap=60
|
|
123
|
+
|
|
124
|
+
box client label="Client App" width=140 height=55
|
|
125
|
+
box server label="API Server" width=140 height=55
|
|
126
|
+
cylinder db label="PostgreSQL" width=140 height=65
|
|
127
|
+
|
|
128
|
+
client --> server label="HTTPS"
|
|
129
|
+
server --> db label="SQL"
|
|
130
|
+
|
|
131
|
+
step highlight client
|
|
132
|
+
step draw client-->server
|
|
133
|
+
step highlight server
|
|
134
|
+
step draw server-->db
|
|
135
|
+
end
|
|
136
|
+
`.trim();
|
|
137
|
+
|
|
138
|
+
const instance = render({
|
|
139
|
+
container: document.getElementById('diagram') as HTMLElement,
|
|
140
|
+
dsl,
|
|
141
|
+
renderer: 'svg',
|
|
142
|
+
svgOptions: { showTitle: true, interactive: true, theme: 'light', transparent: true },
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
const { anim } = instance;
|
|
146
|
+
// Wire up buttons
|
|
147
|
+
document.getElementById('btn-next')!.addEventListener('click', () => { anim.next(); });
|
|
148
|
+
document.getElementById('btn-play')!.addEventListener('click', async () => { await anim.play(700); });
|
|
149
|
+
document.getElementById('btn-reset')!.addEventListener('click', () => { anim.reset(); });
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
### Next.js (App Router)
|
|
155
|
+
|
|
156
|
+
Three rules that **must** all be followed:
|
|
157
|
+
|
|
158
|
+
**Rule 1 — Component must be `'use client'`**:
|
|
159
|
+
|
|
160
|
+
```tsx
|
|
161
|
+
// src/components/SketchmarkDiagram.tsx
|
|
162
|
+
'use client';
|
|
163
|
+
|
|
164
|
+
import { useEffect, useRef } from 'react';
|
|
165
|
+
import { render } from 'sketchmark';
|
|
166
|
+
|
|
167
|
+
interface Props {
|
|
168
|
+
dsl: string;
|
|
169
|
+
showTitle?: boolean;
|
|
170
|
+
showControls?: boolean;
|
|
171
|
+
theme?: 'light' | 'dark';
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export default function SketchmarkDiagram({ dsl, showTitle = true, theme = 'light' }: Props) {
|
|
175
|
+
const containerRef = useRef<HTMLDivElement>(null);
|
|
176
|
+
|
|
177
|
+
useEffect(() => {
|
|
178
|
+
const el = containerRef.current;
|
|
179
|
+
if (!el) return;
|
|
180
|
+
el.innerHTML = '';
|
|
181
|
+
render({
|
|
182
|
+
container: el,
|
|
183
|
+
dsl,
|
|
184
|
+
renderer: 'svg',
|
|
185
|
+
svgOptions: { showTitle, theme, transparent: true, interactive: true },
|
|
186
|
+
});
|
|
187
|
+
}, [dsl, showTitle, theme]);
|
|
188
|
+
|
|
189
|
+
return <div ref={containerRef} />;
|
|
190
|
+
}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
**Rule 3 — DSL strings must never have leading whitespace**:
|
|
194
|
+
|
|
195
|
+
```typescript
|
|
196
|
+
// ✅ Correct — use .trim()
|
|
197
|
+
const dsl = `
|
|
198
|
+
diagram
|
|
199
|
+
box a label="Hello"
|
|
200
|
+
box b label="World"
|
|
201
|
+
a --> b
|
|
202
|
+
end
|
|
203
|
+
`.trim();
|
|
204
|
+
|
|
205
|
+
// ❌ Wrong — leading spaces break the parser
|
|
206
|
+
const dsl = `
|
|
207
|
+
diagram
|
|
208
|
+
box a label="Hello"
|
|
209
|
+
`.trim();
|
|
210
|
+
```
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
## DSL Syntax Overview
|
|
214
|
+
|
|
215
|
+
Every diagram follows this structure:
|
|
216
|
+
|
|
217
|
+
```
|
|
218
|
+
diagram
|
|
219
|
+
[title label="My Title"]
|
|
220
|
+
[layout row|column|grid]
|
|
221
|
+
[config key=value ...]
|
|
222
|
+
[theme name fill="..." stroke="..." color="..."]
|
|
223
|
+
|
|
224
|
+
[nodes, edges, groups, tables, charts, markdown blocks]
|
|
225
|
+
|
|
226
|
+
[step action target ...]
|
|
227
|
+
end
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
- Lines starting with `#` or `//` are comments.
|
|
231
|
+
- All key-value attributes use the `key=value` or `key="quoted value"` syntax.
|
|
232
|
+
- The DSL is **whitespace-sensitive** — do not indent lines.
|
|
233
|
+
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
## Nodes
|
|
237
|
+
|
|
238
|
+
### Shapes
|
|
239
|
+
|
|
240
|
+
Every node has the form:
|
|
241
|
+
```
|
|
242
|
+
<shape> <id> [label="..."] [property=value ...]
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
| Shape | DSL Keyword | Description | Auto-sizes to |
|
|
246
|
+
|-------|-------------|-------------|---------------|
|
|
247
|
+
| Box (default) | `box` | Rectangle | label width |
|
|
248
|
+
| Circle | `circle` | Ellipse | label width |
|
|
249
|
+
| Diamond | `diamond` | Rhombus (decision) | label width + padding |
|
|
250
|
+
| Hexagon | `hexagon` | Six-sided polygon | label width + padding |
|
|
251
|
+
| Triangle | `triangle` | Triangle | label width + padding |
|
|
252
|
+
| Cylinder | `cylinder` | Database drum shape | label width, fixed height 66px |
|
|
253
|
+
| Parallelogram | `parallelogram` | Slanted rectangle | label width + skew |
|
|
254
|
+
| Text | `text` | Label only, no border | wraps to width |
|
|
255
|
+
| Image | `image` | URL-loaded image | label width |
|
|
256
|
+
| Icon | `icon` | Iconify icon | 48×48 + label |
|
|
257
|
+
| Line | `line` | Horizontal rule | label width |
|
|
258
|
+
| Path | `path` | Custom SVG path data | user-specified |
|
|
259
|
+
| Note | `note` | Sticky-note shape | line count × line height |
|
|
260
|
+
|
|
261
|
+
```
|
|
262
|
+
# Examples of each shape
|
|
263
|
+
box myBox label="A Box" width=140 height=55
|
|
264
|
+
circle myCirc label="A Circle" width=100
|
|
265
|
+
diamond myDia label="Decision?" width=150
|
|
266
|
+
hexagon myHex label="Process"
|
|
267
|
+
triangle myTri label="Start"
|
|
268
|
+
cylinder myDb label="PostgreSQL" height=65
|
|
269
|
+
parallelogram myPara label="I/O"
|
|
270
|
+
text myTxt label="Some prose" width=300
|
|
271
|
+
image myImg label="Logo" url="https://example.com/logo.png" width=120 height=60
|
|
272
|
+
icon myIcon label="Settings" name="mdi:cog"
|
|
273
|
+
line myLine label="Section" width=200
|
|
274
|
+
path myPath value="M 0 0 L 50 50 L 100 0 Z" width=100 height=60
|
|
275
|
+
note myNote label="Remember this!"
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
---
|
|
279
|
+
|
|
280
|
+
### Node Properties
|
|
281
|
+
|
|
282
|
+
| Property | Type | Description | Example |
|
|
283
|
+
|----------|------|-------------|---------|
|
|
284
|
+
| `label` | string | Display text (required) | `label="Hello World"` |
|
|
285
|
+
| `width` | number | Override auto-width (px) | `width=140` |
|
|
286
|
+
| `height` | number | Override auto-height (px) | `height=55` |
|
|
287
|
+
| `theme` | string | Named theme preset | `theme=primary` |
|
|
288
|
+
| `fill` | CSS color | Background fill color | `fill="#e8f4ff"` |
|
|
289
|
+
| `stroke` | CSS color | Border/outline color | `stroke="#0044cc"` |
|
|
290
|
+
| `stroke-width` | number | Border thickness | `stroke-width=2` |
|
|
291
|
+
| `color` | CSS color | Text color | `color="#003399"` |
|
|
292
|
+
| `opacity` | 0–1 | Element opacity | `opacity=0.5` |
|
|
293
|
+
| `font-size` | number | Text size in px | `font-size=16` |
|
|
294
|
+
| `font-weight` | number/string | Font weight | `font-weight=700` |
|
|
295
|
+
| `font` | string | Font name (see Fonts section) | `font=caveat` |
|
|
296
|
+
| `text-align` | left/center/right | Horizontal text alignment | `text-align=left` |
|
|
297
|
+
| `vertical-align` | top/middle/bottom | Vertical text alignment | `vertical-align=top` |
|
|
298
|
+
| `line-height` | number | Line height multiplier | `line-height=1.5` |
|
|
299
|
+
| `letter-spacing` | number | Letter spacing in px | `letter-spacing=2` |
|
|
300
|
+
| `padding` | number | Inner padding (px) | `padding=12` |
|
|
301
|
+
| `dash` | numbers | Stroke dash pattern | `dash="6,3"` |
|
|
302
|
+
| `url` | URL string | Image URL (for `image` shape) | `url="https://..."` |
|
|
303
|
+
| `name` | string | Iconify icon name (for `icon`) | `name="mdi:cog"` |
|
|
304
|
+
| `value` | string | SVG path data (for `path`) | `value="M 0 0 L 50 0"` |
|
|
305
|
+
| `deg` | number | Static rotation (degrees) | `deg=45` |
|
|
306
|
+
| `dx` | number | Static X translation (px) | `dx=20` |
|
|
307
|
+
| `dy` | number | Static Y translation (px) | `dy=-10` |
|
|
308
|
+
| `factor` | number | Static scale factor | `factor=1.2` |
|
|
309
|
+
|
|
310
|
+
---
|
|
311
|
+
|
|
312
|
+
## Edges (Connectors)
|
|
313
|
+
|
|
314
|
+
Edges connect two node/group IDs:
|
|
315
|
+
|
|
316
|
+
```
|
|
317
|
+
<from> <connector> <to> [label="..."] [style properties]
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
### Connector Syntax
|
|
321
|
+
|
|
322
|
+
| Connector | Direction | Dashed | Arrowhead |
|
|
323
|
+
|-----------|-----------|--------|-----------|
|
|
324
|
+
| `->` | Forward | No | Single end |
|
|
325
|
+
| `-->` | Forward | Yes | Single end |
|
|
326
|
+
| `<-` | Backward | No | Single start |
|
|
327
|
+
| `<--` | Backward | Yes | Single start |
|
|
328
|
+
| `<->` | Bidirectional | No | Both ends |
|
|
329
|
+
| `<-->` | Bidirectional | Yes | Both ends |
|
|
330
|
+
| `--` | None | No | No arrow |
|
|
331
|
+
| `---` | None | Yes | No arrow |
|
|
332
|
+
|
|
333
|
+
```
|
|
334
|
+
# Edge examples
|
|
335
|
+
a -> b
|
|
336
|
+
a --> b label="Async call"
|
|
337
|
+
a <-> b
|
|
338
|
+
a <--> b label="Sync"
|
|
339
|
+
a -- b # line, no arrow
|
|
340
|
+
a --- b # dashed line, no arrow
|
|
341
|
+
|
|
342
|
+
# With style overrides
|
|
343
|
+
a --> b label="HTTPS" stroke="#cc0000" stroke-width=2 color="#aa0000" font-size=10
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
### Edge Style Properties
|
|
347
|
+
|
|
348
|
+
| Property | Description |
|
|
349
|
+
|----------|-------------|
|
|
350
|
+
| `label` | Text label floating on the edge |
|
|
351
|
+
| `stroke` | Line color |
|
|
352
|
+
| `stroke-width` | Line thickness |
|
|
353
|
+
| `color` | Label text color |
|
|
354
|
+
| `font-size` | Label font size |
|
|
355
|
+
| `font` | Label font family |
|
|
356
|
+
| `letter-spacing` | Label letter spacing |
|
|
357
|
+
|
|
358
|
+
---
|
|
359
|
+
|
|
360
|
+
## Groups
|
|
361
|
+
|
|
362
|
+
Groups visually contain one or more nodes, tables, or nested groups.
|
|
363
|
+
|
|
364
|
+
```
|
|
365
|
+
group <id> [label="..."] [layout=row|column|grid] [gap=N] [padding=N]
|
|
366
|
+
[columns=N] [align=start|center|end]
|
|
367
|
+
[justify=start|center|end|space-between|space-around]
|
|
368
|
+
[theme=...] [fill="..."] [stroke="..."] [width=N] [height=N]
|
|
369
|
+
{
|
|
370
|
+
box a label="Node A"
|
|
371
|
+
box b label="Node B"
|
|
372
|
+
# nested groups allowed:
|
|
373
|
+
group inner label="Inner Group" layout=row { box c label="C" }
|
|
374
|
+
}
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
### Group Properties
|
|
378
|
+
|
|
379
|
+
| Property | Type | Description |
|
|
380
|
+
|----------|------|-------------|
|
|
381
|
+
| `label` | string | Group title (shown at top) |
|
|
382
|
+
| `layout` | row / column / grid | Child arrangement direction |
|
|
383
|
+
| `gap` | number | Space between children (px) |
|
|
384
|
+
| `padding` | number | Inner padding (px) |
|
|
385
|
+
| `columns` | number | Column count (for `layout=grid`) |
|
|
386
|
+
| `align` | start/center/end | Cross-axis alignment (align-items) |
|
|
387
|
+
| `justify` | start/center/end/space-between/space-around | Main-axis alignment |
|
|
388
|
+
| `width` | number | Minimum width override |
|
|
389
|
+
| `height` | number | Minimum height override |
|
|
390
|
+
| `theme` | string | Named theme preset |
|
|
391
|
+
| `fill` | CSS color | Background color |
|
|
392
|
+
| `stroke` | CSS color | Border color |
|
|
393
|
+
| `stroke-width` | number | Border thickness |
|
|
394
|
+
|
|
395
|
+
#### `bare` keyword
|
|
396
|
+
|
|
397
|
+
`bare` is an alias for a group with no visible border or fill:
|
|
398
|
+
|
|
399
|
+
```
|
|
400
|
+
bare myContainer {
|
|
401
|
+
box a label="Floating A"
|
|
402
|
+
box b label="Floating B"
|
|
403
|
+
}
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
---
|
|
407
|
+
|
|
408
|
+
## Tables
|
|
409
|
+
|
|
410
|
+
```
|
|
411
|
+
table <id> [label="..."] [theme=...] [fill="..."] [stroke="..."]
|
|
412
|
+
{
|
|
413
|
+
header Col1 Col2 Col3
|
|
414
|
+
row "Value A" "Value B" "Value C"
|
|
415
|
+
row "Value D" "Value E" "Value F"
|
|
416
|
+
}
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
- `header` rows get a shaded background and bold text.
|
|
420
|
+
- `row` rows use regular styling.
|
|
421
|
+
- `"value"` must use a double-quoted string literal.
|
|
422
|
+
- Column widths auto-size to content.
|
|
423
|
+
- Tables support `fill`, `stroke`, `color`, `font-size`, `font`, `text-align`, `letter-spacing`, `theme`, `opacity` style props (same as nodes).
|
|
424
|
+
|
|
425
|
+
---
|
|
426
|
+
|
|
427
|
+
## Charts
|
|
428
|
+
|
|
429
|
+
```
|
|
430
|
+
<chart-type> <id> [label="Title"] [width=N] [height=N] [theme=...] [style props]
|
|
431
|
+
data
|
|
432
|
+
[["Category", "Series1", "Series2"],
|
|
433
|
+
["Jan", 120, 80],
|
|
434
|
+
["Feb", 150, 90]]
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
### Chart Types
|
|
438
|
+
|
|
439
|
+
| DSL Keyword | Chart | Notes |
|
|
440
|
+
|-------------|-------|-------|
|
|
441
|
+
| `bar-chart` | Grouped bar chart | Multiple series supported |
|
|
442
|
+
| `line-chart` | Line chart | Multiple series supported |
|
|
443
|
+
| `area-chart` | Area/filled line chart | Multiple series supported |
|
|
444
|
+
| `pie-chart` | Pie chart | `["Label", value]` rows |
|
|
445
|
+
| `donut-chart` | Donut chart | Same data as pie |
|
|
446
|
+
| `scatter-chart` | Scatter plot | `["Label", x, y]` rows |
|
|
447
|
+
|
|
448
|
+
```
|
|
449
|
+
# Bar chart example
|
|
450
|
+
bar-chart sales label="Monthly Sales" width=400 height=280
|
|
451
|
+
data
|
|
452
|
+
[["Month", "Revenue", "Cost"],
|
|
453
|
+
["Jan", 1200, 800],
|
|
454
|
+
["Feb", 1500, 900],
|
|
455
|
+
["Mar", 1100, 750]]
|
|
456
|
+
|
|
457
|
+
# Pie chart example
|
|
458
|
+
pie-chart share label="Market Share" width=300 height=240
|
|
459
|
+
data
|
|
460
|
+
[["Company", "Share"],
|
|
461
|
+
["Alpha", 42],
|
|
462
|
+
["Beta", 31],
|
|
463
|
+
["Gamma", 27]]
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
---
|
|
467
|
+
|
|
468
|
+
## Markdown Blocks
|
|
469
|
+
|
|
470
|
+
Renders inline rich text with headings and bold/italic:
|
|
471
|
+
|
|
472
|
+
```
|
|
473
|
+
markdown <id> [width=N] [height=N] [theme=...] [style props]
|
|
474
|
+
"""
|
|
475
|
+
# Heading 1
|
|
476
|
+
## Heading 2
|
|
477
|
+
### Heading 3
|
|
478
|
+
|
|
479
|
+
Normal paragraph with **bold** and *italic* text.
|
|
480
|
+
|
|
481
|
+
Another paragraph here.
|
|
482
|
+
"""
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
- Triple-quote `"""` delimiters for the content block.
|
|
486
|
+
- Supported formatting: `# H1`, `## H2`, `### H3`, `**bold**`, `*italic*`, blank lines.
|
|
487
|
+
- Style props: `color`, `font`, `font-size`, `text-align`, `padding`, `fill`, `stroke`, `opacity`, `letter-spacing`.
|
|
488
|
+
|
|
489
|
+
---
|
|
490
|
+
|
|
491
|
+
## Themes
|
|
492
|
+
|
|
493
|
+
### Global Palette Themes
|
|
494
|
+
|
|
495
|
+
Activate via `config theme=<name>` in the DSL.
|
|
496
|
+
|
|
497
|
+
| Theme Name | Description |
|
|
498
|
+
|------------|-------------|
|
|
499
|
+
| `light` | Warm parchment (default) |
|
|
500
|
+
| `dark` | Dark warm brown |
|
|
501
|
+
| `sketch` | Neutral grey pencil |
|
|
502
|
+
| `ocean` | Blue tones |
|
|
503
|
+
| `forest` | Green tones |
|
|
504
|
+
| `sunset` | Orange/red warm |
|
|
505
|
+
| `slate` | Cool blue-grey (like Tailwind) |
|
|
506
|
+
| `rose` | Pink/rose |
|
|
507
|
+
| `midnight` | GitHub dark-style |
|
|
508
|
+
|
|
509
|
+
```
|
|
510
|
+
# Activate in DSL
|
|
511
|
+
config theme=ocean
|
|
512
|
+
|
|
513
|
+
# Or pass as render option
|
|
514
|
+
render({ ..., svgOptions: { theme: 'dark' } });
|
|
515
|
+
# 'auto' follows system prefers-color-scheme
|
|
516
|
+
render({ ..., svgOptions: { theme: 'auto' } });
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
### Named Custom Themes (per-element)
|
|
520
|
+
|
|
521
|
+
Define a named theme and apply it to any element with `theme=<name>`:
|
|
522
|
+
|
|
523
|
+
```
|
|
524
|
+
theme primary fill="#e8f4ff" stroke="#0044cc" color="#003399"
|
|
525
|
+
theme success fill="#e8ffe8" stroke="#007700" color="#004400"
|
|
526
|
+
theme warning fill="#fff9e6" stroke="#f0a500" color="#7a5000"
|
|
527
|
+
theme muted fill="#f5f5f5" stroke="#999999" color="#444444"
|
|
528
|
+
|
|
529
|
+
box client label="Client" theme=primary
|
|
530
|
+
box server label="Server" theme=warning
|
|
531
|
+
cylinder db label="DB" theme=success
|
|
532
|
+
group services label="Services" theme=muted { ... }
|
|
533
|
+
```
|
|
534
|
+
|
|
535
|
+
---
|
|
536
|
+
|
|
537
|
+
## Fonts
|
|
538
|
+
|
|
539
|
+
Set globally with `config font=<name>` or per-element with `font=<name>`.
|
|
540
|
+
|
|
541
|
+
| Font Name | Family | Type |
|
|
542
|
+
|-----------|--------|------|
|
|
543
|
+
| `caveat` | Caveat | Hand-drawn cursive |
|
|
544
|
+
| `handlee` | Handlee | Hand-drawn cursive |
|
|
545
|
+
| `indie-flower` | Indie Flower | Hand-drawn cursive |
|
|
546
|
+
| `patrick-hand` | Patrick Hand | Hand-drawn cursive |
|
|
547
|
+
| `dm-mono` | DM Mono | Monospace |
|
|
548
|
+
| `jetbrains` | JetBrains Mono | Monospace |
|
|
549
|
+
| `instrument` | Instrument Serif | Serif |
|
|
550
|
+
| `playfair` | Playfair Display | Serif |
|
|
551
|
+
| `system` | system-ui, sans-serif | System (default) |
|
|
552
|
+
| `mono` | Courier New | Monospace |
|
|
553
|
+
| `serif` | Georgia | Serif |
|
|
554
|
+
|
|
555
|
+
```
|
|
556
|
+
# Global font
|
|
557
|
+
config font=caveat
|
|
558
|
+
|
|
559
|
+
# Per-element font
|
|
560
|
+
box a label="Handwritten" font=caveat
|
|
561
|
+
box b label="Mono" font=dm-mono
|
|
562
|
+
```
|
|
563
|
+
|
|
564
|
+
You can also pass any valid CSS font-family string directly.
|
|
565
|
+
|
|
566
|
+
---
|
|
567
|
+
|
|
568
|
+
## Animation System
|
|
569
|
+
|
|
570
|
+
### Step Syntax
|
|
571
|
+
|
|
572
|
+
```
|
|
573
|
+
step <action> <target> [options]
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
- `<target>` is a node/group/table/chart/markdown ID, or an edge in `from-->to` format.
|
|
577
|
+
- Steps play in sequence via `anim.next()` or `anim.play(msPerStep)`.
|
|
578
|
+
|
|
579
|
+
### Animation Actions
|
|
580
|
+
|
|
581
|
+
| Action | Target | Options | Description |
|
|
582
|
+
|--------|--------|---------|-------------|
|
|
583
|
+
| `highlight` | node/edge/group | — | Pulsing glow highlight (only one element at a time) |
|
|
584
|
+
| `draw` | node/edge/group/table/chart/markdown | `duration=N` | Animated stroke-drawing reveal |
|
|
585
|
+
| `fade` | node/edge/group | — | Fade to 22% opacity |
|
|
586
|
+
| `unfade` | node/edge/group | — | Restore from fade |
|
|
587
|
+
| `erase` | node/edge/group | `duration=N` | Fade to invisible (opacity 0) |
|
|
588
|
+
| `show` | node/edge/group | `duration=N` | Fade to visible |
|
|
589
|
+
| `hide` | node/edge/group | `duration=N` | Fade to hidden |
|
|
590
|
+
| `pulse` | node/edge/group | `duration=N` | One-shot brightness pulse |
|
|
591
|
+
| `move` | node | `dx=N dy=N duration=N` | Translate by (dx, dy) px |
|
|
592
|
+
| `scale` | node | `factor=N duration=N` | Scale to factor (absolute) |
|
|
593
|
+
| `rotate` | node | `deg=N duration=N` | Rotate by deg (cumulative) |
|
|
594
|
+
| `color` | node/edge | `fill="#..."` or `color="#..."` | Change fill/stroke color |
|
|
595
|
+
|
|
596
|
+
### Step Options
|
|
597
|
+
|
|
598
|
+
| Option | Description | Default |
|
|
599
|
+
|--------|-------------|---------|
|
|
600
|
+
| `duration=N` | Animation duration in ms | varies by type |
|
|
601
|
+
| `delay=N` | Delay before this step fires (ms) | 0 |
|
|
602
|
+
| `dx=N` | X translation for `move` | 0 |
|
|
603
|
+
| `dy=N` | Y translation for `move` | 0 |
|
|
604
|
+
| `factor=N` | Scale factor for `scale` | 1 |
|
|
605
|
+
| `deg=N` | Rotation degrees for `rotate` | 0 |
|
|
606
|
+
| `fill="..."` | New color for `color` action | — |
|
|
607
|
+
| `color="..."` | Alias for fill in `color` action | — |
|
|
608
|
+
|
|
609
|
+
### Animation Examples
|
|
610
|
+
|
|
611
|
+
```
|
|
612
|
+
# Draw edges incrementally
|
|
613
|
+
step draw client-->server
|
|
614
|
+
step highlight server
|
|
615
|
+
step draw server-->db
|
|
616
|
+
step highlight db
|
|
617
|
+
|
|
618
|
+
# Move a node
|
|
619
|
+
step move myBox dx=100 dy=0 duration=500
|
|
620
|
+
|
|
621
|
+
# Scale up then back
|
|
622
|
+
step scale myBox factor=1.5 duration=300
|
|
623
|
+
step scale myBox factor=1 duration=300
|
|
624
|
+
|
|
625
|
+
# Rotate
|
|
626
|
+
step rotate myBox deg=45 duration=400
|
|
627
|
+
|
|
628
|
+
# Change color
|
|
629
|
+
step color myBox fill="#ff0000"
|
|
630
|
+
|
|
631
|
+
# Show/hide
|
|
632
|
+
step hide myBox duration=400
|
|
633
|
+
step show myBox duration=400
|
|
634
|
+
|
|
635
|
+
# Fade background nodes
|
|
636
|
+
step fade nodeA
|
|
637
|
+
step unfade nodeA
|
|
638
|
+
|
|
639
|
+
# Pulse a node
|
|
640
|
+
step pulse myBox duration=600
|
|
641
|
+
|
|
642
|
+
# Delay before a step
|
|
643
|
+
step highlight server delay=500
|
|
644
|
+
```
|
|
645
|
+
|
|
646
|
+
### JavaScript Animation API
|
|
647
|
+
|
|
648
|
+
```javascript
|
|
649
|
+
const { anim } = render({ ... });
|
|
650
|
+
|
|
651
|
+
// Properties
|
|
652
|
+
anim.total // number of steps
|
|
653
|
+
anim.currentStep // current step index (-1 = before start)
|
|
654
|
+
anim.canNext // boolean
|
|
655
|
+
anim.canPrev // boolean
|
|
656
|
+
anim.atEnd // boolean
|
|
657
|
+
|
|
658
|
+
// Methods
|
|
659
|
+
anim.next() // advance one step (returns bool)
|
|
660
|
+
anim.prev() // go back one step (returns bool)
|
|
661
|
+
anim.reset() // reset to before step 0
|
|
662
|
+
anim.goTo(index) // jump to step N
|
|
663
|
+
await anim.play(700) // play all remaining steps (700ms between)
|
|
664
|
+
|
|
665
|
+
// Event listener
|
|
666
|
+
const unsub = anim.on((event) => {
|
|
667
|
+
console.log(event.type); // 'step-change' | 'animation-start' | 'animation-end' | 'animation-reset'
|
|
668
|
+
console.log(event.stepIndex); // number
|
|
669
|
+
console.log(event.step); // ASTStep object
|
|
670
|
+
console.log(event.total); // total steps
|
|
671
|
+
});
|
|
672
|
+
unsub(); // unsubscribe
|
|
673
|
+
```
|
|
674
|
+
|
|
675
|
+
### Pre-hidden Elements (Draw Targets)
|
|
676
|
+
|
|
677
|
+
Any element targeted by a `step draw` action starts **hidden** and only appears when that step fires. Elements NOT targeted by `draw` are always visible.
|
|
678
|
+
|
|
679
|
+
---
|
|
680
|
+
|
|
681
|
+
## Config Options
|
|
682
|
+
|
|
683
|
+
Set in DSL with `config key=value`:
|
|
684
|
+
|
|
685
|
+
| Key | Description | Default |
|
|
686
|
+
|-----|-------------|---------|
|
|
687
|
+
| `theme` | Global palette name | `light` |
|
|
688
|
+
| `font` | Global font name | `system` |
|
|
689
|
+
| `gap` | Space between root-level items (px) | `80` |
|
|
690
|
+
| `margin` | Canvas outer margin (px) | `60` |
|
|
691
|
+
| `columns` | Column count for `layout=grid` | `1` |
|
|
692
|
+
| `title-color` | Diagram title text color | palette default |
|
|
693
|
+
| `title-size` | Diagram title font size | `18` |
|
|
694
|
+
| `title-weight` | Diagram title font weight | `600` |
|
|
695
|
+
|
|
696
|
+
```
|
|
697
|
+
diagram
|
|
698
|
+
title label="My System"
|
|
699
|
+
layout row
|
|
700
|
+
config gap=60
|
|
701
|
+
config margin=40
|
|
702
|
+
config theme=ocean
|
|
703
|
+
config font=caveat
|
|
704
|
+
config title-size=24
|
|
705
|
+
config title-color="#001f5b"
|
|
706
|
+
```
|
|
707
|
+
|
|
708
|
+
---
|
|
709
|
+
|
|
710
|
+
## Export
|
|
711
|
+
|
|
712
|
+
### From JavaScript API
|
|
713
|
+
|
|
714
|
+
```javascript
|
|
715
|
+
const instance = render({ ... });
|
|
716
|
+
|
|
717
|
+
// SVG file download
|
|
718
|
+
instance.exportSVG('my-diagram.svg');
|
|
719
|
+
|
|
720
|
+
// PNG file download
|
|
721
|
+
await instance.exportPNG('my-diagram.png');
|
|
722
|
+
|
|
723
|
+
// Advanced: get SVG string
|
|
724
|
+
import { getSVGString } from 'sketchmark';
|
|
725
|
+
const svgString = getSVGString(instance.svg);
|
|
726
|
+
|
|
727
|
+
// Advanced: get PNG data URL
|
|
728
|
+
import { svgToPNGDataURL } from 'sketchmark';
|
|
729
|
+
const dataUrl = await svgToPNGDataURL(instance.svg, { scale: 2, background: '#ffffff' });
|
|
730
|
+
|
|
731
|
+
// Self-contained HTML file
|
|
732
|
+
import { exportHTML } from 'sketchmark';
|
|
733
|
+
exportHTML(instance.svg, dslSource, { filename: 'diagram.html' });
|
|
734
|
+
```
|
|
735
|
+
|
|
736
|
+
### Export Options
|
|
737
|
+
|
|
738
|
+
| Option | Type | Description |
|
|
739
|
+
|--------|------|-------------|
|
|
740
|
+
| `filename` | string | Download filename |
|
|
741
|
+
| `scale` | number | PNG pixel density (default: 2 = @2x) |
|
|
742
|
+
| `background` | CSS color | PNG background color (default: `#f8f4ea`) |
|
|
743
|
+
|
|
744
|
+
### Available Export Functions
|
|
745
|
+
|
|
746
|
+
| Function | Output | Status |
|
|
747
|
+
|----------|--------|--------|
|
|
748
|
+
| `exportSVG(svg, opts)` | `.svg` file download | ✅ Stable |
|
|
749
|
+
| `exportPNG(svg, opts)` | `.png` file download | ✅ Stable |
|
|
750
|
+
| `exportHTML(svg, dsl, opts)` | Self-contained `.html` | ✅ Stable |
|
|
751
|
+
| `exportCanvasPNG(canvas, opts)` | `.png` from canvas renderer | ✅ Stable |
|
|
752
|
+
| `getSVGString(svg)` | SVG string | ✅ Stable |
|
|
753
|
+
| `getSVGBlob(svg)` | SVG Blob | ✅ Stable |
|
|
754
|
+
| `svgToPNGDataURL(svg, opts)` | PNG data URL string | ✅ Stable |
|
|
755
|
+
| `exportGIF(frames, opts)` | GIF (requires gifshot) | ⚠️ Stub only |
|
|
756
|
+
| `exportMP4(canvas, dur, opts)` | WebM via MediaRecorder | ⚠️ Stub only |
|
|
757
|
+
|
|
758
|
+
---
|
|
759
|
+
|
|
760
|
+
## Supported vs Unsupported Features
|
|
761
|
+
|
|
762
|
+
### Nodes
|
|
763
|
+
|
|
764
|
+
| Feature | Supported | Notes |
|
|
765
|
+
|---------|-----------|-------|
|
|
766
|
+
| box | ✅ | Default shape |
|
|
767
|
+
| circle | ✅ | |
|
|
768
|
+
| diamond | ✅ | |
|
|
769
|
+
| hexagon | ✅ | |
|
|
770
|
+
| triangle | ✅ | |
|
|
771
|
+
| cylinder | ✅ | |
|
|
772
|
+
| parallelogram | ✅ | |
|
|
773
|
+
| text | ✅ | Auto word-wraps |
|
|
774
|
+
| image (URL) | ✅ | Cross-origin images |
|
|
775
|
+
| icon (Iconify) | ✅ | Uses Iconify API |
|
|
776
|
+
| line | ✅ | Horizontal rule with label |
|
|
777
|
+
| path (SVG path data) | ✅ | Raw SVG `d` attribute |
|
|
778
|
+
| note | ✅ | Sticky-note shape |
|
|
779
|
+
| Multiline label (`\n`) | ✅ | Use `\n` in label strings |
|
|
780
|
+
| Per-node font override | ✅ | |
|
|
781
|
+
| Per-node opacity | ✅ | |
|
|
782
|
+
| Per-node static transform (deg/dx/dy/factor) | ✅ | Set at parse time |
|
|
783
|
+
| Rounded corners | ❌ | Not configurable |
|
|
784
|
+
| Custom SVG shapes | ❌ | Only `path` workaround |
|
|
785
|
+
| Rich text inside nodes | ❌ | Plain text only |
|
|
786
|
+
|
|
787
|
+
### Edges
|
|
788
|
+
|
|
789
|
+
| Feature | Supported | Notes |
|
|
790
|
+
|---------|-----------|-------|
|
|
791
|
+
| Single arrow `->` / `-->` | ✅ | |
|
|
792
|
+
| Reverse arrow `<-` / `<--` | ✅ | |
|
|
793
|
+
| Bidirectional `<->` / `<-->` | ✅ | |
|
|
794
|
+
| No arrow `--` / `---` | ✅ | |
|
|
795
|
+
| Dashed lines (`--`, `---`, `<-->`) | ✅ | |
|
|
796
|
+
| Edge labels | ✅ | |
|
|
797
|
+
| Edge color/stroke override | ✅ | |
|
|
798
|
+
| Self-loops | ❌ | |
|
|
799
|
+
| Curved/bezier edges | ❌ | Straight lines only |
|
|
800
|
+
| Waypoints / routing control | ❌ | Auto-routed |
|
|
801
|
+
| Multiple edges between same nodes | ✅ | Stack visually |
|
|
802
|
+
| Edge from/to groups | ✅ | Uses group center |
|
|
803
|
+
|
|
804
|
+
### Groups
|
|
805
|
+
|
|
806
|
+
| Feature | Supported | Notes |
|
|
807
|
+
|---------|-----------|-------|
|
|
808
|
+
| Nested groups | ✅ | Unlimited depth |
|
|
809
|
+
| Row / column / grid layout | ✅ | |
|
|
810
|
+
| justify-content variants | ✅ | start, center, end, space-between, space-around |
|
|
811
|
+
| align-items variants | ✅ | start, center, end |
|
|
812
|
+
| Fixed width/height | ✅ | Minimum size override |
|
|
813
|
+
| `bare` (invisible group) | ✅ | |
|
|
814
|
+
| Scrolling | ❌ | |
|
|
815
|
+
|
|
816
|
+
### Charts
|
|
817
|
+
|
|
818
|
+
| Feature | Supported | Notes |
|
|
819
|
+
|---------|-----------|-------|
|
|
820
|
+
| Bar chart (grouped) | ✅ | Multiple series |
|
|
821
|
+
| Line chart | ✅ | Multiple series |
|
|
822
|
+
| Area chart | ✅ | Multiple series |
|
|
823
|
+
| Pie chart | ✅ | |
|
|
824
|
+
| Donut chart | ✅ | |
|
|
825
|
+
| Scatter plot | ✅ | |
|
|
826
|
+
| Axes and tick labels | ✅ | Auto-generated Y axis |
|
|
827
|
+
| Legend | ✅ | Auto-generated |
|
|
828
|
+
| X-axis labels | ✅ | |
|
|
829
|
+
| Interactive tooltips | ❌ | |
|
|
830
|
+
| Stacked bars | ❌ | |
|
|
831
|
+
| Custom colors per series | ❌ | Uses built-in palette |
|
|
832
|
+
| Logarithmic scale | ❌ | |
|
|
833
|
+
|
|
834
|
+
### Animation
|
|
835
|
+
|
|
836
|
+
| Feature | Supported | Notes |
|
|
837
|
+
|---------|-----------|-------|
|
|
838
|
+
| highlight | ✅ | Pulsing glow |
|
|
839
|
+
| draw (nodes) | ✅ | Stroke-path reveal |
|
|
840
|
+
| draw (edges) | ✅ | Animated line draw |
|
|
841
|
+
| draw (groups) | ✅ | |
|
|
842
|
+
| draw (tables) | ✅ | |
|
|
843
|
+
| draw (charts) | ✅ | Fade-in |
|
|
844
|
+
| draw (markdown) | ✅ | Fade-in |
|
|
845
|
+
| fade / unfade | ✅ | |
|
|
846
|
+
| show / hide | ✅ | |
|
|
847
|
+
| erase | ✅ | |
|
|
848
|
+
| pulse | ✅ | |
|
|
849
|
+
| move | ✅ | CSS transform translate |
|
|
850
|
+
| scale | ✅ | CSS transform scale |
|
|
851
|
+
| rotate | ✅ | CSS transform rotate |
|
|
852
|
+
| color | ✅ | Dynamic fill/stroke color change |
|
|
853
|
+
| delay per step | ✅ | `delay=N` ms |
|
|
854
|
+
| custom duration | ✅ | `duration=N` ms |
|
|
855
|
+
| Canvas renderer animation | ❌ | SVG renderer only |
|
|
856
|
+
| Click-triggered steps | ❌ | Parsed but not implemented |
|
|
857
|
+
| Parallel steps | ❌ | Sequential only |
|
|
858
|
+
|
|
859
|
+
### Export
|
|
860
|
+
|
|
861
|
+
| Feature | Supported |
|
|
862
|
+
|---------|-----------|
|
|
863
|
+
| SVG download | ✅ |
|
|
864
|
+
| PNG download (via canvas) | ✅ |
|
|
865
|
+
| HTML (self-contained) | ✅ |
|
|
866
|
+
| SVG string / Blob | ✅ |
|
|
867
|
+
| GIF | ❌ (stub) |
|
|
868
|
+
| MP4/WebM | ❌ (stub) |
|
|
869
|
+
|
|
870
|
+
---
|
|
871
|
+
|
|
872
|
+
## Full DSL Reference Table
|
|
873
|
+
|
|
874
|
+
| Keyword | Category | Example |
|
|
875
|
+
|---------|----------|---------|
|
|
876
|
+
| `diagram` | Structure | `diagram` |
|
|
877
|
+
| `end` | Structure | `end` |
|
|
878
|
+
| `title` | Meta | `title label="My Diagram"` |
|
|
879
|
+
| `description` | Meta | `description "Some text"` |
|
|
880
|
+
| `layout` | Meta | `layout row` / `layout column` / `layout grid` |
|
|
881
|
+
| `config` | Meta | `config gap=60` |
|
|
882
|
+
| `theme` | Styling | `theme primary fill="#e8f4ff" stroke="#0044cc" color="#003399"` |
|
|
883
|
+
| `style` | Styling | `style nodeId fill="#ff0" stroke="#000"` |
|
|
884
|
+
| `box` | Node | `box myId label="Label" width=120 height=50` |
|
|
885
|
+
| `circle` | Node | `circle myId label="Label"` |
|
|
886
|
+
| `diamond` | Node | `diamond myId label="Decision?"` |
|
|
887
|
+
| `hexagon` | Node | `hexagon myId label="Process"` |
|
|
888
|
+
| `triangle` | Node | `triangle myId label="Start"` |
|
|
889
|
+
| `cylinder` | Node | `cylinder myId label="DB" height=65` |
|
|
890
|
+
| `parallelogram` | Node | `parallelogram myId label="I/O"` |
|
|
891
|
+
| `text` | Node | `text myId label="Plain text" width=300` |
|
|
892
|
+
| `image` | Node | `image myId label="Logo" url="https://..."` |
|
|
893
|
+
| `icon` | Node | `icon myId label="Settings" name="mdi:cog"` |
|
|
894
|
+
| `line` | Node | `line myId label="Divider" width=400` |
|
|
895
|
+
| `path` | Node | `path myId value="M 0 0 L 100 0 L 50 80 Z"` |
|
|
896
|
+
| `note` | Node | `note myId label="Sticky note text"` |
|
|
897
|
+
| `->` | Edge | `a -> b label="call"` |
|
|
898
|
+
| `-->` | Edge | `a --> b` |
|
|
899
|
+
| `<-` | Edge | `a <- b` |
|
|
900
|
+
| `<--` | Edge | `a <-- b` |
|
|
901
|
+
| `<->` | Edge | `a <-> b` |
|
|
902
|
+
| `<-->` | Edge | `a <--> b` |
|
|
903
|
+
| `--` | Edge | `a -- b` |
|
|
904
|
+
| `---` | Edge | `a --- b` |
|
|
905
|
+
| `group` | Group | `group myGroup label="Services" layout=column { ... }` |
|
|
906
|
+
| `bare` | Group | `bare myWrap { ... }` |
|
|
907
|
+
| `table` | Table | `table myTable label="Users" { header Name Age }` |
|
|
908
|
+
| `bar-chart` | Chart | `bar-chart sales label="Sales" data [...]` |
|
|
909
|
+
| `line-chart` | Chart | `line-chart trend data [...]` |
|
|
910
|
+
| `pie-chart` | Chart | `pie-chart share data [...]` |
|
|
911
|
+
| `donut-chart` | Chart | `donut-chart share data [...]` |
|
|
912
|
+
| `scatter-chart` | Chart | `scatter-chart pts data [...]` |
|
|
913
|
+
| `area-chart` | Chart | `area-chart filled data [...]` |
|
|
914
|
+
| `markdown` | Markdown | `markdown md1 """ # Title ... """` |
|
|
915
|
+
| `step highlight` | Animation | `step highlight nodeId` |
|
|
916
|
+
| `step draw` | Animation | `step draw nodeId` / `step draw a-->b` |
|
|
917
|
+
| `step fade` | Animation | `step fade nodeId` |
|
|
918
|
+
| `step unfade` | Animation | `step unfade nodeId` |
|
|
919
|
+
| `step erase` | Animation | `step erase nodeId duration=400` |
|
|
920
|
+
| `step show` | Animation | `step show nodeId duration=300` |
|
|
921
|
+
| `step hide` | Animation | `step hide nodeId duration=300` |
|
|
922
|
+
| `step pulse` | Animation | `step pulse nodeId duration=500` |
|
|
923
|
+
| `step move` | Animation | `step move nodeId dx=100 dy=0 duration=400` |
|
|
924
|
+
| `step scale` | Animation | `step scale nodeId factor=1.5 duration=300` |
|
|
925
|
+
| `step rotate` | Animation | `step rotate nodeId deg=90 duration=400` |
|
|
926
|
+
| `step color` | Animation | `step color nodeId fill="#ff0000"` |
|
|
927
|
+
|
|
928
|
+
---
|
|
929
|
+
|
|
930
|
+
## Complete Example
|
|
931
|
+
|
|
932
|
+
This example demonstrates most features in a single diagram:
|
|
933
|
+
|
|
934
|
+
```
|
|
935
|
+
diagram
|
|
936
|
+
title label="Full Stack Architecture"
|
|
937
|
+
layout row
|
|
938
|
+
config gap=50
|
|
939
|
+
config theme=light
|
|
940
|
+
config font=system
|
|
941
|
+
|
|
942
|
+
# Define named themes
|
|
943
|
+
theme primary fill="#e8f4ff" stroke="#0044cc" color="#003399"
|
|
944
|
+
theme success fill="#e8ffe8" stroke="#007700" color="#004400"
|
|
945
|
+
theme warning fill="#fff9e6" stroke="#f0a500" color="#7a5000"
|
|
946
|
+
theme muted fill="#f5f5f5" stroke="#999999" color="#444444"
|
|
947
|
+
|
|
948
|
+
# Standalone node
|
|
949
|
+
box client label="Browser" theme=primary width=120 height=50
|
|
950
|
+
|
|
951
|
+
# Group of services
|
|
952
|
+
group backend label="Backend" layout=column gap=12 padding=24 theme=muted
|
|
953
|
+
{
|
|
954
|
+
box api label="REST API" theme=warning width=130 height=48
|
|
955
|
+
box auth label="Auth" theme=primary width=130 height=48
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
# Database
|
|
959
|
+
cylinder db label="PostgreSQL" theme=success width=130 height=65
|
|
960
|
+
|
|
961
|
+
# Edges
|
|
962
|
+
client --> api label="HTTPS"
|
|
963
|
+
api --> auth
|
|
964
|
+
api --> db label="SQL"
|
|
965
|
+
auth --> db label="SQL"
|
|
966
|
+
|
|
967
|
+
# Inline table
|
|
968
|
+
table users label="Users Table"
|
|
969
|
+
{
|
|
970
|
+
header ID Name Email
|
|
971
|
+
row "1" "Alice" "alice@example.com"
|
|
972
|
+
row "2" "Bob" "bob@example.com"
|
|
973
|
+
}
|
|
974
|
+
|
|
975
|
+
# A chart
|
|
976
|
+
bar-chart traffic label="Daily Traffic" width=300 height=200
|
|
977
|
+
data
|
|
978
|
+
[["Day", "Requests"],
|
|
979
|
+
["Mon", 1200],
|
|
980
|
+
["Tue", 1500],
|
|
981
|
+
["Wed", 900]]
|
|
982
|
+
|
|
983
|
+
# Animation sequence
|
|
984
|
+
step highlight client
|
|
985
|
+
step draw client-->api
|
|
986
|
+
step highlight api
|
|
987
|
+
step draw api-->auth
|
|
988
|
+
step draw api-->db
|
|
989
|
+
step highlight db
|
|
990
|
+
end
|
|
991
|
+
```
|
|
992
|
+
|
|
993
|
+
---
|
|
994
|
+
|
|
995
|
+
## `render()` API Reference
|
|
996
|
+
|
|
997
|
+
```typescript
|
|
998
|
+
render(options: RenderOptions): DiagramInstance
|
|
999
|
+
|
|
1000
|
+
interface RenderOptions {
|
|
1001
|
+
container: string | HTMLElement | SVGSVGElement; // CSS selector or element
|
|
1002
|
+
dsl: string; // DSL source text
|
|
1003
|
+
renderer?: 'svg' | 'canvas'; // default: 'svg'
|
|
1004
|
+
injectCSS?: boolean; // inject animation CSS (default: true)
|
|
1005
|
+
svgOptions?: SVGRendererOptions;
|
|
1006
|
+
canvasOptions?: CanvasRendererOptions;
|
|
1007
|
+
onNodeClick?: (nodeId: string) => void; // click handler
|
|
1008
|
+
onReady?: (anim, svg?) => void; // callback after render
|
|
1009
|
+
}
|
|
1010
|
+
|
|
1011
|
+
interface SVGRendererOptions {
|
|
1012
|
+
roughness?: number; // default 1.3
|
|
1013
|
+
bowing?: number; // default 0.7
|
|
1014
|
+
showTitle?: boolean; // show diagram title
|
|
1015
|
+
interactive?: boolean; // enable hover/click
|
|
1016
|
+
onNodeClick?: (id: string) => void;
|
|
1017
|
+
theme?: 'light' | 'dark' | 'auto';
|
|
1018
|
+
transparent?: boolean; // transparent background
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
interface DiagramInstance {
|
|
1022
|
+
scene: SceneGraph;
|
|
1023
|
+
anim: AnimationController;
|
|
1024
|
+
svg?: SVGSVGElement;
|
|
1025
|
+
canvas?: HTMLCanvasElement;
|
|
1026
|
+
update: (dsl: string) => DiagramInstance; // re-render with new DSL
|
|
1027
|
+
exportSVG: (filename?: string) => void;
|
|
1028
|
+
exportPNG: (filename?: string) => Promise<void>;
|
|
1029
|
+
}
|
|
1030
|
+
```
|
|
1031
|
+
|
|
1032
|
+
---
|
|
1033
|
+
|
|
1034
|
+
## Important Gotchas
|
|
1035
|
+
|
|
1036
|
+
1. **DSL must not be indented** — every DSL line must start at column 0 (no leading spaces/tabs).
|
|
1037
|
+
2. **Always call `.trim()`** on template literals to strip the leading newline from the opening backtick.
|
|
1038
|
+
3. **Animation only works with SVG renderer** — the canvas renderer does not support animated steps.
|
|
1039
|
+
4. **`step draw` makes elements start hidden** — any element you intend to `draw` will be invisible until its step fires.
|
|
1040
|
+
5. **Node IDs must be unique** — duplicate IDs are silently deduplicated (only first definition kept).
|
|
1041
|
+
6. **Group children inherit group's coordinate space** — edges can connect across group boundaries using the node/group ID directly.
|