zombie-mermaid 2.2.3 → 2.2.6

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 (321) hide show
  1. package/README.md +4 -4
  2. package/dist/ascii.cjs +1 -11
  3. package/dist/ascii.d.cts +1 -167
  4. package/dist/ascii.d.ts +1 -167
  5. package/dist/ascii.js +1 -6591
  6. package/dist/cli.js +836 -10946
  7. package/dist/index.cjs +2 -81
  8. package/dist/index.cjs.map +1 -1
  9. package/dist/index.d.cts +42 -680
  10. package/dist/index.d.ts +42 -680
  11. package/dist/index.js +408 -10002
  12. package/dist/index.js.map +1 -1
  13. package/dist/mcp.cjs +1 -17909
  14. package/dist/mcp.d.cts +1 -11
  15. package/dist/mcp.d.ts +1 -11
  16. package/dist/mcp.js +1 -17884
  17. package/package.json +29 -29
  18. package/src/__tests__/workspace-package-boundaries.test.ts +15 -16
  19. package/src/__tests__/xychart-parser-categories.test.ts +78 -0
  20. package/src/ascii-entry.ts +14 -0
  21. package/src/cli/html-viewer.ts +5 -0
  22. package/src/mcp-entry.ts +21 -0
  23. package/dist/ascii.cjs.map +0 -1
  24. package/dist/ascii.js.map +0 -1
  25. package/dist/mcp.cjs.map +0 -1
  26. package/dist/mcp.js.map +0 -1
  27. package/packages/ascii-renderer/LICENSE +0 -22
  28. package/packages/ascii-renderer/src/ansi.ts +0 -490
  29. package/packages/ascii-renderer/src/canvas.ts +0 -658
  30. package/packages/ascii-renderer/src/class-diagram.ts +0 -2001
  31. package/packages/ascii-renderer/src/converter.ts +0 -446
  32. package/packages/ascii-renderer/src/coords.ts +0 -58
  33. package/packages/ascii-renderer/src/display-width.ts +0 -151
  34. package/packages/ascii-renderer/src/draw-arrows.ts +0 -549
  35. package/packages/ascii-renderer/src/draw-boxes.ts +0 -267
  36. package/packages/ascii-renderer/src/draw-bundles.ts +0 -611
  37. package/packages/ascii-renderer/src/draw-lines.ts +0 -174
  38. package/packages/ascii-renderer/src/draw-subgraphs.ts +0 -108
  39. package/packages/ascii-renderer/src/draw.ts +0 -337
  40. package/packages/ascii-renderer/src/edge-bundling.ts +0 -435
  41. package/packages/ascii-renderer/src/edge-cell-styles.ts +0 -81
  42. package/packages/ascii-renderer/src/edge-routing.ts +0 -1049
  43. package/packages/ascii-renderer/src/er-diagram.ts +0 -1488
  44. package/packages/ascii-renderer/src/flowchart.ts +0 -94
  45. package/packages/ascii-renderer/src/grid-occupancy.ts +0 -234
  46. package/packages/ascii-renderer/src/grid.ts +0 -1267
  47. package/packages/ascii-renderer/src/hyperlinks.ts +0 -248
  48. package/packages/ascii-renderer/src/index.ts +0 -163
  49. package/packages/ascii-renderer/src/lane-search.ts +0 -68
  50. package/packages/ascii-renderer/src/multiline-utils.ts +0 -82
  51. package/packages/ascii-renderer/src/pathfinder.ts +0 -448
  52. package/packages/ascii-renderer/src/registry.ts +0 -88
  53. package/packages/ascii-renderer/src/sequence.ts +0 -1318
  54. package/packages/ascii-renderer/src/shapes/circle.ts +0 -31
  55. package/packages/ascii-renderer/src/shapes/corners.ts +0 -273
  56. package/packages/ascii-renderer/src/shapes/diamond.ts +0 -31
  57. package/packages/ascii-renderer/src/shapes/hexagon.ts +0 -31
  58. package/packages/ascii-renderer/src/shapes/index.ts +0 -123
  59. package/packages/ascii-renderer/src/shapes/rectangle.ts +0 -199
  60. package/packages/ascii-renderer/src/shapes/rounded.ts +0 -31
  61. package/packages/ascii-renderer/src/shapes/special.ts +0 -352
  62. package/packages/ascii-renderer/src/shapes/stadium.ts +0 -122
  63. package/packages/ascii-renderer/src/shapes/state.ts +0 -204
  64. package/packages/ascii-renderer/src/shapes/types.ts +0 -78
  65. package/packages/ascii-renderer/src/territory.ts +0 -136
  66. package/packages/ascii-renderer/src/types.ts +0 -454
  67. package/packages/ascii-renderer/src/validate.ts +0 -189
  68. package/packages/ascii-renderer/src/xychart.ts +0 -1085
  69. package/packages/core/LICENSE +0 -22
  70. package/packages/core/src/click-directive.ts +0 -106
  71. package/packages/core/src/color-utils.ts +0 -205
  72. package/packages/core/src/diagram-type.ts +0 -35
  73. package/packages/core/src/direction-override.ts +0 -46
  74. package/packages/core/src/direction.ts +0 -56
  75. package/packages/core/src/index.ts +0 -34
  76. package/packages/core/src/init-directive.ts +0 -248
  77. package/packages/core/src/multiline-utils.ts +0 -275
  78. package/packages/core/src/statements.ts +0 -197
  79. package/packages/core/src/style-directives.ts +0 -214
  80. package/packages/core/src/text-metrics.ts +0 -498
  81. package/packages/core/src/theme.ts +0 -696
  82. package/packages/core/src/types.ts +0 -670
  83. package/packages/mcp/LICENSE +0 -22
  84. package/packages/mcp/src/index.ts +0 -17
  85. package/packages/mcp/src/server.ts +0 -135
  86. package/packages/mcp/src/tools/check-sequence-activations.ts +0 -91
  87. package/packages/mcp/src/tools/fix-sequence-activations.ts +0 -77
  88. package/packages/mcp/src/tools/render-ascii.ts +0 -99
  89. package/packages/mcp/src/tools/render-svg.ts +0 -95
  90. package/packages/mermaid-parser/LICENSE +0 -22
  91. package/packages/mermaid-parser/src/class/format.ts +0 -15
  92. package/packages/mermaid-parser/src/class/parser.ts +0 -593
  93. package/packages/mermaid-parser/src/class/types.ts +0 -166
  94. package/packages/mermaid-parser/src/er/parser.ts +0 -286
  95. package/packages/mermaid-parser/src/er/types.ts +0 -99
  96. package/packages/mermaid-parser/src/expanded-shapes.ts +0 -376
  97. package/packages/mermaid-parser/src/index.ts +0 -48
  98. package/packages/mermaid-parser/src/sequence/activation-check.ts +0 -149
  99. package/packages/mermaid-parser/src/sequence/activation-fix.ts +0 -112
  100. package/packages/mermaid-parser/src/sequence/box-color.ts +0 -85
  101. package/packages/mermaid-parser/src/sequence/parser.ts +0 -613
  102. package/packages/mermaid-parser/src/sequence/types.ts +0 -242
  103. package/packages/mermaid-parser/src/xychart/colors.ts +0 -177
  104. package/packages/mermaid-parser/src/xychart/parser.ts +0 -203
  105. package/packages/mermaid-parser/src/xychart/types.ts +0 -150
  106. package/packages/svg-renderer/LICENSE +0 -22
  107. package/packages/svg-renderer/src/class/layout.ts +0 -360
  108. package/packages/svg-renderer/src/class/renderer.ts +0 -636
  109. package/packages/svg-renderer/src/edge-curves.ts +0 -204
  110. package/packages/svg-renderer/src/elk-instance.ts +0 -292
  111. package/packages/svg-renderer/src/er/layout.ts +0 -200
  112. package/packages/svg-renderer/src/er/renderer.ts +0 -493
  113. package/packages/svg-renderer/src/index.ts +0 -58
  114. package/packages/svg-renderer/src/layout-engine/constants.ts +0 -19
  115. package/packages/svg-renderer/src/layout-engine/edge-bundling.ts +0 -379
  116. package/packages/svg-renderer/src/layout-engine/elk-adapter-utils.ts +0 -81
  117. package/packages/svg-renderer/src/layout-engine/elk-graph-builder.ts +0 -240
  118. package/packages/svg-renderer/src/layout-engine/from-elk.ts +0 -685
  119. package/packages/svg-renderer/src/layout-engine/layer-alignment.ts +0 -174
  120. package/packages/svg-renderer/src/layout-engine/to-elk.ts +0 -695
  121. package/packages/svg-renderer/src/layout-engine.ts +0 -74
  122. package/packages/svg-renderer/src/layout.ts +0 -8
  123. package/packages/svg-renderer/src/renderer.ts +0 -1485
  124. package/packages/svg-renderer/src/resolve-colors.ts +0 -339
  125. package/packages/svg-renderer/src/sequence/layout.ts +0 -698
  126. package/packages/svg-renderer/src/sequence/renderer.ts +0 -546
  127. package/packages/svg-renderer/src/shape-clipping.ts +0 -197
  128. package/packages/svg-renderer/src/styles.ts +0 -118
  129. package/packages/svg-renderer/src/xychart/layout.ts +0 -682
  130. package/packages/svg-renderer/src/xychart/renderer.ts +0 -684
  131. package/src/__tests__/ascii-canvas-write.test.ts +0 -137
  132. package/src/__tests__/ascii-charset-border-junctions.test.ts +0 -63
  133. package/src/__tests__/ascii-cjk-width.test.ts +0 -150
  134. package/src/__tests__/ascii-class-box-occupancy.test.ts +0 -462
  135. package/src/__tests__/ascii-class-column-width-488-489.test.ts +0 -639
  136. package/src/__tests__/ascii-class-cross-level-jog-corruption.test.ts +0 -187
  137. package/src/__tests__/ascii-class-detour-label-routing-487.test.ts +0 -114
  138. package/src/__tests__/ascii-class-diagram-compartments.test.ts +0 -70
  139. package/src/__tests__/ascii-class-label-box-collision.test.ts +0 -60
  140. package/src/__tests__/ascii-class-label-row-collision-531.test.ts +0 -135
  141. package/src/__tests__/ascii-class-label-territory-row-awareness.test.ts +0 -57
  142. package/src/__tests__/ascii-class-padding.test.ts +0 -104
  143. package/src/__tests__/ascii-class-parent-alignment-971.test.ts +0 -139
  144. package/src/__tests__/ascii-class-parent-alignment-972.test.ts +0 -208
  145. package/src/__tests__/ascii-class-reciprocal-relationships-448.test.ts +0 -169
  146. package/src/__tests__/ascii-combining-mark-width.test.ts +0 -70
  147. package/src/__tests__/ascii-coords-overlay.test.ts +0 -64
  148. package/src/__tests__/ascii-decision-lr-box-start.test.ts +0 -106
  149. package/src/__tests__/ascii-display-width-unit.test.ts +0 -154
  150. package/src/__tests__/ascii-draw-arrows-coverage.test.ts +0 -171
  151. package/src/__tests__/ascii-draw-arrows-single-point-path.test.ts +0 -112
  152. package/src/__tests__/ascii-edge-bundling-rank-violation-454.test.ts +0 -72
  153. package/src/__tests__/ascii-edge-ending-glyphs.test.ts +0 -206
  154. package/src/__tests__/ascii-edge-label-diagonal-fallback-418.test.ts +0 -95
  155. package/src/__tests__/ascii-edge-routing-fixes.test.ts +0 -178
  156. package/src/__tests__/ascii-edge-routing-single-point-path.test.ts +0 -107
  157. package/src/__tests__/ascii-edge-styles.test.ts +0 -149
  158. package/src/__tests__/ascii-emoji-cluster-width.test.ts +0 -101
  159. package/src/__tests__/ascii-er-box-occupancy.test.ts +0 -251
  160. package/src/__tests__/ascii-er-cardinality.test.ts +0 -40
  161. package/src/__tests__/ascii-er-corner-glyphs.test.ts +0 -249
  162. package/src/__tests__/ascii-er-jog-stray-line.test.ts +0 -111
  163. package/src/__tests__/ascii-er-label-padding.test.ts +0 -118
  164. package/src/__tests__/ascii-er-padding.test.ts +0 -114
  165. package/src/__tests__/ascii-er-relationship-label-corruption-350.test.ts +0 -458
  166. package/src/__tests__/ascii-er-relationship-overwrite.test.ts +0 -325
  167. package/src/__tests__/ascii-er-stray-connectors.test.ts +0 -347
  168. package/src/__tests__/ascii-er-unrelated-stem-separation-411.test.ts +0 -98
  169. package/src/__tests__/ascii-er-vertical-one-marker.test.ts +0 -110
  170. package/src/__tests__/ascii-label-line-terminal-fallback.test.ts +0 -172
  171. package/src/__tests__/ascii-lane-search.test.ts +0 -207
  172. package/src/__tests__/ascii-multibox-cjk-width.test.ts +0 -184
  173. package/src/__tests__/ascii-multiline.test.ts +0 -291
  174. package/src/__tests__/ascii-padding-edge-cases.test.ts +0 -154
  175. package/src/__tests__/ascii-pathfinder-route-edge.test.ts +0 -194
  176. package/src/__tests__/ascii-sequence-alt-else-label.test.ts +0 -236
  177. package/src/__tests__/ascii-sequence-block-wall-clearance.test.ts +0 -217
  178. package/src/__tests__/ascii-sequence-box-group.test.ts +0 -159
  179. package/src/__tests__/ascii-sequence-cjk-width.test.ts +0 -235
  180. package/src/__tests__/ascii-sequence-create-destroy.test.ts +0 -114
  181. package/src/__tests__/ascii-sequence-form-invariants.test.ts +0 -432
  182. package/src/__tests__/ascii-sequence-mermaid-parity.test.ts +0 -219
  183. package/src/__tests__/ascii-sequence-notes.test.ts +0 -61
  184. package/src/__tests__/ascii-sequence-padding.test.ts +0 -119
  185. package/src/__tests__/ascii-sequence-self-arrow.test.ts +0 -206
  186. package/src/__tests__/ascii-shape-diamond.test.ts +0 -38
  187. package/src/__tests__/ascii-shape-rectangle.test.ts +0 -258
  188. package/src/__tests__/ascii-shape-rounded.test.ts +0 -36
  189. package/src/__tests__/ascii-shapes-circle.test.ts +0 -41
  190. package/src/__tests__/ascii-shapes-hexagon.test.ts +0 -42
  191. package/src/__tests__/ascii-shapes-special.test.ts +0 -349
  192. package/src/__tests__/ascii-shapes-stadium.test.ts +0 -217
  193. package/src/__tests__/ascii-shapes-state.test.ts +0 -234
  194. package/src/__tests__/ascii-state-bidirectional-label-swap-530.test.ts +0 -130
  195. package/src/__tests__/ascii-subgraph-direction-honored-445.test.ts +0 -90
  196. package/src/__tests__/ascii-subgraph-label-border-clip.test.ts +0 -152
  197. package/src/__tests__/ascii-subgraph-title-padding.test.ts +0 -77
  198. package/src/__tests__/ascii-territory-unit.test.ts +0 -219
  199. package/src/__tests__/ascii-validate.test.ts +0 -220
  200. package/src/__tests__/ascii.test.ts +0 -328
  201. package/src/__tests__/box-color.test.ts +0 -80
  202. package/src/__tests__/class-arrow-directions.test.ts +0 -505
  203. package/src/__tests__/click-directive.test.ts +0 -63
  204. package/src/__tests__/color-utils.test.ts +0 -186
  205. package/src/__tests__/diagram-type.test.ts +0 -28
  206. package/src/__tests__/draw-lines.test.ts +0 -93
  207. package/src/__tests__/edge-cell-styles.test.ts +0 -180
  208. package/src/__tests__/elk-adapter-utils.test.ts +0 -166
  209. package/src/__tests__/grid-occupancy.test.ts +0 -240
  210. package/src/__tests__/helpers/ascii-form.ts +0 -142
  211. package/src/__tests__/helpers/terminal-display-width.ts +0 -74
  212. package/src/__tests__/mcp-check-sequence-activations-tool.test.ts +0 -85
  213. package/src/__tests__/mcp-fix-sequence-activations-tool.test.ts +0 -134
  214. package/src/__tests__/mcp-server.test.ts +0 -163
  215. package/src/__tests__/pathfinder.test.ts +0 -246
  216. package/src/__tests__/sequence-activation-fix.test.ts +0 -91
  217. package/src/__tests__/testdata/ascii/ampersand_lhs.txt +0 -18
  218. package/src/__tests__/testdata/ascii/ampersand_lhs_and_rhs.txt +0 -18
  219. package/src/__tests__/testdata/ascii/ampersand_rhs.txt +0 -18
  220. package/src/__tests__/testdata/ascii/ampersand_td_fanin.txt +0 -18
  221. package/src/__tests__/testdata/ascii/ampersand_td_fanout.txt +0 -18
  222. package/src/__tests__/testdata/ascii/ampersand_without_edge.txt +0 -18
  223. package/src/__tests__/testdata/ascii/back_reference_from_child.txt +0 -10
  224. package/src/__tests__/testdata/ascii/backlink_from_bottom.txt +0 -22
  225. package/src/__tests__/testdata/ascii/backlink_from_top.txt +0 -22
  226. package/src/__tests__/testdata/ascii/backlink_with_short_y_padding.txt +0 -20
  227. package/src/__tests__/testdata/ascii/cls_all_relationships.txt +0 -19
  228. package/src/__tests__/testdata/ascii/cls_annotation.txt +0 -29
  229. package/src/__tests__/testdata/ascii/cls_association.txt +0 -14
  230. package/src/__tests__/testdata/ascii/cls_basic.txt +0 -15
  231. package/src/__tests__/testdata/ascii/cls_dependency.txt +0 -14
  232. package/src/__tests__/testdata/ascii/cls_inheritance.txt +0 -20
  233. package/src/__tests__/testdata/ascii/cls_methods.txt +0 -21
  234. package/src/__tests__/testdata/ascii/comments.txt +0 -23
  235. package/src/__tests__/testdata/ascii/custom_padding.txt +0 -10
  236. package/src/__tests__/testdata/ascii/duplicate_labels.txt +0 -19
  237. package/src/__tests__/testdata/ascii/er_attributes.txt +0 -21
  238. package/src/__tests__/testdata/ascii/er_basic.txt +0 -8
  239. package/src/__tests__/testdata/ascii/er_identifying.txt +0 -18
  240. package/src/__tests__/testdata/ascii/flowchart_tb_simple.txt +0 -29
  241. package/src/__tests__/testdata/ascii/graph_bt_direction.txt +0 -28
  242. package/src/__tests__/testdata/ascii/graph_tb_direction.txt +0 -26
  243. package/src/__tests__/testdata/ascii/nested_subgraphs_with_labels.txt +0 -36
  244. package/src/__tests__/testdata/ascii/preserve_order_of_definition.txt +0 -23
  245. package/src/__tests__/testdata/ascii/self_reference.txt +0 -10
  246. package/src/__tests__/testdata/ascii/self_reference_with_edge.txt +0 -10
  247. package/src/__tests__/testdata/ascii/seq_basic.txt +0 -17
  248. package/src/__tests__/testdata/ascii/seq_multiple_messages.txt +0 -25
  249. package/src/__tests__/testdata/ascii/seq_self_message.txt +0 -18
  250. package/src/__tests__/testdata/ascii/single_node.txt +0 -8
  251. package/src/__tests__/testdata/ascii/single_node_longer_name.txt +0 -8
  252. package/src/__tests__/testdata/ascii/subgraph_complex_mixed.txt +0 -38
  253. package/src/__tests__/testdata/ascii/subgraph_complex_nested.txt +0 -49
  254. package/src/__tests__/testdata/ascii/subgraph_direction_override.txt +0 -47
  255. package/src/__tests__/testdata/ascii/subgraph_empty.txt +0 -10
  256. package/src/__tests__/testdata/ascii/subgraph_mixed_nodes.txt +0 -20
  257. package/src/__tests__/testdata/ascii/subgraph_mixed_nodes_td.txt +0 -48
  258. package/src/__tests__/testdata/ascii/subgraph_multiple_edges.txt +0 -32
  259. package/src/__tests__/testdata/ascii/subgraph_multiple_nodes.txt +0 -16
  260. package/src/__tests__/testdata/ascii/subgraph_nested.txt +0 -24
  261. package/src/__tests__/testdata/ascii/subgraph_nested_with_external.txt +0 -30
  262. package/src/__tests__/testdata/ascii/subgraph_node_outside_lr.txt +0 -17
  263. package/src/__tests__/testdata/ascii/subgraph_single_node.txt +0 -16
  264. package/src/__tests__/testdata/ascii/subgraph_td_direction.txt +0 -26
  265. package/src/__tests__/testdata/ascii/subgraph_td_multiple.txt +0 -44
  266. package/src/__tests__/testdata/ascii/subgraph_td_multiple_paddingy.txt +0 -42
  267. package/src/__tests__/testdata/ascii/subgraph_three_levels_nested.txt +0 -32
  268. package/src/__tests__/testdata/ascii/subgraph_three_separate.txt +0 -24
  269. package/src/__tests__/testdata/ascii/subgraph_two_separate.txt +0 -20
  270. package/src/__tests__/testdata/ascii/subgraph_with_labels.txt +0 -20
  271. package/src/__tests__/testdata/ascii/three_nodes.txt +0 -9
  272. package/src/__tests__/testdata/ascii/three_nodes_single_line.txt +0 -8
  273. package/src/__tests__/testdata/ascii/two_layer_single_graph.txt +0 -19
  274. package/src/__tests__/testdata/ascii/two_layer_single_graph_longer_names.txt +0 -19
  275. package/src/__tests__/testdata/ascii/two_nodes_linked.txt +0 -8
  276. package/src/__tests__/testdata/ascii/two_nodes_longer_names.txt +0 -8
  277. package/src/__tests__/testdata/ascii/two_root_nodes.txt +0 -19
  278. package/src/__tests__/testdata/ascii/two_root_nodes_longer_names.txt +0 -19
  279. package/src/__tests__/testdata/ascii/two_single_root_nodes.txt +0 -19
  280. package/src/__tests__/testdata/unicode/ampersand_lhs.txt +0 -18
  281. package/src/__tests__/testdata/unicode/ampersand_lhs_and_rhs.txt +0 -18
  282. package/src/__tests__/testdata/unicode/ampersand_rhs.txt +0 -18
  283. package/src/__tests__/testdata/unicode/ampersand_without_edge.txt +0 -18
  284. package/src/__tests__/testdata/unicode/back_reference_from_child.txt +0 -10
  285. package/src/__tests__/testdata/unicode/backlink_from_bottom.txt +0 -22
  286. package/src/__tests__/testdata/unicode/backlink_from_top.txt +0 -22
  287. package/src/__tests__/testdata/unicode/cls_all_relationships.txt +0 -19
  288. package/src/__tests__/testdata/unicode/cls_annotation.txt +0 -29
  289. package/src/__tests__/testdata/unicode/cls_association.txt +0 -14
  290. package/src/__tests__/testdata/unicode/cls_basic.txt +0 -15
  291. package/src/__tests__/testdata/unicode/cls_dependency.txt +0 -14
  292. package/src/__tests__/testdata/unicode/cls_inheritance.txt +0 -20
  293. package/src/__tests__/testdata/unicode/cls_methods.txt +0 -21
  294. package/src/__tests__/testdata/unicode/comments.txt +0 -23
  295. package/src/__tests__/testdata/unicode/duplicate_labels.txt +0 -19
  296. package/src/__tests__/testdata/unicode/er_attributes.txt +0 -21
  297. package/src/__tests__/testdata/unicode/er_basic.txt +0 -8
  298. package/src/__tests__/testdata/unicode/er_identifying.txt +0 -18
  299. package/src/__tests__/testdata/unicode/graph_bt_direction.txt +0 -28
  300. package/src/__tests__/testdata/unicode/preserve_order_of_definition.txt +0 -23
  301. package/src/__tests__/testdata/unicode/self_reference.txt +0 -10
  302. package/src/__tests__/testdata/unicode/self_reference_with_edge.txt +0 -10
  303. package/src/__tests__/testdata/unicode/seq_basic.txt +0 -17
  304. package/src/__tests__/testdata/unicode/seq_multiple_messages.txt +0 -25
  305. package/src/__tests__/testdata/unicode/seq_self_message.txt +0 -18
  306. package/src/__tests__/testdata/unicode/single_node.txt +0 -8
  307. package/src/__tests__/testdata/unicode/single_node_longer_name.txt +0 -8
  308. package/src/__tests__/testdata/unicode/three_nodes.txt +0 -9
  309. package/src/__tests__/testdata/unicode/three_nodes_single_line.txt +0 -8
  310. package/src/__tests__/testdata/unicode/two_layer_single_graph.txt +0 -19
  311. package/src/__tests__/testdata/unicode/two_layer_single_graph_longer_names.txt +0 -19
  312. package/src/__tests__/testdata/unicode/two_nodes_linked.txt +0 -8
  313. package/src/__tests__/testdata/unicode/two_nodes_longer_names.txt +0 -8
  314. package/src/__tests__/testdata/unicode/two_root_nodes.txt +0 -19
  315. package/src/__tests__/testdata/unicode/two_root_nodes_longer_names.txt +0 -19
  316. package/src/__tests__/testdata/unicode/two_single_root_nodes.txt +0 -19
  317. package/src/__tests__/text-metrics.test.ts +0 -473
  318. package/src/__tests__/theme-palette-contrast.test.ts +0 -84
  319. package/src/__tests__/theme.test.ts +0 -132
  320. package/src/__tests__/xychart-ascii.test.ts +0 -376
  321. package/src/__tests__/xychart-colors.test.ts +0 -149
@@ -1,61 +0,0 @@
1
- // ============================================================================
2
- // ASCII sequence diagram note tests
3
- // ============================================================================
4
-
5
- import { describe, it, expect } from 'vitest'
6
- import { renderMermaidASCII } from '@zombie-mermaid/ascii-renderer'
7
-
8
- describe('ASCII sequence diagrams – pre-message notes', () => {
9
- it('renders a note placed before the first message (regression)', () => {
10
- const result = renderMermaidASCII(`sequenceDiagram
11
- participant A as Alice
12
- participant B as Bob
13
- Note over A: note 1
14
- A->>B: Hello`)
15
- expect(result).toContain('note 1')
16
- expect(result).toContain('Hello')
17
- })
18
-
19
- it('renders a notes-only diagram (0 messages) without crashing', () => {
20
- const result = renderMermaidASCII(`sequenceDiagram
21
- participant A
22
- Note over A: lonely note`)
23
- expect(result).toContain('lonely note')
24
- })
25
- })
26
-
27
- describe('ASCII sequence diagrams – note box vs. lifeline collision (regression)', () => {
28
- // When a "Note over A,B" box is computed wide enough that its own right
29
- // padding column lands exactly on B's lifeline x-position, the lifeline
30
- // (drawn in an earlier pass) must not leak through as a second border
31
- // character next to the note's real right border. 8-9 'x' characters is
32
- // the exact width, given these actors' default spacing, that reproduces
33
- // the collision — shorter or longer text misses the colliding column.
34
- for (const n of [8, 9]) {
35
- it(`does not double up border characters for a ${n}-char note spanning two actors`, () => {
36
- const noteText = 'x'.repeat(n)
37
- const result = renderMermaidASCII(
38
- `sequenceDiagram
39
- participant A
40
- participant B
41
- A->>B: hi
42
- Note over A,B: ${noteText}`,
43
- { colorMode: 'none' },
44
- )
45
- const lines = result.split('\n')
46
- const contentLine = lines.find((l) => l.includes(noteText))
47
- expect(contentLine).toBeDefined()
48
-
49
- // No two border/line-drawing characters should sit directly adjacent
50
- // with no space between them anywhere in the note's rows — that
51
- // shape (e.g. "││") only occurs when a stale lifeline character
52
- // leaks through an unblanked padding column next to a real border.
53
- const noteLineIndex = lines.indexOf(contentLine!)
54
- const topBorderLine = lines[noteLineIndex - 1]!
55
- const bottomBorderLine = lines[noteLineIndex + 1]!
56
- for (const line of [topBorderLine, contentLine!, bottomBorderLine]) {
57
- expect(line).not.toMatch(/[│|┌┐└┘][│|┌┐└┘]/)
58
- }
59
- })
60
- }
61
- })
@@ -1,119 +0,0 @@
1
- // ============================================================================
2
- // ASCII sequence diagram padding tests (issue #343)
3
- //
4
- // `-x`/`-y`/`-p` (AsciiRenderOptions.paddingX/paddingY/boxBorderPadding)
5
- // previously only affected the flowchart/state grid layout — sequence
6
- // diagrams ignored them entirely and always used fixed internal spacing
7
- // constants. This file verifies the fix: padding now visibly widens/
8
- // tightens lifeline spacing, actor-box size, and vertical row spacing,
9
- // while a render with no explicit padding option still renders byte-for-
10
- // byte identical to before the fix (see the DEFAULT_PADDING_* comment in
11
- // src/ascii/types.ts for why that matters).
12
- // ============================================================================
13
-
14
- import { describe, it, expect } from 'vitest'
15
- import { renderMermaidASCII } from '@zombie-mermaid/ascii-renderer'
16
-
17
- const SEQ = `sequenceDiagram
18
- participant A
19
- participant B
20
- A->>B: Hi`
21
-
22
- /** Column index of the first occurrence of `needle` on a given line. */
23
- function colOf(ascii: string, lineIndex: number, needle: string): number {
24
- const line = ascii.split('\n')[lineIndex]
25
- if (line === undefined) throw new Error(`no line ${lineIndex}`)
26
- const idx = line.indexOf(needle)
27
- if (idx === -1) throw new Error(`"${needle}" not found on line ${lineIndex}`)
28
- return idx
29
- }
30
-
31
- /** Width (in chars) of the first `+---+`-style border run on a line. */
32
- function borderWidth(ascii: string, lineIndex: number): number {
33
- const line = ascii.split('\n')[lineIndex]
34
- if (line === undefined) throw new Error(`no line ${lineIndex}`)
35
- const match = /\+-+\+/.exec(line)
36
- if (!match) throw new Error(`no border run on line ${lineIndex}: ${line}`)
37
- return match[0].length
38
- }
39
-
40
- function lineCount(ascii: string): number {
41
- return ascii.split('\n').filter((l) => l.length > 0).length
42
- }
43
-
44
- describe('ASCII sequence diagrams — padding (issue #343)', () => {
45
- it('renders identically with no padding options and with explicit defaults', () => {
46
- const withoutOptions = renderMermaidASCII(SEQ, { useAscii: true })
47
- const withDefaults = renderMermaidASCII(SEQ, {
48
- useAscii: true,
49
- paddingX: 5,
50
- paddingY: 5,
51
- boxBorderPadding: 1,
52
- })
53
- expect(withDefaults).toBe(withoutOptions)
54
- })
55
-
56
- it('paddingX widens the gap between lifelines (actor B shifts right)', () => {
57
- const base = renderMermaidASCII(SEQ, { useAscii: true })
58
- const wide = renderMermaidASCII(SEQ, { useAscii: true, paddingX: 25 })
59
- const baseCol = colOf(base, 1, '| B |')
60
- const wideCol = colOf(wide, 1, '| B |')
61
- expect(wideCol).toBeGreaterThan(baseCol)
62
- // Two independent step sizes from two different starting points produce
63
- // the same shift — demonstrates paddingX scales lifeline spacing
64
- // linearly rather than just "doing something" once.
65
- const mid = renderMermaidASCII(SEQ, { useAscii: true, paddingX: 15 })
66
- const midCol = colOf(mid, 1, '| B |')
67
- expect(midCol - baseCol).toBe(wideCol - midCol)
68
- })
69
-
70
- it('a very small paddingX tightens lifeline spacing below the default', () => {
71
- const base = renderMermaidASCII(SEQ, { useAscii: true })
72
- const tight = renderMermaidASCII(SEQ, { useAscii: true, paddingX: -10 })
73
- expect(colOf(tight, 1, '| B |')).toBeLessThan(colOf(base, 1, '| B |'))
74
- })
75
-
76
- it('paddingY adds extra blank rows (taller diagram)', () => {
77
- const base = renderMermaidASCII(SEQ, { useAscii: true })
78
- const tall = renderMermaidASCII(SEQ, { useAscii: true, paddingY: 25 })
79
- expect(lineCount(tall)).toBeGreaterThan(lineCount(base))
80
- // Same linearity check as paddingX above.
81
- const mid = renderMermaidASCII(SEQ, { useAscii: true, paddingY: 15 })
82
- expect(lineCount(mid) - lineCount(base)).toBe(
83
- lineCount(tall) - lineCount(mid),
84
- )
85
- })
86
-
87
- it('boxBorderPadding widens actor boxes by exactly 2 columns per unit', () => {
88
- const base = renderMermaidASCII(SEQ, { useAscii: true })
89
- const padded = renderMermaidASCII(SEQ, {
90
- useAscii: true,
91
- boxBorderPadding: 4,
92
- })
93
- // boxWidth = labelWidth + 2*boxBorderPadding + 2 (border chars) — going
94
- // from the default (1) to 4 adds 2*(4-1) = 6 columns to each actor box.
95
- expect(borderWidth(padded, 0) - borderWidth(base, 0)).toBe(6)
96
- })
97
-
98
- it('boxBorderPadding also widens note boxes and shifts note content', () => {
99
- const withNote = `sequenceDiagram
100
- participant A
101
- Note over A: hello`
102
- const base = renderMermaidASCII(withNote, { useAscii: true })
103
- const padded = renderMermaidASCII(withNote, {
104
- useAscii: true,
105
- boxBorderPadding: 4,
106
- })
107
- // The note's own top border is the second '+---+' run rendered (the
108
- // first belongs to the actor header box), so isolate it before
109
- // comparing width.
110
- const noteBorder = (ascii: string) => {
111
- const line = ascii.split('\n')[4] // note top border row
112
- const match = line ? /\+-+\+/.exec(line) : null
113
- if (!match) throw new Error(`no note border found: ${line}`)
114
- return match[0].length
115
- }
116
- expect(noteBorder(padded) - noteBorder(base)).toBe(6)
117
- expect(colOf(padded, 5, 'hello')).toBeGreaterThan(colOf(base, 5, 'hello'))
118
- })
119
- })
@@ -1,206 +0,0 @@
1
- // ============================================================================
2
- // ASCII sequence diagram — self-arrow regression tests (issue #68)
3
- //
4
- // Two bugs in the ASCII sequence-diagram renderer's handling of self-arrows
5
- // (A->>A: ...):
6
- // 1. <br/> in a self-arrow label wrote the raw string (with an embedded
7
- // newline) onto a single canvas row instead of splitting it onto
8
- // multiple rows, corrupting every column to the right for the rest of
9
- // the diagram.
10
- // 2. A self-arrow inside an alt/loop/opt block could be drawn outside the
11
- // block's wall because the wall's width was computed from lifeline
12
- // positions only, ignoring the self-arrow's loop glyphs and label.
13
- // ============================================================================
14
-
15
- import { describe, it, expect } from 'vitest'
16
- import { renderMermaidASCII } from '@zombie-mermaid/ascii-renderer'
17
-
18
- describe('ASCII sequence diagrams – self-arrow labels (issue #68)', () => {
19
- it('splits <br/> in a self-arrow label across rows without corrupting the canvas', () => {
20
- const result = renderMermaidASCII(
21
- `
22
- sequenceDiagram
23
- participant A
24
- participant B
25
- A->>A: line one<br/>line two
26
- `,
27
- { useAscii: false },
28
- )
29
-
30
- const lines = result.split('\n')
31
- const line1Idx = lines.findIndex((l) => l.includes('line one'))
32
- const line2Idx = lines.findIndex((l) => l.includes('line two'))
33
-
34
- expect(line1Idx).toBeGreaterThan(-1)
35
- expect(line2Idx).toBeGreaterThan(-1)
36
- // Each line of the label gets its own row, immediately below the last.
37
- expect(line2Idx).toBe(line1Idx + 1)
38
-
39
- // A corrupted canvas dumps the raw "line one\nline two" string onto one
40
- // cell: the terminal newline forces "line two" to print flush against
41
- // column 0 (no box-drawing indentation) instead of as a properly
42
- // positioned canvas row.
43
- expect(lines[line2Idx]!.startsWith(' ')).toBe(true)
44
-
45
- // B's lifeline must still be intact on both label rows — a corrupted
46
- // canvas shifts every column right of the embedded newline down one
47
- // row for the rest of the diagram, destroying the B column.
48
- expect(lines[line1Idx]).toContain('│')
49
- expect(lines[line2Idx]).toContain('│')
50
-
51
- // The footer actor boxes must render correctly and stay aligned with
52
- // the header boxes (proves later rows weren't shifted by the newline).
53
- const bottomBorders = (result.match(/└───┘/g) || []).length
54
- expect(bottomBorders).toBe(2) // one footer box per actor (A, B)
55
- })
56
-
57
- it('handles 3+ line self-arrow labels', () => {
58
- const result = renderMermaidASCII(
59
- `
60
- sequenceDiagram
61
- participant A
62
- A->>A: one<br/>two<br/>three
63
- `,
64
- { useAscii: false },
65
- )
66
- const lines = result.split('\n')
67
- const idxOne = lines.findIndex((l) => l.includes('one'))
68
- const idxTwo = lines.findIndex((l) => l.includes('two'))
69
- const idxThree = lines.findIndex((l) => l.includes('three'))
70
- expect(idxTwo).toBe(idxOne + 1)
71
- expect(idxThree).toBe(idxTwo + 1)
72
- })
73
-
74
- it("extends an alt block's wall past a self-arrow's loop and label", () => {
75
- const result = renderMermaidASCII(
76
- `
77
- sequenceDiagram
78
- participant A
79
- participant B
80
- alt some condition
81
- A->>A: a fairly long self-arrow label here
82
- end
83
- `,
84
- { useAscii: false },
85
- )
86
-
87
- // The block header label must not be clipped by an undersized wall.
88
- expect(result).toContain('alt [some condition]')
89
-
90
- // The self-arrow's loop corners must stay intact — a wall drawn too
91
- // far left overwrites them with the wall's vertical-bar character.
92
- expect(result).toContain('├───┐')
93
- expect(result).toContain('◀───┘')
94
-
95
- // The label and the block's right wall must coexist on the same row,
96
- // with the wall to the right of (not through) the label.
97
- const labelLine = result
98
- .split('\n')
99
- .find((l) => l.includes('a fairly long self-arrow label here'))
100
- expect(labelLine).toBeDefined()
101
- expect(labelLine!.trimEnd().endsWith('│')).toBe(true)
102
- })
103
-
104
- it("extends a loop block's wall past a self-arrow's loop and label", () => {
105
- const result = renderMermaidASCII(
106
- `
107
- sequenceDiagram
108
- participant A
109
- loop every request
110
- A->>A: a fairly long self-arrow label for the loop block
111
- end
112
- `,
113
- { useAscii: false },
114
- )
115
-
116
- expect(result).toContain('loop [every request]')
117
- expect(result).toContain('├───┐')
118
- expect(result).toContain('◀───┘')
119
-
120
- const labelLine = result
121
- .split('\n')
122
- .find((l) =>
123
- l.includes('a fairly long self-arrow label for the loop block'),
124
- )
125
- expect(labelLine).toBeDefined()
126
- expect(labelLine!.trimEnd().endsWith('│')).toBe(true)
127
- })
128
- })
129
-
130
- // ============================================================================
131
- // Self-message autonumber badge (issue #342)
132
- //
133
- // `autonumber` consumed a sequence number for a self-message but never drew
134
- // the badge glyph on the loop — the counter still advanced correctly, but a
135
- // numbered self-message and an unnumbered one looked identical. Fixed by
136
- // widening the loop (see `selfLoopWidth` in sequence.ts) to make room for the
137
- // badge digits at the start of the top arm, without disturbing the corner
138
- // glyphs (├/┐ on top, ◀/┘ on bottom).
139
- // ============================================================================
140
-
141
- describe('ASCII sequence diagrams – self-message autonumber badge (issue #342)', () => {
142
- it('draws the autonumber badge on a self-message loop', () => {
143
- const result = renderMermaidASCII(
144
- `sequenceDiagram
145
- autonumber
146
- A->>A: Reflect`,
147
- { useAscii: false },
148
- )
149
- const lines = result.split('\n')
150
- // The badge digit "1" sits on the loop's top arm, between the left
151
- // junction and the top-right corner. (Actor boxes also contain "┐", so
152
- // match on the junction character "├" to find the loop row specifically.)
153
- const topArmLine = lines.find((l) => l.includes('├'))
154
- expect(topArmLine).toBeDefined()
155
- expect(topArmLine).toMatch(/├1─+┐/)
156
- // The loop's corner glyphs must stay intact — a corrupted badge
157
- // placement would overwrite the corner instead of just the dashes.
158
- expect(result).toContain('┐')
159
- expect(result).toContain('┘')
160
- expect(result).toContain('Reflect')
161
- })
162
-
163
- it('keeps numbering in sequence across self-messages mixed with normal messages', () => {
164
- const result = renderMermaidASCII(
165
- `sequenceDiagram
166
- participant A
167
- participant B
168
- autonumber
169
- A->>B: First
170
- A->>A: Self
171
- A->>B: Third`,
172
- { useAscii: false },
173
- )
174
- const lines = result.split('\n')
175
-
176
- // First normal message numbered 1.
177
- const firstArrowLine = lines.find((l) => l.includes('▶') && l.includes('1'))
178
- expect(firstArrowLine).toBeDefined()
179
-
180
- // Self-message numbered 2, badge drawn on its loop's top arm.
181
- const selfTopArmLine = lines.find((l) => l.includes('├'))
182
- expect(selfTopArmLine).toBeDefined()
183
- expect(selfTopArmLine).toMatch(/├2─+┐/)
184
-
185
- // Third message (also A->>B) numbered 3, appearing after the self
186
- // message's rows.
187
- const selfIdx = lines.indexOf(selfTopArmLine ?? '')
188
- const thirdArrowLine = lines
189
- .slice(selfIdx + 1)
190
- .find((l) => l.includes('▶') && l.includes('3'))
191
- expect(thirdArrowLine).toBeDefined()
192
- })
193
-
194
- it('renders a self-message without autonumber unchanged (no stray digits, no regression)', () => {
195
- const result = renderMermaidASCII(
196
- `sequenceDiagram
197
- A->>A: Reflect`,
198
- { useAscii: false },
199
- )
200
- // No autonumber active — the loop must render exactly as before: plain
201
- // corners with no digit inserted into the top arm.
202
- expect(result).toContain('├───┐')
203
- expect(result).toContain('◀───┘')
204
- expect(result).toContain('Reflect')
205
- })
206
- })
@@ -1,38 +0,0 @@
1
- import { describe, it, expect } from 'vitest'
2
- import { diamondRenderer } from '../../packages/ascii-renderer/src/shapes/diamond.ts'
3
- import { canvasToString } from '../../packages/ascii-renderer/src/canvas.ts'
4
- import type { ShapeRenderOptions } from '../../packages/ascii-renderer/src/shapes/types.ts'
5
-
6
- describe('diamondRenderer.render', () => {
7
- it('draws unicode diamond corner markers around a short label', () => {
8
- const options: ShapeRenderOptions = { useAscii: false, padding: 1 }
9
- const dimensions = diamondRenderer.getDimensions('Yes', options)
10
- const canvas = diamondRenderer.render('Yes', dimensions, options)
11
-
12
- const text = canvasToString(canvas)
13
- const lines = text.split('\n')
14
-
15
- expect(lines[0]!.startsWith('◇')).toBe(true)
16
- expect(lines[0]!.endsWith('◇')).toBe(true)
17
- expect(lines[lines.length - 1]!.startsWith('◇')).toBe(true)
18
- expect(lines[lines.length - 1]!.endsWith('◇')).toBe(true)
19
- expect(text).toContain('Yes')
20
- })
21
-
22
- it('draws ascii diamond corner markers around a multi-line label', () => {
23
- const options: ShapeRenderOptions = { useAscii: true, padding: 1 }
24
- const label = 'Retry?\nCheck'
25
- const dimensions = diamondRenderer.getDimensions(label, options)
26
- const canvas = diamondRenderer.render(label, dimensions, options)
27
-
28
- const text = canvasToString(canvas)
29
- const lines = text.split('\n')
30
-
31
- expect(lines[0]!.startsWith('<')).toBe(true)
32
- expect(lines[0]!.endsWith('>')).toBe(true)
33
- expect(lines[lines.length - 1]!.startsWith('<')).toBe(true)
34
- expect(lines[lines.length - 1]!.endsWith('>')).toBe(true)
35
- expect(text).toContain('Retry?')
36
- expect(text).toContain('Check')
37
- })
38
- })
@@ -1,258 +0,0 @@
1
- import { describe, it, expect } from 'vitest'
2
- import {
3
- getBoxDimensions,
4
- renderBox,
5
- getBoxAttachmentPoint,
6
- rectangleRenderer,
7
- } from '../../packages/ascii-renderer/src/shapes/rectangle.ts'
8
- import { canvasToString } from '../../packages/ascii-renderer/src/canvas.ts'
9
- import { getCorners } from '../../packages/ascii-renderer/src/shapes/corners.ts'
10
- import {
11
- Up,
12
- Down,
13
- Left,
14
- Right,
15
- UpperLeft,
16
- UpperRight,
17
- LowerLeft,
18
- LowerRight,
19
- Middle,
20
- } from '../../packages/ascii-renderer/src/types.ts'
21
- import type { ShapeRenderOptions } from '../../packages/ascii-renderer/src/shapes/types.ts'
22
-
23
- const optsP0: ShapeRenderOptions = { useAscii: false, padding: 0 }
24
- const optsP1: ShapeRenderOptions = { useAscii: false, padding: 1 }
25
- const optsAsciiP0: ShapeRenderOptions = { useAscii: true, padding: 0 }
26
-
27
- describe('rectangle shape: getBoxDimensions', () => {
28
- it('sizes a single-line label with zero padding', () => {
29
- const dims = getBoxDimensions('Hi', optsP0)
30
- expect(dims.width).toBe(4)
31
- expect(dims.height).toBe(3)
32
- expect(dims.labelArea).toEqual({ x: 1, y: 1, width: 2, height: 1 })
33
- expect(dims.gridColumns).toEqual([1, 2, 1])
34
- expect(dims.gridRows).toEqual([1, 1, 1])
35
- })
36
-
37
- it('grows width and height with padding', () => {
38
- const dims = getBoxDimensions('Hi', optsP1)
39
- expect(dims.width).toBe(6)
40
- // rawInnerHeight = 1 + 2*1 = 3 (odd) -> innerHeight stays 3
41
- expect(dims.height).toBe(5)
42
- expect(dims.gridColumns).toEqual([1, 4, 1])
43
- expect(dims.gridRows).toEqual([1, 3, 1])
44
- })
45
-
46
- it('bumps innerHeight to odd when line count makes it even', () => {
47
- const dims = getBoxDimensions('One\nTwo', optsP0)
48
- // lineCount=2, rawInnerHeight=2 (even) -> innerHeight=3
49
- expect(dims.gridRows).toEqual([1, 3, 1])
50
- expect(dims.height).toBe(5)
51
- expect(dims.labelArea.height).toBe(2)
52
- })
53
-
54
- it('keeps innerHeight odd when line count already makes it odd', () => {
55
- const dims = getBoxDimensions('One\nTwo\nThree', optsP0)
56
- // lineCount=3, rawInnerHeight=3 (odd) -> innerHeight stays 3
57
- expect(dims.gridRows).toEqual([1, 3, 1])
58
- expect(dims.height).toBe(5)
59
- })
60
-
61
- it('uses the widest line to size width for multi-line labels', () => {
62
- const dims = getBoxDimensions('Short\nA much longer line', optsP0)
63
- const expectedWidth = 'A much longer line'.length + 2
64
- expect(dims.width).toBe(expectedWidth)
65
- expect(dims.labelArea.width).toBe('A much longer line'.length)
66
- })
67
-
68
- it('handles an empty label', () => {
69
- const dims = getBoxDimensions('', optsP0)
70
- expect(dims.labelArea.width).toBe(0)
71
- expect(dims.labelArea.height).toBe(1)
72
- expect(dims.width).toBe(2)
73
- })
74
- })
75
-
76
- describe('rectangle shape: renderBox', () => {
77
- it('draws unicode borders and corners for a single-line label', () => {
78
- const dims = getBoxDimensions('Hi', optsP0)
79
- const corners = getCorners('rectangle', false)
80
- const canvas = renderBox('Hi', dims, corners, false)
81
- const text = canvasToString(canvas)
82
- expect(text).toContain('┌')
83
- expect(text).toContain('┐')
84
- expect(text).toContain('└')
85
- expect(text).toContain('┘')
86
- expect(text).toContain('─')
87
- expect(text).toContain('│')
88
- expect(text).toContain('Hi')
89
- })
90
-
91
- it('draws ascii borders and corners for a single-line label', () => {
92
- const dims = getBoxDimensions('Hi', optsAsciiP0)
93
- const corners = getCorners('rectangle', true)
94
- const canvas = renderBox('Hi', dims, corners, true)
95
- const text = canvasToString(canvas)
96
- expect(text).toContain('+')
97
- expect(text).toContain('-')
98
- expect(text).toContain('|')
99
- expect(text).not.toContain('┌')
100
- expect(text).toContain('Hi')
101
- })
102
-
103
- it('centers a single-line label horizontally and vertically', () => {
104
- const dims = getBoxDimensions('Hi', optsP1)
105
- const corners = getCorners('rectangle', false)
106
- const canvas = renderBox('Hi', dims, corners, false)
107
- const lines = canvasToString(canvas).split('\n')
108
- const labelRow = lines.findIndex((l) => l.includes('Hi'))
109
- expect(labelRow).toBeGreaterThan(0)
110
- expect(labelRow).toBeLessThan(lines.length - 1)
111
- const col = lines[labelRow]!.indexOf('Hi')
112
- expect(col).toBeGreaterThan(0)
113
- })
114
-
115
- it('stacks a multi-line label across separate rows in order', () => {
116
- const dims = getBoxDimensions('One\nTwo\nThree', optsP0)
117
- const corners = getCorners('rectangle', false)
118
- const canvas = renderBox('One\nTwo\nThree', dims, corners, false)
119
- const lines = canvasToString(canvas).split('\n')
120
- const oneRow = lines.findIndex((l) => l.includes('One'))
121
- const twoRow = lines.findIndex((l) => l.includes('Two'))
122
- const threeRow = lines.findIndex((l) => l.includes('Three'))
123
- expect(oneRow).toBeGreaterThan(-1)
124
- expect(twoRow).toBeGreaterThan(oneRow)
125
- expect(threeRow).toBeGreaterThan(twoRow)
126
- })
127
-
128
- it('centers an even number of label lines around the middle row', () => {
129
- const dims = getBoxDimensions('One\nTwo', optsP0)
130
- const corners = getCorners('rectangle', false)
131
- const canvas = renderBox('One\nTwo', dims, corners, false)
132
- const lines = canvasToString(canvas).split('\n')
133
- const oneRow = lines.findIndex((l) => l.includes('One'))
134
- const twoRow = lines.findIndex((l) => l.includes('Two'))
135
- expect(twoRow).toBe(oneRow + 1)
136
- })
137
-
138
- it('clips label characters that fall outside the canvas bounds', () => {
139
- const tinyDims = getBoxDimensions('', optsP0)
140
- const corners = getCorners('rectangle', false)
141
- const canvas = renderBox('Hello World', tinyDims, corners, false)
142
- const text = canvasToString(canvas)
143
- expect(text).not.toContain('Hello World')
144
- })
145
-
146
- it('uses custom corner characters when provided', () => {
147
- const dims = getBoxDimensions('Hi', optsP0)
148
- const canvas = renderBox(
149
- 'Hi',
150
- dims,
151
- { tl: '<', tr: '>', bl: '<', br: '>' },
152
- false,
153
- )
154
- const text = canvasToString(canvas)
155
- expect(text).toContain('<')
156
- expect(text).toContain('>')
157
- })
158
- })
159
-
160
- describe('rectangle shape: getBoxAttachmentPoint', () => {
161
- const dims = getBoxDimensions('Hi', optsP1)
162
- const base = { x: 10, y: 20 }
163
-
164
- it('returns the top-center point for Up', () => {
165
- expect(getBoxAttachmentPoint(Up, dims, base)).toEqual({
166
- x: base.x + Math.floor(dims.width / 2),
167
- y: base.y,
168
- })
169
- })
170
-
171
- it('returns the bottom-center point for Down', () => {
172
- expect(getBoxAttachmentPoint(Down, dims, base)).toEqual({
173
- x: base.x + Math.floor(dims.width / 2),
174
- y: base.y + dims.height - 1,
175
- })
176
- })
177
-
178
- it('returns the left-middle point for Left', () => {
179
- expect(getBoxAttachmentPoint(Left, dims, base)).toEqual({
180
- x: base.x,
181
- y: base.y + Math.floor(dims.height / 2),
182
- })
183
- })
184
-
185
- it('returns the right-middle point for Right', () => {
186
- expect(getBoxAttachmentPoint(Right, dims, base)).toEqual({
187
- x: base.x + dims.width - 1,
188
- y: base.y + Math.floor(dims.height / 2),
189
- })
190
- })
191
-
192
- it('returns the top-left corner for UpperLeft', () => {
193
- expect(getBoxAttachmentPoint(UpperLeft, dims, base)).toEqual({
194
- x: base.x,
195
- y: base.y,
196
- })
197
- })
198
-
199
- it('returns the top-right corner for UpperRight', () => {
200
- expect(getBoxAttachmentPoint(UpperRight, dims, base)).toEqual({
201
- x: base.x + dims.width - 1,
202
- y: base.y,
203
- })
204
- })
205
-
206
- it('returns the bottom-left corner for LowerLeft', () => {
207
- expect(getBoxAttachmentPoint(LowerLeft, dims, base)).toEqual({
208
- x: base.x,
209
- y: base.y + dims.height - 1,
210
- })
211
- })
212
-
213
- it('returns the bottom-right corner for LowerRight', () => {
214
- expect(getBoxAttachmentPoint(LowerRight, dims, base)).toEqual({
215
- x: base.x + dims.width - 1,
216
- y: base.y + dims.height - 1,
217
- })
218
- })
219
-
220
- it('falls back to the center point for Middle', () => {
221
- expect(getBoxAttachmentPoint(Middle, dims, base)).toEqual({
222
- x: base.x + Math.floor(dims.width / 2),
223
- y: base.y + Math.floor(dims.height / 2),
224
- })
225
- })
226
- })
227
-
228
- describe('rectangleRenderer', () => {
229
- it('delegates getDimensions to getBoxDimensions', () => {
230
- expect(rectangleRenderer.getDimensions('Hi', optsP0)).toEqual(
231
- getBoxDimensions('Hi', optsP0),
232
- )
233
- })
234
-
235
- it('renders unicode rectangle corners by default', () => {
236
- const dims = rectangleRenderer.getDimensions('Hi', optsP0)
237
- const canvas = rectangleRenderer.render('Hi', dims, optsP0)
238
- const text = canvasToString(canvas)
239
- expect(text).toContain('┌')
240
- expect(text).toContain('┘')
241
- })
242
-
243
- it('renders ascii rectangle corners when useAscii is set', () => {
244
- const dims = rectangleRenderer.getDimensions('Hi', optsAsciiP0)
245
- const canvas = rectangleRenderer.render('Hi', dims, optsAsciiP0)
246
- const text = canvasToString(canvas)
247
- expect(text).toContain('+')
248
- expect(text).not.toContain('┌')
249
- })
250
-
251
- it('delegates getAttachmentPoint to getBoxAttachmentPoint', () => {
252
- const dims = rectangleRenderer.getDimensions('Hi', optsP0)
253
- const base = { x: 3, y: 4 }
254
- expect(rectangleRenderer.getAttachmentPoint(Down, dims, base)).toEqual(
255
- getBoxAttachmentPoint(Down, dims, base),
256
- )
257
- })
258
- })