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