agentic-mermaid 0.1.1 → 0.1.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 (336) hide show
  1. package/CHANGELOG.md +144 -4
  2. package/LICENSES/Apache-2.0.txt +202 -0
  3. package/README.md +25 -32
  4. package/THIRD_PARTY_NOTICES.md +29 -0
  5. package/dist/agent-core.d.ts +463 -0
  6. package/dist/agent-core.js +397 -0
  7. package/dist/agent.d.ts +73 -1868
  8. package/dist/agent.js +336 -37325
  9. package/dist/agentic-mermaid-mcp.js +7 -38399
  10. package/dist/am.js +33632 -40445
  11. package/dist/chunk-4QECACIA.js +4702 -0
  12. package/dist/chunk-CDPKJ2BQ.js +37 -0
  13. package/dist/chunk-QKDLMOJJ.js +3487 -0
  14. package/dist/chunk-WI35L7IR.js +615 -0
  15. package/dist/chunk-WN3YDOBG.js +149 -0
  16. package/dist/chunk-ZYMMKQ3I.js +62637 -0
  17. package/dist/index-D54dqSdC.d.ts +6777 -0
  18. package/dist/index.d.ts +1 -1
  19. package/dist/index.js +310 -33014
  20. package/dist/mcp-cli-SBQSTJFC.js +17 -0
  21. package/docs/README.md +14 -6
  22. package/docs/schemas/style-spec.schema.json +1221 -30
  23. package/examples/styles/catalog.json +54 -0
  24. package/examples/styles/cloudflare-workers-inspired-prototype.mmd +9 -0
  25. package/examples/styles/cloudflare-workers-inspired-prototype.style.json +110 -0
  26. package/examples/styles/cupertino-prototype.mmd +10 -0
  27. package/examples/styles/cupertino-prototype.style.json +63 -0
  28. package/examples/styles/mid-century-report.style.json +2 -2
  29. package/examples/styles/star-chart-atlas.style.json +2 -1
  30. package/examples/styles/transit-route-map.style.json +2 -2
  31. package/examples/styles/vercel-inspired-prototype.mmd +6 -0
  32. package/examples/styles/vercel-inspired-prototype.style.json +87 -0
  33. package/package.json +68 -43
  34. package/server.json +2 -2
  35. package/skills/agentic-mermaid-diagram-workflow/SKILL.md +17 -36
  36. package/skills/agentic-mermaid-diagram-workflow/references/cli.md +4 -5
  37. package/skills/agentic-mermaid-diagram-workflow/references/code-mode.md +15 -31
  38. package/skills/agentic-mermaid-diagram-workflow/references/sequence.md +10 -14
  39. package/skills/agentic-mermaid-live-editor/SKILL.md +100 -206
  40. package/AGENT_NATIVE.md +0 -607
  41. package/Instructions_for_agents.md +0 -89
  42. package/TODO.md +0 -684
  43. package/assets/hero.png +0 -0
  44. package/dist/index-wjRjbsP-.d.ts +0 -1102
  45. package/docs/agent-api-cookbook.md +0 -308
  46. package/docs/agent-mutation-policy.md +0 -104
  47. package/docs/agent-workflow-examples.md +0 -46
  48. package/docs/api.md +0 -211
  49. package/docs/ascii.md +0 -103
  50. package/docs/assets/improvements/box-start-connector.png +0 -0
  51. package/docs/assets/improvements/comment-dropped-lint.png +0 -0
  52. package/docs/assets/improvements/er-content-loss.png +0 -0
  53. package/docs/assets/improvements/fan-in-trunks.png +0 -0
  54. package/docs/assets/improvements/gantt-family.png +0 -0
  55. package/docs/assets/improvements/gantt-milestone-clamp.png +0 -0
  56. package/docs/assets/improvements/gantt-verify-seam.png +0 -0
  57. package/docs/assets/improvements/subgraph-container-edges.png +0 -0
  58. package/docs/assets/improvements/wrapper-frontmatter.png +0 -0
  59. package/docs/assets/improvements/wrapper-init-directive.png +0 -0
  60. package/docs/assets/improvements/wrapper-leading-comment.png +0 -0
  61. package/docs/assets/style-cookbook/mid-century-report.png +0 -0
  62. package/docs/assets/style-cookbook/star-chart-atlas.png +0 -0
  63. package/docs/assets/style-cookbook/transit-route-map.png +0 -0
  64. package/docs/comparison.md +0 -94
  65. package/docs/config.md +0 -105
  66. package/docs/contributing/adding-diagram-types.md +0 -144
  67. package/docs/contributing/diagram-family-citizenship.matrix.json +0 -2127
  68. package/docs/contributing/diagram-family-citizenship.md +0 -82
  69. package/docs/contributing/harvesting-upstream-tests.md +0 -126
  70. package/docs/contributing/lessons-learned.md +0 -276
  71. package/docs/contributing/releasing.md +0 -82
  72. package/docs/contributing/visual-review-evidence.md +0 -53
  73. package/docs/custom-style-cookbook.md +0 -154
  74. package/docs/design/families/README.md +0 -26
  75. package/docs/design/families/architecture-beta.md +0 -48
  76. package/docs/design/families/flowchart-parser-conformance.md +0 -22
  77. package/docs/design/families/gantt-research.md +0 -137
  78. package/docs/design/families/gantt.md +0 -329
  79. package/docs/design/families/journey-agentic-cards-before.png +0 -0
  80. package/docs/design/families/journey-experience-curve-implementation.png +0 -0
  81. package/docs/design/families/journey-mermaid-classic-implementation.png +0 -0
  82. package/docs/design/families/journey-mermaid-classic-prototype.png +0 -0
  83. package/docs/design/families/journey-mermaid-classic-prototype.svg +0 -163
  84. package/docs/design/families/journey-mermaid-classic-prototype.svg.png +0 -0
  85. package/docs/design/families/journey-migration-parity.md +0 -439
  86. package/docs/design/families/journey-section-overlap-after.png +0 -0
  87. package/docs/design/families/journey-section-overlap-before.png +0 -0
  88. package/docs/design/families/journey-usage-research.md +0 -423
  89. package/docs/design/families/journey.md +0 -153
  90. package/docs/design/families/xychart.md +0 -85
  91. package/docs/design/system/README.md +0 -45
  92. package/docs/design/system/abstraction-audit.md +0 -224
  93. package/docs/design/system/abstraction-recommendations.md +0 -655
  94. package/docs/design/system/architecture.mmd +0 -29
  95. package/docs/design/system/architecture.svg +0 -137
  96. package/docs/design/system/layout-guarantees-and-robustness.md +0 -351
  97. package/docs/design/system/layout-rubric.md +0 -138
  98. package/docs/design/system/route-contracts.md +0 -848
  99. package/docs/design/system/source-preservation-ladder.md +0 -52
  100. package/docs/design/system/styles-rollout.md +0 -216
  101. package/docs/design/system/ugly-layouts.md +0 -119
  102. package/docs/diagram-families.md +0 -193
  103. package/docs/features.md +0 -147
  104. package/docs/fork-differences.md +0 -130
  105. package/docs/getting-started.md +0 -175
  106. package/docs/issue-derived-test-cases.md +0 -156
  107. package/docs/layout-characterization/README.md +0 -245
  108. package/docs/layout-characterization/contact-sheet-families.md +0 -498
  109. package/docs/layout-characterization/contact-sheet.md +0 -638
  110. package/docs/layout-characterization/properties.md +0 -281
  111. package/docs/layout-characterization/visual-quality.md +0 -160
  112. package/docs/layout-characterization/visual-snapshots/architecture.svg +0 -79
  113. package/docs/layout-characterization/visual-snapshots/class.svg +0 -60
  114. package/docs/layout-characterization/visual-snapshots/er.svg +0 -61
  115. package/docs/layout-characterization/visual-snapshots/flowchart.svg +0 -58
  116. package/docs/layout-characterization/visual-snapshots/gantt.svg +0 -52
  117. package/docs/layout-characterization/visual-snapshots/journey.svg +0 -98
  118. package/docs/layout-characterization/visual-snapshots/pie.svg +0 -36
  119. package/docs/layout-characterization/visual-snapshots/quadrant.svg +0 -47
  120. package/docs/layout-characterization/visual-snapshots/sequence.svg +0 -59
  121. package/docs/layout-characterization/visual-snapshots/state.svg +0 -52
  122. package/docs/layout-characterization/visual-snapshots/timeline.svg +0 -64
  123. package/docs/layout-characterization/visual-snapshots/xychart.svg +0 -97
  124. package/docs/mcp-code-mode-rationale.md +0 -101
  125. package/docs/mcp-http-transport.md +0 -223
  126. package/docs/mermaid-layout-complaints.md +0 -837
  127. package/docs/mutation-testing.md +0 -206
  128. package/docs/project/divergences.md +0 -98
  129. package/docs/project/dogfooding-docs-strategy.md +0 -66
  130. package/docs/project/hosted-mcp-cloudflare-plan.md +0 -338
  131. package/docs/project/lessons-learned.md +0 -1019
  132. package/docs/project/remove-role-styling-plan.md +0 -176
  133. package/docs/quality.md +0 -215
  134. package/docs/react.md +0 -97
  135. package/docs/style-authoring.md +0 -133
  136. package/docs/testing-strategy.md +0 -335
  137. package/docs/theming.md +0 -162
  138. package/examples/agent-improve-auth-flow.ts +0 -206
  139. package/examples/agent-loop.ts +0 -53
  140. package/examples/mcp-vs-cli-complex-diagrams.ts +0 -133
  141. package/llms.txt +0 -104
  142. package/skill-evals/README.md +0 -77
  143. package/skill-evals/fixtures/architecture-cache/input.mmd +0 -5
  144. package/skill-evals/fixtures/class-payment/input.mmd +0 -4
  145. package/skill-evals/fixtures/er-orders/input.mmd +0 -10
  146. package/skill-evals/fixtures/flowchart-cache/input.mmd +0 -3
  147. package/skill-evals/fixtures/gantt-release/input.mmd +0 -7
  148. package/skill-evals/fixtures/journey-checkout/input.mmd +0 -6
  149. package/skill-evals/fixtures/pie-exports/input.mmd +0 -5
  150. package/skill-evals/fixtures/quadrant-priorities/input.mmd +0 -11
  151. package/skill-evals/fixtures/sequence-retry/input.mmd +0 -8
  152. package/skill-evals/fixtures/state-lifecycle/input.mmd +0 -5
  153. package/skill-evals/fixtures/timeline-release/input.mmd +0 -6
  154. package/skill-evals/fixtures/xychart-growth/input.mmd +0 -5
  155. package/skill-evals/shared-benchmark.json +0 -510
  156. package/src/agent/analyze.ts +0 -157
  157. package/src/agent/apply.ts +0 -146
  158. package/src/agent/architecture-body.ts +0 -458
  159. package/src/agent/certificates.ts +0 -110
  160. package/src/agent/class-body.ts +0 -319
  161. package/src/agent/core.ts +0 -207
  162. package/src/agent/create.ts +0 -106
  163. package/src/agent/describe.ts +0 -368
  164. package/src/agent/er-body.ts +0 -224
  165. package/src/agent/facts.ts +0 -360
  166. package/src/agent/families-builtin.ts +0 -920
  167. package/src/agent/families.ts +0 -232
  168. package/src/agent/family-layouts.ts +0 -832
  169. package/src/agent/flowchart-body.ts +0 -372
  170. package/src/agent/flowchart-unsupported.ts +0 -243
  171. package/src/agent/font-coverage.ts +0 -288
  172. package/src/agent/gantt-body.ts +0 -495
  173. package/src/agent/index.ts +0 -10
  174. package/src/agent/journey-body.ts +0 -374
  175. package/src/agent/label-metrics.ts +0 -28
  176. package/src/agent/layout-to-rendered.ts +0 -63
  177. package/src/agent/mutate.ts +0 -97
  178. package/src/agent/mutation-ops.ts +0 -51
  179. package/src/agent/op-schema.ts +0 -443
  180. package/src/agent/parse.ts +0 -223
  181. package/src/agent/pie-body.ts +0 -270
  182. package/src/agent/png.ts +0 -171
  183. package/src/agent/quadrant-body.ts +0 -336
  184. package/src/agent/quality.ts +0 -363
  185. package/src/agent/readability-audit.ts +0 -92
  186. package/src/agent/rendered-route-audit.ts +0 -61
  187. package/src/agent/sequence-body.ts +0 -345
  188. package/src/agent/serialize.ts +0 -214
  189. package/src/agent/state-body.ts +0 -589
  190. package/src/agent/structural-count.ts +0 -150
  191. package/src/agent/timeline-body.ts +0 -280
  192. package/src/agent/trace-log.ts +0 -43
  193. package/src/agent/types.ts +0 -995
  194. package/src/agent/verify.ts +0 -603
  195. package/src/agent/xychart-body.ts +0 -472
  196. package/src/architecture/config.ts +0 -282
  197. package/src/architecture/layout.ts +0 -496
  198. package/src/architecture/parser.ts +0 -375
  199. package/src/architecture/renderer.ts +0 -611
  200. package/src/architecture/types.ts +0 -113
  201. package/src/ascii/ansi.ts +0 -423
  202. package/src/ascii/architecture.ts +0 -210
  203. package/src/ascii/canvas.ts +0 -443
  204. package/src/ascii/class-diagram.ts +0 -697
  205. package/src/ascii/converter.ts +0 -475
  206. package/src/ascii/draw.ts +0 -1693
  207. package/src/ascii/edge-bundling.ts +0 -328
  208. package/src/ascii/edge-routing.ts +0 -330
  209. package/src/ascii/er-diagram.ts +0 -439
  210. package/src/ascii/gantt.ts +0 -276
  211. package/src/ascii/grid.ts +0 -747
  212. package/src/ascii/index.ts +0 -196
  213. package/src/ascii/journey.ts +0 -169
  214. package/src/ascii/meta.ts +0 -244
  215. package/src/ascii/multiline-utils.ts +0 -80
  216. package/src/ascii/pathfinder.ts +0 -301
  217. package/src/ascii/pie.ts +0 -67
  218. package/src/ascii/quadrant.ts +0 -158
  219. package/src/ascii/reverse.ts +0 -216
  220. package/src/ascii/sequence.ts +0 -499
  221. package/src/ascii/shapes/circle.ts +0 -27
  222. package/src/ascii/shapes/corners.ts +0 -143
  223. package/src/ascii/shapes/diamond.ts +0 -27
  224. package/src/ascii/shapes/hexagon.ts +0 -27
  225. package/src/ascii/shapes/index.ts +0 -106
  226. package/src/ascii/shapes/rectangle.ts +0 -168
  227. package/src/ascii/shapes/rounded.ts +0 -27
  228. package/src/ascii/shapes/special.ts +0 -332
  229. package/src/ascii/shapes/stadium.ts +0 -110
  230. package/src/ascii/shapes/state.ts +0 -192
  231. package/src/ascii/shapes/types.ts +0 -73
  232. package/src/ascii/timeline.ts +0 -141
  233. package/src/ascii/types.ts +0 -312
  234. package/src/ascii/validate.ts +0 -120
  235. package/src/ascii/width.ts +0 -81
  236. package/src/ascii/wrap.ts +0 -131
  237. package/src/ascii/xychart.ts +0 -919
  238. package/src/browser.ts +0 -29
  239. package/src/class/layout.ts +0 -240
  240. package/src/class/parser.ts +0 -332
  241. package/src/class/renderer.ts +0 -638
  242. package/src/class/types.ts +0 -129
  243. package/src/cli/agent-instructions.ts +0 -1
  244. package/src/cli/am-bin.ts +0 -6
  245. package/src/cli/exit-codes.ts +0 -18
  246. package/src/cli/index.ts +0 -1132
  247. package/src/cli/init-agent.ts +0 -147
  248. package/src/cli/run-entrypoint.ts +0 -10
  249. package/src/color-resolver.ts +0 -152
  250. package/src/elk-instance.ts +0 -114
  251. package/src/er/layout.ts +0 -187
  252. package/src/er/parser.ts +0 -226
  253. package/src/er/renderer.ts +0 -792
  254. package/src/er/types.ts +0 -99
  255. package/src/family-rubric.ts +0 -425
  256. package/src/font-manifest.ts +0 -31
  257. package/src/gantt/layout.ts +0 -365
  258. package/src/gantt/parser.ts +0 -282
  259. package/src/gantt/pipeline.ts +0 -27
  260. package/src/gantt/renderer.ts +0 -414
  261. package/src/gantt/schedule.ts +0 -513
  262. package/src/gantt/types.ts +0 -255
  263. package/src/index.ts +0 -368
  264. package/src/journey/layout.ts +0 -554
  265. package/src/journey/parse-core.ts +0 -251
  266. package/src/journey/parser.ts +0 -101
  267. package/src/journey/renderer.ts +0 -917
  268. package/src/journey/types.ts +0 -144
  269. package/src/layout/geometry.ts +0 -182
  270. package/src/layout/pass.ts +0 -142
  271. package/src/layout/passes/index.ts +0 -3916
  272. package/src/layout-engine.ts +0 -1565
  273. package/src/layout-rubric.ts +0 -659
  274. package/src/mcp/artifacts.ts +0 -137
  275. package/src/mcp/dynamic-harness.ts +0 -31
  276. package/src/mcp/dynamic-modules.d.ts +0 -7
  277. package/src/mcp/facade.ts +0 -608
  278. package/src/mcp/harness-runtime.ts +0 -203
  279. package/src/mcp/hosted-server.ts +0 -468
  280. package/src/mcp/mcp-bin.ts +0 -3
  281. package/src/mcp/mcp-cli.ts +0 -82
  282. package/src/mcp/protocol.ts +0 -13
  283. package/src/mcp/sandbox.ts +0 -195
  284. package/src/mcp/sdk-decl.ts +0 -391
  285. package/src/mcp/server.ts +0 -362
  286. package/src/mcp/tool-surface.ts +0 -146
  287. package/src/mermaid-source.ts +0 -655
  288. package/src/multiline-utils.ts +0 -228
  289. package/src/parser.ts +0 -1031
  290. package/src/pie/layout.ts +0 -168
  291. package/src/pie/parser.ts +0 -136
  292. package/src/pie/renderer.ts +0 -234
  293. package/src/pie/types.ts +0 -82
  294. package/src/quadrant/layout.ts +0 -191
  295. package/src/quadrant/parser.ts +0 -183
  296. package/src/quadrant/renderer.ts +0 -322
  297. package/src/quadrant/types.ts +0 -113
  298. package/src/render-family-hooks.ts +0 -244
  299. package/src/renderer.ts +0 -1099
  300. package/src/route-contracts.ts +0 -2723
  301. package/src/scene/backend.ts +0 -76
  302. package/src/scene/fidelity.ts +0 -183
  303. package/src/scene/hybrid-backend.ts +0 -174
  304. package/src/scene/ir.ts +0 -181
  305. package/src/scene/marks.ts +0 -127
  306. package/src/scene/rough-backend.ts +0 -378
  307. package/src/scene/seed.ts +0 -46
  308. package/src/scene/style-registry.ts +0 -556
  309. package/src/sequence/layout.ts +0 -456
  310. package/src/sequence/parser.ts +0 -255
  311. package/src/sequence/renderer.ts +0 -604
  312. package/src/sequence/types.ts +0 -154
  313. package/src/shape-clipping.ts +0 -351
  314. package/src/shared/accessibility-directives.ts +0 -22
  315. package/src/shared/batched.ts +0 -61
  316. package/src/shared/color-math.ts +0 -93
  317. package/src/shared/svg-a11y.ts +0 -29
  318. package/src/shared/syntax-error.ts +0 -17
  319. package/src/shared/unicode-ranges.ts +0 -135
  320. package/src/styles.ts +0 -318
  321. package/src/svg-paths.ts +0 -28
  322. package/src/text-metrics.ts +0 -248
  323. package/src/theme.ts +0 -710
  324. package/src/timeline/layout.ts +0 -381
  325. package/src/timeline/parser.ts +0 -215
  326. package/src/timeline/renderer.ts +0 -538
  327. package/src/timeline/types.ts +0 -105
  328. package/src/types.ts +0 -462
  329. package/src/website-worker-modules.d.ts +0 -18
  330. package/src/xychart/axis-utils.ts +0 -109
  331. package/src/xychart/colors.ts +0 -124
  332. package/src/xychart/config.ts +0 -88
  333. package/src/xychart/layout.ts +0 -656
  334. package/src/xychart/parser.ts +0 -504
  335. package/src/xychart/renderer.ts +0 -640
  336. package/src/xychart/types.ts +0 -282
@@ -1,312 +0,0 @@
1
- // ============================================================================
2
- // ASCII renderer — type definitions
3
- //
4
- // Ported from AlexanderGrooff/mermaid-ascii (Go).
5
- // These types model the grid-based coordinate system, 2D text canvas,
6
- // and graph structures used by the ASCII/Unicode renderer.
7
- // ============================================================================
8
-
9
- import type { NodeShape, EdgeMarker, RouteClass } from '../types.ts'
10
-
11
- // Re-export shared graph types for convenience
12
- export type { NodeShape, EdgeMarker }
13
-
14
- /**
15
- * Shape type for ASCII rendering — maps parser shapes to ASCII renderers.
16
- * Most shapes from the parser are supported, with fallback to 'rectangle'.
17
- */
18
- export type AsciiNodeShape = NodeShape
19
-
20
- /** Logical grid coordinate — nodes occupy 3x3 blocks on this grid. */
21
- export interface GridCoord {
22
- x: number
23
- y: number
24
- }
25
-
26
- /** Character-level coordinate on the 2D text canvas. */
27
- export interface DrawingCoord {
28
- x: number
29
- y: number
30
- }
31
-
32
- /**
33
- * Direction constants model positions on a node's 3x3 grid block.
34
- * Each node occupies grid cells [x..x+2, y..y+2].
35
- * Directions are offsets into that block, used for edge attachment points.
36
- *
37
- * (0,0) UL (1,0) Up (2,0) UR
38
- * (0,1) Left (1,1) Mid (2,1) Right
39
- * (0,2) LL (1,2) Down (2,2) LR
40
- */
41
- export interface Direction {
42
- readonly x: number
43
- readonly y: number
44
- }
45
-
46
- export const Up: Direction = { x: 1, y: 0 }
47
- export const Down: Direction = { x: 1, y: 2 }
48
- export const Left: Direction = { x: 0, y: 1 }
49
- export const Right: Direction = { x: 2, y: 1 }
50
- export const UpperRight: Direction = { x: 2, y: 0 }
51
- export const UpperLeft: Direction = { x: 0, y: 0 }
52
- export const LowerRight: Direction = { x: 2, y: 2 }
53
- export const LowerLeft: Direction = { x: 0, y: 2 }
54
- export const Middle: Direction = { x: 1, y: 1 }
55
-
56
- /** All named directions for iteration. */
57
- export const ALL_DIRECTIONS: readonly Direction[] = [
58
- Up, Down, Left, Right, UpperRight, UpperLeft, LowerRight, LowerLeft, Middle,
59
- ]
60
-
61
- /**
62
- * 2D text canvas — column-major (canvas[x][y]).
63
- * Each cell holds a single character (or space).
64
- */
65
- export type Canvas = string[][]
66
-
67
- /** A node in the ASCII graph, positioned on the grid. */
68
- export interface AsciiNode {
69
- /** Unique identity key — the original node ID from the parser (e.g. "A", "B"). */
70
- name: string
71
- /** Human-readable label for rendering inside the box (e.g. "Web Server"). */
72
- displayLabel: string
73
- /** Node shape from the parser (e.g. "rectangle", "diamond", "circle"). */
74
- shape: AsciiNodeShape
75
- index: number
76
- gridCoord: GridCoord | null
77
- drawingCoord: DrawingCoord | null
78
- drawing: Canvas | null
79
- drawn: boolean
80
- styleClassName: string
81
- styleClass: AsciiStyleClass
82
- }
83
-
84
- /** Style class for colored node text (ported from Go's classDef). */
85
- export interface AsciiStyleClass {
86
- name: string
87
- styles: Record<string, string>
88
- }
89
-
90
- /** Edge line style for ASCII rendering. */
91
- export type AsciiEdgeStyle = 'solid' | 'dotted' | 'thick' | 'invisible'
92
-
93
- /** An edge in the ASCII graph, with a routed path. */
94
- export interface AsciiEdge {
95
- from: AsciiNode
96
- to: AsciiNode
97
- /**
98
- * Source container when the Mermaid edge targets a subgraph id.
99
- * Consumed by the converter/grid (grid.ts attachment-point selection) and by
100
- * draw.ts's getSubgraphAttachmentPoint to choose WHERE on the container the
101
- * edge anchors. NOT the same as attachFromSubgraph (see below), which only
102
- * drives border clipping.
103
- */
104
- fromSubgraph?: AsciiSubgraph
105
- /**
106
- * Target container when the Mermaid edge targets a subgraph id.
107
- * Mirror of fromSubgraph for the edge target. Consumed by grid.ts and
108
- * draw.ts's getSubgraphAttachmentPoint for attachment-point selection.
109
- */
110
- toSubgraph?: AsciiSubgraph
111
- text: string
112
- path: GridCoord[]
113
- labelLine: GridCoord[]
114
- startDir: Direction
115
- endDir: Direction
116
- /** Shared semantic route intent from classifyRoutes(); consumed by grid placement/routing parity. */
117
- routeClass?: RouteClass
118
- /** Line style: solid (default), dotted (-.->) or thick (==>) */
119
- style: AsciiEdgeStyle
120
- /** Whether to render a marker at the start (source end) of the edge */
121
- hasArrowStart: boolean
122
- /** Whether to render a marker at the end (target end) of the edge */
123
- hasArrowEnd: boolean
124
- /** Marker shape at start when hasArrowStart=true. Defaults to 'arrow' if undefined. */
125
- startMarker?: EdgeMarker
126
- /** Marker shape at end when hasArrowEnd=true. Defaults to 'arrow' if undefined. */
127
- endMarker?: EdgeMarker
128
- /** Bundle this edge belongs to (if any). Set during bundling analysis. */
129
- bundle?: EdgeBundle
130
- /**
131
- * For bundled edges: path from source/target to the junction point.
132
- * The full visual path is: pathToJunction + bundle.sharedPath (for fan-in)
133
- * or bundle.sharedPath + pathToJunction (for fan-out).
134
- */
135
- pathToJunction?: GridCoord[]
136
- /**
137
- * BUILD-14: when an edge endpoint is a subgraph id (rather than a real node),
138
- * the edge attaches to the subgraph container, not a phantom node. For
139
- * layout/routing we anchor the edge on a representative member of the
140
- * container, but the visible terminus is clipped to the container's border.
141
- * - attachFromSubgraph: the SOURCE of the edge is a subgraph container.
142
- * - attachToSubgraph: the TARGET of the edge is a subgraph container.
143
- *
144
- * Consumed ONLY by draw.ts's drawContainerEdge, which clips the routed
145
- * polyline at the container border (clipPolylineAtBorder). Distinct from
146
- * fromSubgraph/toSubgraph above: those pick the attachment point; these pick
147
- * where to clip. Both pairs can be set, and they are not interchangeable.
148
- */
149
- attachFromSubgraph?: AsciiSubgraph
150
- attachToSubgraph?: AsciiSubgraph
151
- }
152
-
153
- /** A subgraph container with bounding box for rendering. */
154
- export interface AsciiSubgraph {
155
- /** Mermaid subgraph id (distinct from the display label); used for container-edge references. */
156
- id: string
157
- name: string
158
- nodes: AsciiNode[]
159
- parent: AsciiSubgraph | null
160
- children: AsciiSubgraph[]
161
- minX: number
162
- minY: number
163
- maxX: number
164
- maxY: number
165
- /** Optional direction override for layout within this subgraph (LR or TD). */
166
- direction?: 'LR' | 'TD'
167
- }
168
-
169
- /** Configuration for ASCII rendering. */
170
- export interface AsciiConfig {
171
- /** true = ASCII chars (+,-,|), false = Unicode box-drawing (┌,─,│). Default: false */
172
- useAscii: boolean
173
- /** Horizontal spacing between nodes. Default: 5 */
174
- paddingX: number
175
- /** Vertical spacing between nodes. Default: 5 */
176
- paddingY: number
177
- /** Padding inside node boxes. Default: 1 */
178
- boxBorderPadding: number
179
- /** Graph direction: "LR" or "TD". */
180
- graphDirection: 'LR' | 'TD'
181
- }
182
-
183
- /** Full ASCII graph state used during layout and rendering. */
184
- export interface AsciiGraph {
185
- nodes: AsciiNode[]
186
- edges: AsciiEdge[]
187
- canvas: Canvas
188
- /** Role canvas — tracks the role of each character for colored output. */
189
- roleCanvas: RoleCanvas
190
- /** Grid occupancy map — maps "x,y" keys to node references. */
191
- grid: Map<string, AsciiNode>
192
- columnWidth: Map<number, number>
193
- rowHeight: Map<number, number>
194
- subgraphs: AsciiSubgraph[]
195
- config: AsciiConfig
196
- /** Offset applied to all drawing coords to accommodate subgraph borders. */
197
- offsetX: number
198
- offsetY: number
199
- /** Edge bundles for parallel link visualization. Set during bundling analysis. */
200
- bundles: EdgeBundle[]
201
- /** Grid coordinates where sibling-edge trunk branches need explicit T-junctions. */
202
- trunkJunctions: GridCoord[]
203
- }
204
-
205
- // ============================================================================
206
- // Coordinate helpers
207
- // ============================================================================
208
-
209
- export function gridCoordEquals(a: GridCoord, b: GridCoord): boolean {
210
- return a.x === b.x && a.y === b.y
211
- }
212
-
213
- export function drawingCoordEquals(a: DrawingCoord, b: DrawingCoord): boolean {
214
- return a.x === b.x && a.y === b.y
215
- }
216
-
217
- /** Apply a direction offset to a grid coordinate (move into the 3x3 block). */
218
- export function gridCoordDirection(c: GridCoord, dir: Direction): GridCoord {
219
- return { x: c.x + dir.x, y: c.y + dir.y }
220
- }
221
-
222
- /** Key for storing GridCoord in a Map. */
223
- export function gridKey(c: GridCoord): string {
224
- return `${c.x},${c.y}`
225
- }
226
-
227
- /** Default empty style class. */
228
- export const EMPTY_STYLE: AsciiStyleClass = { name: '', styles: {} }
229
-
230
- // ============================================================================
231
- // Character role types for colored output
232
- // ============================================================================
233
-
234
- /**
235
- * Role of a character in the ASCII diagram, used for theming.
236
- * Each role maps to a different color when colors are enabled.
237
- */
238
- export type CharRole =
239
- | 'text' // Node labels, edge labels
240
- | 'border' // Node box borders, subgraph borders
241
- | 'line' // Edge lines (paths between nodes)
242
- | 'arrow' // Arrowheads (▲▼◄► or ^v<>)
243
- | 'corner' // Corner characters at path bends
244
- | 'junction' // Junction characters (┬┴├┤ where edges meet boxes)
245
-
246
- /**
247
- * Role canvas — parallel to Canvas, tracks the role of each character.
248
- * Same column-major structure: roleCanvas[x][y] gives the role at (x, y).
249
- * null means the character has no role (whitespace).
250
- */
251
- export type RoleCanvas = (CharRole | null)[][]
252
-
253
- /**
254
- * Theme colors for ASCII output — hex color strings.
255
- * Derived from the SVG theme system for visual consistency.
256
- */
257
- export interface AsciiTheme {
258
- /** Text color (node labels, edge labels) */
259
- fg: string
260
- /** Box border color (node borders, subgraph borders) */
261
- border: string
262
- /** Edge line color (paths between nodes) */
263
- line: string
264
- /** Arrowhead color (▲▼◄► or ^v<>) */
265
- arrow: string
266
- /** Theme accent color (optional, used by xycharts for series 0) */
267
- accent?: string
268
- /** Background color (optional, used by xycharts for dark-mode-aware shading) */
269
- bg?: string
270
- /** Corner character color (optional, defaults to line) */
271
- corner?: string
272
- /** Junction character color (optional, defaults to border) */
273
- junction?: string
274
- }
275
-
276
- /** Color mode for output. */
277
- export type ColorMode =
278
- | 'none' // No colors (plain text)
279
- | 'ansi16' // 16-color ANSI (basic terminals)
280
- | 'ansi256' // 256-color ANSI (xterm)
281
- | 'truecolor' // 24-bit RGB (modern terminals)
282
- | 'html' // HTML <span> tags with inline color styles (browsers)
283
-
284
- // ============================================================================
285
- // Edge bundling types
286
- // ============================================================================
287
-
288
- /**
289
- * Edge bundle — groups edges that share a common source or target.
290
- * Used to visually merge parallel links before they reach the shared node.
291
- *
292
- * For fan-in (A & B --> C): multiple sources converge to one target.
293
- * For fan-out (A --> B & C): one source diverges to multiple targets.
294
- */
295
- export interface EdgeBundle {
296
- /** Bundle type: fan-in = many→one, fan-out = one→many */
297
- type: 'fan-in' | 'fan-out'
298
- /** Edges in this bundle */
299
- edges: AsciiEdge[]
300
- /** The common node (target for fan-in, source for fan-out) */
301
- sharedNode: AsciiNode
302
- /** The non-shared nodes (sources for fan-in, targets for fan-out) */
303
- otherNodes: AsciiNode[]
304
- /** Junction point where edges merge/split — set during routing */
305
- junctionPoint: GridCoord | null
306
- /** Path from junction to shared node (drawn once for all edges) */
307
- sharedPath: GridCoord[]
308
- /** Direction when entering/exiting the junction */
309
- junctionDir: Direction
310
- /** Direction when entering/exiting the shared node */
311
- sharedNodeDir: Direction
312
- }
@@ -1,120 +0,0 @@
1
- /**
2
- * ASCII Rendering Validation Utilities
3
- *
4
- * Provides validation functions for ASCII diagram output,
5
- * including diagonal line detection to ensure orthogonal-only routing.
6
- */
7
-
8
- /**
9
- * Characters that represent diagonal lines in ASCII and Unicode modes.
10
- * These should never appear in properly rendered diagrams.
11
- */
12
- export const DIAGONAL_CHARS = {
13
- ascii: ['/', '\\'],
14
- unicode: ['\u2571', '\u2572'], // ╱ ╲
15
- all: ['/', '\\', '\u2571', '\u2572'],
16
- } as const
17
-
18
- /**
19
- * Position of a diagonal character in ASCII output.
20
- */
21
- export interface DiagonalPosition {
22
- line: number
23
- col: number
24
- char: string
25
- }
26
-
27
- /**
28
- * Check if ASCII output contains any diagonal line characters.
29
- * Returns true if diagonals are found (which is an error condition).
30
- *
31
- * @param asciiOutput - The rendered ASCII diagram string
32
- * @returns true if diagonal characters are present, false otherwise
33
- */
34
- export function hasDiagonalLines(asciiOutput: string): boolean {
35
- return DIAGONAL_CHARS.all.some((char) => asciiOutput.includes(char))
36
- }
37
-
38
- /**
39
- * Find all diagonal line character positions in ASCII output.
40
- * Useful for debugging when diagonals are detected.
41
- *
42
- * Skips diagonal characters that appear inside node labels (between box borders).
43
- * This prevents false positives from labels like "feature/auth" or "release/1.0".
44
- *
45
- * @param asciiOutput - The rendered ASCII diagram string
46
- * @returns Array of positions where diagonal characters were found
47
- */
48
- export function findDiagonalLines(asciiOutput: string): DiagonalPosition[] {
49
- const positions: DiagonalPosition[] = []
50
- const lines = asciiOutput.split('\n')
51
-
52
- // Box-drawing characters that indicate node boundaries
53
- const boxBorders = new Set(['│', '┤', '├', '║', '┃', '|'])
54
-
55
- for (let lineNum = 0; lineNum < lines.length; lineNum++) {
56
- const line = lines[lineNum]!
57
-
58
- // Find all box border positions in this line
59
- const borderPositions: number[] = []
60
- for (let col = 0; col < line.length; col++) {
61
- if (boxBorders.has(line[col]!)) {
62
- borderPositions.push(col)
63
- }
64
- }
65
-
66
- for (let col = 0; col < line.length; col++) {
67
- const char = line[col]!
68
- if (DIAGONAL_CHARS.all.includes(char as '/' | '\\' | '╱' | '╲')) {
69
- // Check if this position is inside a node (between two box borders)
70
- // Find the nearest borders before and after this position
71
- let insideNode = false
72
- for (let i = 0; i < borderPositions.length - 1; i++) {
73
- const leftBorder = borderPositions[i]!
74
- const rightBorder = borderPositions[i + 1]!
75
- if (col > leftBorder && col < rightBorder) {
76
- // This diagonal char is between two borders - likely inside a node label
77
- insideNode = true
78
- break
79
- }
80
- }
81
-
82
- if (!insideNode) {
83
- positions.push({
84
- line: lineNum + 1, // 1-indexed for human readability
85
- col: col + 1,
86
- char,
87
- })
88
- }
89
- }
90
- }
91
- }
92
-
93
- return positions
94
- }
95
-
96
- /**
97
- * Assert that ASCII output contains no diagonal lines.
98
- * Throws an error with detailed position information if diagonals are found.
99
- *
100
- * @param asciiOutput - The rendered ASCII diagram string
101
- * @param context - Optional context string for error message (e.g., diagram name)
102
- * @throws Error if diagonal characters are present
103
- */
104
- export function assertNoDiagonals(asciiOutput: string, context?: string): void {
105
- if (!hasDiagonalLines(asciiOutput)) {
106
- return
107
- }
108
-
109
- const positions = findDiagonalLines(asciiOutput)
110
- const contextStr = context ? ` in "${context}"` : ''
111
- const positionStr = positions
112
- .map((p) => ` Line ${p.line}, Col ${p.col}: '${p.char}'`)
113
- .join('\n')
114
-
115
- throw new Error(
116
- `Diagonal lines detected${contextStr}. ` +
117
- `Edges must use orthogonal Manhattan routing (90° bends only).\n` +
118
- `Found ${positions.length} diagonal character(s):\n${positionStr}`
119
- )
120
- }
@@ -1,81 +0,0 @@
1
- // ============================================================================
2
- // Terminal display width helpers for ASCII/Unicode rendering.
3
- //
4
- // Range tables live in src/shared/unicode-ranges.ts so the SVG metrics
5
- // module can share them without the ascii/ → core import that the
6
- // substrate lint forbids.
7
- //
8
- // Variation selectors (U+FE0E / U+FE0F) modify the WIDTH of the preceding
9
- // base codepoint, so `visualWidth` does a two-pass tally rather than a
10
- // per-codepoint sum: it remembers the last-emitted width and rewrites it
11
- // when a selector arrives. ZWJ (U+200D) and FE0E both have width 0; FE0F
12
- // forces the previous base to width 2.
13
- // ============================================================================
14
-
15
- import { isWideRange, isZeroWidth, VS_TEXT, VS_EMOJI, ZWJ } from '../shared/unicode-ranges.ts'
16
-
17
- /** Sentinel stored in the canvas cell following a fullwidth character. */
18
- export const WIDE_CHAR_CONTINUATION = '\x00'
19
-
20
- /**
21
- * Width of a single codepoint, with no knowledge of neighbours.
22
- * Variation selectors are reported as zero-width here; the per-string
23
- * `visualWidth` applies the selector's retroactive width override.
24
- */
25
- export function charVisualWidth(ch: string): number {
26
- const code = ch.codePointAt(0) ?? 0
27
- if (code === VS_TEXT || code === VS_EMOJI || code === ZWJ) return 0
28
- if (isZeroWidth(code)) return 0
29
- if (isWideRange(code)) return 2
30
- return 1
31
- }
32
-
33
- /**
34
- * Terminal display width of a string, in cells.
35
- *
36
- * Iterates codepoints and applies these post-process rules:
37
- * - FE0F (emoji-presentation selector): force the preceding base to width 2
38
- * - FE0E (text-presentation selector): force the preceding base to width 1
39
- * - 200D (ZWJ): zero width; binds the next base
40
- * into an emoji ZWJ sequence — the next base is also forced to 0
41
- * so a man-with-laptop (👨‍💻) totals 2 cells, not 4.
42
- */
43
- export function visualWidth(text: string): number {
44
- let total = 0
45
- let lastBaseWidth = 0
46
- let zwjPending = false
47
- for (const ch of text) {
48
- const code = ch.codePointAt(0) ?? 0
49
- if (code === VS_EMOJI) {
50
- if (lastBaseWidth === 1) {
51
- total += 1
52
- lastBaseWidth = 2
53
- }
54
- continue
55
- }
56
- if (code === VS_TEXT) {
57
- if (lastBaseWidth === 2) {
58
- total -= 1
59
- lastBaseWidth = 1
60
- }
61
- continue
62
- }
63
- if (code === ZWJ) {
64
- zwjPending = true
65
- lastBaseWidth = 0
66
- continue
67
- }
68
- if (isZeroWidth(code)) {
69
- lastBaseWidth = 0
70
- continue
71
- }
72
- let w = isWideRange(code) ? 2 : 1
73
- if (zwjPending) {
74
- w = 0
75
- zwjPending = false
76
- }
77
- total += w
78
- lastBaseWidth = w
79
- }
80
- return total
81
- }
package/src/ascii/wrap.ts DELETED
@@ -1,131 +0,0 @@
1
- // ============================================================================
2
- // ASCII renderer — width-aware text wrapping.
3
- //
4
- // Shared by the journey and timeline ASCII renderers. Wrapping iterates
5
- // grapheme clusters (Intl.Segmenter) rather than codepoints and measures
6
- // candidates with the whole-string `visualWidth`, so FE0F emoji count their
7
- // display width (a per-codepoint sum sees ❤️ as 1 cell; it renders as 2)
8
- // and ZWJ sequences (👩‍🔬) are never split mid-grapheme.
9
- //
10
- // Mid-word breaks follow the SVG layout's breakWordToWidth convention
11
- // (src/journey/layout.ts): the continuing chunk takes a trailing '-',
12
- // except when the break falls between two double-width clusters — CJK and
13
- // fullwidth text wraps at any character without hyphenation.
14
- // ============================================================================
15
-
16
- import { visualWidth } from './width.ts'
17
-
18
- /** Options for wrapText/wrapParagraph/breakWord. */
19
- export interface WrapOptions {
20
- /**
21
- * Append '-' where a word is broken mid-line (suppressed between
22
- * double-width clusters, and when the hyphen itself would not fit).
23
- * Default: true. Glyph strips (e.g. the journey score strip) disable it.
24
- */
25
- hyphenate?: boolean
26
- }
27
-
28
- /** Grapheme segmentation is locale-independent (UAX #29), so this is deterministic. */
29
- const segmenter = new Intl.Segmenter(undefined, { granularity: 'grapheme' })
30
-
31
- /** Split a string into grapheme clusters (emoji ZWJ sequences stay whole). */
32
- export function graphemes(text: string): string[] {
33
- return Array.from(segmenter.segment(text), s => s.segment)
34
- }
35
-
36
- /**
37
- * Wrap text to at most `maxWidth` display cells per line. Embedded '\n' are
38
- * hard breaks. Without a positive finite maxWidth, only splits on '\n'.
39
- */
40
- export function wrapText(text: string, maxWidth: number | undefined, options?: WrapOptions): string[] {
41
- if (!maxWidth || !Number.isFinite(maxWidth) || maxWidth <= 0) return text.split('\n')
42
- const limit = Math.max(1, Math.floor(maxWidth))
43
- const lines: string[] = []
44
- for (const paragraph of text.split('\n')) {
45
- lines.push(...wrapParagraph(paragraph, limit, options))
46
- }
47
- return lines.length > 0 ? lines : ['']
48
- }
49
-
50
- /**
51
- * Wrap a single paragraph (no '\n') at word boundaries by display width.
52
- * Words wider than maxWidth are broken by `breakWord`.
53
- */
54
- export function wrapParagraph(text: string, maxWidth: number, options?: WrapOptions): string[] {
55
- if (visualWidth(text) <= maxWidth) return [text]
56
- const words = text.split(/\s+/).filter(Boolean)
57
- if (words.length === 0) return ['']
58
-
59
- const lines: string[] = []
60
- let current = ''
61
- for (const word of words) {
62
- if (!current) {
63
- const chunks = breakWord(word, maxWidth, options)
64
- lines.push(...chunks.slice(0, -1))
65
- current = chunks[chunks.length - 1] ?? ''
66
- continue
67
- }
68
-
69
- const candidate = `${current} ${word}`
70
- if (visualWidth(candidate) <= maxWidth) {
71
- current = candidate
72
- continue
73
- }
74
-
75
- lines.push(current)
76
- const chunks = breakWord(word, maxWidth, options)
77
- lines.push(...chunks.slice(0, -1))
78
- current = chunks[chunks.length - 1] ?? ''
79
- }
80
- if (current) lines.push(current)
81
- return lines
82
- }
83
-
84
- /**
85
- * Break a single word into chunks of at most maxWidth cells. Greedy over
86
- * grapheme clusters: each line takes as many whole clusters as fit,
87
- * reserving one cell for the trailing hyphen when its break needs one.
88
- * A cluster wider than maxWidth still gets emitted alone (nothing narrower
89
- * exists to emit), matching the pre-grapheme behavior.
90
- */
91
- export function breakWord(word: string, maxWidth: number, options?: WrapOptions): string[] {
92
- if (visualWidth(word) <= maxWidth) return [word]
93
- const hyphenate = options?.hyphenate ?? true
94
- const clusters = graphemes(word)
95
- const lines: string[] = []
96
- let start = 0
97
- while (start < clusters.length) {
98
- let end = start + 1 // always consume at least one cluster per line
99
- while (end < clusters.length && fitsWithBreak(clusters, start, end + 1, maxWidth, hyphenate)) end++
100
- const chunk = clusters.slice(start, end).join('')
101
- const hyphen = end < clusters.length
102
- && breakNeedsHyphen(clusters[end - 1]!, clusters[end]!, hyphenate)
103
- && visualWidth(chunk) + 1 <= maxWidth
104
- lines.push(hyphen ? `${chunk}-` : chunk)
105
- start = end
106
- }
107
- return lines
108
- }
109
-
110
- /** Would clusters[start..end) fit in maxWidth, counting the hyphen its break would need? */
111
- function fitsWithBreak(
112
- clusters: string[],
113
- start: number,
114
- end: number,
115
- maxWidth: number,
116
- hyphenate: boolean,
117
- ): boolean {
118
- const width = visualWidth(clusters.slice(start, end).join(''))
119
- const hyphen = end < clusters.length && breakNeedsHyphen(clusters[end - 1]!, clusters[end]!, hyphenate) ? 1 : 0
120
- return width + hyphen <= maxWidth
121
- }
122
-
123
- /**
124
- * A mid-word break takes a hyphen unless it falls between two double-width
125
- * clusters (CJK, fullwidth forms, emoji), where hyphenation is not a text
126
- * convention.
127
- */
128
- function breakNeedsHyphen(before: string, after: string, hyphenate: boolean): boolean {
129
- if (!hyphenate) return false
130
- return !(visualWidth(before) === 2 && visualWidth(after) === 2)
131
- }