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,17 +0,0 @@
1
- // A prescriptive syntax error: say WHAT is wrong AND how to fix it — the
2
- // expected form plus a copyable example (and, when known, the valid identifiers
3
- // in scope) — so a caller, especially a smaller model driving the hosted MCP,
4
- // can correct from the message alone instead of trial-and-error. The render-path
5
- // parsers throw plain Errors that `verifyMermaid` flattens into the RENDER_FAILED
6
- // warning's `reason` string, so the prescriptive text rides straight through to
7
- // the agent. Message shape mirrors the architecture edge errors:
8
- // `<what> — expected <expectedForm>, e.g. <example>[ (known: a, b, c)]`
9
- export function syntaxError(detail: {
10
- what: string
11
- expectedForm: string
12
- example: string
13
- known?: readonly string[]
14
- }): Error {
15
- const known = detail.known && detail.known.length > 0 ? ` (known: ${detail.known.join(', ')})` : ''
16
- return new Error(`${detail.what} — expected ${detail.expectedForm}, e.g. ${detail.example}${known}`)
17
- }
@@ -1,135 +0,0 @@
1
- // ============================================================================
2
- // Shared Unicode range tables.
3
- //
4
- // Both the ASCII renderer (src/ascii/width.ts) and the SVG text-metrics
5
- // module (src/text-metrics.ts) need to know which codepoints are wide
6
- // (CJK), which are emoji, and which are zero-width (combining marks,
7
- // ZWJ, variation selectors). Cross-importing between ascii/ and core
8
- // would violate the substrate lint (ascii should not pull core; core
9
- // should not pull ascii). This neutral module is the shared substrate.
10
- //
11
- // Conventions:
12
- // - Ranges are inclusive [start, end] pairs of codepoints.
13
- // - Helpers operate on codepoint integers, not string chars, so callers
14
- // can iterate via `for ... of` (which yields codepoints, not UTF-16
15
- // code units) and pass the result of `String.prototype.codePointAt`.
16
- // ============================================================================
17
-
18
- export type CodepointRange = readonly [number, number]
19
-
20
- // ----------------------------------------------------------------------------
21
- // CJK + Hangul ranges — fullwidth in terminals and 2x width in proportional
22
- // fonts. Sourced from Unicode East Asian Width Wide/Fullwidth ranges plus
23
- // CJK Unified Ideographs and related supplements.
24
- // ----------------------------------------------------------------------------
25
- export const CJK_RANGES: readonly CodepointRange[] = [
26
- [0x2e80, 0x2eff], // CJK Radicals Supplement
27
- [0x2f00, 0x2fdf], // Kangxi Radicals
28
- [0x3000, 0x303f], // CJK Symbols and Punctuation
29
- [0x3040, 0x309f], // Hiragana
30
- [0x30a0, 0x30ff], // Katakana
31
- [0x3100, 0x312f], // Bopomofo
32
- [0x3190, 0x31ff], // Kanbun + extensions
33
- [0x3200, 0x33ff], // Enclosed CJK + Compatibility
34
- [0x3400, 0x4dbf], // CJK Extension A
35
- [0x4e00, 0x9fff], // CJK Unified Ideographs
36
- [0xf900, 0xfaff], // CJK Compatibility Ideographs
37
- [0x20000, 0x2ffff], // CJK Extension B and beyond
38
- ]
39
-
40
- // ----------------------------------------------------------------------------
41
- // Hangul ranges — Korean syllabic block. Separate from CJK_RANGES so callers
42
- // can distinguish Korean from Han characters when needed (e.g., font shaping).
43
- // ----------------------------------------------------------------------------
44
- export const HANGUL_RANGES: readonly CodepointRange[] = [
45
- [0x1100, 0x115f], // Hangul Jamo (leading)
46
- [0x3130, 0x318f], // Hangul Compatibility Jamo
47
- [0xac00, 0xd7af], // Hangul Syllables
48
- ]
49
-
50
- // ----------------------------------------------------------------------------
51
- // Fullwidth ASCII and symbol ranges — the U+FF00 block plus angle brackets
52
- // and a few other "halfwidth-and-fullwidth forms" that render as 2 cells.
53
- // ----------------------------------------------------------------------------
54
- export const FULLWIDTH_RANGES: readonly CodepointRange[] = [
55
- [0x2329, 0x232a], // Angle brackets
56
- [0xfe10, 0xfe19], // Vertical forms
57
- [0xfe30, 0xfe6f], // CJK Compatibility Forms + Small Form Variants
58
- [0xff00, 0xff60], // Fullwidth ASCII
59
- [0xffe0, 0xffe6], // Fullwidth symbols
60
- ]
61
-
62
- // ----------------------------------------------------------------------------
63
- // Emoji presentation ranges — the SMP planes where emoji live by default.
64
- // The Unicode regex `\p{Emoji_Presentation}|\p{Extended_Pictographic}` is a
65
- // more precise check for individual characters; these ranges are useful for
66
- // fast codepoint-integer checks and for callers that cannot afford a regex.
67
- // ----------------------------------------------------------------------------
68
- export const EMOJI_RANGES: readonly CodepointRange[] = [
69
- [0x1f300, 0x1faff], // Misc Symbols & Pictographs through Symbols & Pictographs Extended-A
70
- ]
71
-
72
- // ----------------------------------------------------------------------------
73
- // Combining-mark and zero-width ranges. Iterating codepoints and treating
74
- // these as width 0 keeps display-width math correct for accented Latin and
75
- // Devanagari/Arabic shaping marks.
76
- // ----------------------------------------------------------------------------
77
- export const COMBINING_RANGES: readonly CodepointRange[] = [
78
- [0x0300, 0x036f], // Combining Diacritical Marks
79
- [0x1ab0, 0x1aff], // Combining Diacritical Marks Extended
80
- [0x1dc0, 0x1dff], // Combining Diacritical Marks Supplement
81
- [0x20d0, 0x20ff], // Combining Diacritical Marks for Symbols
82
- [0xfe20, 0xfe2f], // Combining Half Marks
83
- ]
84
-
85
- // ----------------------------------------------------------------------------
86
- // Special zero-width codepoints. Separate from COMBINING_RANGES because they
87
- // have semantic meaning beyond "no advance":
88
- // - U+200B ZERO WIDTH SPACE
89
- // - U+200C ZERO WIDTH NON-JOINER
90
- // - U+200D ZERO WIDTH JOINER (binds emoji into sequences)
91
- // - U+FEFF ZERO WIDTH NO-BREAK SPACE / BOM
92
- // ----------------------------------------------------------------------------
93
- export const ZERO_WIDTH_CODEPOINTS: ReadonlySet<number> = new Set([
94
- 0x200b, 0x200c, 0x200d, 0xfeff,
95
- ])
96
-
97
- // ----------------------------------------------------------------------------
98
- // Variation selectors — modify the preceding base codepoint:
99
- // - U+FE0E Text-presentation selector (force width 1)
100
- // - U+FE0F Emoji-presentation selector (force width 2)
101
- // ----------------------------------------------------------------------------
102
- export const VS_TEXT = 0xfe0e
103
- export const VS_EMOJI = 0xfe0f
104
- export const ZWJ = 0x200d
105
-
106
- // ----------------------------------------------------------------------------
107
- // Range-membership helpers.
108
- // ----------------------------------------------------------------------------
109
-
110
- function inRanges(cp: number, ranges: readonly CodepointRange[]): boolean {
111
- for (const [lo, hi] of ranges) if (cp >= lo && cp <= hi) return true
112
- return false
113
- }
114
-
115
- /**
116
- * Is the codepoint wide (CJK / Hangul / Fullwidth / Emoji)?
117
- *
118
- * Note: emoji ZWJ sequences and variation selectors are NOT handled here —
119
- * the caller (visualWidth) must apply them on top of this base check.
120
- */
121
- export function isWideRange(cp: number): boolean {
122
- return (
123
- inRanges(cp, CJK_RANGES) ||
124
- inRanges(cp, HANGUL_RANGES) ||
125
- inRanges(cp, FULLWIDTH_RANGES) ||
126
- inRanges(cp, EMOJI_RANGES)
127
- )
128
- }
129
-
130
- /**
131
- * Is the codepoint zero-width (combining mark or a special ZWS/ZWJ/BOM)?
132
- */
133
- export function isZeroWidth(cp: number): boolean {
134
- return inRanges(cp, COMBINING_RANGES) || ZERO_WIDTH_CODEPOINTS.has(cp)
135
- }
package/src/styles.ts DELETED
@@ -1,318 +0,0 @@
1
- // ============================================================================
2
- // Font metrics — character width estimates for Inter at different sizes.
3
- // Used to approximate text bounding boxes without DOM measurement.
4
- // These are calibrated for Inter's typical glyph widths.
5
- //
6
- // NOTE: Theme/color system has moved to src/theme.ts. This file only
7
- // contains font metrics, spacing constants, and stroke widths.
8
- // ============================================================================
9
-
10
- import { measureTextWidth } from './text-metrics'
11
- import { styleFaceOf } from './scene/style-registry.ts'
12
- import type { InternalStyleFace, StyleInput } from './scene/style-registry.ts'
13
- import type { TextTransform } from './types.ts'
14
-
15
- /** Average character width in px at the given font size and weight (proportional font) */
16
- export function estimateTextWidth(text: string, fontSize: number, fontWeight: number): number {
17
- // Delegate to variable-width character measurement for better accuracy
18
- // with mixed character sets (Latin narrow/wide, CJK, emoji, etc.)
19
- return measureTextWidth(text, fontSize, fontWeight)
20
- }
21
-
22
- /** Average character width in px for monospace fonts (uniform glyph width) */
23
- export function estimateMonoTextWidth(text: string, fontSize: number): number {
24
- // Monospace fonts have uniform character width — 0.6 of fontSize matches actual
25
- // glyph widths for JetBrains Mono / SF Mono / Fira Code at small sizes (11px).
26
- // Previous value of 0.55 underestimated widths, causing class member labels to
27
- // extend beyond their box boundaries.
28
- return text.length * fontSize * 0.6
29
- }
30
-
31
- /** Monospace font family used for code-like text (class members, types) */
32
- export const MONO_FONT = "'JetBrains Mono'" as const
33
-
34
- /** Full CSS fallback chain for monospace text */
35
- export const MONO_FONT_STACK = `${MONO_FONT}, 'SF Mono', 'Fira Code', ui-monospace, monospace` as const
36
-
37
- /** Fixed font sizes used in the renderer (in px) */
38
- export const FONT_SIZES = {
39
- /** Node label text */
40
- nodeLabel: 13,
41
- /** Edge label text */
42
- edgeLabel: 11,
43
- /** Subgraph header text */
44
- groupHeader: 12,
45
- } as const
46
-
47
- /** Font weights used per element type */
48
- export const FONT_WEIGHTS = {
49
- nodeLabel: 500,
50
- edgeLabel: 400,
51
- groupHeader: 600,
52
- } as const
53
-
54
- // ============================================================================
55
- // Spacing & sizing constants
56
- // ============================================================================
57
-
58
- /** Vertical gap between a subgraph header band and the content area below it (px).
59
- * Without this, nested subgraph headers sit flush against their parent's header band.
60
- * Increased from 8 to 12 to provide more clearance for edges routing near headers. */
61
- export const GROUP_HEADER_CONTENT_PAD = 12
62
-
63
- /** Padding inside node shapes */
64
- export const NODE_PADDING = {
65
- /** Horizontal padding inside rectangles/rounded/stadium (increased from 16 for better label fit) */
66
- horizontal: 20,
67
- /** Vertical padding inside rectangles/rounded/stadium */
68
- vertical: 10,
69
- /** Extra padding for diamond shapes (they need more space due to rotation) */
70
- diamondExtra: 24,
71
- } as const
72
-
73
- /** Stroke widths per element type (in px) */
74
- export const STROKE_WIDTHS = {
75
- outerBox: 1,
76
- innerBox: 0.75,
77
- /** Edge connector stroke (increased from 0.75 for better visibility) */
78
- connector: 1,
79
- } as const
80
-
81
- /**
82
- * Vertical shift applied to all text elements for font-agnostic centering.
83
- *
84
- * Instead of relying on `dominant-baseline="central"` (which each font interprets
85
- * differently based on its own ascent/descent metrics), we use the default alphabetic
86
- * baseline and shift down by 0.35em. This places the optical center of text at the
87
- * y coordinate, regardless of font family (Inter, JetBrains Mono, system fallbacks).
88
- *
89
- * The 0.35em value approximates the distance from alphabetic baseline to visual
90
- * center of Latin text. Using `em` units ensures it scales with font size.
91
- */
92
- export const TEXT_BASELINE_SHIFT = '0.35em' as const
93
-
94
- /** Arrow head dimensions — matches spec: 8px wide × ~5px tall */
95
- export const ARROW_HEAD = {
96
- width: 8,
97
- height: 5,
98
- } as const
99
-
100
- /** Flowchart dotted-edge stroke pattern; renderer emits stroke-dasharray="4 4". */
101
- export const FLOWCHART_DOTTED_DASH = {
102
- dash: 4,
103
- gap: 4,
104
- } as const
105
-
106
- // ============================================================================
107
- // Render style option resolution
108
- // ============================================================================
109
-
110
- export interface RenderStyleOptions {
111
- /** A style input (name | spec | stack); built-in style faces are read here. */
112
- style?: StyleInput | StyleInput[]
113
- /** @internal Projected families can pass precomputed face metrics without exposing them as public style JSON. */
114
- styleFace?: InternalStyleFace
115
- }
116
-
117
- export interface RenderStyleDefaults {
118
- nodeLabelFontSize: number
119
- edgeLabelFontSize: number
120
- groupHeaderFontSize: number
121
- nodeLabelFontWeight: number
122
- edgeLabelFontWeight: number
123
- groupHeaderFontWeight: number
124
- nodeTextTransform?: TextTransform
125
- edgeTextTransform?: TextTransform
126
- nodeLetterSpacing?: number
127
- edgeLetterSpacing?: number
128
- groupLetterSpacing?: number
129
- nodePaddingX: number
130
- nodePaddingY: number
131
- diamondExtraPadding?: number
132
- nodeCornerRadius?: number
133
- nodeLineWidth?: number
134
- nodeFillColor?: string
135
- nodeBorderColor?: string
136
- nodeTextColor?: string
137
- edgeLineWidth: number
138
- edgeBendRadius?: number
139
- edgeStrokeColor?: string
140
- edgeTextColor?: string
141
- groupFont?: string
142
- groupTextTransform?: TextTransform
143
- groupCornerRadius: number
144
- groupBorderColor?: string
145
- groupFillColor?: string
146
- groupHeaderFillColor?: string
147
- groupTextColor?: string
148
- groupPaddingX: number
149
- groupPaddingY: number
150
- groupLabelPaddingX?: number
151
- groupLineWidth?: number
152
- }
153
-
154
- export interface ResolvedRenderStyle {
155
- nodeLabelFontSize: number
156
- edgeLabelFontSize: number
157
- groupHeaderFontSize: number
158
- nodeLabelFontWeight: number
159
- edgeLabelFontWeight: number
160
- groupHeaderFontWeight: number
161
- nodeTextTransform?: TextTransform
162
- edgeTextTransform?: TextTransform
163
- nodeLetterSpacing: number
164
- edgeLetterSpacing: number
165
- groupLetterSpacing: number
166
- nodePaddingX: number
167
- nodePaddingY: number
168
- diamondExtraPadding: number
169
- cornerRadius?: number
170
- nodeLineWidth: number
171
- nodeFillColor?: string
172
- nodeBorderColor?: string
173
- nodeTextColor?: string
174
- lineWidth: number
175
- edgeBendRadius: number
176
- edgeStrokeColor?: string
177
- edgeTextColor?: string
178
- groupFont?: string
179
- groupTextTransform?: TextTransform
180
- groupCornerRadius: number
181
- groupBorderColor?: string
182
- groupFillColor?: string
183
- groupHeaderFillColor?: string
184
- groupTextColor?: string
185
- groupPaddingX: number
186
- groupPaddingY: number
187
- groupLabelPaddingX: number
188
- groupLineWidth: number
189
- }
190
-
191
- export const FLOWCHART_STYLE_DEFAULTS: RenderStyleDefaults = {
192
- nodeLabelFontSize: FONT_SIZES.nodeLabel,
193
- edgeLabelFontSize: FONT_SIZES.edgeLabel,
194
- groupHeaderFontSize: FONT_SIZES.groupHeader,
195
- nodeLabelFontWeight: FONT_WEIGHTS.nodeLabel,
196
- edgeLabelFontWeight: FONT_WEIGHTS.edgeLabel,
197
- groupHeaderFontWeight: FONT_WEIGHTS.groupHeader,
198
- nodePaddingX: NODE_PADDING.horizontal,
199
- nodePaddingY: NODE_PADDING.vertical,
200
- diamondExtraPadding: NODE_PADDING.diamondExtra,
201
- edgeLineWidth: STROKE_WIDTHS.connector,
202
- groupCornerRadius: 0,
203
- groupPaddingX: 16,
204
- groupPaddingY: 16,
205
- groupLabelPaddingX: 12,
206
- groupLineWidth: STROKE_WIDTHS.outerBox,
207
- }
208
-
209
- function finiteNumber(value: number | undefined): number | undefined {
210
- return typeof value === 'number' && Number.isFinite(value) ? value : undefined
211
- }
212
-
213
- function positiveNumber(fallback: number, ...values: Array<number | undefined>): number {
214
- for (const value of values) {
215
- const finite = finiteNumber(value)
216
- if (finite != null && finite > 0) return finite
217
- }
218
- return fallback
219
- }
220
-
221
- function nonNegativeNumber(fallback: number, ...values: Array<number | undefined>): number
222
- function nonNegativeNumber(fallback: undefined, ...values: Array<number | undefined>): number | undefined
223
- function nonNegativeNumber(fallback: number | undefined, ...values: Array<number | undefined>): number | undefined {
224
- for (const value of values) {
225
- const finite = finiteNumber(value)
226
- if (finite != null && finite >= 0) return finite
227
- }
228
- return fallback
229
- }
230
-
231
- function finiteString(...values: Array<string | undefined>): string | undefined {
232
- for (const value of values) {
233
- if (typeof value === 'string' && value.trim().length > 0) return value
234
- }
235
- return undefined
236
- }
237
-
238
- function textTransform(...values: Array<string | undefined>): TextTransform | undefined {
239
- for (const value of values) {
240
- const normalized = finiteString(value)?.toLowerCase()
241
- if (normalized === 'uppercase' || normalized === 'lowercase' || normalized === 'capitalize') {
242
- return normalized
243
- }
244
- }
245
- return undefined
246
- }
247
-
248
- const INLINE_FORMAT_TAG = /(<\/?(?:b|strong|i|em|u|s|del)\s*>)/gi
249
-
250
- export function applyTextTransform(text: string, transform: TextTransform | undefined): string {
251
- if (!transform) return text
252
- const transformPlain = (chunk: string): string => {
253
- switch (transform) {
254
- case 'uppercase':
255
- return chunk.toUpperCase()
256
- case 'lowercase':
257
- return chunk.toLowerCase()
258
- case 'capitalize':
259
- return chunk.replace(/\b\p{L}/gu, ch => ch.toUpperCase())
260
- }
261
- }
262
- return text
263
- .split(INLINE_FORMAT_TAG)
264
- .map(part => /^<\/?(?:b|strong|i|em|u|s|del)\s*>$/i.test(part) ? part : transformPlain(part))
265
- .join('')
266
- }
267
-
268
- export function resolveRenderStyle(
269
- options: RenderStyleOptions = {},
270
- defaults: RenderStyleDefaults = FLOWCHART_STYLE_DEFAULTS,
271
- ): ResolvedRenderStyle {
272
- const face = options.styleFace ?? styleFaceOf(options.style)
273
- const text = face?.text
274
- const node = face?.node
275
- const edge = face?.edge
276
- const group = face?.group
277
- const explicitGroupPaddingX = nonNegativeNumber(undefined, group?.paddingX)
278
- const cornerRadius = defaults.nodeCornerRadius == null
279
- ? nonNegativeNumber(undefined, node?.cornerRadius)
280
- : nonNegativeNumber(defaults.nodeCornerRadius, node?.cornerRadius)
281
-
282
- return {
283
- nodeLabelFontSize: positiveNumber(defaults.nodeLabelFontSize, node?.fontSize, text?.fontSize),
284
- edgeLabelFontSize: positiveNumber(defaults.edgeLabelFontSize, edge?.fontSize, text?.fontSize),
285
- groupHeaderFontSize: positiveNumber(defaults.groupHeaderFontSize, group?.fontSize, text?.fontSize),
286
- nodeLabelFontWeight: positiveNumber(defaults.nodeLabelFontWeight, node?.fontWeight, text?.fontWeight),
287
- edgeLabelFontWeight: positiveNumber(defaults.edgeLabelFontWeight, edge?.fontWeight, text?.fontWeight),
288
- groupHeaderFontWeight: positiveNumber(defaults.groupHeaderFontWeight, group?.fontWeight, text?.fontWeight),
289
- nodeTextTransform: textTransform(node?.textTransform, text?.textTransform, defaults.nodeTextTransform),
290
- edgeTextTransform: textTransform(edge?.textTransform, text?.textTransform, defaults.edgeTextTransform),
291
- nodeLetterSpacing: finiteNumber(node?.letterSpacing) ?? finiteNumber(text?.letterSpacing) ?? defaults.nodeLetterSpacing ?? 0,
292
- edgeLetterSpacing: finiteNumber(edge?.letterSpacing) ?? finiteNumber(text?.letterSpacing) ?? defaults.edgeLetterSpacing ?? 0,
293
- groupLetterSpacing: finiteNumber(group?.letterSpacing) ?? finiteNumber(text?.letterSpacing) ?? defaults.groupLetterSpacing ?? 0,
294
- nodePaddingX: nonNegativeNumber(defaults.nodePaddingX, node?.paddingX),
295
- nodePaddingY: nonNegativeNumber(defaults.nodePaddingY, node?.paddingY),
296
- diamondExtraPadding: defaults.diamondExtraPadding ?? NODE_PADDING.diamondExtra,
297
- cornerRadius,
298
- nodeLineWidth: positiveNumber(defaults.nodeLineWidth ?? STROKE_WIDTHS.innerBox, node?.lineWidth),
299
- nodeFillColor: finiteString(node?.fillColor, defaults.nodeFillColor),
300
- nodeBorderColor: finiteString(node?.borderColor, defaults.nodeBorderColor),
301
- nodeTextColor: finiteString(node?.textColor, text?.textColor, defaults.nodeTextColor),
302
- lineWidth: positiveNumber(defaults.edgeLineWidth, edge?.lineWidth),
303
- edgeBendRadius: nonNegativeNumber(defaults.edgeBendRadius ?? 0, edge?.bendRadius),
304
- edgeStrokeColor: finiteString(edge?.strokeColor, defaults.edgeStrokeColor),
305
- edgeTextColor: finiteString(edge?.textColor, text?.textColor, defaults.edgeTextColor),
306
- groupFont: finiteString(group?.fontFamily, defaults.groupFont),
307
- groupTextTransform: textTransform(group?.textTransform, text?.textTransform, defaults.groupTextTransform),
308
- groupCornerRadius: nonNegativeNumber(defaults.groupCornerRadius, group?.cornerRadius),
309
- groupBorderColor: finiteString(group?.borderColor, defaults.groupBorderColor),
310
- groupFillColor: finiteString(group?.fillColor, defaults.groupFillColor),
311
- groupHeaderFillColor: finiteString(group?.headerFillColor, defaults.groupHeaderFillColor),
312
- groupTextColor: finiteString(group?.textColor, text?.textColor, defaults.groupTextColor),
313
- groupPaddingX: explicitGroupPaddingX ?? defaults.groupPaddingX,
314
- groupPaddingY: nonNegativeNumber(defaults.groupPaddingY, group?.paddingY),
315
- groupLabelPaddingX: explicitGroupPaddingX ?? defaults.groupLabelPaddingX ?? defaults.groupPaddingX,
316
- groupLineWidth: positiveNumber(defaults.groupLineWidth ?? STROKE_WIDTHS.outerBox, group?.lineWidth),
317
- }
318
- }
package/src/svg-paths.ts DELETED
@@ -1,28 +0,0 @@
1
- // ============================================================================
2
- // SVG path helpers for partial fills inside rounded boxes.
3
- //
4
- // Use this instead of rounded <rect> elements for header bands: a full rounded
5
- // rect gives partial-height fills their own rounded bottom corners, which creates
6
- // visual seams and pill/crescent artifacts.
7
- // ============================================================================
8
-
9
- export function topRoundedRectPath(x: number, y: number, width: number, height: number, radius: number): string {
10
- const r = clampRadius(radius, width / 2, height)
11
- if (r === 0) return `M${x},${y} H${x + width} V${y + height} H${x} Z`
12
-
13
- return [
14
- `M${x + r},${y}`,
15
- `H${x + width - r}`,
16
- `A${r},${r} 0 0 1 ${x + width},${y + r}`,
17
- `V${y + height}`,
18
- `H${x}`,
19
- `V${y + r}`,
20
- `A${r},${r} 0 0 1 ${x + r},${y}`,
21
- 'Z',
22
- ].join(' ')
23
- }
24
-
25
-
26
- function clampRadius(radius: number, maxX: number, maxY: number): number {
27
- return Math.max(0, Math.min(radius, maxX, maxY))
28
- }