schematex 0.2.5 → 0.3.2

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 (194) hide show
  1. package/README.md +4 -3
  2. package/dist/ai/ai-sdk.cjs +25 -25
  3. package/dist/ai/ai-sdk.d.cts +2 -2
  4. package/dist/ai/ai-sdk.d.ts +2 -2
  5. package/dist/ai/ai-sdk.js +20 -20
  6. package/dist/ai/index.cjs +28 -28
  7. package/dist/ai/index.d.cts +3 -3
  8. package/dist/ai/index.d.ts +3 -3
  9. package/dist/ai/index.js +20 -20
  10. package/dist/{api-bQZ98gkJ.d.cts → api-BuFilDQB.d.cts} +1 -1
  11. package/dist/{api-bQZ98gkJ.d.ts → api-BuFilDQB.d.ts} +1 -1
  12. package/dist/browser.cjs +22 -22
  13. package/dist/browser.d.cts +2 -2
  14. package/dist/browser.d.ts +2 -2
  15. package/dist/browser.js +20 -20
  16. package/dist/{chunk-J2LVOWVY.js → chunk-2J2QWNGI.js} +46 -24
  17. package/dist/chunk-2J2QWNGI.js.map +1 -0
  18. package/dist/{chunk-MCFQAUQV.cjs → chunk-2UJAVPA4.cjs} +58 -39
  19. package/dist/chunk-2UJAVPA4.cjs.map +1 -0
  20. package/dist/{chunk-5AEN2PLB.cjs → chunk-3YXXZ4LT.cjs} +33 -33
  21. package/dist/{chunk-5AEN2PLB.cjs.map → chunk-3YXXZ4LT.cjs.map} +1 -1
  22. package/dist/{chunk-RP5UATRA.js → chunk-56LXBM45.js} +4 -4
  23. package/dist/{chunk-RP5UATRA.js.map → chunk-56LXBM45.js.map} +1 -1
  24. package/dist/{chunk-OC22GGQN.js → chunk-6BKUD5EJ.js} +54 -4
  25. package/dist/chunk-6BKUD5EJ.js.map +1 -0
  26. package/dist/{chunk-ULYRO2KY.cjs → chunk-75BMFCP5.cjs} +44 -44
  27. package/dist/{chunk-ULYRO2KY.cjs.map → chunk-75BMFCP5.cjs.map} +1 -1
  28. package/dist/{chunk-ZNDIGQJD.js → chunk-7BEJHG43.js} +3 -3
  29. package/dist/{chunk-ZNDIGQJD.js.map → chunk-7BEJHG43.js.map} +1 -1
  30. package/dist/{chunk-WYFXOXVK.cjs → chunk-7MVDN5UC.cjs} +35 -35
  31. package/dist/{chunk-WYFXOXVK.cjs.map → chunk-7MVDN5UC.cjs.map} +1 -1
  32. package/dist/{chunk-JDTB7IKL.js → chunk-BJ65PKDU.js} +3 -3
  33. package/dist/{chunk-JDTB7IKL.js.map → chunk-BJ65PKDU.js.map} +1 -1
  34. package/dist/{chunk-FE6GAUNW.js → chunk-BJWMPPEA.js} +5 -5
  35. package/dist/{chunk-FE6GAUNW.js.map → chunk-BJWMPPEA.js.map} +1 -1
  36. package/dist/{chunk-MJGDP3CS.cjs → chunk-BUN3CRMP.cjs} +488 -109
  37. package/dist/chunk-BUN3CRMP.cjs.map +1 -0
  38. package/dist/{chunk-COLTVQWR.cjs → chunk-C3IVD7DI.cjs} +25 -25
  39. package/dist/{chunk-COLTVQWR.cjs.map → chunk-C3IVD7DI.cjs.map} +1 -1
  40. package/dist/{chunk-3YZ6FPQW.cjs → chunk-EYHD7LV3.cjs} +131 -131
  41. package/dist/{chunk-3YZ6FPQW.cjs.map → chunk-EYHD7LV3.cjs.map} +1 -1
  42. package/dist/{chunk-UGCUNADI.js → chunk-F6OROIHS.js} +35 -16
  43. package/dist/chunk-F6OROIHS.js.map +1 -0
  44. package/dist/{chunk-UAGSCTYI.cjs → chunk-GYTWJ6VB.cjs} +85 -63
  45. package/dist/chunk-GYTWJ6VB.cjs.map +1 -0
  46. package/dist/{chunk-MR5HU5WU.js → chunk-H4CJTKEH.js} +50 -4
  47. package/dist/chunk-H4CJTKEH.js.map +1 -0
  48. package/dist/{chunk-45KP67RR.js → chunk-HIQPEAL7.js} +5 -5
  49. package/dist/chunk-HIQPEAL7.js.map +1 -0
  50. package/dist/{chunk-LR4X4ZRG.js → chunk-IT2TVXC7.js} +20 -16
  51. package/dist/chunk-IT2TVXC7.js.map +1 -0
  52. package/dist/{chunk-2JDVJRR3.cjs → chunk-K5QG53GT.cjs} +28 -28
  53. package/dist/chunk-K5QG53GT.cjs.map +1 -0
  54. package/dist/{chunk-B37IKTI7.cjs → chunk-KUXOHLGC.cjs} +97 -47
  55. package/dist/chunk-KUXOHLGC.cjs.map +1 -0
  56. package/dist/{chunk-A5D2IMOX.cjs → chunk-L2KUGWFR.cjs} +47 -47
  57. package/dist/{chunk-A5D2IMOX.cjs.map → chunk-L2KUGWFR.cjs.map} +1 -1
  58. package/dist/{chunk-HDKDQAEQ.cjs → chunk-LFZZ4NCP.cjs} +14 -2
  59. package/dist/chunk-LFZZ4NCP.cjs.map +1 -0
  60. package/dist/{chunk-U6L3FAML.js → chunk-M3R6RCXY.js} +3 -3
  61. package/dist/{chunk-U6L3FAML.js.map → chunk-M3R6RCXY.js.map} +1 -1
  62. package/dist/{chunk-5YYAYW67.js → chunk-M5ZC3LFJ.js} +3 -3
  63. package/dist/{chunk-5YYAYW67.js.map → chunk-M5ZC3LFJ.js.map} +1 -1
  64. package/dist/{chunk-B6INLQBU.cjs → chunk-MKKFIPKU.cjs} +46 -46
  65. package/dist/{chunk-B6INLQBU.cjs.map → chunk-MKKFIPKU.cjs.map} +1 -1
  66. package/dist/{chunk-M5B2UUNW.js → chunk-NFT6VW73.js} +4 -4
  67. package/dist/{chunk-M5B2UUNW.js.map → chunk-NFT6VW73.js.map} +1 -1
  68. package/dist/{chunk-X7RPFTTR.cjs → chunk-OK5RYX55.cjs} +26 -26
  69. package/dist/{chunk-X7RPFTTR.cjs.map → chunk-OK5RYX55.cjs.map} +1 -1
  70. package/dist/{chunk-VPKCW4PB.js → chunk-RNGYXGHS.js} +2854 -42
  71. package/dist/chunk-RNGYXGHS.js.map +1 -0
  72. package/dist/{chunk-DPQYGWCT.cjs → chunk-RODV6PC4.cjs} +52 -6
  73. package/dist/chunk-RODV6PC4.cjs.map +1 -0
  74. package/dist/{chunk-H2OEUBPO.js → chunk-SE23X5OE.js} +441 -62
  75. package/dist/chunk-SE23X5OE.js.map +1 -0
  76. package/dist/{chunk-FCGHV6ZK.js → chunk-SFSZUOFT.js} +4 -4
  77. package/dist/{chunk-FCGHV6ZK.js.map → chunk-SFSZUOFT.js.map} +1 -1
  78. package/dist/{chunk-E65ITQXV.cjs → chunk-UK7JF5QB.cjs} +52 -48
  79. package/dist/chunk-UK7JF5QB.cjs.map +1 -0
  80. package/dist/{chunk-QSQX77S2.cjs → chunk-W7GIQTJV.cjs} +21 -21
  81. package/dist/{chunk-QSQX77S2.cjs.map → chunk-W7GIQTJV.cjs.map} +1 -1
  82. package/dist/{chunk-KLJEK547.js → chunk-WHJXRLFD.js} +14 -3
  83. package/dist/chunk-WHJXRLFD.js.map +1 -0
  84. package/dist/{chunk-YQANC7HQ.js → chunk-X4F6VVEJ.js} +3 -3
  85. package/dist/{chunk-YQANC7HQ.js.map → chunk-X4F6VVEJ.js.map} +1 -1
  86. package/dist/{chunk-ZNOD4VZT.cjs → chunk-XI6JOG76.cjs} +46 -46
  87. package/dist/{chunk-ZNOD4VZT.cjs.map → chunk-XI6JOG76.cjs.map} +1 -1
  88. package/dist/{chunk-4S2WILLW.cjs → chunk-XUEROLSB.cjs} +72 -19
  89. package/dist/chunk-XUEROLSB.cjs.map +1 -0
  90. package/dist/{chunk-MSYBSOU2.cjs → chunk-YTEEZV6J.cjs} +3055 -241
  91. package/dist/chunk-YTEEZV6J.cjs.map +1 -0
  92. package/dist/{chunk-PGALHQFF.js → chunk-ZNLEUL7T.js} +60 -7
  93. package/dist/chunk-ZNLEUL7T.js.map +1 -0
  94. package/dist/{chunk-DNZFOCV7.js → chunk-ZTSO3S4P.js} +3 -3
  95. package/dist/{chunk-DNZFOCV7.js.map → chunk-ZTSO3S4P.js.map} +1 -1
  96. package/dist/diagrams/blockdiagram/index.cjs +6 -6
  97. package/dist/diagrams/blockdiagram/index.d.cts +1 -1
  98. package/dist/diagrams/blockdiagram/index.d.ts +1 -1
  99. package/dist/diagrams/blockdiagram/index.js +2 -2
  100. package/dist/diagrams/circuit/index.cjs +8 -8
  101. package/dist/diagrams/circuit/index.d.cts +1 -1
  102. package/dist/diagrams/circuit/index.d.ts +1 -1
  103. package/dist/diagrams/circuit/index.js +2 -2
  104. package/dist/diagrams/ecomap/index.cjs +8 -8
  105. package/dist/diagrams/ecomap/index.d.cts +1 -1
  106. package/dist/diagrams/ecomap/index.d.ts +1 -1
  107. package/dist/diagrams/ecomap/index.js +3 -3
  108. package/dist/diagrams/entity/index.cjs +6 -6
  109. package/dist/diagrams/entity/index.d.cts +1 -1
  110. package/dist/diagrams/entity/index.d.ts +1 -1
  111. package/dist/diagrams/entity/index.js +2 -2
  112. package/dist/diagrams/fishbone/index.cjs +8 -8
  113. package/dist/diagrams/fishbone/index.d.cts +1 -1
  114. package/dist/diagrams/fishbone/index.d.ts +1 -1
  115. package/dist/diagrams/fishbone/index.js +2 -2
  116. package/dist/diagrams/flowchart/index.cjs +8 -8
  117. package/dist/diagrams/flowchart/index.d.cts +2 -2
  118. package/dist/diagrams/flowchart/index.d.ts +2 -2
  119. package/dist/diagrams/flowchart/index.js +2 -2
  120. package/dist/diagrams/genogram/index.cjs +10 -10
  121. package/dist/diagrams/genogram/index.d.cts +1 -1
  122. package/dist/diagrams/genogram/index.d.ts +1 -1
  123. package/dist/diagrams/genogram/index.js +3 -3
  124. package/dist/diagrams/ladder/index.cjs +6 -6
  125. package/dist/diagrams/ladder/index.d.cts +1 -1
  126. package/dist/diagrams/ladder/index.d.ts +1 -1
  127. package/dist/diagrams/ladder/index.js +2 -2
  128. package/dist/diagrams/logic/index.cjs +6 -6
  129. package/dist/diagrams/logic/index.d.cts +1 -1
  130. package/dist/diagrams/logic/index.d.ts +1 -1
  131. package/dist/diagrams/logic/index.js +2 -2
  132. package/dist/diagrams/orgchart/index.cjs +7 -7
  133. package/dist/diagrams/orgchart/index.d.cts +1 -1
  134. package/dist/diagrams/orgchart/index.d.ts +1 -1
  135. package/dist/diagrams/orgchart/index.js +2 -2
  136. package/dist/diagrams/pedigree/index.cjs +8 -8
  137. package/dist/diagrams/pedigree/index.d.cts +1 -1
  138. package/dist/diagrams/pedigree/index.d.ts +1 -1
  139. package/dist/diagrams/pedigree/index.js +3 -3
  140. package/dist/diagrams/phylo/index.cjs +7 -7
  141. package/dist/diagrams/phylo/index.d.cts +1 -1
  142. package/dist/diagrams/phylo/index.d.ts +1 -1
  143. package/dist/diagrams/phylo/index.js +2 -2
  144. package/dist/diagrams/sld/index.cjs +6 -6
  145. package/dist/diagrams/sld/index.d.cts +1 -1
  146. package/dist/diagrams/sld/index.d.ts +1 -1
  147. package/dist/diagrams/sld/index.js +2 -2
  148. package/dist/diagrams/sociogram/index.cjs +7 -7
  149. package/dist/diagrams/sociogram/index.d.cts +1 -1
  150. package/dist/diagrams/sociogram/index.d.ts +1 -1
  151. package/dist/diagrams/sociogram/index.js +3 -3
  152. package/dist/diagrams/timing/index.cjs +5 -5
  153. package/dist/diagrams/timing/index.d.cts +1 -1
  154. package/dist/diagrams/timing/index.d.ts +1 -1
  155. package/dist/diagrams/timing/index.js +2 -2
  156. package/dist/diagrams/venn/index.cjs +9 -9
  157. package/dist/diagrams/venn/index.d.cts +1 -1
  158. package/dist/diagrams/venn/index.d.ts +1 -1
  159. package/dist/diagrams/venn/index.js +2 -2
  160. package/dist/{index-BTZEka65.d.cts → index-BrLxEzSQ.d.cts} +1 -1
  161. package/dist/{index-DcU88F9i.d.ts → index-dWDwG6BW.d.ts} +1 -1
  162. package/dist/index.cjs +47 -39
  163. package/dist/index.d.cts +8 -4
  164. package/dist/index.d.ts +8 -4
  165. package/dist/index.js +19 -19
  166. package/dist/react.cjs +20 -20
  167. package/dist/react.cjs.map +1 -1
  168. package/dist/react.d.cts +1 -1
  169. package/dist/react.d.ts +1 -1
  170. package/dist/react.js +19 -19
  171. package/dist/react.js.map +1 -1
  172. package/dist/{types-C4LnMEcB.d.cts → types-BtiUg7Gx.d.cts} +25 -4
  173. package/dist/{types-C4LnMEcB.d.ts → types-BtiUg7Gx.d.ts} +25 -4
  174. package/package.json +2 -2
  175. package/dist/chunk-2JDVJRR3.cjs.map +0 -1
  176. package/dist/chunk-45KP67RR.js.map +0 -1
  177. package/dist/chunk-4S2WILLW.cjs.map +0 -1
  178. package/dist/chunk-B37IKTI7.cjs.map +0 -1
  179. package/dist/chunk-DPQYGWCT.cjs.map +0 -1
  180. package/dist/chunk-E65ITQXV.cjs.map +0 -1
  181. package/dist/chunk-H2OEUBPO.js.map +0 -1
  182. package/dist/chunk-HDKDQAEQ.cjs.map +0 -1
  183. package/dist/chunk-J2LVOWVY.js.map +0 -1
  184. package/dist/chunk-KLJEK547.js.map +0 -1
  185. package/dist/chunk-LR4X4ZRG.js.map +0 -1
  186. package/dist/chunk-MCFQAUQV.cjs.map +0 -1
  187. package/dist/chunk-MJGDP3CS.cjs.map +0 -1
  188. package/dist/chunk-MR5HU5WU.js.map +0 -1
  189. package/dist/chunk-MSYBSOU2.cjs.map +0 -1
  190. package/dist/chunk-OC22GGQN.js.map +0 -1
  191. package/dist/chunk-PGALHQFF.js.map +0 -1
  192. package/dist/chunk-UAGSCTYI.cjs.map +0 -1
  193. package/dist/chunk-UGCUNADI.js.map +0 -1
  194. package/dist/chunk-VPKCW4PB.js.map +0 -1
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkMSYBSOU2_cjs = require('./chunk-MSYBSOU2.cjs');
3
+ var chunkYTEEZV6J_cjs = require('./chunk-YTEEZV6J.cjs');
4
4
 
5
5
  // src/ai/registry.ts
6
6
  var DIAGRAM_REGISTRY = [
@@ -105,6 +105,15 @@ var DIAGRAM_REGISTRY = [
105
105
  standard: "IEEE Std 315 + ANSI device numbering",
106
106
  syntaxKey: "sld"
107
107
  },
108
+ {
109
+ type: "pid",
110
+ name: "P&ID (Piping & Instrumentation)",
111
+ tagline: "ISA-5.1 process equipment, valves, and instrument bubbles.",
112
+ useWhen: "Use for chemical / petrochemical / pharmaceutical / water-treatment process diagrams \u2014 vessels, columns, heat exchangers, pumps, valves, and instrument loops with ISA tag codes (FT/FIC/PT/etc.). Equipment + piping + instrumentation in one diagram.",
113
+ cluster: "electrical-industrial",
114
+ standard: "ANSI/ISA-5.1-2009 + ISO 10628-1:2014",
115
+ syntaxKey: "pid"
116
+ },
108
117
  // ── Corporate / Legal ────────────────────────────────────────
109
118
  {
110
119
  type: "entity",
@@ -143,6 +152,16 @@ var DIAGRAM_REGISTRY = [
143
152
  standard: "Howard-Raiffa / CART-sklearn / taxonomy",
144
153
  syntaxKey: "decisiontree"
145
154
  },
155
+ // ── Behavior modeling ────────────────────────────────────────
156
+ {
157
+ type: "state",
158
+ name: "State diagram",
159
+ tagline: "UML 2.5 / Harel statechart with composite states and pseudo-states.",
160
+ useWhen: "Use for modeling reactive system behavior \u2014 finite state machines, lifecycle states, controller modes, UI workflows. Supports simple states, composite (nested) states, fork/join, choice, history, and full Mermaid `stateDiagram-v2` syntax.",
161
+ cluster: "behavior-modeling",
162
+ standard: "OMG UML 2.5.1 \xA714 + Harel (1987) statechart",
163
+ syntaxKey: "state"
164
+ },
146
165
  // ── Generic process / flow ───────────────────────────────────
147
166
  {
148
167
  type: "flowchart",
@@ -464,6 +483,25 @@ var EXAMPLES = [
464
483
  "dsl": 'genogram "BRCA1 Family"\n I_1 [male, 1930, 1995, deceased]\n I_2 [female, 1932, 1990, deceased, conditions: ovarian_cancer(full, #B388FF)]\n I_1 -- I_2\n II_1 [female, 1955, conditions: breast_cancer(full, #EC407A)]\n II_2 [male, 1958]\n II_3 [female, 1960]\n II_1 -- II_4 [male, 1954]\n III_1 [female, 1985, index, conditions: breast_cancer(full, #EC407A)]\n III_2 [male, 1988]',
465
484
  "notes": "## Scenario\n\nA family history genogram for hereditary breast/ovarian cancer, documented at the initial genetic counseling intake before formal pedigree analysis. For standardized clinical pedigree notation (NSGC), use the Pedigree diagram type instead.\n\n## Annotation key\n\n- `conditions: ovarian_cancer(full)` / `conditions: breast_cancer(full)` \u2014 medical conditions filling the symbol; color is optional hex\n- `deceased` with birth and death years \u2014 marks individuals with a slash and date range\n- `index` \u2014 marks the proband who triggered the clinical referral\n\n## How to read\n\nThe maternal grandmother (I_2) had ovarian cancer and is deceased. Her daughter (II_1) developed breast cancer. The proband (III_1, index) is a third-generation female with breast cancer \u2014 the inheritance pattern spanning three generations justifies BRCA genetic testing."
466
485
  },
486
+ {
487
+ "slug": "genogram-foster-care",
488
+ "diagram": "genogram",
489
+ "title": "Foster care / child protection",
490
+ "description": "Foster-care genogram for a real LATAM child-protection case \u2014 biological parents (cohabitation ended), abuse, current foster placement (dotted secondary link), unknown-count siblings, and a maternal uncle as known-relative-with-unknown-ancestry.",
491
+ "standard": "McGoldrick 2020 + Bennett 2022 (adopted-out / dual-parent convention)",
492
+ "tags": [
493
+ "foster-care",
494
+ "dual-parent",
495
+ "abuse",
496
+ "sibling-of",
497
+ "unknown-siblings",
498
+ "latam"
499
+ ],
500
+ "complexity": 3,
501
+ "featured": true,
502
+ "dsl": 'genogram "Familia Isa\xEDas"\n victor [male, label: "V\xEDctor Seguel"]\n monica [female, label: "M\xF3nica Barrientos"]\n victor ~/~ monica\n ?\n isaias [male, 2020, age: 6, label: "Isa\xEDas", index]\n pablo_sr [male, label: "Don Pablo"]\n priscila [female, label: "Do\xF1a Priscila"]\n pablo_sr -- priscila\n pablo_jr [male, label: "Pablo (jr)"]\n alanis [female, label: "Alanis"]\n isaias [foster]\n tio_materno [male, label: "T\xEDo materno", sibling-of: monica]\n victor -physical-abuse-> isaias\n monica -physical-abuse-> isaias\n tio_materno -nevermet- isaias',
503
+ "notes": '## Scenario\n\nA foster-care social worker in Chile is preparing the case file for Isa\xEDas, a 6-year-old boy removed from his biological parents (V\xEDctor and M\xF3nica) due to physical abuse from both. He currently lives with foster parents Don Pablo and Do\xF1a Priscila, who have two biological children of their own. The case file mentions Isa\xEDas has siblings whose names and ages are unknown, and a maternal uncle who is a potential reunification resource but currently has no contact.\n\nA judge or psychologist receiving this diagram must, at a glance, correctly conclude:\n\n1. Isa\xEDas is the **biological son** of V\xEDctor and M\xF3nica \u2014 solid parent-child line down from the bio couple.\n2. He **currently lives** with Don Pablo and Do\xF1a Priscila as a foster child \u2014 *secondary dotted link* from the foster couple, drawn without pulling Isa\xEDas away from his bio-parent position.\n3. He was **removed due to physical abuse** from both bio parents \u2014 directional red zigzag arrows.\n4. The **maternal uncle** is M\xF3nica\'s brother (`sibling-of: monica`) with **no current relationship** to Isa\xEDas \u2014 dashed bracket between M\xF3nica and T\xEDo + `nevermet` line.\n5. Isa\xEDas has **unknown-count siblings** still with the bio parents \u2014 single `?` diamond placeholder.\n6. **Isa\xEDas is the index person** \u2014 concentric outer border highlight.\n\n## Annotation key\n\n- `~/~` \u2014 cohabitation ended (never-married); standard for LATAM caseloads where bio parents lived together unmarried and the relationship has broken. Distinct from `-x-` divorce (no marriage) and `-/-` separation (still married).\n- Re-declaring `isaias [foster]` under the foster couple after declaring him under the bio couple \u2192 engine treats the second declaration as a **secondary "current caregiver" link** (dotted), preserving all attributes from the first declaration.\n- `?` on a child line \u2192 a single diamond with `?` glyph meaning "\u22651 siblings, count and identities unknown" (standard pedigree convention).\n- `[sibling-of: monica]` \u2192 places T\xEDo materno on M\xF3nica\'s generation with a dashed bracket between them, **without** synthesizing phantom maternal grandparents.\n- `-physical-abuse->` \u2192 directional red arrow; the `>` indicates the perpetrator (left side) and victim (right side).\n\n## Why this matters\n\nA genogram engine that quietly rendered Isa\xEDas as a third biological child of Don Pablo + Do\xF1a Priscila \u2014 or dropped his sex and label when the `[foster]` redeclaration overwrote the original \u2014 would invert the case story. This example exercises every fix from the 2026-04 foster-care brief: dual-parent rendering, same-id merge, sibling-of, cohabiting-ended, and the unknown-siblings placeholder.'
504
+ },
467
505
  {
468
506
  "slug": "genogram-medical-history",
469
507
  "diagram": "genogram",
@@ -921,7 +959,7 @@ var EXAMPLES = [
921
959
  var SYNTAX = {
922
960
  "genogram": {
923
961
  "title": "Genogram",
924
- "content": '## 1. Your first genogram\n\nThe smallest clinically useful genogram: two parents, one child.\n\n```\ngenogram\n alice [female, 1980]\n bob [male, 1978]\n alice -- bob "m. 2005"\n carol [female, 2008]\n```\n\nFour rules cover 80% of usage:\n\n1. Start with the keyword `genogram`, optionally followed by a quoted title.\n2. Declare each person on their own line: `id [attributes]`. Attributes go in square brackets, comma-separated.\n3. Connect two people with a **couple operator** \u2014 `--` (marriage) here; see \xA74.1 for all six. A trailing quoted string is the relationship label.\n4. **Indent under the couple line** to add their children.\n\n> Comments must be on their own line, starting with `#`. Trailing inline comments (`bob [male, 1978] # ...`) are not supported and will break the parser \u2014 see \xA78.\n\n---\n\n## 2. Individuals\n\nAn individual line is `id [attr1, attr2, \u2026]`. Attributes are comma-separated, order-independent, all optional.\n\n**ID rules.** Must match `[a-zA-Z][a-zA-Z0-9_-]*`. IDs are case-insensitive internally but preserve their original casing as the display label (override with `label:"\u2026"`).\n\n**Attributes accepted by the parser today:**\n\n| Attribute | Values | Effect |\n|---|---|---|\n| Sex | `male`, `female`, `unknown`, `other` | Shape: square, circle, diamond, diamond |\n| Status | `deceased`, `stillborn`, `miscarriage`, `abortion` | Visual modifier (X-out, scaled shape, etc.) |\n| Birth year | 4-digit number, e.g. `1980` | First 4-digit token = birth year |\n| Death year | 4-digit number after birth, e.g. `1980, 2055` | Second 4-digit token = death year |\n| `index` | flag | Concentric shape = identified patient |\n| `age:N` | e.g. `age:42` | Age shown inside shape |\n| `death:YYYY` | e.g. `death:2020` | Explicit death year |\n| `label:"\u2026"` | e.g. `label:"Dr. Smith"` | Display label override |\n| `conditions:\u2026` | see \xA75 | Medical/psychological conditions |\n| `key:value` | any custom | Stored as metadata |\n\n```\ngenogram\n grandma [female, 1920, 2002, deceased]\n dad [male, 1950, age:74]\n me [male, 1985, index]\n daughter [female, 2012, label:"Em"]\n```\n\n---\n\n## 3. Shapes\n\n| Visual | Sex value | Meaning |\n|---|---|---|\n| \u2610 Square | `male` | Male |\n| \u25CB Circle | `female` | Female |\n| \u25C7 Diamond | `unknown`, `other`, *or* attribute omitted | Unknown / unspecified |\n\nStatus modifiers layer on top of the base shape:\n\n```\ngenogram\n alive [male, 1960]\n passed [male, 1930, 2010, deceased]\n stillborn_child [unknown, stillborn]\n lost [unknown, miscarriage]\n```\n\n---\n\n## 4. Connections\n\n### 4.1 Couple operators\n\nThe parser tries these in order. The first one that matches wins \u2014 so `-x-` beats `--`.\n\n| Operator | Type | Example | Meaning |\n|---|---|---|---|\n| `-x-` | divorced | `a -x- b` | Divorce |\n| `-/-` | separated | `a -/- b` | Separation |\n| `-o-` | engaged | `a -o- b` | Engagement |\n| `==` | consanguineous | `a == b` | Blood-related couple |\n| `--` | married | `a -- b` | Marriage |\n| `~` | cohabiting | `a ~ b` | Cohabiting / LTR |\n\nA trailing quoted string becomes the relationship label (`a -- b "m. 2005"`).\n\n### 4.2 Inline individual on the right side\n\nIf the right-hand person hasn\'t been declared yet, you can declare them in-place:\n\n```\ngenogram\n ann [female, 1970]\n ann -- ben [male, 1968] "m. 1995"\n kim [female, 1997]\n```\n\n### 4.3 Children (indented under a couple)\n\nIndentation under a couple line = "these are the children of this couple." Any indent greater than the couple\'s indent works; by convention use 2 more spaces. Children are rendered in order of declaration (render also sorts by birth year when present).\n\n```\ngenogram\n dad [male, 1950]\n mom [female, 1952]\n dad -- mom\n eldest [male, 1975]\n middle [female, 1978, adopted]\n twin_a [male, 1985, twin-identical]\n twin_b [male, 1985, twin-identical]\n```\n\n**Special child attributes:**\n\n| Attribute | Effect |\n|---|---|\n| `adopted` | Adoption line style |\n| `foster` | Foster relationship |\n| `twin-identical` | Grouped with other `twin-identical` children of the same couple |\n| `twin-fraternal` | Grouped with other `twin-fraternal` children |\n\n### 4.4 Emotional relationships\n\nSeparate line, parser pattern `A -TYPE- B` (non-directional) or `A -TYPE-> B` (directional). An optional quoted label goes at the end. **Both individuals must already be declared** before the emotional line.\n\n```\nharry -cutoff- petunia # non-directional\nharry -hostile- dudley "since 1991"\nuncle -abuse-> nephew # directional (arrow)\n```\n\nAll 32 types the parser accepts today:\n\n| Category | Types |\n|---|---|\n| Positive / close | `harmony`, `close`, `bestfriends`, `love`, `inlove`, `friendship` |\n| Negative / hostile | `hostile`, `conflict`, `enmity`, `distant-hostile`, `cutoff` |\n| Ambivalent | `close-hostile`, `fused`, `fused-hostile` |\n| Distance | `distant`, `normal`, `nevermet` |\n| Abuse *(directional)* | `abuse`, `physical-abuse`, `emotional-abuse`, `sexual-abuse`, `neglect` |\n| Control *(directional)* | `manipulative`, `controlling`, `jealous` |\n| Special | `focused`, `focused-neg`, `distrust`, `admirer`, `limerence` |\n\n```\ngenogram\n dad [male, 1950]\n son [male, 1985]\n daughter [female, 1988]\n dad -close- daughter\n dad -conflict- son\n son -cutoff- dad "since 2010"\n```\n\n---\n\n## 5. Medical conditions\n\nSyntax: `conditions: name(fill) [+ name(fill, #color)]\u2026`\n\n```\nfather [male, 1945, conditions: heart(full, #E53935)]\nmother [female, 1948, conditions: diabetes(half-left) + anxiety(half-right, #26A69A)]\n```\n\n- **`name`** \u2014 any identifier you choose (displayed in legend/tooltip).\n- **`fill`** \u2014 required, controls which region of the shape is colored. See table below.\n- **`color`** \u2014 optional hex. Default depends on the renderer theme.\n- Multiple conditions are joined with `+`. Each needs its own `(fill)`.\n\n**Fill positions:**\n\n| `fill` value | Region |\n|---|---|\n| `full` | Entire shape |\n| `half-left` / `half-right` | Left / right half |\n| `half-top` / `half-bottom` | Top / bottom half |\n| `quad-tl` / `quad-tr` / `quad-bl` / `quad-br` | One quadrant |\n| `striped` | Diagonal stripe pattern (asymptomatic carrier) |\n| `dotted` | Dot pattern |\n\n```\ngenogram\n dad [male, 1950, conditions: heart(full, #E53935)]\n mom [female, 1952, conditions: diabetes(half-left) + depression(half-right, #5C6BC0)]\n dad -- mom\n son [male, 1980, conditions: carrier(striped)]\n```\n\n---\n\n## 6. Labels & comments\n\n- **Title:** `genogram "Smith Family"` \u2014 first line only.\n- **Person label override:** `alice [female, label:"Dr. Alice Smith"]`.\n- **Relationship label:** trailing quoted string on a couple or emotional line \u2014 `alice -- bob "m. 2005"`.\n- **Comments:** `#` at the start of a line (after leading whitespace). Inline comments are **not** supported.\n\n```\ngenogram "Smith Family"\n # this line is a comment \u2014 fine\n alice [female, 1980] # \u2190 THIS trailing comment breaks the parser\n```\n\n---\n\n## 7. Reserved words & escaping\n\n**Reserved at line start:** `genogram` (header keyword).\n\n**Reserved operator tokens** inside a line \u2014 avoid using these sequences in IDs:\n`--`, `~`, `==`, `-x-`, `-/-`, `-o-`, and any `-<type>-` / `-<type>->` matching an emotional-relationship type.\n\n**Strings with spaces** must be double-quoted: titles, labels, `label:"\u2026"`. Single quotes and backticks are not recognized.\n\n---\n\n## 8. Common mistakes\n\nReal parser errors, what triggers them, and how to fix.\n\n| You wrote | Parser says | Fix |\n|---|---|---|\n| `alex [nonbinary, 1995]` | `Unknown property \'nonbinary\'` | Use `unknown` or `other` (nonbinary is \xA713 Roadmap) |\n| `alice [female, transgender]` | `Unknown property \'transgender\'` | Not yet parseable (\xA713 Roadmap) |\n| `dad -- mom` \u2190 followed by `child [male, 2010]` at the **same indent** | Child parsed as a new top-level individual, not as their child | Indent the child line deeper than the couple line (2 spaces is enough) |\n| `A -- B` where `A` was never declared | `Unknown individual \'A\'` | Declare `A [sex, year]` on a line above |\n| `father -- mother "married"` on line 1 (no `genogram` header) | `Expected "genogram" header` | Start the file with `genogram` or `genogram "Title"` |\n| `conditions: diabetes + cancer` (no parens) | `Invalid condition format \'diabetes\'` | Add fill: `conditions: diabetes(half-left) + cancer(half-right)` |\n| `[triplet-identical]` | `Unknown property \'triplet-identical\'` | Triplets not yet parseable (\xA713 Roadmap) |\n| `dad -- mom # first marriage` | Trailing inline `#` comment is treated as part of the label / errors | Move the comment to its own line |\n\n---\n\n## 9. Grammar (EBNF)\n\n```text\ndocument = header (blank | comment | individual | couple-block | emotional)*\n\nheader = "genogram" ( WS quoted-string )? NEWLINE\nquoted-string = \'"\' any-char-but-quote* \'"\'\n\nindividual = INDENT id ( "[" attrs "]" )? NEWLINE\ncouple-block = INDENT id WS coupleOp WS right-side ( WS quoted-string )? NEWLINE\n ( deeper-indent child )*\nchild = INDENT id ( "[" attrs "]" )? NEWLINE\nright-side = id ( "[" attrs "]" )?\n\nemotional = INDENT id WS "-" type "-" id ( WS quoted-string )? NEWLINE\n | INDENT id WS "-" type "->" id ( WS quoted-string )? NEWLINE\n\ncoupleOp = "-x-" | "-/-" | "-o-" | "==" | "--" | "~"\ntype = "harmony" | "close" | "bestfriends" | "love" | "inlove"\n | "friendship" | "hostile" | "conflict" | "enmity"\n | "distant-hostile" | "cutoff" | "close-hostile" | "fused"\n | "fused-hostile" | "distant" | "normal" | "nevermet"\n | "abuse" | "physical-abuse" | "emotional-abuse"\n | "sexual-abuse" | "neglect" | "manipulative" | "controlling"\n | "jealous" | "focused" | "focused-neg" | "distrust"\n | "admirer" | "limerence"\n\nid = [a-zA-Z] [a-zA-Z0-9_-]*\nattrs = attr ("," attr)*\nattr = "male" | "female" | "unknown" | "other"\n | "deceased" | "stillborn" | "miscarriage" | "abortion"\n | "adopted" | "foster" | "twin-identical" | "twin-fraternal"\n | "index"\n | digit digit digit digit // year\n | "age" ":" digits\n | "death" ":" digit digit digit digit\n | "label" ":" quoted-string\n | "conditions" ":" condition ("+" condition)*\n | key ":" value // custom\ncondition = name "(" fill ("," "#" hex)? ")"\nfill = "full" | "half-left" | "half-right" | "half-top" | "half-bottom"\n | "quad-tl" | "quad-tr" | "quad-bl" | "quad-br"\n | "striped" | "dotted"\n\ncomment = INDENT "#" any NEWLINE\n```\n\nAuthoritative source: `src/diagrams/genogram/parser.ts`. If this diverges from the parser, the parser wins \u2014 please open an issue.\n\n---'
962
+ "content": '## 1. Your first genogram\n\nThe smallest clinically useful genogram: two parents, one child.\n\n```\ngenogram\n alice [female, 1980]\n bob [male, 1978]\n alice -- bob "m. 2005"\n carol [female, 2008]\n```\n\nFour rules cover 80% of usage:\n\n1. Start with the keyword `genogram`, optionally followed by a quoted title.\n2. Declare each person on their own line: `id [attributes]`. Attributes go in square brackets, comma-separated.\n3. Connect two people with a **couple operator** \u2014 `--` (marriage) here; see \xA74.1 for all six. A trailing quoted string is the relationship label.\n4. **Indent under the couple line** to add their children.\n\n> Comments must be on their own line, starting with `#`. Trailing inline comments (`bob [male, 1978] # ...`) are not supported and will break the parser \u2014 see \xA78.\n\n---\n\n## 2. Individuals\n\nAn individual line is `id [attr1, attr2, \u2026]`. Attributes are comma-separated, order-independent, all optional.\n\n**ID rules.** Must match `[a-zA-Z][a-zA-Z0-9_-]*`. IDs are case-insensitive internally but preserve their original casing as the display label (override with `label:"\u2026"`).\n\n**Attributes accepted by the parser today:**\n\n| Attribute | Values | Effect |\n|---|---|---|\n| Sex | `male`, `female`, `unknown`, `other` | Shape: square, circle, diamond, diamond |\n| Status | `deceased`, `stillborn`, `miscarriage`, `abortion` | Visual modifier (X-out, scaled shape, etc.) |\n| Birth year | 4-digit number, e.g. `1980` | First 4-digit token = birth year |\n| Death year | 4-digit number after birth, e.g. `1980, 2055` | Second 4-digit token = death year |\n| `index` | flag | Concentric shape = identified patient |\n| `unknown-siblings` | flag | Diamond with `?` \u2014 placeholder for \u22651 siblings of unknown count |\n| `age:N` | e.g. `age:42` | Age shown inside shape |\n| `death:YYYY` | e.g. `death:2020` | Explicit death year |\n| `label:"\u2026"` | e.g. `label:"Dr. Smith"` | Display label override |\n| `sibling-of:<id>` | e.g. `sibling-of:monica` | Pins same generation as the referenced sibling, draws a dashed bracket \u2014 for known relatives with unknown ancestry. |\n| `conditions:\u2026` | see \xA75 | Medical/psychological conditions |\n| `key:value` | any custom | Stored as metadata |\n\n```\ngenogram\n grandma [female, 1920, 2002, deceased]\n dad [male, 1950, age:74]\n me [male, 1985, index]\n daughter [female, 2012, label:"Em"]\n```\n\n---\n\n## 3. Shapes\n\n| Visual | Sex value | Meaning |\n|---|---|---|\n| \u2610 Square | `male` | Male |\n| \u25CB Circle | `female` | Female |\n| \u25C7 Diamond | `unknown`, `other`, *or* attribute omitted | Unknown / unspecified |\n\nStatus modifiers layer on top of the base shape:\n\n```\ngenogram\n alive [male, 1960]\n passed [male, 1930, 2010, deceased]\n stillborn_child [unknown, stillborn]\n lost [unknown, miscarriage]\n```\n\n---\n\n## 4. Connections\n\n### 4.1 Couple operators\n\nThe parser tries these in order. The first one that matches wins \u2014 so `-x-` beats `--`.\n\n| Operator | Type | Example | Meaning |\n|---|---|---|---|\n| `-x-` | divorced | `a -x- b` | Divorce |\n| `-/-` | separated | `a -/- b` | Separation (married) |\n| `-//` | separated | `a -// b` | Separation (alias for `-/-`) |\n| `-o-` | engaged | `a -o- b` | Engagement |\n| `==` | consanguineous | `a == b` | Blood-related couple |\n| `--` | married | `a -- b` | Marriage |\n| `~` | cohabiting | `a ~ b` | Cohabiting / LTR (current) |\n| `~/~` | cohabiting-ended | `a ~/~ b` | Cohabitation has ended (never-married). Common in LATAM child-protection caseloads where biological parents lived together unmarried and the relationship has since broken \u2014 distinct from `-x-` divorce (no marriage) and `-/-` separation (still married). |\n\nA trailing quoted string becomes the relationship label (`a -- b "m. 2005"`).\n\n### 4.2 Inline individual on the right side\n\nIf the right-hand person hasn\'t been declared yet, you can declare them in-place:\n\n```\ngenogram\n ann [female, 1970]\n ann -- ben [male, 1968] "m. 1995"\n kim [female, 1997]\n```\n\n### 4.3 Children (indented under a couple)\n\nIndentation under a couple line = "these are the children of this couple." Any indent greater than the couple\'s indent works; by convention use 2 more spaces. Children are rendered in order of declaration (render also sorts by birth year when present).\n\n```\ngenogram\n dad [male, 1950]\n mom [female, 1952]\n dad -- mom\n eldest [male, 1975]\n middle [female, 1978, adopted]\n twin_a [male, 1985, twin-identical]\n twin_b [male, 1985, twin-identical]\n```\n\n**Special child attributes:**\n\n| Attribute | Effect |\n|---|---|\n| `adopted` | Adoption line style |\n| `foster` | Foster relationship |\n| `guardian` | Guardianship by a non-parent relative (e.g. grandparent custody). Same primitive as `foster` \u2014 drawn as a secondary "current caregiver" link when biological parents are also declared. |\n| `twin-identical` | Grouped with other `twin-identical` children of the same couple |\n| `twin-fraternal` | Grouped with other `twin-fraternal` children |\n| `unknown-siblings` | Single diamond with `?` glyph \u2014 "\u22651 siblings, count and identities unknown" (pedigree convention). |\n\n### 4.3.1 Dual-parent families (foster, adoption, guardianship)\n\nChildren placed with a non-biological caregiver while biological parents are still part of the case can be declared under both couples. **Declare the child with full attributes the first time** (under the biological couple), then **redeclare with just `[foster]` / `[adopted]` / `[guardian]`** under the current caregiver. The first declaration wins layout; the second is drawn as a secondary dotted "current caregiver" link that does not pull the child away from their biological position.\n\n```\ngenogram "Foster placement"\n bp1 [male, label: "Bio dad"]\n bp2 [female, label: "Bio mom"]\n bp1 ~/~ bp2\n child [male, 2018, index]\n fp1 [male, label: "Foster dad"]\n fp2 [female, label: "Foster mom"]\n fp1 -- fp2\n own [male, 2010]\n child [foster]\n```\n\nThe same primitive serves adoption (closed/open), foster placement, and guardianship by a relative \u2014 only the keyword differs. Re-declaration **merges** non-conflicting attributes (sex, birth year, label, `index` marker) into the original; declaring a conflicting `male` vs `female` raises a parse error rather than silently overwriting.\n\n### 4.3.2 Unknown-count siblings\n\nWhen a case file mentions "the child has siblings" without naming them, use either the `?` shorthand on its own line, or `[unknown-siblings]` on a regular id. Both render as a single diamond with a "?" glyph \u2014 the standard pedigree marker for "one or more siblings, identities unknown."\n\n```\ngenogram\n dad [male]\n mom [female]\n dad -- mom\n ?\n known_kid [male, 2018]\n```\n\n### 4.3.3 Sibling-of (known relative, unknown ancestry)\n\nTo express "X is a sibling of Y" without inventing parents, use the `sibling-of: <id>` property. The renderer pins X to Y\'s generation and draws a dashed bracket above the two \u2014 the standard pedigree convention for a known relative whose ancestry is not part of the case.\n\n```\ngenogram\n monica [female, 1990]\n uncle [male, label: "T\xEDo materno", sibling-of: monica]\n```\n\n### 4.4 Emotional relationships\n\nSeparate line, parser pattern `A -TYPE- B` (non-directional) or `A -TYPE-> B` (directional). An optional quoted label goes at the end. **Both individuals must already be declared** before the emotional line.\n\n```\nharry -cutoff- petunia # non-directional\nharry -hostile- dudley "since 1991"\nuncle -abuse-> nephew # directional (arrow)\n```\n\nAll 32 types the parser accepts today:\n\n| Category | Types |\n|---|---|\n| Positive / close | `harmony`, `close`, `bestfriends`, `love`, `inlove`, `friendship` |\n| Negative / hostile | `hostile`, `conflict`, `enmity`, `distant-hostile`, `cutoff` |\n| Ambivalent | `close-hostile`, `fused`, `fused-hostile` |\n| Distance | `distant`, `normal`, `nevermet` |\n| Abuse *(directional)* | `abuse`, `physical-abuse`, `emotional-abuse`, `sexual-abuse`, `neglect` |\n| Control *(directional)* | `manipulative`, `controlling`, `jealous` |\n| Special | `focused`, `focused-neg`, `distrust`, `admirer`, `limerence` |\n\n```\ngenogram\n dad [male, 1950]\n son [male, 1985]\n daughter [female, 1988]\n dad -close- daughter\n dad -conflict- son\n son -cutoff- dad "since 2010"\n```\n\n---\n\n## 5. Medical conditions\n\nSyntax: `conditions: name(fill) [+ name(fill, #color)]\u2026`\n\n```\nfather [male, 1945, conditions: heart(full, #E53935)]\nmother [female, 1948, conditions: diabetes(half-left) + anxiety(half-right, #26A69A)]\n```\n\n- **`name`** \u2014 any identifier you choose (displayed in legend/tooltip).\n- **`fill`** \u2014 required, controls which region of the shape is colored. See table below.\n- **`color`** \u2014 optional hex. Default depends on the renderer theme.\n- Multiple conditions are joined with `+`. Each needs its own `(fill)`.\n\n**Fill positions:**\n\n| `fill` value | Region |\n|---|---|\n| `full` | Entire shape |\n| `half-left` / `half-right` | Left / right half |\n| `half-top` / `half-bottom` | Top / bottom half |\n| `quad-tl` / `quad-tr` / `quad-bl` / `quad-br` | One quadrant |\n| `striped` | Diagonal stripe pattern (asymptomatic carrier) |\n| `dotted` | Dot pattern |\n\n```\ngenogram\n dad [male, 1950, conditions: heart(full, #E53935)]\n mom [female, 1952, conditions: diabetes(half-left) + depression(half-right, #5C6BC0)]\n dad -- mom\n son [male, 1980, conditions: carrier(striped)]\n```\n\n---\n\n## 6. Labels & comments\n\n- **Title:** `genogram "Smith Family"` \u2014 first line only.\n- **Person label override:** `alice [female, label:"Dr. Alice Smith"]`.\n- **Relationship label:** trailing quoted string on a couple or emotional line \u2014 `alice -- bob "m. 2005"`.\n- **Comments:** `#` at the start of a line (after leading whitespace). Inline comments are **not** supported.\n\n```\ngenogram "Smith Family"\n # this line is a comment \u2014 fine\n alice [female, 1980] # \u2190 THIS trailing comment breaks the parser\n```\n\n---\n\n## 7. Reserved words & escaping\n\n**Reserved at line start:** `genogram` (header keyword).\n\n**Reserved operator tokens** inside a line \u2014 avoid using these sequences in IDs:\n`--`, `~`, `~/~`, `==`, `-x-`, `-/-`, `-//`, `-o-`, and any `-<type>-` / `-<type>->` matching an emotional-relationship type.\n\n**Reserved id `?`** \u2014 bare `?` on a child line auto-generates a synthetic placeholder with the `unknown-siblings` marker. Do not use `?` as a real id.\n\n**Strings with spaces** must be double-quoted: titles, labels, `label:"\u2026"`. Single quotes and backticks are not recognized.\n\n---\n\n## 8. Common mistakes\n\nReal parser errors, what triggers them, and how to fix.\n\n| You wrote | Parser says | Fix |\n|---|---|---|\n| `alex [nonbinary, 1995]` | `Unknown property \'nonbinary\'` | Use `unknown` or `other` (nonbinary is \xA713 Roadmap) |\n| `alice [female, transgender]` | `Unknown property \'transgender\'` | Not yet parseable (\xA713 Roadmap) |\n| `dad -- mom` \u2190 followed by `child [male, 2010]` at the **same indent** | Child parsed as a new top-level individual, not as their child | Indent the child line deeper than the couple line (2 spaces is enough) |\n| `A -- B` where `A` was never declared | `Unknown individual \'A\'` | Declare `A [sex, year]` on a line above |\n| `father -- mother "married"` on line 1 (no `genogram` header) | `Expected "genogram" header` | Start the file with `genogram` or `genogram "Title"` |\n| `conditions: diabetes + cancer` (no parens) | `Invalid condition format \'diabetes\'` | Add fill: `conditions: diabetes(half-left) + cancer(half-right)` |\n| `[triplet-identical]` | `Unknown property \'triplet-identical\'` | Triplets not yet parseable (\xA713 Roadmap) |\n| `dad -- mom # first marriage` | Trailing inline `#` comment is treated as part of the label / errors | Move the comment to its own line |\n| Same id declared twice with different sex (`x [male]` then `x [female]`) | `Conflicting sex for \'x\': previously \'male\', now \'female\'` | Pick one or rename one of the ids |\n| `child [foster]` redeclared but biological parents never declared | `child` becomes the foster couple\'s regular child (no secondary link drawn) | This is intentional \u2014 secondary links require an existing primary parent-child rel from a prior declaration |\n\n---\n\n## 9. Grammar (EBNF)\n\n```text\ndocument = header (blank | comment | individual | couple-block | emotional)*\n\nheader = "genogram" ( WS quoted-string )? NEWLINE\nquoted-string = \'"\' any-char-but-quote* \'"\'\n\nindividual = INDENT id ( "[" attrs "]" )? NEWLINE\ncouple-block = INDENT id WS coupleOp WS right-side ( WS quoted-string )? NEWLINE\n ( deeper-indent child )*\nchild = INDENT id ( "[" attrs "]" )? NEWLINE\n | INDENT "?" NEWLINE // unknown-count sibling shorthand\nright-side = id ( "[" attrs "]" )?\n\nemotional = INDENT id WS "-" type "-" id ( WS quoted-string )? NEWLINE\n | INDENT id WS "-" type "->" id ( WS quoted-string )? NEWLINE\n\ncoupleOp = "~/~" | "-//" | "-x-" | "-/-" | "-o-" | "==" | "--" | "~"\ntype = "harmony" | "close" | "bestfriends" | "love" | "inlove"\n | "friendship" | "hostile" | "conflict" | "enmity"\n | "distant-hostile" | "cutoff" | "close-hostile" | "fused"\n | "fused-hostile" | "distant" | "normal" | "nevermet"\n | "abuse" | "physical-abuse" | "emotional-abuse"\n | "sexual-abuse" | "neglect" | "manipulative" | "controlling"\n | "jealous" | "focused" | "focused-neg" | "distrust"\n | "admirer" | "limerence"\n\nid = [a-zA-Z] [a-zA-Z0-9_-]*\nattrs = attr ("," attr)*\nattr = "male" | "female" | "unknown" | "other"\n | "deceased" | "stillborn" | "miscarriage" | "abortion"\n | "adopted" | "foster" | "guardian"\n | "twin-identical" | "twin-fraternal"\n | "index" | "unknown-siblings"\n | digit digit digit digit // year\n | "age" ":" digits\n | "death" ":" digit digit digit digit\n | "label" ":" quoted-string\n | "sibling-of" ":" id\n | "conditions" ":" condition ("+" condition)*\n | key ":" value // custom\ncondition = name "(" fill ("," "#" hex)? ")"\nfill = "full" | "half-left" | "half-right" | "half-top" | "half-bottom"\n | "quad-tl" | "quad-tr" | "quad-bl" | "quad-br"\n | "striped" | "dotted"\n\ncomment = INDENT "#" any NEWLINE\n```\n\nAuthoritative source: `src/diagrams/genogram/parser.ts`. If this diverges from the parser, the parser wins \u2014 please open an issue.\n\n---'
925
963
  },
926
964
  "ecomap": {
927
965
  "title": "Ecomap",
@@ -998,6 +1036,14 @@ var SYNTAX = {
998
1036
  "timeline": {
999
1037
  "title": "Timeline diagram",
1000
1038
  "content": '## 1. Your first timeline\n\nThe smallest useful timeline: a title, two ordinary events, and a milestone.\n\n```\ntimeline "Product Launch"\n2024-06-01: "Development complete"\n2024-08-15: "Closed beta"\n2024-09-01: milestone "Public launch"\n```\n\nFour rules cover 80% of usage:\n\n1. Start with the keyword `timeline`, optionally followed by a quoted title.\n2. Each event is `DATE: "Label"` \u2014 a date, a colon, then a quoted label. A `milestone` keyword before the label marks the event as a milestone.\n3. Date ranges use `DATE - DATE:` or `DATE .. DATE:` (both are equivalent).\n4. Add `[key: value]` properties after the quoted label to set color, side placement, shape, or category.\n\n> Comments must start with `#` or `//` on their own line.\n\n---\n\n## 2. Events\n\nAn event line places a labeled marker at a point in time (or a bar across a span).\n\n### 2.1 Point events\n\n```\n2024-09-15: "Conference keynote"\n```\n\n### 2.2 Range events\n\n```\n2024-06-01 - 2024-08-31: "Q3 development sprint"\n2024-06-01 .. 2024-08-31: "Q3 development sprint"\n```\n\nBoth separators (`-` surrounded by spaces, or `..`) are equivalent.\n\n### 2.3 Milestones\n\n```\n2024-09-01: milestone "Public launch"\n```\n\nThe `milestone` keyword before the quoted label switches the marker to a diamond shape.\n\n### 2.4 Event properties\n\nProperties go in `[key: value, \u2026]` after the quoted label, before the newline.\n\n| Property | Values | Meaning |\n|---|---|---|\n| `color:` | hex string | Custom color for this marker or bar |\n| `side:` | `above` \\| `below` | Force placement above or below the axis (swimlane / lollipop) |\n| `icon:` | any text (e.g. emoji) | Icon displayed with the event |\n| `shape:` | `circle` \\| `square` \\| `diamond` \\| `star` \\| `flag` | Point marker shape |\n| `category:` | quoted string | Group label \u2014 drives color in gantt legend |\n\n```\n2024-09-01: milestone "Launch day" [color: #E53935, side: above]\n2024-07-15: "Beta ships" [icon: \u{1F680}, category: "product"]\n```\n\n```\ntimeline "Engineering Milestones"\nconfig: style = lollipop\n\n2024-01-08: "Sprint planning complete"\n2024-02-14: milestone "Design system shipped" [side: above, color: #1565C0]\n2024-03-22: "Incident \u2014 4h outage" [icon: \u26A0\uFE0F]\n2024-04-01 - 2024-06-30: "API v2 build"\n2024-07-01: milestone "API v2 GA" [side: above, color: #2E7D32]\n```\n\n---\n\n## 3. Date formats\n\nAll date formats can appear anywhere a date is expected \u2014 in events, eras, and ranges.\n\n| Format | Example | Notes |\n|---|---|---|\n| Full date | `2024-09-15` | Day-precision; `YYYY-MM-DD` |\n| Year-month | `2024-09` | Month-precision |\n| Year | `2024` | Year-precision |\n| Quarter | `2024-Q3` | Maps to start of that quarter |\n| BC year (negative) | `-753` | 753 BC |\n| BC year (suffix) | `753BC` or `753BCE` | Same as `-753` |\n| Geological | `65Ma`, `4.6Ga`, `12ka` | Million / billion / thousand years ago |\n\n```\ntimeline "Age of Earth"\nconfig: style = lollipop\nconfig: scale = log\n\n4600Ma: "Earth forms"\n540Ma: "Cambrian explosion"\n252Ma: milestone "Permian extinction \u2014 96% of species lost"\n66Ma: milestone "K-Pg extinction \u2014 end of non-avian dinosaurs"\n3Ma: "Earliest stone tools (Lomekwi)"\n0: "Present day"\n```\n\n---\n\n## 4. Eras (background spans)\n\nAn `era` line draws a shaded background band across the time axis. It always requires a date range.\n\n```\nera 2020 - 2022: "Foundation Phase"\nera 2022 .. 2025: "Growth Phase" [color: #E8F5E9]\n```\n\nThe `[color: \u2026]` property is optional. Overlapping eras stack into separate bands automatically.\n\n```\ntimeline "Company History"\nconfig: style = swimlane\n\nera 2019..2021: "Early Stage" [color: #FFF8E1]\nera 2021..2024: "Series A & B" [color: #E8F5E9]\n\n2019-03-01: "Founded"\n2019-11-15: "First paying customer"\n2020-05-01: milestone "Product-market fit" [side: above]\n2021-02-10: "Series A \u2014 $8M"\n2022-09-01: "Series B \u2014 $30M"\n2023-06-15: milestone "Profitability" [color: #1B5E20]\n```\n\n---\n\n## 5. Tracks (swimlane grouping)\n\nA `track` block groups related events into a named swimlane. Indented event lines (2 spaces) belong to the track.\n\n```\ntrack "Engineering":\n 2024-01-15 - 2024-03-31: "API design"\n 2024-04-01 - 2024-07-31: "Implementation"\n\ntrack "Marketing":\n 2024-06-01: "Campaign kick-off"\n 2024-09-01: milestone "Launch campaign" [color: #1B5E20]\n```\n\nTracks are most useful in `gantt` style, where each track becomes its own labeled row.\n\n```\ntimeline "Q3 Project Plan"\nconfig: style = gantt\n\ntrack "Backend":\n 2024-07-01 - 2024-08-15: "Database migration"\n 2024-08-16 - 2024-09-30: "API hardening"\n\ntrack "Frontend":\n 2024-07-01 - 2024-08-31: "New design system"\n 2024-09-01 - 2024-09-30: "Integration & QA"\n\ntrack "DevOps":\n 2024-07-15 - 2024-08-01: "Staging environment"\n 2024-09-30: milestone "Go-live" [color: #2E7D32]\n```\n\n---\n\n## 6. Notes\n\nA `note:` line indented under an event attaches a tooltip annotation to it.\n\n```\n2024-06-01: "Beta launch"\n note: "First external users; NPS target 40+"\n```\n\nNotes work both for flat events and for events inside tracks.\n\n---\n\n## 7. Configuration\n\n`config:` lines tune the layout and visual style. Each is its own line in the form `config: key = value`.\n\n| Key | Values | Default | Effect |\n|---|---|---|---|\n| `style` | `swimlane` \\| `gantt` \\| `lollipop` | `swimlane` | Visual rendering mode |\n| `orientation` | `horizontal` \\| `vertical` | `horizontal` | Axis direction |\n| `scale` | `proportional` \\| `equidistant` \\| `log` | `proportional` | How time maps to screen space |\n| `axis` | `bottom` \\| `center` | `bottom` | Where the time axis is drawn |\n\n**Style notes:**\n- `swimlane` \u2014 events alternate above and below a horizontal axis; `side:` controls per-event placement. Eras add colored background bands. Best for roadmaps and biographies.\n- `gantt` \u2014 each named track becomes a horizontal bar lane; milestones become pins above the bars. `gantt-project` is an alias. Best for project scheduling.\n- `lollipop` \u2014 a center axis with labeled cards on alternating stems. Best for historical retrospectives with sparse, memorable events.\n\n**Swimlane** \u2014 roadmaps, product timelines, biographies. Eras add color bands; events alternate above and below.\n\n```\ntimeline "SaaS Platform Roadmap"\nconfig: style = swimlane\n\nera 2024-Q1..2024-Q2: "Foundation" [color: #E3F2FD]\nera 2024-Q3..2024-Q4: "Growth" [color: #E8F5E9]\n\n2024-01-15: "Kick-off & team onboarding"\n2024-02-01: milestone "Architecture sign-off" [side: above]\n2024-03-01 - 2024-05-31: "API v2 build"\n2024-04-10: "Security audit" [color: #F9A825]\n2024-06-30: milestone "Beta launch" [side: above]\n2024-07-01 - 2024-09-30: "Performance & scaling"\n2024-10-15: milestone "General availability" [color: #2E7D32]\n```\n\n**Gantt** \u2014 parallel tracks with horizontal duration bars and milestone pins. Best for project scheduling.\n\n```\ntimeline "Product Launch \u2014 Q4"\nconfig: style = gantt\n\ntrack "Engineering":\n 2024-10-01 - 2024-11-15: "Feature freeze & hardening"\n 2024-11-16 - 2024-11-30: "Load testing"\n\ntrack "Design":\n 2024-10-01 - 2024-10-31: "Final UI polish"\n 2024-11-01 - 2024-11-14: "Asset delivery"\n\ntrack "Marketing":\n 2024-10-15 - 2024-11-14: "Campaign prep"\n 2024-11-15 - 2024-11-30: "Launch campaign"\n 2024-12-01: milestone "Launch day" [color: #2E7D32]\n```\n\n**Lollipop** \u2014 sparse milestones on a centered axis with alternating cards. Best for historical retrospectives and brand stories.\n\n```\ntimeline "History of Computing"\nconfig: style = lollipop\nconfig: scale = equidistant\n\n1936: "Turing \u2014 On Computable Numbers"\n1945: "ENIAC \u2014 first general-purpose computer"\n1969: "ARPANET"\n1971: milestone "Intel 4004 microprocessor" [side: above]\n1976: "Apple I"\n1991: "World Wide Web (Berners-Lee)"\n2007: milestone "iPhone" [color: #1565C0, side: above]\n```\n\n---\n\n## 8. Labels & comments\n\n- **Title:** `timeline "My Title"` \u2014 first line only.\n- **Event label:** quoted string after the colon: `DATE: "Label"`.\n- **Milestone label:** `DATE: milestone "Label"`.\n- **Era label:** `era DATE - DATE: "Label"`.\n- **Track name:** `track "Name":`.\n- **Note:** `note: "text"` indented under an event.\n- **Comments:** `#` or `//` at the start of a line (after leading whitespace).\n\n---\n\n## 9. Reserved words & escaping\n\n**Reserved at line start:** `timeline` (header), `config:`, `era`, `track`, `note:`.\n\n**Date range separators:** ` - ` (space-hyphen-space) and `..` \u2014 avoid these sequences inside label text that appears before the colon.\n\n**BC years as negative integers:** `-753` is the year 753 BC. The parser distinguishes the negative sign from a range separator by checking for surrounding whitespace \u2014 ` - ` (with spaces) is a range; `-753` (no leading space after a colon) is a BC year.\n\n**Property blocks:** `[key: value]` must appear *after* the quoted label on the same line. The closing `]` must be present; unclosed brackets produce a parse error.\n\n---\n\n## 10. Common mistakes\n\n| You wrote | Parser says | Fix |\n|---|---|---|\n| `2024-06-01: Launch day` (unquoted label) | Line not recognized as an event \u2014 `TimelineParseError` | Quote the label: `2024-06-01: "Launch day"` |\n| `2024-06 - 2024-09: "Q3"` (year-month range) | Parsed correctly | This works \u2014 all date formats are valid in ranges |\n| `era 2024: "Whole year"` (no range) | `TimelineParseError: era requires a date range` | Use a range: `era 2024 - 2024: "Whole year"` |\n| `track "Backend"` (no colon) | `TimelineParseError: Expected \':\' after track name` | Add the colon: `track "Backend":` |\n| `2024-01-01: "Event" [side: left]` | `side: left` silently ignored; only `above` and `below` are valid | Use `side: above` or `side: below` |\n| `config: style = Gantt` (capital G) | `TimelineParseError: Invalid style: Gantt` | Use lowercase: `config: style = gantt` |\n| `2024-01-01-2024-03-31: "Q1"` (no spaces around `-`) | Parser reads `2024-01-01-2024` as a date \u2014 fails | Use spaces: `2024-01-01 - 2024-03-31:` or `..`: `2024-01-01..2024-03-31:` |\n| Indented event without a track | Indented lines under the timeline header that aren\'t inside a `track` block \u2014 parsed as flat events | Only indent events that are inside a `track "Name":` block |\n\n---\n\n## 11. Grammar (EBNF)\n\n```text\ndocument = header ( blank | comment | config | era | track | event )*\n\nheader = "timeline" ( WS quoted-string )? NEWLINE\nquoted-string = \'"\' any-char-but-quote* \'"\'\n\nconfig = "config:" WS key WS "=" WS value NEWLINE\nkey = "style" | "orientation" | "scale" | "axis"\n\nera = "era" WS date-range ":" WS quoted-string ( WS props )? NEWLINE\ntrack = "track" WS quoted-string ":" NEWLINE\n ( INDENT\u22652 event | INDENT\u22652 note )*\n\nevent = date-spec ":" WS event-body ( WS props )? NEWLINE\n ( INDENT note )?\nevent-body = ( "milestone" WS )? quoted-string\ndate-spec = date ( ( " - " | ".." ) date )?\n\nnote = "note:" WS quoted-string NEWLINE\n\nprops = "[" prop-list "]"\nprop-list = prop ( "," prop )*\nprop = key ":" WS value\n | key ":" WS quoted-string\n\ndate = iso-date | year-month | year | quarter | bc-year | geological\niso-date = digit{4} "-" digit{2} "-" digit{2}\nyear-month = digit{4} "-" digit{2}\nyear = "-"? digit{1,5}\nquarter = digit{4} "-"? "Q" [1-4]\nbc-year = digit+ ( "BC" | "BCE" )\ngeological = number ( "Ma" | "Ga" | "ka" )\n\ncomment = ( "#" | "//" ) any NEWLINE\n```\n\nAuthoritative source: `src/diagrams/timeline/parser.ts`. If this diverges from the parser, the parser wins \u2014 please open an issue.\n\n---'
1039
+ },
1040
+ "state": {
1041
+ "title": "State diagram",
1042
+ "content": '## 1. Your first state diagram\n\nThe smallest useful state diagram has an initial state, a final state, and one transition.\n\n```\nstateDiagram-v2\n[*] --> Running\nRunning --> [*] : done\n```\n\nThree rules cover 80% of usage:\n\n1. Start with `stateDiagram-v2` (Mermaid-style) or `state` (Schematex-style) header.\n2. Use `[*]` for the implicit start node (when on the left of `-->`) or end node (when on the right).\n3. Connect states with `-->`. Add a label after `:` \u2014 full UML form is `trigger [guard] / action`.\n\nThe default direction is **TB** (top-to-bottom) to match Mermaid. Override with `direction LR` on its own line, or `[direction: LR]` on the header.\n\n> Comments use `%%` (Mermaid), `#`, or `//`.\n\n---\n\n## 2. State declarations\n\nStates are auto-created when first referenced in a transition, but explicit declarations let you control the label and shape.\n\n```\nstate Authenticating\nstate "Awaiting Approval" as Approval\nIdle: Waiting for input\n```\n\n| Form | Effect |\n|---|---|\n| `Idle` | Bare ID \u2014 created as a simple state with `Idle` as both id and label |\n| `state Idle` | Explicit declaration; same effect |\n| `state "Awaiting Approval" as Approval` | Aliased \u2014 display `Awaiting Approval`, refer to it by `Approval` in transitions |\n| `Idle: Waiting for input` | Inline label \u2014 `Idle` is the id, `Waiting for input` is the visible label |\n\n---\n\n## 3. Pseudo-states\n\nPseudo-states control the flow of a state machine without representing a stable resting state.\n\n| Mermaid | Schematex | Symbol | Purpose |\n|---|---|---|---|\n| `[*]` (source) | `initial id` | Filled black circle | Entry point of a region |\n| `[*]` (target) | `final id` | Filled circle inside outer ring | Successful exit |\n| `state X <<choice>>` | `choice X` | Diamond | Dynamic branch (guards evaluated at runtime) |\n| `state X <<fork>>` | `fork X` | Thick black bar | One-input \u2192 N parallel outputs |\n| `state X <<join>>` | `join X` | Thick black bar | N inputs \u2192 one output |\n| \u2014 | `junction X` | Small filled circle | Static merge point |\n| \u2014 | `history X` | Circle with `H` | Re-enter at last visited sub-state |\n| \u2014 | `dhistory X` | Circle with `H*` | Deep history (recursive) |\n| \u2014 | `terminate X` | `\xD7` mark | Abnormal termination (no cleanup) |\n| \u2014 | `entry_point X` / `exit_point X` | Hollow circle on composite border | Named entry / exit points |\n\n`[*]` is the Mermaid alias and is always direction-resolved: on the **source** side of `-->` it\'s an `initial`, on the **target** side it\'s a `final`. Each composite scope gets its own pair.\n\n```\nstateDiagram-v2\n[*] --> Idle\nstate Decide <<choice>>\nstate Joiner <<join>>\nIdle --> Decide : evaluate\nDecide --> Authorized : [role == "admin"]\nDecide --> Joiner : [role == "user"]\nAuthorized --> Joiner\nJoiner --> [*]\n```\n\n---\n\n## 4. Transitions\n\nThe full UML 2.5 transition label has three optional parts:\n\n```\ntrigger [guard] / action\n```\n\n| Field | Meaning | Example |\n|---|---|---|\n| `trigger` | Event that fires the transition | `submit`, `tick`, `timeout(30s)` |\n| `[guard]` | Boolean expression evaluated at trigger time | `[count > 0]`, `[role == "admin"]` |\n| `/ action` | Action(s) executed when transition is taken | `/ log(); increment()` |\n\nAll three are optional \u2014 an unlabeled transition is anonymous (completion transition).\n\n```\nA --> B %% anonymous completion\nA --> B : tick %% trigger only\nA --> B : [count > 0] %% guard only\nA --> B : / clearErrors() %% action only\nA --> B : tick [count > 0] / log() %% all three\nA --> B : tick, tock [enabled] / handle() %% multi-trigger\n```\n\nLong labels wrap automatically when they exceed the lane width.\n\n---\n\n## 5. Composite states\n\nA composite state contains a nested sub-statechart. The outer state acts as a container with its own initial / final pseudo-states.\n\n```\nstate Playing {\n [*] --> Buffering\n Buffering --> Streaming : buffer_full\n Streaming --> Buffering : underflow\n}\n```\n\nBoth Mermaid syntax (`state X { \u2026 }`) and the Schematex form (`composite X { \u2026 }`) are accepted. Activities can be declared inside the composite block:\n\n```\nstate Playing {\n entry / startBuffer()\n exit / stopBuffer()\n do / decodeFrames()\n\n [*] --> Buffering\n Buffering --> Streaming : buffer_full\n Streaming --> Buffering : underflow\n}\n```\n\nThe renderer draws composites as a styled cluster with title bar + activity compartment.\n\n```\nstateDiagram-v2\n\n[*] --> Stopped\n\nStopped --> Playing : play / loadSource()\nPlaying --> Paused : pause\nPaused --> Playing : play\nPlaying --> Stopped : stop / releaseSource()\n\nstate Playing {\n entry / startBuffer()\n exit / stopBuffer()\n do / decodeFrames()\n\n [*] --> Buffering\n Buffering --> Streaming : buffer_full\n Streaming --> Buffering : underflow\n}\n```\n\nCross-boundary transitions (`Outside --> Inside`) are routed automatically \u2014 the Sugiyama layout pulls the source/target through the composite border.\n\n---\n\n## 6. Concurrent regions\n\nInside a composite, the `--` separator (Mermaid) or `---` (Schematex) splits the body into orthogonal regions that run concurrently.\n\n```\nstate Active {\n [*] --> r1_idle\n r1_idle --> Connected : connect\n --\n [*] --> r2_idle\n r2_idle --> Working : start\n}\n```\n\nUse `fork` and `join` to spawn / synchronize across regions:\n\n```\nstateDiagram-v2 [direction: LR]\n\n[*] --> F\nstate F <<fork>>\nstate J <<join>>\nF --> A\nF --> B\nA --> J : done_a\nB --> J : done_b\nJ --> [*]\n```\n\n---\n\n## 7. Notes\n\nA short annotation can be attached to either side of any state.\n\n```\nnote right of Checking : Calls /api/verify synchronously.\nnote left of Idle : Anonymous landing state\n```\n\nMulti-line notes use the Mermaid `end note` block form, or the Schematex `{ \u2026 }` form:\n\n```\nnote right of Authenticating\n Stores the JWT in localStorage\n on success.\nend note\n\nnote left_of Idle {\n Anonymous landing state.\n Returns here on 401.\n}\n```\n\n---\n\n## 8. Self-transitions\n\nA transition `A --> A` renders as a curved arc on the right side of the node.\n\n```\nIdle --> Idle : poll / refresh()\n```\n\nThe label is placed beside the arc, outside the bounding box.\n\n---\n\n## 9. Layout direction\n\nSchematex defaults to **`TB`** (top-to-bottom), matching Mermaid. Override on the header:\n\n```\nstateDiagram-v2\ndirection LR\n\n[*] --> Loading\nLoading --> Ready\n```\n\nOr with the Schematex bracket-attr form:\n\n```\nstate "Order Lifecycle" [direction: TB]\n\n[*] --> Pending\nPending --> Paid\n```\n\n`BT` and `RL` are accepted by the parser but normalized to `TB` and `LR` respectively (the layout engine doesn\'t yet flip the visual order).\n\n---\n\n## 10. Common mistakes\n\n| You wrote | Parser says | Fix |\n|---|---|---|\n| `[*] -> [*]` | Treated as both initial alias and final alias on the same line | Always have at least one named state between `[*]` aliases |\n| `state X <<branch>>` | `branch` is not a stereotype | Use `<<choice>>` (dynamic) or `<<fork>>` / `<<join>>` |\n| `note right of`<br/>`text` | Multi-line note must end with `end note` | Add `end note` on its own line |\n| `composite X` (no braces) | Treated as a bare state declaration | Open the block: `composite X {` |\n| `direction LR` inside composite | Per-region direction not yet supported | Set direction on the header line |\n\n---\n\n## 11. Grammar (EBNF)\n\n```text\ndocument = header statement*\nheader = ("stateDiagram-v2" | "stateDiagram" | "state")\n ( title )? ( "[" attrs "]" )? NEWLINE\nattrs = attr ("," attr)*\nattr = "direction:" ("TB" | "LR")\n\nstatement = comment\n | direction-stmt %% direction LR / TB / BT / RL\n | state-decl\n | alias-decl %% state "Long" as ID\n | stereotype-decl %% state ID <<choice|fork|join|end>>\n | pseudo-decl %% initial / final / choice / ... ID\n | composite-block %% (state | composite) ID { ... }\n | label-stmt %% ID : description\n | transition\n | note-stmt\n | region-sep %% -- or ---\n\ntransition = (ID | "[*]") "-->" (ID | "[*]") ( ":" trans-label )? NEWLINE\ntrans-label = trigger? ( "[" guard "]" )? ( "/" action )?\n\nnote-stmt = "note" side ID ":" inline-text NEWLINE\n | "note" side ID NEWLINE text-line+ ("end note" | "}") NEWLINE\nside = "left of" | "right of" | "left_of" | "right_of"\n\ncomment = "%%" any | "#" any | "//" any\n\nID = [A-Za-z_] [A-Za-z0-9_]*\n```\n\nAuthoritative source: `src/diagrams/state/parser.ts`. If this diverges from the parser, the parser wins \u2014 please open an issue.\n\n---'
1043
+ },
1044
+ "pid": {
1045
+ "title": "P&ID (Piping & Instrumentation Diagram)",
1046
+ "content": '## 1. Your first P&ID\n\nA minimal P&ID has at least one piece of equipment and one process line.\n\n```\npid\n\nequip T-1 : tank_atm\nequip P-1 : pump_centrifugal\nequip V-1 : vessel_v\n\nline L1 from T-1.bottom to P-1.in [size: "2\\\\"", type: "process"]\nline L2 from P-1.out to V-1.in [size: "2\\\\"", type: "process"]\n```\n\nThree rules cover 80% of usage:\n\n1. Start the document with `pid` (optional title and `[direction: LR]` attrs).\n2. Declare each piece of equipment: `equip : <type> [tag: "label"]`.\n3. Connect them with `line from <equip>.<port> to <equip>.<port> [type: "process", size: "4\\""]`.\n\nInstrumentation is added separately with `inst : <category>` plus indented `measures` / `controls` clauses.\n\n> Comments use `#` at the start of a line.\n\n---\n\n## 2. Equipment\n\nThe `equip` statement declares process equipment. The catalog follows ISO 10628 / ISA-5.1 conventions.\n\n```\nequip T-101 : tank_atm [tag: "Feed Tank"]\nequip P-101 : pump_centrifugal\nequip E-201 : hx_shell_tube [tag: "Overhead Cond"]\nequip T-201 : column_tray [tag: "Stripper"]\n```\n\n### 2.1 Equipment catalog\n\n| Type | Symbol | Purpose |\n|---|---|---|\n| `tank_atm` | Cylinder + dome top | Atmospheric storage tank |\n| `tank_cone_roof` | Cylinder + cone roof | Cone-roof storage tank |\n| `vessel_v` | Vertical capsule | Vertical pressure vessel |\n| `vessel_h` | Horizontal capsule | Horizontal pressure vessel |\n| `sphere` | Filled circle | LPG / ammonia sphere |\n| `column_tray` | Tall capsule + horizontal tray lines | Distillation tray column |\n| `column_packed` | Tall capsule + cross-hatch | Packed absorption column |\n| `hx_shell_tube` | Horizontal capsule + tube bundle | Shell-and-tube heat exchanger |\n| `hx_air_cooled` | Rectangle + fan circle | Air-cooled (fin-fan) cooler |\n| `reboiler` | Capsule + parallel tube lines | Kettle reboiler |\n| `condenser` | Horizontal capsule + tubes | Overhead condenser |\n| `pump_centrifugal` | Circle + right-side triangle outlet | Centrifugal pump |\n| `pump_pd` | Circle + internal gears | Positive-displacement pump |\n| `compressor` | Trapezoid (narrow on right) | Centrifugal compressor |\n| `blower` | Circle + 3-blade fan | Blower / fan |\n| `reactor_cstr` | Vertical capsule + agitator | Stirred tank reactor (CSTR) |\n| `reactor_pfr` | Horizontal capsule + packed bed dots | Plug-flow / fixed-bed reactor |\n| `filter` | Rectangle + diagonal hatch | Filter |\n| `cyclone` | Cylinder + cone bottom | Cyclone separator |\n| `flare` | Tall stack + flame | Flare stack |\n| `cooling_tower` | Hourglass | Induced-draft cooling tower |\n\n### 2.2 Valve catalog\n\nValves are equipment that sit on the piping line. Render in `bowtie` style with type-specific actuator decoration.\n\n| Type | Decoration | Purpose |\n|---|---|---|\n| `valve_gate` | Plain bowtie | Manual on/off (full-port) |\n| `valve_ball` | Bowtie + filled center circle | Manual on/off (quarter-turn) |\n| `valve_globe` | Bowtie + small top circle | Manual flow control |\n| `valve_butterfly` | Bowtie + center vertical line | Quarter-turn throttle |\n| `valve_check` | Bowtie + arc | Non-return check valve |\n| `valve_control` | Bowtie + diaphragm actuator | Pneumatic control valve (paired with FIC) |\n| `valve_psv` | Bowtie + 45\xB0 outlet + spring stack | Pressure safety relief valve |\n\n```\nequip V-101 : valve_control [tag: "V-101 (FC)"]\nequip V-303 : valve_psv [tag: "V-303 \xB7 150 psig"]\n```\n\n---\n\n## 3. Piping & signal lines\n\nThe `line` statement connects two anchor points (equipment ports or instrument tags).\n\n```\nline L1 from T-101.bottom to P-101.in [size: "4\\"", service: "water", type: "process"]\nline s1 from FT-101 to FIC-101 [type: "electric"]\nline s2 from FIC-101 to V-101 [type: "pneumatic"]\n```\n\n### 3.1 Anchor syntax\n\nEach end of a line is either:\n- `<equip-id>.<port>` \u2014 port name from \xA72.2 (`in`, `out`, `top`, `bottom`, `feed`, `shell_in`, `tube_out`, `reflux`, etc.)\n- `<equip-id>` \u2014 port omitted; defaults to `in` (target) / `out` (source) per equipment family\n- `<inst-tag>` \u2014 instrument bubble center (signal lines)\n\n### 3.2 Line types (ISA-5.1 \xA75)\n\n| `type:` | Stroke | Use |\n|---|---|---|\n| `process` | Solid, thick | Major process line (default) |\n| `process_minor` | Solid, thin | Auxiliary / utility |\n| `pneumatic` | Solid + diagonal tick marks | Air-actuator signal |\n| `electric` | Long-dash | Electric / 4\u201320 mA signal |\n| `hydraulic` | Long-dash + pause | Hydraulic actuator |\n| `capillary` | Dotted (round caps) | Filled-system temperature |\n| `software` | Short-dash, light | DCS / PLC internal data link |\n| `mechanical` | Mixed dash | Mechanical linkage |\n\n### 3.3 Line tags\n\nThe standard PIP PIC001 tag format is `<size>"-<service>-<sequence>-<spec>`. Pass it via the `tag:` attribute and the renderer places a small white tag rectangle at the line midpoint.\n\n```\nline L1 from T-101.bottom to P-101.in [size: "4\\"", service: "PG", tag: "4\\"-PG-101-A1B"]\n```\n\n---\n\n## 4. Instrumentation (ISA-5.1 \xA74)\n\nThe `inst` statement declares an instrument bubble. The **tag** uses the ISA letter-code convention: first letter is the *measured variable*, subsequent letters are *modifiers* and *function*.\n\n```\ninst FT-101 : field_discrete %% Flow Transmitter, loop 101\ninst FIC-101 : cr_shared %% Flow Indicating Controller (DCS)\ninst PSHH-301: cr_plc %% Pressure Switch High-High (PLC)\ninst LIC-201 : cr_shared\n measures D-201\n controls V-202\n```\n\n### 4.1 Letter codes (first letter)\n\nMost-used: `F` flow \xB7 `L` level \xB7 `P` pressure \xB7 `T` temperature \xB7 `A` analysis \xB7 `S` speed \xB7 `H` hand \xB7 `Y` event/state. Full list in ISA-5.1 Table 1.\n\n### 4.2 Function modifiers\n\n`I` indicator \xB7 `R` recorder \xB7 `C` controller \xB7 `T` transmitter \xB7 `E` element \xB7 `V` valve \xB7 `S` switch \xB7 `A` alarm \xB7 `H`/`L` high/low. Combine into the multi-letter tag: `FIC` = Flow Indicating Controller; `PSHH` = Pressure Switch High-High.\n\n### 4.3 Bubble categories\n\nISA-5.1 distinguishes **location** (where the instrument lives) and **type** (analog vs. shared vs. computer vs. PLC). Schematex implements the four most common combinations:\n\n| Category | Bubble shape | Use |\n|---|---|---|\n| `field_discrete` | Plain circle | Field-mounted analog instrument (FT, PT) |\n| `cr_shared` | Circle + horizontal line + inscribed hexagon | DCS-controlled HMI display |\n| `cr_computer` | Circle + horizontal line + inscribed diamond | Computer function (FY, calculation) |\n| `cr_plc` | Circle + horizontal line + inscribed square | PLC-driven logic |\n\n`field_*` variants omit the horizontal centerline; `local_*` variants use a dashed centerline; `cr_*` variants use a solid centerline indicating "main control panel \u2014 front."\n\n### 4.4 measures / controls\n\nIndented under an `inst` declaration:\n\n| Clause | Effect |\n|---|---|\n| `measures <equip-id>` | Auto-routed dashed-electric signal line from the equipment to the bubble |\n| `controls <equip-id>` | Auto-routed pneumatic signal line from the bubble to the equipment (typically a `valve_control`) |\n\n```\ninst FT-101 : field_discrete\n measures P-101\ninst FIC-101 : cr_shared\n controls V-101\n```\n\nThese auto-signals are independent of the explicit `line` statements \u2014 they get rendered with the appropriate signal-line style based on the relation type.\n\n---\n\n## 5. Layout direction\n\nThe default direction is **`LR`** (left-to-right) \u2014 process feed enters on the left, product exits on the right. Override on the header:\n\n```\npid "Distillation Tower" [direction: TB]\n\nequip T-201 : column_tray\n\u2026\n```\n\nThe MVP layout places equipment in declaration order along the primary direction with Manhattan signal-line routing. **Multi-row / parallel-flow layouts and tee junctions are roadmap items** \u2014 see \xA79.\n\n---\n\n## 6. Worked example: Distillation column\n\nA real overhead-condenser loop with reboiler, reflux drum, and instrumentation:\n\n```\npid "Distillation T-201"\n\nequip T-201 : column_tray [tag: "T-201"]\nequip E-201 : condenser [tag: "Overhead Cond"]\nequip D-201 : vessel_h [tag: "Reflux Drum"]\nequip P-201 : pump_centrifugal [tag: "Reflux Pump"]\nequip E-202 : reboiler [tag: "Reboiler"]\n\nline L1 from T-201.top to E-201.shell_in [size: "8\\\\"", service: "vapor", type: "process"]\nline L2 from E-201.shell_out to D-201.in [size: "8\\\\"", type: "process"]\nline L3 from D-201.bottom to P-201.in [size: "3\\\\"", type: "process"]\nline L4 from P-201.out to T-201.reflux [size: "3\\\\"", type: "process"]\nline L5 from T-201.bottom to E-202.in [size: "6\\\\"", type: "process"]\n\ninst PT-201 : field_discrete\n measures T-201\ninst LIC-201 : cr_shared\n measures D-201\ninst TIC-201 : cr_shared\n measures T-201\n```\n\n---\n\n## 7. Grammar (EBNF)\n\n```text\ndocument = header statement*\nheader = "pid" ( title )? ( "[" attrs "]" )? NEWLINE\nattrs = attr ("," attr)*\nattr = "direction:" ("LR" | "TB")\n | "units:" ("imperial" | "metric")\n\nstatement = comment\n | equipment-decl\n | line-decl\n | instrument-decl\n\nequipment-decl = "equip" ID ":" equip-type ( "[" attr-list "]" )? NEWLINE\nequip-type = "tank_atm" | "tank_cone_roof"\n | "vessel_v" | "vessel_h" | "sphere"\n | "column_tray" | "column_packed"\n | "hx_shell_tube" | "hx_air_cooled" | "reboiler" | "condenser"\n | "pump_centrifugal" | "pump_pd"\n | "compressor" | "blower"\n | "reactor_cstr" | "reactor_pfr"\n | "filter" | "cyclone" | "flare" | "cooling_tower"\n | "valve_gate" | "valve_ball" | "valve_globe" | "valve_butterfly"\n | "valve_check" | "valve_control" | "valve_psv"\n\nline-decl = "line" ID "from" anchor "to" anchor ( "[" attr-list "]" )? NEWLINE\nanchor = ID ( "." port )?\nport = "in" | "out" | "top" | "bottom" | "left" | "right"\n | "feed" | "reflux" | "shell_in" | "shell_out"\n | "tube_in" | "tube_out" | "vapor_out" | "liquid_out"\n | "bottom_return"\n\ninstrument-decl = "inst" tag ":" inst-category ( "[" attr-list "]" )? NEWLINE\n ( indented "measures" anchor NEWLINE )*\n ( indented "controls" ID NEWLINE )*\ntag = letter-code "-" loop-num %% e.g., "FIC-101"\ninst-category = "field_discrete" | "field_shared" | "field_computer" | "field_plc"\n | "cr_discrete" | "cr_shared" | "cr_computer" | "cr_plc"\n | "local_discrete" | "local_shared"\n\nattr-list = attr ("," attr)*\nattr = key ":" value\nkey = "tag" | "size" | "service" | "type" | "set_pressure"\n | "actuator" | "fail" | "trays" | \u2026\nvalue = quoted-string | bare-word\n\nID = [A-Za-z] [A-Za-z0-9_-]*\n```\n\nAuthoritative source: `src/diagrams/pid/parser.ts`. If this diverges from the parser, the parser wins \u2014 please open an issue.\n\n---'
1001
1047
  }
1002
1048
  };
1003
1049
 
@@ -1077,7 +1123,7 @@ function getExamples(type, opts = {}) {
1077
1123
  function validateDsl(type, dsl) {
1078
1124
  const config = type ? { type } : void 0;
1079
1125
  try {
1080
- chunkMSYBSOU2_cjs.parse(dsl, config);
1126
+ chunkYTEEZV6J_cjs.parse(dsl, config);
1081
1127
  return { ok: true, type: type ?? resolveTypeFromText(dsl) };
1082
1128
  } catch (err) {
1083
1129
  return {
@@ -1093,7 +1139,7 @@ function renderDsl(type, dsl, options = {}) {
1093
1139
  ...type ? { type } : {}
1094
1140
  };
1095
1141
  try {
1096
- const svg = chunkMSYBSOU2_cjs.render(dsl, config);
1142
+ const svg = chunkYTEEZV6J_cjs.render(dsl, config);
1097
1143
  return { ok: true, type: type ?? resolveTypeFromText(dsl), svg };
1098
1144
  } catch (err) {
1099
1145
  return {
@@ -1117,5 +1163,5 @@ exports.getSyntax = getSyntax;
1117
1163
  exports.listDiagrams = listDiagrams;
1118
1164
  exports.renderDsl = renderDsl;
1119
1165
  exports.validateDsl = validateDsl;
1120
- //# sourceMappingURL=chunk-DPQYGWCT.cjs.map
1121
- //# sourceMappingURL=chunk-DPQYGWCT.cjs.map
1166
+ //# sourceMappingURL=chunk-RODV6PC4.cjs.map
1167
+ //# sourceMappingURL=chunk-RODV6PC4.cjs.map