@diagrammo/dgmo 0.92.1 → 0.93.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.
Files changed (164) hide show
  1. package/dist/advanced.d.ts +77 -20
  2. package/dist/advanced.js +453 -420
  3. package/dist/block.d.ts +2 -2
  4. package/dist/block.js +75 -70
  5. package/dist/{chart-meta-BBqLnv5q.d.ts → chart-meta-BbjsRY7o.d.ts} +2 -2
  6. package/dist/chart-meta.d.ts +3 -3
  7. package/dist/chart-meta.js +25 -19
  8. package/dist/{chart-types-CbXlZFLd.d.ts → chart-types-Cppnp31G.d.ts} +173 -4
  9. package/dist/{charts-d3-QUUDVETP.js → charts-d3-ERYYVGP6.js} +7 -6
  10. package/dist/{chunk-HIWHIYLD.js → chunk-2TFXRBCD.js} +19 -19
  11. package/dist/{chunk-O5WUZGPV.js → chunk-3GCASUWA.js} +17 -17
  12. package/dist/{chunk-ZJAK6C7Y.js → chunk-3PP746YM.js} +6 -1
  13. package/dist/{chunk-WLLO3PZ3.js → chunk-472EOHVW.js} +17 -17
  14. package/dist/{chunk-JLU52ZDT.js → chunk-5CBX66KB.js} +10 -10
  15. package/dist/{chunk-DEFBUZWV.js → chunk-5HAYT43L.js} +70 -54
  16. package/dist/{chunk-S7W75MIM.js → chunk-65GPEV5V.js} +21 -3
  17. package/dist/{chunk-Q6W2K33N.js → chunk-6XLMTAEX.js} +1 -1
  18. package/dist/{chunk-JKST4RTT.js → chunk-7OWK5K5C.js} +6 -6
  19. package/dist/{chunk-73EYNV4O.js → chunk-A5WIAMCT.js} +4 -6
  20. package/dist/{chunk-X5BUX2GK.js → chunk-ADVGV3P7.js} +1 -1
  21. package/dist/{chunk-45QUTYPD.js → chunk-CYDM2XII.js} +17 -17
  22. package/dist/chunk-CYTFO2LF.js +209 -0
  23. package/dist/{chunk-JRWUHLRP.js → chunk-D6PVMUCX.js} +51 -8
  24. package/dist/{chunk-BRSM6Z34.js → chunk-DAHQL57W.js} +14 -14
  25. package/dist/{chunk-RBFJT23E.js → chunk-EQWC76GQ.js} +6 -6
  26. package/dist/{chunk-ADNIO3XY.js → chunk-FIYW7JW4.js} +5 -5
  27. package/dist/{chunk-7ENDOHAA.js → chunk-FMAVHTYB.js} +919 -927
  28. package/dist/{chunk-3PFMGNOM.js → chunk-GJXMG4S3.js} +26 -11
  29. package/dist/chunk-GXCDD6NG.js +24 -0
  30. package/dist/{chunk-Y2V5AEVG.js → chunk-IESUM4N5.js} +2331 -2236
  31. package/dist/{chunk-QQPNCXAO.js → chunk-IIV4SMJL.js} +18 -18
  32. package/dist/{chunk-5EBYPETE.js → chunk-J43OCO22.js} +3 -5
  33. package/dist/{chunk-L5NW3PVL.js → chunk-J6AEKIRQ.js} +1 -1
  34. package/dist/{chunk-2BJW7FSF.js → chunk-KBEWVCK3.js} +1 -1
  35. package/dist/{chunk-LRP5FXST.js → chunk-KCHQVED5.js} +18 -17
  36. package/dist/{chunk-Q6ZQX2HX.js → chunk-KCMGIYPO.js} +4 -6
  37. package/dist/{chunk-MDVJYRJT.js → chunk-KPGPK4SK.js} +22 -22
  38. package/dist/{chunk-Q2UFOKPB.js → chunk-KPSSNGAE.js} +22 -22
  39. package/dist/{chunk-V4D2ZQBE.js → chunk-KRPLP5LP.js} +6 -1
  40. package/dist/{chunk-BZX7QCXJ.js → chunk-KRU2LCIP.js} +15 -15
  41. package/dist/{chunk-HXULJZA2.js → chunk-LDDDKWL6.js} +6 -1
  42. package/dist/{chunk-NREU4JFE.js → chunk-LNVB75QU.js} +6 -8
  43. package/dist/{chunk-MX4SZLSV.js → chunk-LUDUDBO6.js} +16 -8
  44. package/dist/{chunk-2YAFDND3.js → chunk-M4NV5PPU.js} +4 -6
  45. package/dist/{chunk-26BBJUBW.js → chunk-M6ZQAFPD.js} +4 -6
  46. package/dist/{chunk-NPWVOFB3.js → chunk-MB2SQF7N.js} +1 -1
  47. package/dist/{chunk-6ZL2XYM7.js → chunk-MLY5ALOV.js} +6 -6
  48. package/dist/chunk-NJJCTEBM.js +416 -0
  49. package/dist/{chunk-OQW4ETJX.js → chunk-NM5V5EKY.js} +6 -1
  50. package/dist/{chunk-ONYO5WJW.js → chunk-NMK7KJZZ.js} +21 -21
  51. package/dist/{chunk-6BNNLVAR.js → chunk-NPDVWFAQ.js} +6 -1
  52. package/dist/{chunk-FTUMRSGT.js → chunk-P5FUWXPW.js} +4 -286
  53. package/dist/chunk-P7TRFL4P.js +54 -0
  54. package/dist/{chunk-A4PNWAUW.js → chunk-PGSGJLUR.js} +6 -1
  55. package/dist/{chunk-DRFGIOZ6.js → chunk-Q7Y6JQ3R.js} +4 -6
  56. package/dist/{chunk-J2E7EUER.js → chunk-QDRCWVV3.js} +17 -17
  57. package/dist/{chunk-MXAP37W6.js → chunk-TNV4F5WA.js} +16 -7
  58. package/dist/{chunk-EBSFSOJC.js → chunk-U7U64UUN.js} +22 -22
  59. package/dist/chunk-UCHZJJIT.js +421 -0
  60. package/dist/{chunk-FSJ3ZA6N.js → chunk-UG7AQQNR.js} +12 -12
  61. package/dist/{chunk-WFA6IULY.js → chunk-URRAWU5D.js} +5 -0
  62. package/dist/{chunk-VOR32OHN.js → chunk-USAGHYRD.js} +13 -15
  63. package/dist/{chunk-QUGC7GWB.js → chunk-UVX3IYXF.js} +15 -15
  64. package/dist/{chunk-B5PEKSRH.js → chunk-VSAKEMDD.js} +6 -1
  65. package/dist/{chunk-5SSTVFPX.js → chunk-WK5QEYFA.js} +5 -7
  66. package/dist/{chunk-KTGZDMDX.js → chunk-XUTR7GNT.js} +76 -28
  67. package/dist/{chunk-6WVX4KNP.js → chunk-YDZIVDVR.js} +97 -297
  68. package/dist/{chunk-URQIWIKX.js → chunk-YXXIRM4C.js} +3 -3
  69. package/dist/{chunk-H5UEVW6Q.js → chunk-ZD3QCNB7.js} +1 -1
  70. package/dist/{chunk-DUPZ2BBY.js → chunk-ZTLMEBAC.js} +66 -4
  71. package/dist/clock.js +168 -0
  72. package/dist/completion-registry.js +3 -1
  73. package/dist/countdown.js +36 -395
  74. package/dist/{dgmo-router-4UAPPIKN.js → dgmo-router-CZN36TR3.js} +50 -43
  75. package/dist/{dimensions-SCNVYLRF.js → dimensions-7HHKO5BS.js} +3 -3
  76. package/dist/{d3-BThYBTQk.d.ts → export-context-Ceh3wr0E.d.ts} +2 -8
  77. package/dist/{flowchart-parser-NA75YQ77.js → flowchart-parser-4MZPWYK6.js} +8 -3
  78. package/dist/{flowchart-renderer-6MGGX4RC.js → flowchart-renderer-5XDN575E.js} +13 -17
  79. package/dist/index.d.ts +8 -7
  80. package/dist/index.js +80 -74
  81. package/dist/{layout-S3RLVPH4.js → layout-33FHGDEV.js} +10 -12
  82. package/dist/{layout-MBVBAMPA.js → layout-3TSVAGWH.js} +2 -2
  83. package/dist/{layout-WRG4APSJ.js → layout-5GHV7HNM.js} +9 -13
  84. package/dist/layout-FTOGDNUL.js +23 -0
  85. package/dist/{layout-BNLFQHSB.js → layout-QXGPY7KA.js} +7 -9
  86. package/dist/{layout-search-PMYL3VWS.js → layout-search-EMTCDC3C.js} +8 -10
  87. package/dist/{palettes-IN7ZFRJM.js → palettes-4Y7CL2QL.js} +4 -2
  88. package/dist/{parser-3MK56JZC.js → parser-4Y6PODW6.js} +2 -2
  89. package/dist/{parser-2NWH5JUS.js → parser-A3AN76RQ.js} +2 -1
  90. package/dist/{parser-LCJ76UXS.js → parser-BT4NI6JY.js} +5 -1
  91. package/dist/{parser-FXDS4JDK.js → parser-F7NDRPMA.js} +2 -2
  92. package/dist/{parser-BES6LV3G.js → parser-GDLKUBTO.js} +5 -1
  93. package/dist/{parser-SEUTXN6U.js → parser-KJPPUN4D.js} +2 -2
  94. package/dist/{parser-SIKL4PLF.js → parser-KMKVFET2.js} +5 -1
  95. package/dist/{parser-5LW5JDYG.js → parser-NL73FSFI.js} +5 -1
  96. package/dist/{parser-VA7ZQQTA.js → parser-NUU3DVW4.js} +5 -1
  97. package/dist/{parser-L6RWDXQN.js → parser-OGF2CDA6.js} +8 -3
  98. package/dist/{parser-XZUKNZPB.js → parser-R3LPEQIT.js} +7 -1
  99. package/dist/{parser-X23GRTQJ.js → parser-RCIEKN7Y.js} +5 -1
  100. package/dist/{parser-GX5YLRIP.js → parser-VKYUAT4Y.js} +8 -3
  101. package/dist/{parser-QYISOAGR.js → parser-YX72VLDZ.js} +8 -3
  102. package/dist/redraw-MSXU4ZD2.js +73 -0
  103. package/dist/redraw-T324XAF3.js +1698 -0
  104. package/dist/{renderer-5VKPB4LL.js → renderer-37PLQHVB.js} +5 -5
  105. package/dist/{renderer-ISSDGK54.js → renderer-3F47TPZ2.js} +3 -3
  106. package/dist/{renderer-3QAFDXEY.js → renderer-5ITLW7MX.js} +14 -12
  107. package/dist/{renderer-ZZ6MWVB7.js → renderer-6GJWADLO.js} +4 -4
  108. package/dist/{renderer-MM27BSBO.js → renderer-7Y3LR4R2.js} +3 -4
  109. package/dist/{renderer-2FVUPBGV.js → renderer-AM7P4LN7.js} +1 -1
  110. package/dist/{renderer-ZHGHTSNG.js → renderer-BO73LSVT.js} +13 -12
  111. package/dist/{renderer-3IHQI4A4.js → renderer-CNRQFIEI.js} +11 -10
  112. package/dist/{renderer-OAR5VPH4.js → renderer-DAZWHNLI.js} +2 -2
  113. package/dist/{renderer-NDA2FFYB.js → renderer-DD6T3C4J.js} +5 -5
  114. package/dist/{renderer-WIU5BJUK.js → renderer-DDWDCM2K.js} +2 -2
  115. package/dist/{renderer-7ZZG5HR3.js → renderer-EVKWGUGT.js} +8 -9
  116. package/dist/{renderer-3JY6JAQJ.js → renderer-FL7EOSBU.js} +5 -6
  117. package/dist/{renderer-RUSFL7WU.js → renderer-GFALLIYT.js} +7 -6
  118. package/dist/{renderer-O6DY46AV.js → renderer-GFGFHYWY.js} +7 -7
  119. package/dist/{renderer-5TZVFQ7K.js → renderer-GOXAP2IE.js} +7 -8
  120. package/dist/{renderer-NHTR7IRR.js → renderer-GPAVVUET.js} +4 -5
  121. package/dist/{renderer-TO2NVJP3.js → renderer-HJ54YXT3.js} +50 -45
  122. package/dist/{renderer-LM4ICK6I.js → renderer-HYGTMBHT.js} +4 -5
  123. package/dist/{renderer-S3YCLJKL.js → renderer-IHCWBFPI.js} +17 -20
  124. package/dist/{renderer-XO57LTU4.js → renderer-ISDKO3DI.js} +5 -5
  125. package/dist/{renderer-LQP3AGEJ.js → renderer-J3QWK6IM.js} +3 -4
  126. package/dist/{renderer-J666LZXJ.js → renderer-J6H4Q3RM.js} +7 -8
  127. package/dist/{renderer-ALWVK3EJ.js → renderer-JJ4QW3SK.js} +6 -6
  128. package/dist/{renderer-DC7C5Q3G.js → renderer-NOYLNVTI.js} +2 -2
  129. package/dist/{renderer-ZGY7P4BM.js → renderer-PBKTAWQV.js} +16 -20
  130. package/dist/{renderer-XGG2UNXT.js → renderer-POBGKIUT.js} +3 -4
  131. package/dist/{renderer-QGIHLZOJ.js → renderer-RDI2RYUP.js} +9 -10
  132. package/dist/{renderer-JEJT3YET.js → renderer-TSCSZ6CL.js} +2 -3
  133. package/dist/{renderer-VPIELEE5.js → renderer-VDBNC7A6.js} +8 -9
  134. package/dist/{renderer-DVNMCYHZ.js → renderer-VI34SD5V.js} +14 -14
  135. package/dist/{renderer-J5FKF423.js → renderer-W4MUMXJE.js} +7 -4
  136. package/dist/{renderer-RSK6QFWN.js → renderer-XJMVG2WJ.js} +7 -9
  137. package/dist/{state-parser-TIR2ORJY.js → state-parser-NPYTMRXP.js} +8 -3
  138. package/dist/{state-renderer-G6SUXU4J.js → state-renderer-44K2KDX7.js} +15 -19
  139. package/dist/{tag-groups-DsoVpAY-.d.ts → tag-groups-DydewK3D.d.ts} +2 -173
  140. package/dist/{themes-DRNjxX7Q.d.ts → themes-DzIH3Hjv.d.ts} +3 -2
  141. package/docs/ai-integration.md +1 -1
  142. package/docs/language-reference.md +23 -2
  143. package/gallery/fixtures/whiteboard.dgmo +3 -0
  144. package/package.json +2 -6
  145. package/dist/chunk-3Y63RFJL.js +0 -75
  146. package/dist/chunk-5DH3KYFH.js +0 -20
  147. package/dist/chunk-O753JUEZ.js +0 -67
  148. package/dist/chunk-RJNZHFNG.js +0 -51
  149. package/dist/chunk-Z6DXWULM.js +0 -23
  150. package/dist/layout-5USEVQBY.js +0 -25
  151. package/dist/{chunk-YITHYQCL.js → chunk-4FT5KQ7H.js} +7 -7
  152. package/dist/{chunk-GE7ICBX6.js → chunk-4RY5D5RE.js} +4 -4
  153. package/dist/{chunk-4QLGGQNO.js → chunk-4WQX55VX.js} +14 -14
  154. package/dist/{chunk-DGUGE67L.js → chunk-CDYV46JE.js} +3 -3
  155. package/dist/{chunk-IGKFOHBG.js → chunk-CQYFZOUC.js} +13 -13
  156. package/dist/{chunk-TKAB3FTK.js → chunk-DRQSB72S.js} +11 -11
  157. package/dist/{chunk-ZKP77MB3.js → chunk-FVTYJUXR.js} +5 -5
  158. package/dist/{chunk-MA42PIGJ.js → chunk-H5NVCOEJ.js} +4 -4
  159. package/dist/{chunk-BEA4D7OS.js → chunk-IXHWS2HI.js} +3 -3
  160. package/dist/{chunk-QKY6W4NA.js → chunk-KHL652SX.js} +25 -25
  161. package/dist/{chunk-6OIMUSDX.js → chunk-MUJVNSEW.js} +9 -9
  162. package/dist/{chunk-YO6AQU4A.js → chunk-QJOVZ4TC.js} +12 -12
  163. package/dist/{chunk-SOHZDW6N.js → chunk-UXNA2H2V.js} +3 -3
  164. package/dist/{chunk-NO3UX6AP.js → chunk-V2NQV7VL.js} +4 -4
@@ -5,23 +5,24 @@ import {
5
5
  NODE_LABEL_LINE_HEIGHT,
6
6
  layoutGraph,
7
7
  wrapNodeLabel
8
- } from "./chunk-5SSTVFPX.js";
8
+ } from "./chunk-WK5QEYFA.js";
9
9
  import {
10
10
  appendArrowheadMarkers
11
11
  } from "./chunk-XBJJP2HN.js";
12
- import {
13
- NOTE_BADGE_RADIUS,
14
- noteConnectorPoints,
15
- renderNoteBadge,
16
- renderNoteBox,
17
- renderNoteConnector
18
- } from "./chunk-JRWUHLRP.js";
19
12
  import {
20
13
  fitDiagramToCanvas
21
14
  } from "./chunk-EPDBWATV.js";
15
+ import {
16
+ serializeSvg
17
+ } from "./chunk-CYRB2JTN.js";
22
18
  import {
23
19
  ScaleContext
24
20
  } from "./chunk-24YPR5EH.js";
21
+ import {
22
+ TITLE_FONT_SIZE,
23
+ TITLE_FONT_WEIGHT,
24
+ TITLE_Y
25
+ } from "./chunk-VLC6WNRD.js";
25
26
  import {
26
27
  ARROWHEAD_HEIGHT,
27
28
  ARROWHEAD_WIDTH,
@@ -30,19 +31,18 @@ import {
30
31
  NODE_STROKE_WIDTH
31
32
  } from "./chunk-XCKNFFKM.js";
32
33
  import {
33
- serializeSvg
34
- } from "./chunk-CYRB2JTN.js";
34
+ parseFlowchart
35
+ } from "./chunk-M6ZQAFPD.js";
35
36
  import {
36
- TITLE_FONT_SIZE,
37
- TITLE_FONT_WEIGHT,
38
- TITLE_Y
39
- } from "./chunk-VLC6WNRD.js";
37
+ NOTE_BADGE_RADIUS,
38
+ noteConnectorPoints,
39
+ renderNoteBadge,
40
+ renderNoteBox,
41
+ renderNoteConnector
42
+ } from "./chunk-D6PVMUCX.js";
40
43
  import {
41
44
  FONT_FAMILY
42
45
  } from "./chunk-ICLB27PZ.js";
43
- import {
44
- parseFlowchart
45
- } from "./chunk-26BBJUBW.js";
46
46
  import {
47
47
  fillModeFromOptions
48
48
  } from "./chunk-TIIZIAGS.js";
@@ -1,6 +1,3 @@
1
- import {
2
- renderInlineText
3
- } from "./chunk-S7W75MIM.js";
4
1
  import {
5
2
  BOX_H,
6
3
  BOX_W,
@@ -9,21 +6,24 @@ import {
9
6
  layoutBracket,
10
7
  wrapText
11
8
  } from "./chunk-ZI6WC24V.js";
12
- import {
13
- renderIntegratedLegend
14
- } from "./chunk-NMS5XSLX.js";
15
9
  import {
16
10
  layoutInlineHeader
17
11
  } from "./chunk-42UJ23H3.js";
18
- import {
19
- getLegendExtent,
20
- getMaxLegendReservedHeight
21
- } from "./chunk-JILEYZ2V.js";
22
12
  import {
23
13
  TITLE_FONT_SIZE,
24
14
  TITLE_FONT_WEIGHT,
25
15
  TITLE_Y
26
16
  } from "./chunk-VLC6WNRD.js";
17
+ import {
18
+ renderIntegratedLegend
19
+ } from "./chunk-NMS5XSLX.js";
20
+ import {
21
+ getLegendExtent,
22
+ getMaxLegendReservedHeight
23
+ } from "./chunk-JILEYZ2V.js";
24
+ import {
25
+ renderInlineText
26
+ } from "./chunk-65GPEV5V.js";
27
27
  import {
28
28
  FONT_FAMILY
29
29
  } from "./chunk-ICLB27PZ.js";
@@ -1,3 +1,18 @@
1
+ import {
2
+ WHITEBOARD_COLORS,
3
+ WHITEBOARD_ELEMENT_KEYWORDS,
4
+ WHITEBOARD_NOTE_COLOR,
5
+ WHITEBOARD_NOTE_HEIGHT,
6
+ WHITEBOARD_NOTE_WIDTH,
7
+ isWhiteboardColor,
8
+ isWhiteboardShapeKind
9
+ } from "./chunk-P7TRFL4P.js";
10
+ import {
11
+ extractPaletteDirective
12
+ } from "./chunk-CYTFO2LF.js";
13
+ import {
14
+ matchTagBlockHeading
15
+ } from "./chunk-4SACN2C5.js";
1
16
  import {
2
17
  parseFirstLine,
3
18
  recognizeGlobalBoolean
@@ -20,7 +35,8 @@ var WHITEBOARD_DIAGNOSTIC_CODES = {
20
35
  BAD_INK: "W_WHITEBOARD_BAD_INK",
21
36
  BAD_IMAGE_REF: "W_WHITEBOARD_BAD_IMAGE_REF",
22
37
  EMPTY_TEXT: "W_WHITEBOARD_EMPTY_TEXT",
23
- UNEXPECTED_BODY: "W_WHITEBOARD_UNEXPECTED_BODY"
38
+ UNEXPECTED_BODY: "W_WHITEBOARD_UNEXPECTED_BODY",
39
+ BAD_TAG_ENTRY: "W_WHITEBOARD_BAD_TAG_ENTRY"
24
40
  };
25
41
  var s = (v) => typeof v === "string" || typeof v === "number" ? String(v) : "?";
26
42
  var WHITEBOARD_DIAGNOSTICS = [
@@ -122,6 +138,15 @@ var WHITEBOARD_DIAGNOSTICS = [
122
138
  message: (p) => `${s(p.element)} takes no indented lines \u2014 ${s(p.count)} ignored`,
123
139
  hint: "Only shapes, notes, arrows, lines and text have a label that can run over indented lines. Unindent the line if it is meant as its own element.",
124
140
  example: "whiteboard\nimage board.assets/a.webp at: 0 0, size: 320 200\n caption"
141
+ },
142
+ {
143
+ code: WHITEBOARD_DIAGNOSTIC_CODES.BAD_TAG_ENTRY,
144
+ severity: "warning",
145
+ chartType: "whiteboard",
146
+ title: "Tag entry without a colour",
147
+ message: (p) => `Tag entry "${s(p.entry)}" names no colour \u2014 ignored (end it with one of: red, green, blue, teal, purple, orange, yellow, cyan, gray)`,
148
+ hint: "A whiteboard tag entry gives a colour a meaning, so it ends with the colour it names: `Blocked red`.",
149
+ example: "whiteboard\ntag Meaning\n Blocked"
125
150
  }
126
151
  ];
127
152
  var BY_CODE = new Map(WHITEBOARD_DIAGNOSTICS.map((d) => [d.code, d]));
@@ -319,47 +344,6 @@ function decodeInk(encoded) {
319
344
  return { points, error: null };
320
345
  }
321
346
 
322
- // src/whiteboard/types.ts
323
- var WHITEBOARD_COLORS = [
324
- "ink",
325
- "red",
326
- "green",
327
- "blue",
328
- "teal",
329
- "purple",
330
- "orange",
331
- "yellow",
332
- "cyan",
333
- "gray"
334
- ];
335
- var WHITEBOARD_SHAPE_KINDS = [
336
- "rectangle",
337
- "ellipse",
338
- "database",
339
- "queue"
340
- ];
341
- var WHITEBOARD_ELEMENT_KEYWORDS = [
342
- ...WHITEBOARD_SHAPE_KINDS,
343
- "note",
344
- "arrow",
345
- "line",
346
- "text",
347
- "image",
348
- "ink"
349
- ];
350
- var WHITEBOARD_STROKE_STYLES = ["solid", "dashed"];
351
- var WHITEBOARD_FILLS = ["tint", "solid", "outline"];
352
- var WHITEBOARD_HEADS = ["end", "both"];
353
- var WHITEBOARD_NOTE_WIDTH = 160;
354
- var WHITEBOARD_NOTE_HEIGHT = 99;
355
- var WHITEBOARD_NOTE_COLOR = "yellow";
356
- function isWhiteboardColor(value) {
357
- return WHITEBOARD_COLORS.includes(value);
358
- }
359
- function isWhiteboardShapeKind(value) {
360
- return WHITEBOARD_SHAPE_KINDS.includes(value);
361
- }
362
-
363
347
  // src/whiteboard/parser.ts
364
348
  var WHITEBOARD_COORD_MAX = 1e6;
365
349
  var META_KEY_RE = /(^|\s)([a-z][a-z-]*):(?=\s|$)/;
@@ -451,6 +435,7 @@ function parseWhiteboard(content, _palette) {
451
435
  titleLineNumber: null,
452
436
  elements,
453
437
  options,
438
+ tagGroups: [],
454
439
  diagnostics: [],
455
440
  error: null
456
441
  };
@@ -559,7 +544,9 @@ function parseWhiteboard(content, _palette) {
559
544
  });
560
545
  }
561
546
  };
562
- const lines = content.split("\n");
547
+ const directive = extractPaletteDirective(content);
548
+ result.diagnostics.push(...directive.diagnostics);
549
+ const lines = directive.content.split("\n");
563
550
  let firstLineSeen = false;
564
551
  for (let i = 0; i < lines.length; i++) {
565
552
  const lineNumber = i + 1;
@@ -587,6 +574,46 @@ function parseWhiteboard(content, _palette) {
587
574
  const sp = trimmed.search(/\s/);
588
575
  const word = (sp === -1 ? trimmed : trimmed.slice(0, sp)).toLowerCase();
589
576
  const rest = sp === -1 ? "" : trimmed.slice(sp + 1).trim();
577
+ if (word === "tag") {
578
+ const heading = matchTagBlockHeading(trimmed);
579
+ if (heading) {
580
+ const entries = [];
581
+ const addEntry = (raw, line) => {
582
+ const text = raw.trim();
583
+ const sp2 = text.lastIndexOf(" ");
584
+ const color = sp2 === -1 ? "" : text.slice(sp2 + 1);
585
+ const value = sp2 === -1 ? "" : text.slice(0, sp2).trim();
586
+ if (!value || !isWhiteboardColor(color) || color === "ink") {
587
+ warn(line, WHITEBOARD_DIAGNOSTIC_CODES.BAD_TAG_ENTRY, { entry: text });
588
+ return;
589
+ }
590
+ entries.push({
591
+ value,
592
+ color,
593
+ authoredColor: color,
594
+ lineNumber: line
595
+ });
596
+ };
597
+ for (const v of heading.inlineValues ?? []) addEntry(v, lineNumber);
598
+ const base = indentOf(lines[i]);
599
+ for (let j = i + 1; j < lines.length; j++) {
600
+ const raw = lines[j];
601
+ if (!raw.trim()) continue;
602
+ if (indentOf(raw) <= base) break;
603
+ i = j;
604
+ if (raw.trim().startsWith("//")) continue;
605
+ addEntry(raw, j + 1);
606
+ }
607
+ const group = {
608
+ name: heading.name,
609
+ ...heading.alias !== void 0 && { alias: heading.alias },
610
+ entries,
611
+ lineNumber
612
+ };
613
+ result.tagGroups.push(group);
614
+ continue;
615
+ }
616
+ }
590
617
  const { body, end } = collectBody(lines, i);
591
618
  i = end;
592
619
  const noBody = (element) => {
@@ -765,17 +792,6 @@ export {
765
792
  INK_PRESSURE_LEVELS,
766
793
  encodeInk,
767
794
  decodeInk,
768
- WHITEBOARD_COLORS,
769
- WHITEBOARD_SHAPE_KINDS,
770
- WHITEBOARD_ELEMENT_KEYWORDS,
771
- WHITEBOARD_STROKE_STYLES,
772
- WHITEBOARD_FILLS,
773
- WHITEBOARD_HEADS,
774
- WHITEBOARD_NOTE_WIDTH,
775
- WHITEBOARD_NOTE_HEIGHT,
776
- WHITEBOARD_NOTE_COLOR,
777
- isWhiteboardColor,
778
- isWhiteboardShapeKind,
779
795
  isWhiteboardImageRef,
780
796
  parseWhiteboard
781
797
  };
@@ -1,10 +1,27 @@
1
- import {
2
- safeHref
3
- } from "./chunk-Z6DXWULM.js";
4
1
  import {
5
2
  MONO_FAMILY
6
3
  } from "./chunk-ICLB27PZ.js";
7
4
 
5
+ // src/utils/safe-href.ts
6
+ var ALLOWED_SCHEMES = ["http", "https", "mailto"];
7
+ var SCHEME_RE = /^([a-z][a-z0-9+.-]*):/i;
8
+ var LEADING_TRIM_RE = /^[\x00-\x20]+/;
9
+ var URL_STRIP_RE = /[\x09\x0A\x0D]/g;
10
+ function safeHref(url) {
11
+ if (typeof url !== "string") return null;
12
+ const trimmed = url.replace(URL_STRIP_RE, "").replace(LEADING_TRIM_RE, "");
13
+ if (trimmed.length === 0) return null;
14
+ const match = SCHEME_RE.exec(trimmed);
15
+ if (!match) {
16
+ return url;
17
+ }
18
+ const scheme = match[1].toLowerCase();
19
+ if (ALLOWED_SCHEMES.includes(scheme)) {
20
+ return url;
21
+ }
22
+ return null;
23
+ }
24
+
8
25
  // src/utils/inline-markdown.ts
9
26
  function parseInlineMarkdown(text) {
10
27
  const spans = [];
@@ -72,6 +89,7 @@ function renderInlineText(textEl, text, palette, fontSize) {
72
89
  }
73
90
 
74
91
  export {
92
+ safeHref,
75
93
  parseInlineMarkdown,
76
94
  truncateBareUrl,
77
95
  stripInlineMarkdown,
@@ -93,7 +93,7 @@ var EXPORT_WIDTH = 1200;
93
93
  var EXPORT_HEIGHT = 800;
94
94
  async function resolveExportPalette(theme, palette) {
95
95
  if (palette) return palette;
96
- const { getPalette, DEFAULT_PALETTE_ID } = await import("./palettes-IN7ZFRJM.js");
96
+ const { getPalette, DEFAULT_PALETTE_ID } = await import("./palettes-4Y7CL2QL.js");
97
97
  const cfg = getPalette(DEFAULT_PALETTE_ID);
98
98
  return theme === "dark" ? cfg.dark : cfg.light;
99
99
  }
@@ -1,9 +1,3 @@
1
- import {
2
- wrapDescriptionLines
3
- } from "./chunk-NPWVOFB3.js";
4
- import {
5
- renderInlineText
6
- } from "./chunk-S7W75MIM.js";
7
1
  import {
8
2
  ScaleContext
9
3
  } from "./chunk-24YPR5EH.js";
@@ -12,6 +6,12 @@ import {
12
6
  TITLE_FONT_WEIGHT,
13
7
  TITLE_Y
14
8
  } from "./chunk-VLC6WNRD.js";
9
+ import {
10
+ wrapDescriptionLines
11
+ } from "./chunk-MB2SQF7N.js";
12
+ import {
13
+ renderInlineText
14
+ } from "./chunk-65GPEV5V.js";
15
15
  import {
16
16
  FONT_FAMILY
17
17
  } from "./chunk-ICLB27PZ.js";
@@ -1,12 +1,10 @@
1
- import {
2
- tryCollectNote
3
- } from "./chunk-3Y63RFJL.js";
4
- import {
5
- resolveNotes
6
- } from "./chunk-O753JUEZ.js";
7
1
  import {
8
2
  parseInArrowLabel
9
3
  } from "./chunk-N7VMGZCU.js";
4
+ import {
5
+ resolveNotes,
6
+ tryCollectNote
7
+ } from "./chunk-NJJCTEBM.js";
10
8
  import {
11
9
  normalizeName
12
10
  } from "./chunk-NOTA6TEI.js";
@@ -4,7 +4,7 @@ import {
4
4
  } from "./chunk-EJS3K44P.js";
5
5
  import {
6
6
  computeNodeSize
7
- } from "./chunk-FTUMRSGT.js";
7
+ } from "./chunk-P5FUWXPW.js";
8
8
  import {
9
9
  EDGE_LABEL_FONT_SIZE,
10
10
  NODE_HEIGHT,
@@ -1,15 +1,19 @@
1
- import {
2
- renderInlineText
3
- } from "./chunk-S7W75MIM.js";
4
1
  import {
5
2
  renderNodeCard
6
3
  } from "./chunk-R2K5L4UA.js";
4
+ import {
5
+ serializeSvg
6
+ } from "./chunk-CYRB2JTN.js";
7
7
  import {
8
8
  ScaleContext
9
9
  } from "./chunk-24YPR5EH.js";
10
10
  import {
11
- renderIntegratedLegend
12
- } from "./chunk-NMS5XSLX.js";
11
+ layoutInlineHeader
12
+ } from "./chunk-42UJ23H3.js";
13
+ import {
14
+ TITLE_FONT_SIZE,
15
+ TITLE_FONT_WEIGHT
16
+ } from "./chunk-VLC6WNRD.js";
13
17
  import {
14
18
  ARROWHEAD_HEIGHT,
15
19
  ARROWHEAD_WIDTH,
@@ -30,25 +34,21 @@ import {
30
34
  SEPARATOR_GAP
31
35
  } from "./chunk-XCKNFFKM.js";
32
36
  import {
33
- layoutInlineHeader
34
- } from "./chunk-42UJ23H3.js";
35
- import {
36
- serializeSvg
37
- } from "./chunk-CYRB2JTN.js";
37
+ renderIntegratedLegend
38
+ } from "./chunk-NMS5XSLX.js";
38
39
  import {
39
40
  getLegendExtent,
40
41
  getMaxLegendReservedHeight
41
42
  } from "./chunk-JILEYZ2V.js";
42
43
  import {
43
- TITLE_FONT_SIZE,
44
- TITLE_FONT_WEIGHT
45
- } from "./chunk-VLC6WNRD.js";
44
+ preprocessDescriptionLine
45
+ } from "./chunk-IYULMRBE.js";
46
+ import {
47
+ renderInlineText
48
+ } from "./chunk-65GPEV5V.js";
46
49
  import {
47
50
  FONT_FAMILY
48
51
  } from "./chunk-ICLB27PZ.js";
49
- import {
50
- preprocessDescriptionLine
51
- } from "./chunk-IYULMRBE.js";
52
52
  import {
53
53
  tagAttrKey
54
54
  } from "./chunk-4SACN2C5.js";
@@ -460,7 +460,7 @@ function renderLegend(parent, legendGroups, palette, isDark, activeTagGroup, fix
460
460
  async function renderSitemapForExport(content, theme, palette) {
461
461
  const { parseSitemap } = await import("./parser-6TDWUKM5.js");
462
462
  const { layoutSitemap } = await import("./layout-ND26WVX2.js");
463
- const { getPalette, DEFAULT_PALETTE_ID } = await import("./palettes-IN7ZFRJM.js");
463
+ const { getPalette, DEFAULT_PALETTE_ID } = await import("./palettes-4Y7CL2QL.js");
464
464
  const isDark = theme === "dark";
465
465
  const defaultCfg = getPalette(DEFAULT_PALETTE_ID);
466
466
  const effectivePalette = palette ?? (isDark ? defaultCfg.dark : defaultCfg.light);
@@ -0,0 +1,209 @@
1
+ import {
2
+ COLOR_KEYS,
3
+ SEMANTIC_KEYS,
4
+ validateThemeFile
5
+ } from "./chunk-FMAVHTYB.js";
6
+ import {
7
+ BUILT_IN_PALETTE_IDS
8
+ } from "./chunk-3UR4F7FE.js";
9
+ import {
10
+ makeDgmoError
11
+ } from "./chunk-BYU54C3S.js";
12
+
13
+ // src/palettes/directive.ts
14
+ var PALETTE_LINE_RE = /^palette(?:\s+(.*))?$/;
15
+ var MODES = /* @__PURE__ */ new Set(["light", "dark"]);
16
+ var COLOR_NAMES = new Set(COLOR_KEYS);
17
+ var kebab = (key) => key.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`);
18
+ var camel = (key) => key.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
19
+ var ROLE_KEYS = new Set(SEMANTIC_KEYS.map(kebab));
20
+ function builtInList() {
21
+ return [...BUILT_IN_PALETTE_IDS].sort().join(", ");
22
+ }
23
+ function warn(line, message, code) {
24
+ return makeDgmoError(line, message, "warning", code);
25
+ }
26
+ function readBlock(name, headerLine, block) {
27
+ const diagnostics = [];
28
+ const sections = {};
29
+ const where = /* @__PURE__ */ new Map();
30
+ let section;
31
+ for (const { line, text } of block) {
32
+ const [key = "", value, ...rest] = text.trim().split(/\s+/);
33
+ if (MODES.has(key) && value === void 0) {
34
+ section = key;
35
+ if (sections[section]) {
36
+ diagnostics.push(
37
+ warn(
38
+ line,
39
+ `The "${section}" section appears twice in palette "${name}".`,
40
+ "W_PALETTE_INVALID"
41
+ )
42
+ );
43
+ }
44
+ sections[section] = { roles: {}, colors: {} };
45
+ where.set(section, line);
46
+ continue;
47
+ }
48
+ if (key === "colors" && value === void 0) continue;
49
+ if (!section) {
50
+ diagnostics.push(
51
+ warn(
52
+ line,
53
+ `"${key}" sits outside a light or dark section of palette "${name}".`,
54
+ "W_PALETTE_INVALID"
55
+ )
56
+ );
57
+ continue;
58
+ }
59
+ if (value === void 0 || rest.length > 0) {
60
+ diagnostics.push(
61
+ warn(
62
+ line,
63
+ `Write "${key}" as one key and one hex colour, e.g. "${key} #282a36".`,
64
+ "W_PALETTE_INVALID"
65
+ )
66
+ );
67
+ continue;
68
+ }
69
+ if (COLOR_NAMES.has(key)) {
70
+ sections[section].colors[key] = value;
71
+ where.set(`${section}.colors.${key}`, line);
72
+ } else {
73
+ const field = ROLE_KEYS.has(key) ? camel(key) : key;
74
+ sections[section].roles[field] = value;
75
+ where.set(`${section}.${field}`, line);
76
+ }
77
+ }
78
+ if (diagnostics.length > 0) return diagnostics;
79
+ const modes = Object.keys(sections);
80
+ const input = {
81
+ id: name.toLowerCase(),
82
+ name,
83
+ ...modes.length === 1 && { mode: modes[0] }
84
+ };
85
+ for (const mode of modes) {
86
+ const { roles, colors } = sections[mode];
87
+ input[mode] = { ...roles, colors };
88
+ }
89
+ const result = validateThemeFile(input);
90
+ if (result.ok) return { palette: result.palette, mode: result.mode };
91
+ return result.errors.map((error) => {
92
+ const field = /^(light|dark)(?:\.colors)?\.(\w+)/.exec(error) ?? /^(light|dark)\b[^:]*: (\w+) /.exec(error);
93
+ const at = field ? where.get(`${field[1]}.colors.${field[2]}`) ?? where.get(`${field[1]}.${field[2]}`) ?? where.get(field[1]) : void 0;
94
+ return warn(
95
+ at ?? headerLine,
96
+ `Palette "${name}" is not drawn \u2014 ${error.replace(/\b(text[A-Z]\w*|[a-z]+[A-Z]\w*)\b/g, kebab)}.`,
97
+ "W_PALETTE_INVALID"
98
+ );
99
+ });
100
+ }
101
+ function extractPaletteDirective(content) {
102
+ if (!/^palette\b/m.test(content)) return { content, diagnostics: [] };
103
+ const lines = content.split("\n");
104
+ const diagnostics = [];
105
+ let paletteId;
106
+ let palette;
107
+ let mode;
108
+ for (let i = 0; i < lines.length; i++) {
109
+ const match = PALETTE_LINE_RE.exec(lines[i].replace(/\r$/, ""));
110
+ if (!match) continue;
111
+ const lineNumber = i + 1;
112
+ lines[i] = "//";
113
+ const block = [];
114
+ let blockEnd = i;
115
+ for (let j = i + 1; j < lines.length; j++) {
116
+ const next = lines[j].replace(/\r$/, "");
117
+ if (next.trim() === "") continue;
118
+ if (!/^\s/.test(next)) break;
119
+ blockEnd = j;
120
+ block.push({ line: j + 1, text: next });
121
+ }
122
+ for (let j = i + 1; j <= blockEnd; j++) lines[j] = "//";
123
+ i = blockEnd;
124
+ const words = (match[1] ?? "").trim().split(/\s+/).filter(Boolean);
125
+ const name = words[0];
126
+ if (!name) {
127
+ diagnostics.push(
128
+ warn(
129
+ lineNumber,
130
+ `"palette" needs a palette name \u2014 one of ${builtInList()}.`,
131
+ "W_PALETTE_UNKNOWN"
132
+ )
133
+ );
134
+ continue;
135
+ }
136
+ if (block.length > 0) {
137
+ if (words.length > 1) {
138
+ diagnostics.push(
139
+ warn(
140
+ lineNumber,
141
+ `An embedded palette takes its name only \u2014 its sections say which modes it has.`,
142
+ "W_PALETTE_MODE_UNKNOWN"
143
+ )
144
+ );
145
+ }
146
+ const read = readBlock(name, lineNumber, block);
147
+ if (Array.isArray(read)) {
148
+ diagnostics.push(...read);
149
+ continue;
150
+ }
151
+ paletteId = void 0;
152
+ palette = read.palette;
153
+ mode = read.mode ?? void 0;
154
+ continue;
155
+ }
156
+ const id = name.toLowerCase();
157
+ if (!BUILT_IN_PALETTE_IDS.has(id)) {
158
+ diagnostics.push(
159
+ warn(
160
+ lineNumber,
161
+ `"${name}" is not a built-in palette \u2014 this diagram uses the default palette. Built-in palettes: ${builtInList()}. An embedded palette needs its colours in an indented block.`,
162
+ "W_PALETTE_UNKNOWN"
163
+ )
164
+ );
165
+ continue;
166
+ }
167
+ const modeWord = words[1];
168
+ if (words.length > 2 || modeWord !== void 0 && !MODES.has(modeWord)) {
169
+ diagnostics.push(
170
+ warn(
171
+ lineNumber,
172
+ `"palette ${name}" takes one optional mode word, light or dark \u2014 the rest of the line is ignored.`,
173
+ "W_PALETTE_MODE_UNKNOWN"
174
+ )
175
+ );
176
+ }
177
+ paletteId = id;
178
+ palette = void 0;
179
+ mode = modeWord !== void 0 && MODES.has(modeWord) ? modeWord : void 0;
180
+ }
181
+ return {
182
+ content: lines.join("\n"),
183
+ ...paletteId !== void 0 && { paletteId },
184
+ ...palette !== void 0 && { palette },
185
+ ...mode !== void 0 && { mode },
186
+ diagnostics
187
+ };
188
+ }
189
+ function choosePalette(directive, caller) {
190
+ const callerTheme = caller.theme ?? "light";
191
+ if (caller.paletteOverride !== void 0) {
192
+ return { paletteId: caller.paletteOverride, theme: callerTheme };
193
+ }
194
+ const fileId = directive.palette?.id ?? directive.paletteId;
195
+ if (fileId !== void 0) {
196
+ const theme = directive.mode === "dark" ? "dark" : directive.mode === "light" && callerTheme !== "transparent" ? "light" : callerTheme;
197
+ return {
198
+ paletteId: fileId,
199
+ ...directive.palette && { palette: directive.palette },
200
+ theme
201
+ };
202
+ }
203
+ return { paletteId: caller.palette ?? "slate", theme: callerTheme };
204
+ }
205
+
206
+ export {
207
+ extractPaletteDirective,
208
+ choosePalette
209
+ };