agentic-mermaid 0.1.0 → 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 (333) hide show
  1. package/CHANGELOG.md +149 -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/assets/fonts/FONT-LICENSES.md +9 -5
  6. package/assets/fonts/Inter-Bold.ttf +0 -0
  7. package/assets/fonts/Inter-Medium.ttf +0 -0
  8. package/assets/fonts/Inter-Regular.ttf +0 -0
  9. package/assets/fonts/Inter-SemiBold.ttf +0 -0
  10. package/dist/agent-core.d.ts +463 -0
  11. package/dist/agent-core.js +397 -0
  12. package/dist/agent.d.ts +81 -1822
  13. package/dist/agent.js +336 -36839
  14. package/dist/agentic-mermaid-mcp.js +7 -37908
  15. package/dist/am.js +33638 -36261
  16. package/dist/chunk-4QECACIA.js +4702 -0
  17. package/dist/chunk-CDPKJ2BQ.js +37 -0
  18. package/dist/chunk-QKDLMOJJ.js +3487 -0
  19. package/dist/chunk-WI35L7IR.js +615 -0
  20. package/dist/chunk-WN3YDOBG.js +149 -0
  21. package/dist/chunk-ZYMMKQ3I.js +62637 -0
  22. package/dist/index-D54dqSdC.d.ts +6777 -0
  23. package/dist/index.d.ts +1 -1
  24. package/dist/index.js +310 -32836
  25. package/dist/mcp-cli-SBQSTJFC.js +17 -0
  26. package/docs/README.md +14 -6
  27. package/docs/schemas/style-spec.schema.json +1221 -30
  28. package/examples/styles/catalog.json +54 -0
  29. package/examples/styles/cloudflare-workers-inspired-prototype.mmd +9 -0
  30. package/examples/styles/cloudflare-workers-inspired-prototype.style.json +110 -0
  31. package/examples/styles/cupertino-prototype.mmd +10 -0
  32. package/examples/styles/cupertino-prototype.style.json +63 -0
  33. package/examples/styles/mid-century-report.style.json +2 -2
  34. package/examples/styles/star-chart-atlas.style.json +2 -1
  35. package/examples/styles/transit-route-map.style.json +2 -2
  36. package/examples/styles/vercel-inspired-prototype.mmd +6 -0
  37. package/examples/styles/vercel-inspired-prototype.style.json +87 -0
  38. package/package.json +70 -43
  39. package/server.json +41 -0
  40. package/skills/agentic-mermaid-diagram-workflow/SKILL.md +17 -36
  41. package/skills/agentic-mermaid-diagram-workflow/references/cli.md +4 -5
  42. package/skills/agentic-mermaid-diagram-workflow/references/code-mode.md +15 -31
  43. package/skills/agentic-mermaid-diagram-workflow/references/sequence.md +10 -14
  44. package/skills/agentic-mermaid-live-editor/SKILL.md +100 -206
  45. package/AGENT_NATIVE.md +0 -602
  46. package/Instructions_for_agents.md +0 -83
  47. package/TODO.md +0 -662
  48. package/assets/hero.png +0 -0
  49. package/dist/index-x2Cj1dVv.d.ts +0 -1089
  50. package/docs/agent-api-cookbook.md +0 -308
  51. package/docs/agent-mutation-policy.md +0 -104
  52. package/docs/agent-workflow-examples.md +0 -46
  53. package/docs/api.md +0 -203
  54. package/docs/ascii.md +0 -103
  55. package/docs/assets/improvements/box-start-connector.png +0 -0
  56. package/docs/assets/improvements/comment-dropped-lint.png +0 -0
  57. package/docs/assets/improvements/er-content-loss.png +0 -0
  58. package/docs/assets/improvements/fan-in-trunks.png +0 -0
  59. package/docs/assets/improvements/gantt-family.png +0 -0
  60. package/docs/assets/improvements/gantt-milestone-clamp.png +0 -0
  61. package/docs/assets/improvements/gantt-verify-seam.png +0 -0
  62. package/docs/assets/improvements/subgraph-container-edges.png +0 -0
  63. package/docs/assets/improvements/wrapper-frontmatter.png +0 -0
  64. package/docs/assets/improvements/wrapper-init-directive.png +0 -0
  65. package/docs/assets/improvements/wrapper-leading-comment.png +0 -0
  66. package/docs/assets/style-cookbook/mid-century-report.png +0 -0
  67. package/docs/assets/style-cookbook/star-chart-atlas.png +0 -0
  68. package/docs/assets/style-cookbook/transit-route-map.png +0 -0
  69. package/docs/comparison.md +0 -94
  70. package/docs/config.md +0 -105
  71. package/docs/contributing/adding-diagram-types.md +0 -144
  72. package/docs/contributing/diagram-family-citizenship.matrix.json +0 -2127
  73. package/docs/contributing/diagram-family-citizenship.md +0 -82
  74. package/docs/contributing/harvesting-upstream-tests.md +0 -126
  75. package/docs/contributing/lessons-learned.md +0 -276
  76. package/docs/contributing/releasing.md +0 -71
  77. package/docs/contributing/visual-review-evidence.md +0 -53
  78. package/docs/custom-style-cookbook.md +0 -154
  79. package/docs/design/families/README.md +0 -26
  80. package/docs/design/families/architecture-beta.md +0 -48
  81. package/docs/design/families/flowchart-parser-conformance.md +0 -22
  82. package/docs/design/families/gantt-research.md +0 -137
  83. package/docs/design/families/gantt.md +0 -329
  84. package/docs/design/families/journey-agentic-cards-before.png +0 -0
  85. package/docs/design/families/journey-mermaid-classic-implementation.png +0 -0
  86. package/docs/design/families/journey-mermaid-classic-prototype.png +0 -0
  87. package/docs/design/families/journey-mermaid-classic-prototype.svg +0 -163
  88. package/docs/design/families/journey-mermaid-classic-prototype.svg.png +0 -0
  89. package/docs/design/families/journey-migration-parity.md +0 -433
  90. package/docs/design/families/journey-usage-research.md +0 -423
  91. package/docs/design/families/journey.md +0 -125
  92. package/docs/design/families/xychart.md +0 -85
  93. package/docs/design/system/README.md +0 -45
  94. package/docs/design/system/abstraction-audit.md +0 -224
  95. package/docs/design/system/abstraction-recommendations.md +0 -655
  96. package/docs/design/system/architecture.mmd +0 -29
  97. package/docs/design/system/architecture.svg +0 -137
  98. package/docs/design/system/layout-guarantees-and-robustness.md +0 -351
  99. package/docs/design/system/layout-rubric.md +0 -138
  100. package/docs/design/system/route-contracts.md +0 -848
  101. package/docs/design/system/source-preservation-ladder.md +0 -52
  102. package/docs/design/system/styles-rollout.md +0 -216
  103. package/docs/design/system/ugly-layouts.md +0 -119
  104. package/docs/diagram-families.md +0 -193
  105. package/docs/features.md +0 -147
  106. package/docs/fork-differences.md +0 -130
  107. package/docs/getting-started.md +0 -175
  108. package/docs/issue-derived-test-cases.md +0 -156
  109. package/docs/layout-characterization/README.md +0 -245
  110. package/docs/layout-characterization/contact-sheet-families.md +0 -496
  111. package/docs/layout-characterization/contact-sheet.md +0 -638
  112. package/docs/layout-characterization/properties.md +0 -281
  113. package/docs/layout-characterization/visual-quality.md +0 -160
  114. package/docs/layout-characterization/visual-snapshots/architecture.svg +0 -79
  115. package/docs/layout-characterization/visual-snapshots/class.svg +0 -60
  116. package/docs/layout-characterization/visual-snapshots/er.svg +0 -61
  117. package/docs/layout-characterization/visual-snapshots/flowchart.svg +0 -58
  118. package/docs/layout-characterization/visual-snapshots/gantt.svg +0 -52
  119. package/docs/layout-characterization/visual-snapshots/journey.svg +0 -118
  120. package/docs/layout-characterization/visual-snapshots/pie.svg +0 -36
  121. package/docs/layout-characterization/visual-snapshots/quadrant.svg +0 -47
  122. package/docs/layout-characterization/visual-snapshots/sequence.svg +0 -59
  123. package/docs/layout-characterization/visual-snapshots/state.svg +0 -52
  124. package/docs/layout-characterization/visual-snapshots/timeline.svg +0 -64
  125. package/docs/layout-characterization/visual-snapshots/xychart.svg +0 -97
  126. package/docs/mcp-code-mode-rationale.md +0 -101
  127. package/docs/mcp-http-transport.md +0 -223
  128. package/docs/mermaid-layout-complaints.md +0 -837
  129. package/docs/mutation-testing.md +0 -206
  130. package/docs/project/divergences.md +0 -98
  131. package/docs/project/dogfooding-docs-strategy.md +0 -66
  132. package/docs/project/hosted-mcp-cloudflare-plan.md +0 -338
  133. package/docs/project/lessons-learned.md +0 -1019
  134. package/docs/project/remove-role-styling-plan.md +0 -176
  135. package/docs/quality.md +0 -212
  136. package/docs/react.md +0 -97
  137. package/docs/style-authoring.md +0 -133
  138. package/docs/testing-strategy.md +0 -335
  139. package/docs/theming.md +0 -162
  140. package/examples/agent-improve-auth-flow.ts +0 -206
  141. package/examples/agent-loop.ts +0 -53
  142. package/examples/mcp-vs-cli-complex-diagrams.ts +0 -133
  143. package/llms.txt +0 -104
  144. package/skill-evals/README.md +0 -77
  145. package/skill-evals/fixtures/architecture-cache/input.mmd +0 -5
  146. package/skill-evals/fixtures/class-payment/input.mmd +0 -4
  147. package/skill-evals/fixtures/er-orders/input.mmd +0 -10
  148. package/skill-evals/fixtures/flowchart-cache/input.mmd +0 -3
  149. package/skill-evals/fixtures/gantt-release/input.mmd +0 -7
  150. package/skill-evals/fixtures/journey-checkout/input.mmd +0 -6
  151. package/skill-evals/fixtures/pie-exports/input.mmd +0 -5
  152. package/skill-evals/fixtures/quadrant-priorities/input.mmd +0 -11
  153. package/skill-evals/fixtures/sequence-retry/input.mmd +0 -8
  154. package/skill-evals/fixtures/state-lifecycle/input.mmd +0 -5
  155. package/skill-evals/fixtures/timeline-release/input.mmd +0 -6
  156. package/skill-evals/fixtures/xychart-growth/input.mmd +0 -5
  157. package/skill-evals/shared-benchmark.json +0 -510
  158. package/src/agent/analyze.ts +0 -157
  159. package/src/agent/apply.ts +0 -146
  160. package/src/agent/architecture-body.ts +0 -458
  161. package/src/agent/certificates.ts +0 -110
  162. package/src/agent/class-body.ts +0 -319
  163. package/src/agent/core.ts +0 -207
  164. package/src/agent/create.ts +0 -106
  165. package/src/agent/describe.ts +0 -364
  166. package/src/agent/er-body.ts +0 -224
  167. package/src/agent/facts.ts +0 -337
  168. package/src/agent/families-builtin.ts +0 -934
  169. package/src/agent/families.ts +0 -232
  170. package/src/agent/family-layouts.ts +0 -826
  171. package/src/agent/flowchart-body.ts +0 -372
  172. package/src/agent/flowchart-unsupported.ts +0 -243
  173. package/src/agent/gantt-body.ts +0 -495
  174. package/src/agent/index.ts +0 -10
  175. package/src/agent/journey-body.ts +0 -414
  176. package/src/agent/label-metrics.ts +0 -28
  177. package/src/agent/layout-to-rendered.ts +0 -63
  178. package/src/agent/mutate.ts +0 -97
  179. package/src/agent/mutation-ops.ts +0 -51
  180. package/src/agent/op-schema.ts +0 -439
  181. package/src/agent/parse.ts +0 -223
  182. package/src/agent/pie-body.ts +0 -270
  183. package/src/agent/png.ts +0 -117
  184. package/src/agent/quadrant-body.ts +0 -336
  185. package/src/agent/quality.ts +0 -363
  186. package/src/agent/readability-audit.ts +0 -92
  187. package/src/agent/rendered-route-audit.ts +0 -61
  188. package/src/agent/sequence-body.ts +0 -345
  189. package/src/agent/serialize.ts +0 -214
  190. package/src/agent/state-body.ts +0 -589
  191. package/src/agent/structural-count.ts +0 -150
  192. package/src/agent/timeline-body.ts +0 -280
  193. package/src/agent/trace-log.ts +0 -43
  194. package/src/agent/types.ts +0 -979
  195. package/src/agent/verify.ts +0 -571
  196. package/src/agent/xychart-body.ts +0 -472
  197. package/src/architecture/config.ts +0 -282
  198. package/src/architecture/layout.ts +0 -496
  199. package/src/architecture/parser.ts +0 -375
  200. package/src/architecture/renderer.ts +0 -611
  201. package/src/architecture/types.ts +0 -113
  202. package/src/ascii/ansi.ts +0 -423
  203. package/src/ascii/architecture.ts +0 -210
  204. package/src/ascii/canvas.ts +0 -443
  205. package/src/ascii/class-diagram.ts +0 -697
  206. package/src/ascii/converter.ts +0 -475
  207. package/src/ascii/draw.ts +0 -1693
  208. package/src/ascii/edge-bundling.ts +0 -328
  209. package/src/ascii/edge-routing.ts +0 -330
  210. package/src/ascii/er-diagram.ts +0 -439
  211. package/src/ascii/gantt.ts +0 -276
  212. package/src/ascii/grid.ts +0 -747
  213. package/src/ascii/index.ts +0 -196
  214. package/src/ascii/journey.ts +0 -189
  215. package/src/ascii/meta.ts +0 -244
  216. package/src/ascii/multiline-utils.ts +0 -80
  217. package/src/ascii/pathfinder.ts +0 -301
  218. package/src/ascii/pie.ts +0 -67
  219. package/src/ascii/quadrant.ts +0 -158
  220. package/src/ascii/reverse.ts +0 -216
  221. package/src/ascii/sequence.ts +0 -499
  222. package/src/ascii/shapes/circle.ts +0 -27
  223. package/src/ascii/shapes/corners.ts +0 -143
  224. package/src/ascii/shapes/diamond.ts +0 -27
  225. package/src/ascii/shapes/hexagon.ts +0 -27
  226. package/src/ascii/shapes/index.ts +0 -106
  227. package/src/ascii/shapes/rectangle.ts +0 -168
  228. package/src/ascii/shapes/rounded.ts +0 -27
  229. package/src/ascii/shapes/special.ts +0 -332
  230. package/src/ascii/shapes/stadium.ts +0 -110
  231. package/src/ascii/shapes/state.ts +0 -192
  232. package/src/ascii/shapes/types.ts +0 -73
  233. package/src/ascii/timeline.ts +0 -128
  234. package/src/ascii/types.ts +0 -312
  235. package/src/ascii/validate.ts +0 -120
  236. package/src/ascii/width.ts +0 -81
  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 -1117
  247. package/src/cli/init-agent.ts +0 -147
  248. package/src/color-resolver.ts +0 -152
  249. package/src/elk-instance.ts +0 -114
  250. package/src/er/layout.ts +0 -187
  251. package/src/er/parser.ts +0 -226
  252. package/src/er/renderer.ts +0 -792
  253. package/src/er/types.ts +0 -99
  254. package/src/font-manifest.ts +0 -27
  255. package/src/gantt/layout.ts +0 -365
  256. package/src/gantt/parser.ts +0 -282
  257. package/src/gantt/pipeline.ts +0 -27
  258. package/src/gantt/renderer.ts +0 -414
  259. package/src/gantt/schedule.ts +0 -513
  260. package/src/gantt/types.ts +0 -255
  261. package/src/index.ts +0 -368
  262. package/src/journey/layout.ts +0 -520
  263. package/src/journey/parser.ts +0 -218
  264. package/src/journey/renderer.ts +0 -811
  265. package/src/journey/types.ts +0 -144
  266. package/src/layout/geometry.ts +0 -182
  267. package/src/layout/pass.ts +0 -142
  268. package/src/layout/passes/index.ts +0 -3916
  269. package/src/layout-engine.ts +0 -1565
  270. package/src/layout-rubric.ts +0 -659
  271. package/src/mcp/artifacts.ts +0 -137
  272. package/src/mcp/dynamic-harness.ts +0 -31
  273. package/src/mcp/dynamic-modules.d.ts +0 -7
  274. package/src/mcp/facade.ts +0 -608
  275. package/src/mcp/harness-runtime.ts +0 -203
  276. package/src/mcp/hosted-server.ts +0 -468
  277. package/src/mcp/mcp-bin.ts +0 -3
  278. package/src/mcp/mcp-cli.ts +0 -82
  279. package/src/mcp/protocol.ts +0 -13
  280. package/src/mcp/sandbox.ts +0 -195
  281. package/src/mcp/sdk-decl.ts +0 -387
  282. package/src/mcp/server.ts +0 -362
  283. package/src/mcp/tool-surface.ts +0 -146
  284. package/src/mermaid-source.ts +0 -655
  285. package/src/multiline-utils.ts +0 -228
  286. package/src/parser.ts +0 -1031
  287. package/src/pie/layout.ts +0 -168
  288. package/src/pie/parser.ts +0 -136
  289. package/src/pie/renderer.ts +0 -234
  290. package/src/pie/types.ts +0 -82
  291. package/src/quadrant/layout.ts +0 -191
  292. package/src/quadrant/parser.ts +0 -183
  293. package/src/quadrant/renderer.ts +0 -322
  294. package/src/quadrant/types.ts +0 -113
  295. package/src/render-family-hooks.ts +0 -244
  296. package/src/renderer.ts +0 -1099
  297. package/src/route-contracts.ts +0 -2723
  298. package/src/scene/backend.ts +0 -76
  299. package/src/scene/fidelity.ts +0 -183
  300. package/src/scene/hybrid-backend.ts +0 -174
  301. package/src/scene/ir.ts +0 -181
  302. package/src/scene/marks.ts +0 -127
  303. package/src/scene/rough-backend.ts +0 -378
  304. package/src/scene/seed.ts +0 -46
  305. package/src/scene/style-registry.ts +0 -556
  306. package/src/sequence/layout.ts +0 -456
  307. package/src/sequence/parser.ts +0 -255
  308. package/src/sequence/renderer.ts +0 -604
  309. package/src/sequence/types.ts +0 -154
  310. package/src/shape-clipping.ts +0 -351
  311. package/src/shared/accessibility-directives.ts +0 -22
  312. package/src/shared/batched.ts +0 -61
  313. package/src/shared/color-math.ts +0 -72
  314. package/src/shared/svg-a11y.ts +0 -29
  315. package/src/shared/syntax-error.ts +0 -17
  316. package/src/shared/unicode-ranges.ts +0 -135
  317. package/src/styles.ts +0 -318
  318. package/src/svg-paths.ts +0 -28
  319. package/src/text-metrics.ts +0 -248
  320. package/src/theme.ts +0 -639
  321. package/src/timeline/layout.ts +0 -381
  322. package/src/timeline/parser.ts +0 -215
  323. package/src/timeline/renderer.ts +0 -538
  324. package/src/timeline/types.ts +0 -105
  325. package/src/types.ts +0 -454
  326. package/src/website-worker-modules.d.ts +0 -18
  327. package/src/xychart/axis-utils.ts +0 -109
  328. package/src/xychart/colors.ts +0 -124
  329. package/src/xychart/config.ts +0 -88
  330. package/src/xychart/layout.ts +0 -656
  331. package/src/xychart/parser.ts +0 -504
  332. package/src/xychart/renderer.ts +0 -640
  333. package/src/xychart/types.ts +0 -282
@@ -1,27 +0,0 @@
1
- // ============================================================================
2
- // Diamond shape renderer — uses corner decorators instead of diagonals
3
- // ============================================================================
4
-
5
- import type { ShapeRenderer } from './types.ts'
6
- import { getBoxDimensions, renderBox, getBoxAttachmentPoint } from './rectangle.ts'
7
- import { getCorners } from './corners.ts'
8
-
9
- /**
10
- * Diamond shape renderer.
11
- * Uses diamond markers (◇) at corners to indicate decision node semantics.
12
- *
13
- * Renders as:
14
- * ◇─────────◇
15
- * │ Label │
16
- * ◇─────────◇
17
- */
18
- export const diamondRenderer: ShapeRenderer = {
19
- getDimensions: getBoxDimensions,
20
-
21
- render(label, dimensions, options) {
22
- const corners = getCorners('diamond', options.useAscii)
23
- return renderBox(label, dimensions, corners, options.useAscii)
24
- },
25
-
26
- getAttachmentPoint: getBoxAttachmentPoint,
27
- }
@@ -1,27 +0,0 @@
1
- // ============================================================================
2
- // Hexagon shape renderer — uses corner decorators instead of diagonals
3
- // ============================================================================
4
-
5
- import type { ShapeRenderer } from './types.ts'
6
- import { getBoxDimensions, renderBox, getBoxAttachmentPoint } from './rectangle.ts'
7
- import { getCorners } from './corners.ts'
8
-
9
- /**
10
- * Hexagon shape renderer.
11
- * Uses hexagon markers (⬡) at corners to indicate process node semantics.
12
- *
13
- * Renders as:
14
- * ⬡─────────⬡
15
- * │ Label │
16
- * ⬡─────────⬡
17
- */
18
- export const hexagonRenderer: ShapeRenderer = {
19
- getDimensions: getBoxDimensions,
20
-
21
- render(label, dimensions, options) {
22
- const corners = getCorners('hexagon', options.useAscii)
23
- return renderBox(label, dimensions, corners, options.useAscii)
24
- },
25
-
26
- getAttachmentPoint: getBoxAttachmentPoint,
27
- }
@@ -1,106 +0,0 @@
1
- // ============================================================================
2
- // Shape registry — pluggable ASCII shape renderers
3
- // ============================================================================
4
-
5
- import type { AsciiNodeShape, Canvas, DrawingCoord, Direction } from '../types.ts'
6
- import type { ShapeRenderer, ShapeDimensions, ShapeRenderOptions, ShapeRegistry } from './types.ts'
7
-
8
- // Import all shape renderers
9
- import { rectangleRenderer } from './rectangle.ts'
10
- import { diamondRenderer } from './diamond.ts'
11
- import { circleRenderer } from './circle.ts'
12
- import { stateStartRenderer, stateEndRenderer } from './state.ts'
13
- import { roundedRenderer } from './rounded.ts'
14
- import { stadiumRenderer } from './stadium.ts'
15
- import { hexagonRenderer } from './hexagon.ts'
16
- import {
17
- subroutineRenderer,
18
- doublecircleRenderer,
19
- cylinderRenderer,
20
- asymmetricRenderer,
21
- trapezoidRenderer,
22
- trapezoidAltRenderer,
23
- leanRRenderer,
24
- leanLRenderer,
25
- } from './special.ts'
26
-
27
- // Re-export types
28
- export type { ShapeRenderer, ShapeDimensions, ShapeRenderOptions, ShapeRegistry }
29
-
30
- /**
31
- * Global shape registry — maps shape types to their renderers.
32
- * Rectangle is the default fallback for unregistered shapes.
33
- */
34
- export const shapeRegistry: ShapeRegistry = new Map<AsciiNodeShape, ShapeRenderer>([
35
- // Core shapes
36
- ['rectangle', rectangleRenderer],
37
- ['service', rectangleRenderer],
38
- ['rounded', roundedRenderer],
39
- ['diamond', diamondRenderer],
40
- ['stadium', stadiumRenderer],
41
- ['circle', circleRenderer],
42
-
43
- // Batch 1 additions
44
- ['subroutine', subroutineRenderer],
45
- ['doublecircle', doublecircleRenderer],
46
- ['hexagon', hexagonRenderer],
47
-
48
- // Batch 2 additions
49
- ['cylinder', cylinderRenderer],
50
- ['asymmetric', asymmetricRenderer],
51
- ['trapezoid', trapezoidRenderer],
52
- ['trapezoid-alt', trapezoidAltRenderer],
53
- ['lean-r', leanRRenderer],
54
- ['lean-l', leanLRenderer],
55
-
56
- // State diagram pseudo-states
57
- ['state-start', stateStartRenderer],
58
- ['state-end', stateEndRenderer],
59
- ])
60
-
61
- /**
62
- * Get the renderer for a shape type, falling back to rectangle.
63
- */
64
- export function getShapeRenderer(shape: AsciiNodeShape): ShapeRenderer {
65
- return shapeRegistry.get(shape) ?? rectangleRenderer
66
- }
67
-
68
- /**
69
- * Render a node shape to a canvas.
70
- * This is the main entry point for shape rendering.
71
- */
72
- export function renderShape(
73
- shape: AsciiNodeShape,
74
- label: string,
75
- options: ShapeRenderOptions
76
- ): Canvas {
77
- const renderer = getShapeRenderer(shape)
78
- const dimensions = renderer.getDimensions(label, options)
79
- return renderer.render(label, dimensions, options)
80
- }
81
-
82
- /**
83
- * Get dimensions for a shape given a label.
84
- * Used during layout to determine node size.
85
- */
86
- export function getShapeDimensions(
87
- shape: AsciiNodeShape,
88
- label: string,
89
- options: ShapeRenderOptions
90
- ): ShapeDimensions {
91
- const renderer = getShapeRenderer(shape)
92
- return renderer.getDimensions(label, options)
93
- }
94
-
95
- /**
96
- * Get edge attachment point for a shape.
97
- */
98
- export function getShapeAttachmentPoint(
99
- shape: AsciiNodeShape,
100
- dir: Direction,
101
- dimensions: ShapeDimensions,
102
- baseCoord: DrawingCoord
103
- ): DrawingCoord {
104
- const renderer = getShapeRenderer(shape)
105
- return renderer.getAttachmentPoint(dir, dimensions, baseCoord)
106
- }
@@ -1,168 +0,0 @@
1
- // ============================================================================
2
- // Rectangle shape renderer — standard box with corners
3
- // ============================================================================
4
- //
5
- // This module provides the base box rendering used by all rectangular shapes.
6
- // The renderBox() function accepts custom corner characters, allowing different
7
- // shapes to reuse the same rendering logic with different visual markers.
8
-
9
- import type { Canvas, DrawingCoord, Direction } from '../types.ts'
10
- import { Up, Down, Left, Right, UpperLeft, UpperRight, LowerLeft, LowerRight, Middle } from '../types.ts'
11
- import { drawText, mkCanvas } from '../canvas.ts'
12
- import { splitLines } from '../multiline-utils.ts'
13
- import { visualWidth } from '../width.ts'
14
- import type { ShapeRenderer, ShapeDimensions, ShapeRenderOptions } from './types.ts'
15
- import { dirEquals } from '../edge-routing.ts'
16
- import { type CornerChars, getCorners } from './corners.ts'
17
-
18
- // ============================================================================
19
- // Shared dimension calculation
20
- // ============================================================================
21
-
22
- /**
23
- * Calculate standard box dimensions for any rectangular shape.
24
- * Used by rectangle, circle, diamond, hexagon, etc.
25
- */
26
- export function getBoxDimensions(label: string, options: ShapeRenderOptions): ShapeDimensions {
27
- const lines = splitLines(label)
28
- const maxLineWidth = Math.max(...lines.map(l => visualWidth(l)), 0)
29
- const lineCount = lines.length
30
-
31
- // Width: 2*padding + maxLineWidth + 2 border chars
32
- const innerWidth = 2 * options.padding + maxLineWidth
33
- const width = innerWidth + 2
34
-
35
- // Height: lineCount + 2*padding + 2 border chars
36
- // Ensure innerHeight is odd for symmetric vertical centering
37
- const rawInnerHeight = lineCount + 2 * options.padding
38
- const innerHeight = rawInnerHeight % 2 === 0 ? rawInnerHeight + 1 : rawInnerHeight
39
- const height = innerHeight + 2
40
-
41
- return {
42
- width,
43
- height,
44
- labelArea: {
45
- x: 1 + options.padding,
46
- y: 1 + options.padding,
47
- width: maxLineWidth,
48
- height: lineCount,
49
- },
50
- // Grid layout: [border=1, content, border=1]
51
- gridColumns: [1, innerWidth, 1],
52
- gridRows: [1, innerHeight, 1],
53
- }
54
- }
55
-
56
- // ============================================================================
57
- // Shared box rendering
58
- // ============================================================================
59
-
60
- /**
61
- * Render a box with custom corner characters.
62
- * This is the core rendering function used by all rectangular shapes.
63
- *
64
- * @param label - Text to display in the box
65
- * @param dimensions - Pre-calculated dimensions
66
- * @param corners - Corner characters (tl, tr, bl, br)
67
- * @param useAscii - Whether to use ASCII or Unicode for lines
68
- */
69
- export function renderBox(
70
- label: string,
71
- dimensions: ShapeDimensions,
72
- corners: CornerChars,
73
- useAscii: boolean
74
- ): Canvas {
75
- const { width, height } = dimensions
76
- const canvas = mkCanvas(width - 1, height - 1)
77
-
78
- const from = { x: 0, y: 0 }
79
- const to = { x: width - 1, y: height - 1 }
80
-
81
- // Line characters
82
- const hLine = useAscii ? '-' : '─'
83
- const vLine = useAscii ? '|' : '│'
84
-
85
- // Draw horizontal lines (top and bottom)
86
- for (let x = from.x + 1; x < to.x; x++) {
87
- canvas[x]![from.y] = hLine
88
- canvas[x]![to.y] = hLine
89
- }
90
-
91
- // Draw vertical lines (left and right)
92
- for (let y = from.y + 1; y < to.y; y++) {
93
- canvas[from.x]![y] = vLine
94
- canvas[to.x]![y] = vLine
95
- }
96
-
97
- // Draw corners
98
- canvas[from.x]![from.y] = corners.tl
99
- canvas[to.x]![from.y] = corners.tr
100
- canvas[from.x]![to.y] = corners.bl
101
- canvas[to.x]![to.y] = corners.br
102
-
103
- // Center the multi-line label
104
- const lines = splitLines(label)
105
- const w = width - 1 // Match original grid-based width calculation
106
- const h = height - 1
107
- const centerY = Math.floor(h / 2)
108
- const startY = centerY - Math.floor((lines.length - 1) / 2)
109
-
110
- for (let i = 0; i < lines.length; i++) {
111
- const line = lines[i]!
112
- const textX = Math.floor(w / 2) - Math.ceil(visualWidth(line) / 2) + 1
113
- drawText(canvas, { x: textX, y: startY + i }, line, true)
114
- }
115
-
116
- return canvas
117
- }
118
-
119
- // ============================================================================
120
- // Shared attachment point calculation
121
- // ============================================================================
122
-
123
- /**
124
- * Calculate edge attachment point for rectangular shapes.
125
- * All box-based shapes use the same attachment logic.
126
- */
127
- export function getBoxAttachmentPoint(
128
- dir: Direction,
129
- dimensions: ShapeDimensions,
130
- baseCoord: DrawingCoord
131
- ): DrawingCoord {
132
- const { width, height } = dimensions
133
- const centerX = baseCoord.x + Math.floor(width / 2)
134
- const centerY = baseCoord.y + Math.floor(height / 2)
135
-
136
- if (dirEquals(dir, Up)) return { x: centerX, y: baseCoord.y }
137
- if (dirEquals(dir, Down)) return { x: centerX, y: baseCoord.y + height - 1 }
138
- if (dirEquals(dir, Left)) return { x: baseCoord.x, y: centerY }
139
- if (dirEquals(dir, Right)) return { x: baseCoord.x + width - 1, y: centerY }
140
- if (dirEquals(dir, UpperLeft)) return { x: baseCoord.x, y: baseCoord.y }
141
- if (dirEquals(dir, UpperRight)) return { x: baseCoord.x + width - 1, y: baseCoord.y }
142
- if (dirEquals(dir, LowerLeft)) return { x: baseCoord.x, y: baseCoord.y + height - 1 }
143
- if (dirEquals(dir, LowerRight)) return { x: baseCoord.x + width - 1, y: baseCoord.y + height - 1 }
144
- // Middle
145
- return { x: centerX, y: centerY }
146
- }
147
-
148
- // ============================================================================
149
- // Rectangle renderer
150
- // ============================================================================
151
-
152
- /**
153
- * Rectangle shape renderer — the default box shape.
154
- * Renders as:
155
- * ┌─────────┐
156
- * │ Label │
157
- * └─────────┘
158
- */
159
- export const rectangleRenderer: ShapeRenderer = {
160
- getDimensions: getBoxDimensions,
161
-
162
- render(label: string, dimensions: ShapeDimensions, options: ShapeRenderOptions): Canvas {
163
- const corners = getCorners('rectangle', options.useAscii)
164
- return renderBox(label, dimensions, corners, options.useAscii)
165
- },
166
-
167
- getAttachmentPoint: getBoxAttachmentPoint,
168
- }
@@ -1,27 +0,0 @@
1
- // ============================================================================
2
- // Rounded rectangle shape renderer — uses rounded corner decorators
3
- // ============================================================================
4
-
5
- import type { ShapeRenderer } from './types.ts'
6
- import { getBoxDimensions, renderBox, getBoxAttachmentPoint } from './rectangle.ts'
7
- import { getCorners } from './corners.ts'
8
-
9
- /**
10
- * Rounded rectangle shape renderer.
11
- * Uses rounded corner markers (╭╮╰╯) to indicate soft edges.
12
- *
13
- * Renders as:
14
- * ╭─────────╮
15
- * │ Label │
16
- * ╰─────────╯
17
- */
18
- export const roundedRenderer: ShapeRenderer = {
19
- getDimensions: getBoxDimensions,
20
-
21
- render(label, dimensions, options) {
22
- const corners = getCorners('rounded', options.useAscii)
23
- return renderBox(label, dimensions, corners, options.useAscii)
24
- },
25
-
26
- getAttachmentPoint: getBoxAttachmentPoint,
27
- }
@@ -1,332 +0,0 @@
1
- // ============================================================================
2
- // Special shape renderers — subroutine, doublecircle, cylinder, etc.
3
- // ============================================================================
4
- //
5
- // Some shapes have unique internal structure (subroutine, cylinder) and keep
6
- // custom rendering. Others use the corner decorator pattern for simplicity.
7
-
8
- import type { Canvas, DrawingCoord, Direction } from '../types.ts'
9
- import { Up, Down, Left, Right } from '../types.ts'
10
- import { drawText, mkCanvas } from '../canvas.ts'
11
- import { splitLines } from '../multiline-utils.ts'
12
- import { visualWidth } from '../width.ts'
13
- import type { ShapeRenderer, ShapeDimensions, ShapeRenderOptions } from './types.ts'
14
- import { dirEquals } from '../edge-routing.ts'
15
- import { getBoxDimensions, renderBox, getBoxAttachmentPoint } from './rectangle.ts'
16
- import { getCorners } from './corners.ts'
17
-
18
- // ============================================================================
19
- // Subroutine — keeps custom double-border rendering
20
- // ============================================================================
21
-
22
- /**
23
- * Subroutine shape renderer — double-bordered rectangle.
24
- * Renders as:
25
- * ┌┬─────────┬┐
26
- * ││ Label ││
27
- * └┴─────────┴┘
28
- */
29
- export const subroutineRenderer: ShapeRenderer = {
30
- getDimensions(label: string, options: ShapeRenderOptions): ShapeDimensions {
31
- const lines = splitLines(label)
32
- const maxLineWidth = Math.max(...lines.map(l => visualWidth(l)), 0)
33
- const lineCount = lines.length
34
-
35
- const innerWidth = 2 * options.padding + maxLineWidth
36
- const width = innerWidth + 4 // Double borders on each side
37
- const innerHeight = lineCount + 2 * options.padding
38
- const height = innerHeight + 2
39
-
40
- return {
41
- width,
42
- height,
43
- labelArea: {
44
- x: 2 + options.padding,
45
- y: 1 + options.padding,
46
- width: maxLineWidth,
47
- height: lineCount,
48
- },
49
- gridColumns: [2, innerWidth, 2],
50
- gridRows: [1, innerHeight, 1],
51
- }
52
- },
53
-
54
- render(label: string, dimensions: ShapeDimensions, options: ShapeRenderOptions): Canvas {
55
- const { width, height } = dimensions
56
- const canvas = mkCanvas(width - 1, height - 1)
57
-
58
- const hChar = options.useAscii ? '-' : '─'
59
- const vChar = options.useAscii ? '|' : '│'
60
-
61
- // Top border
62
- canvas[0]![0] = options.useAscii ? '+' : '┌'
63
- canvas[1]![0] = options.useAscii ? '+' : '┬'
64
- for (let x = 2; x < width - 2; x++) canvas[x]![0] = hChar
65
- canvas[width - 2]![0] = options.useAscii ? '+' : '┬'
66
- canvas[width - 1]![0] = options.useAscii ? '+' : '┐'
67
-
68
- // Sides with double border
69
- for (let y = 1; y < height - 1; y++) {
70
- canvas[0]![y] = vChar
71
- canvas[1]![y] = vChar
72
- canvas[width - 2]![y] = vChar
73
- canvas[width - 1]![y] = vChar
74
- }
75
-
76
- // Bottom border
77
- canvas[0]![height - 1] = options.useAscii ? '+' : '└'
78
- canvas[1]![height - 1] = options.useAscii ? '+' : '┴'
79
- for (let x = 2; x < width - 2; x++) canvas[x]![height - 1] = hChar
80
- canvas[width - 2]![height - 1] = options.useAscii ? '+' : '┴'
81
- canvas[width - 1]![height - 1] = options.useAscii ? '+' : '┘'
82
-
83
- // Center the label
84
- const lines = splitLines(label)
85
- const centerY = Math.floor(height / 2)
86
- const startY = centerY - Math.floor((lines.length - 1) / 2)
87
-
88
- for (let i = 0; i < lines.length; i++) {
89
- const line = lines[i]!
90
- const textX = Math.floor(width / 2) - Math.floor(visualWidth(line) / 2)
91
- const y = startY + i
92
- if (textX > 1 && y > 0 && y < height - 1) {
93
- drawText(canvas, { x: textX, y }, line, true)
94
- }
95
- }
96
-
97
- return canvas
98
- },
99
-
100
- getAttachmentPoint: getBoxAttachmentPoint,
101
- }
102
-
103
- // ============================================================================
104
- // Double circle — uses corner decorators
105
- // ============================================================================
106
-
107
- /**
108
- * Double circle shape renderer.
109
- * Uses double circle markers (◎) at corners.
110
- *
111
- * Renders as:
112
- * ◎─────────◎
113
- * │ Label │
114
- * ◎─────────◎
115
- */
116
- export const doublecircleRenderer: ShapeRenderer = {
117
- getDimensions: getBoxDimensions,
118
-
119
- render(label, dimensions, options) {
120
- const corners = getCorners('doublecircle', options.useAscii)
121
- return renderBox(label, dimensions, corners, options.useAscii)
122
- },
123
-
124
- getAttachmentPoint: getBoxAttachmentPoint,
125
- }
126
-
127
- // ============================================================================
128
- // Cylinder — keeps custom rendering for database appearance
129
- // ============================================================================
130
-
131
- /**
132
- * Cylinder shape renderer — database symbol.
133
- * Renders as:
134
- * ╭─────╮
135
- * │─────│
136
- * │ DB │
137
- * │─────│
138
- * ╰─────╯
139
- */
140
- export const cylinderRenderer: ShapeRenderer = {
141
- getDimensions(label: string, options: ShapeRenderOptions): ShapeDimensions {
142
- const lines = splitLines(label)
143
- const maxLineWidth = Math.max(...lines.map(l => visualWidth(l)), 0)
144
- const lineCount = lines.length
145
-
146
- const innerWidth = 2 * options.padding + maxLineWidth
147
- const width = innerWidth + 2
148
- const innerHeight = lineCount + 2 * options.padding + 2 // Extra for curved top/bottom
149
- const height = innerHeight + 2
150
-
151
- return {
152
- width,
153
- height,
154
- labelArea: {
155
- x: 1 + options.padding,
156
- y: 2 + options.padding,
157
- width: maxLineWidth,
158
- height: lineCount,
159
- },
160
- gridColumns: [1, innerWidth, 1],
161
- gridRows: [2, innerHeight - 2, 2],
162
- }
163
- },
164
-
165
- render(label: string, dimensions: ShapeDimensions, options: ShapeRenderOptions): Canvas {
166
- const { width, height } = dimensions
167
- const canvas = mkCanvas(width - 1, height - 1)
168
-
169
- const hChar = options.useAscii ? '-' : '─'
170
- const vChar = options.useAscii ? '|' : '│'
171
-
172
- // Top ellipse
173
- canvas[0]![0] = options.useAscii ? '.' : '╭'
174
- for (let x = 1; x < width - 1; x++) canvas[x]![0] = hChar
175
- canvas[width - 1]![0] = options.useAscii ? '.' : '╮'
176
-
177
- // Second row - bottom of top ellipse
178
- canvas[0]![1] = vChar
179
- for (let x = 1; x < width - 1; x++) canvas[x]![1] = hChar
180
- canvas[width - 1]![1] = vChar
181
-
182
- // Middle section
183
- for (let y = 2; y < height - 2; y++) {
184
- canvas[0]![y] = vChar
185
- canvas[width - 1]![y] = vChar
186
- }
187
-
188
- // Second to last row - top of bottom ellipse
189
- canvas[0]![height - 2] = vChar
190
- for (let x = 1; x < width - 1; x++) canvas[x]![height - 2] = hChar
191
- canvas[width - 1]![height - 2] = vChar
192
-
193
- // Bottom ellipse
194
- canvas[0]![height - 1] = options.useAscii ? '\'' : '╰'
195
- for (let x = 1; x < width - 1; x++) canvas[x]![height - 1] = hChar
196
- canvas[width - 1]![height - 1] = options.useAscii ? '\'' : '╯'
197
-
198
- // Center the label
199
- const lines = splitLines(label)
200
- const centerY = Math.floor(height / 2)
201
- const startY = centerY - Math.floor((lines.length - 1) / 2)
202
-
203
- for (let i = 0; i < lines.length; i++) {
204
- const line = lines[i]!
205
- const textX = Math.floor(width / 2) - Math.floor(visualWidth(line) / 2)
206
- const y = startY + i
207
- if (textX > 0 && y > 1 && y < height - 2) {
208
- drawText(canvas, { x: textX, y }, line, true)
209
- }
210
- }
211
-
212
- return canvas
213
- },
214
-
215
- getAttachmentPoint: getBoxAttachmentPoint,
216
- }
217
-
218
- // ============================================================================
219
- // Asymmetric (flag) — uses corner decorators
220
- // ============================================================================
221
-
222
- /**
223
- * Asymmetric (flag/banner) shape renderer.
224
- * Uses arrow markers (▷) on left corners.
225
- *
226
- * Renders as:
227
- * ▷─────────┐
228
- * │ Label │
229
- * ▷─────────┘
230
- */
231
- export const asymmetricRenderer: ShapeRenderer = {
232
- getDimensions: getBoxDimensions,
233
-
234
- render(label, dimensions, options) {
235
- const corners = getCorners('asymmetric', options.useAscii)
236
- return renderBox(label, dimensions, corners, options.useAscii)
237
- },
238
-
239
- getAttachmentPoint: getBoxAttachmentPoint,
240
- }
241
-
242
- // ============================================================================
243
- // Trapezoid — uses corner decorators instead of diagonal sides
244
- // ============================================================================
245
-
246
- /**
247
- * Trapezoid shape renderer — wider at bottom.
248
- * Uses slope markers (◸◹) on top corners.
249
- *
250
- * Renders as:
251
- * ◸─────────◹
252
- * │ Label │
253
- * └─────────┘
254
- */
255
- export const trapezoidRenderer: ShapeRenderer = {
256
- getDimensions: getBoxDimensions,
257
-
258
- render(label, dimensions, options) {
259
- const corners = getCorners('trapezoid', options.useAscii)
260
- return renderBox(label, dimensions, corners, options.useAscii)
261
- },
262
-
263
- getAttachmentPoint: getBoxAttachmentPoint,
264
- }
265
-
266
- // ============================================================================
267
- // Trapezoid-alt — uses corner decorators instead of diagonal sides
268
- // ============================================================================
269
-
270
- /**
271
- * Trapezoid-alt shape renderer — wider at top.
272
- * Uses slope markers (◺◿) on bottom corners.
273
- *
274
- * Renders as:
275
- * ┌─────────┐
276
- * │ Label │
277
- * ◺─────────◿
278
- */
279
- export const trapezoidAltRenderer: ShapeRenderer = {
280
- getDimensions: getBoxDimensions,
281
-
282
- render(label, dimensions, options) {
283
- const corners = getCorners('trapezoid-alt', options.useAscii)
284
- return renderBox(label, dimensions, corners, options.useAscii)
285
- },
286
-
287
- getAttachmentPoint: getBoxAttachmentPoint,
288
- }
289
-
290
- // ============================================================================
291
- // Parallelograms — use corner decorators instead of diagonal sides
292
- // ============================================================================
293
-
294
- /**
295
- * Lean-right parallelogram shape renderer — the flowchart I/O symbol.
296
- * Uses '/' markers on the slanted corners.
297
- *
298
- * Renders as:
299
- * /─────────/
300
- * │ Label │
301
- * /─────────/
302
- */
303
- export const leanRRenderer: ShapeRenderer = {
304
- getDimensions: getBoxDimensions,
305
-
306
- render(label, dimensions, options) {
307
- const corners = getCorners('lean-r', options.useAscii)
308
- return renderBox(label, dimensions, corners, options.useAscii)
309
- },
310
-
311
- getAttachmentPoint: getBoxAttachmentPoint,
312
- }
313
-
314
- /**
315
- * Lean-left parallelogram shape renderer.
316
- * Uses '\' markers on the slanted corners.
317
- *
318
- * Renders as:
319
- * \─────────\
320
- * │ Label │
321
- * \─────────\
322
- */
323
- export const leanLRenderer: ShapeRenderer = {
324
- getDimensions: getBoxDimensions,
325
-
326
- render(label, dimensions, options) {
327
- const corners = getCorners('lean-l', options.useAscii)
328
- return renderBox(label, dimensions, corners, options.useAscii)
329
- },
330
-
331
- getAttachmentPoint: getBoxAttachmentPoint,
332
- }