@zombie-mermaid/ascii-renderer 3.0.0 → 3.2.0

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 (37) hide show
  1. package/dist/index.cjs +7 -7
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.js +2484 -1467
  4. package/dist/index.js.map +1 -1
  5. package/package.json +3 -3
  6. package/src/__tests__/ascii-bt-label-order.test.ts +97 -0
  7. package/src/__tests__/ascii-cluster-exit-anchoring-1148.test.ts +774 -0
  8. package/src/__tests__/ascii-cluster-exit-lanes-1182.test.ts +375 -0
  9. package/src/__tests__/ascii-fan-in-then-fan-out-upstream-63.test.ts +78 -0
  10. package/src/__tests__/ascii-fan-out-upstream-113.test.ts +101 -0
  11. package/src/__tests__/ascii-role-colors.test.ts +328 -0
  12. package/src/__tests__/ascii-subgraph-back-edge-1197.test.ts +212 -0
  13. package/src/__tests__/ascii-subgraph-label-border-clip.test.ts +4 -2
  14. package/src/__tests__/ascii-subgraph-title-edge-1222.test.ts +106 -0
  15. package/src/__tests__/c4-ascii.test.ts +311 -0
  16. package/src/__tests__/testdata/ascii/subgraph_direction_override.txt +21 -21
  17. package/src/__tests__/testdata/ascii/subgraph_mixed_nodes_td.txt +1 -1
  18. package/src/__tests__/xychart-ascii-ticks.test.ts +34 -0
  19. package/src/ansi.ts +16 -2
  20. package/src/architecture.ts +33 -0
  21. package/src/c4-diagram.ts +1087 -0
  22. package/src/canvas.ts +78 -8
  23. package/src/cluster-boundary.ts +429 -0
  24. package/src/converter.ts +18 -2
  25. package/src/draw-arrows.ts +120 -18
  26. package/src/draw-boxes.ts +1 -0
  27. package/src/draw-subgraphs.ts +102 -2
  28. package/src/draw.ts +57 -3
  29. package/src/edge-cell-styles.ts +20 -1
  30. package/src/edge-routing.ts +77 -1
  31. package/src/flowchart.ts +28 -3
  32. package/src/frame-avoidance.ts +235 -0
  33. package/src/grid.ts +78 -19
  34. package/src/pathfinder.ts +22 -2
  35. package/src/registry.ts +8 -0
  36. package/src/types.ts +69 -0
  37. package/src/xychart.ts +24 -5
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zombie-mermaid/ascii-renderer",
3
- "version": "3.0.0",
3
+ "version": "3.2.0",
4
4
  "license": "MIT",
5
5
  "description": "ASCII and Unicode box-drawing renderer for zombie-mermaid diagrams.",
6
6
  "repository": {
@@ -35,7 +35,7 @@
35
35
  "LICENSE"
36
36
  ],
37
37
  "dependencies": {
38
- "@zombie-mermaid/core": "3.0.0",
39
- "@zombie-mermaid/mermaid-parser": "3.0.0"
38
+ "@zombie-mermaid/core": "3.2.0",
39
+ "@zombie-mermaid/mermaid-parser": "3.2.0"
40
40
  }
41
41
  }
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Regression tests: BT is laid out as TD and the finished canvas is flipped
3
+ * vertically. The flip must mirror node positions and edge/arrowhead
4
+ * directions but leave each label's lines in reading order, and must not
5
+ * treat label characters (`v`, `^`) as arrowheads.
6
+ */
7
+ import { describe, it, expect } from 'vitest'
8
+ import { renderMermaidASCII } from '@zombie-mermaid/ascii-renderer'
9
+
10
+ const bt = (src: string) => renderMermaidASCII(src, { colorMode: 'none' })
11
+ const rowOf = (out: string, needle: string) =>
12
+ out.split('\n').findIndex((l) => l.includes(needle))
13
+
14
+ describe('BT direction keeps label text intact', () => {
15
+ it('keeps multi-line node label lines in reading order', () => {
16
+ const out = bt('graph BT\n A["Top<br/>Second"] --> B["Below"]')
17
+ expect(rowOf(out, 'Top')).toBeLessThan(rowOf(out, 'Second'))
18
+ // Nodes are still mirrored: the edge target sits above its source.
19
+ expect(rowOf(out, 'Below')).toBeLessThan(rowOf(out, 'Top'))
20
+ })
21
+
22
+ it('keeps multi-line edge label lines in reading order', () => {
23
+ const out = bt('graph BT\n A -->|"up<br/>down"| B')
24
+ expect(rowOf(out, 'up')).toBeLessThan(rowOf(out, 'down'))
25
+ })
26
+
27
+ it('does not rewrite v / ^ characters inside labels', () => {
28
+ const out = bt('graph BT\n A["v ^<br/>x"] --> B')
29
+ expect(out).toContain('v ^')
30
+ expect(rowOf(out, 'v ^')).toBeLessThan(rowOf(out, 'x'))
31
+ })
32
+
33
+ it('draws a cylinder with its rounded caps the right way up', () => {
34
+ const lines = bt('graph BT\n A[("DB")] --> B').split('\n')
35
+ const top = lines.find((l) => l.includes('╭'))!
36
+ const bottom = lines.find((l) => l.includes('╰'))!
37
+ expect(lines.indexOf(top)).toBeLessThan(lines.indexOf(bottom))
38
+ })
39
+
40
+ it('keeps paragraphs on either side of a blank label line in order', () => {
41
+ const out = bt(
42
+ 'graph BT\n A["Name<br/>[type]<br/><br/>Description"] --> B["x"]',
43
+ )
44
+ const [name, type, desc] = ['Name', '[type]', 'Description'].map((t) =>
45
+ rowOf(out, t),
46
+ ) as [number, number, number]
47
+ expect(name).toBeLessThan(type)
48
+ // The blank line stays between [type] and Description.
49
+ expect(desc - type).toBe(2)
50
+ expect(out.split('\n')[type + 1]!.replace(/[│\s]/g, '')).toBe('')
51
+ })
52
+
53
+ it('keeps a wide first line intact above a shorter second line', () => {
54
+ const out = bt(
55
+ 'graph BT\n A["Personal Banking Customer<br/>[Person]"] --> B["x"]',
56
+ )
57
+ const rows = out.split('\n')
58
+ const wide = rows[rowOf(out, 'Personal Banking Customer')]!
59
+ const narrow = rows[rowOf(out, '[Person]')]!
60
+ expect(rowOf(out, 'Personal Banking Customer')).toBeLessThan(
61
+ rowOf(out, '[Person]'),
62
+ )
63
+ // [Person] stays centred under the wide line.
64
+ const mid = (l: string, t: string) => l.indexOf(t) + t.length / 2
65
+ expect(
66
+ Math.abs(
67
+ mid(wide, 'Personal Banking Customer') - mid(narrow, '[Person]'),
68
+ ),
69
+ ).toBeLessThanOrEqual(1)
70
+ })
71
+
72
+ it('does not split a hyphenated node label when it moves', () => {
73
+ const out = bt('graph BT\n A["E-mail System<br/>[Software]"] --> B["x"]')
74
+ expect(out).toContain('E-mail System')
75
+ expect(rowOf(out, 'E-mail System')).toBeLessThan(rowOf(out, '[Software]'))
76
+ })
77
+
78
+ it('draws hyphenated edge labels the same as TD, vertical and horizontal', () => {
79
+ const edgeRow = (out: string) =>
80
+ out
81
+ .split('\n')
82
+ .find((l) => l.includes('E-mail'))!
83
+ .trim()
84
+ for (const src of [
85
+ 'A -->|"E-mail System"| B',
86
+ 'A --> B\n B -->|"E-mail System"| C\n A --> C',
87
+ ]) {
88
+ expect(edgeRow(bt(`graph BT\n ${src}`))).toBe(
89
+ edgeRow(
90
+ renderMermaidASCII(`graph TD\n ${src}`, { colorMode: 'none' }),
91
+ ),
92
+ )
93
+ }
94
+ const tall = bt('graph BT\n A -->|"E-mail<br/>up-down"| B')
95
+ expect(rowOf(tall, 'E-mail')).toBeLessThan(rowOf(tall, 'up-down'))
96
+ })
97
+ })