@zombie-mermaid/svg-renderer 4.0.0 → 4.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.
- package/dist/index.cjs +59 -43
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +51 -1
- package/dist/index.d.ts +51 -1
- package/dist/index.js +1400 -1671
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/__tests__/flowchart-parallel-edge-lanes-1308.test.ts +168 -0
- package/src/__tests__/pie-layout.test.ts +215 -0
- package/src/__tests__/pie-svg.test.ts +194 -0
- package/src/__tests__/svg-edge-to-own-cluster-1310.test.ts +32 -0
- package/src/class/renderer.ts +2 -2
- package/src/er/renderer.ts +2 -2
- package/src/generated/mono-font-subset.ts +32 -0
- package/src/index.ts +2 -0
- package/src/layout-engine/edge-bundling.ts +79 -0
- package/src/layout-engine/to-elk.ts +15 -5
- package/src/layout-engine.ts +5 -1
- package/src/pie/layout.ts +234 -0
- package/src/pie/renderer.ts +161 -0
- package/src/registry.ts +31 -1
- package/src/styles.ts +28 -1
- package/src/title-gaps.ts +17 -2
package/src/registry.ts
CHANGED
|
@@ -57,6 +57,7 @@ import {
|
|
|
57
57
|
parseArchitecture,
|
|
58
58
|
architectureToGraph,
|
|
59
59
|
parseC4Diagram,
|
|
60
|
+
parsePieChart,
|
|
60
61
|
} from '@zombie-mermaid/mermaid-parser'
|
|
61
62
|
import type {
|
|
62
63
|
XYChart,
|
|
@@ -70,6 +71,8 @@ import type {
|
|
|
70
71
|
ArchitectureDiagram,
|
|
71
72
|
C4Diagram,
|
|
72
73
|
PositionedC4Diagram,
|
|
74
|
+
PieChart,
|
|
75
|
+
PositionedPieChart,
|
|
73
76
|
} from '@zombie-mermaid/mermaid-parser'
|
|
74
77
|
import { layoutXYChart } from './xychart/layout.ts'
|
|
75
78
|
import { renderXYChartSvg } from './xychart/renderer.ts'
|
|
@@ -81,9 +84,11 @@ import { layoutClassDiagramSync } from './class/layout.ts'
|
|
|
81
84
|
import { renderClassSvg } from './class/renderer.ts'
|
|
82
85
|
import { layoutC4DiagramSync } from './c4/layout.ts'
|
|
83
86
|
import { renderC4Svg } from './c4/renderer.ts'
|
|
87
|
+
import { layoutPieChart } from './pie/layout.ts'
|
|
88
|
+
import { renderPieSvg } from './pie/renderer.ts'
|
|
84
89
|
import { layoutFlowchartSync, layoutGraphSync } from './layout-engine.ts'
|
|
85
90
|
import { renderSvg as renderFlowchartSvg } from './renderer.ts'
|
|
86
|
-
import { parseMermaid } from '
|
|
91
|
+
import { parseMermaid } from '@zombie-mermaid/mermaid-parser'
|
|
87
92
|
|
|
88
93
|
/**
|
|
89
94
|
* Parameters shared by every per-type SVG renderer today, factored out of
|
|
@@ -380,6 +385,30 @@ const architectureModule: DiagramModule<
|
|
|
380
385
|
renderSvg: flowchartModule.renderSvg,
|
|
381
386
|
}
|
|
382
387
|
|
|
388
|
+
/**
|
|
389
|
+
* Pie charts parse from the raw `text` rather than `lines` (see
|
|
390
|
+
* `parsePieChart`'s doc: `splitStatements` would split `title A; B` and
|
|
391
|
+
* treat `'` as a quote), then lay out and render to Mermaid's geometry —
|
|
392
|
+
* see ./pie/layout.ts. No direction or interactivity applies.
|
|
393
|
+
*/
|
|
394
|
+
const pieModule: DiagramModule<PieChart, PositionedPieChart> = {
|
|
395
|
+
type: 'pie',
|
|
396
|
+
parse: (_lines, text) => parsePieChart(text),
|
|
397
|
+
layoutForSvg: layoutPieChart,
|
|
398
|
+
renderSvg(positioned, ctx) {
|
|
399
|
+
return renderPieSvg(
|
|
400
|
+
positioned,
|
|
401
|
+
ctx.colors,
|
|
402
|
+
ctx.font,
|
|
403
|
+
ctx.transparent,
|
|
404
|
+
ctx.embedSource,
|
|
405
|
+
ctx.title,
|
|
406
|
+
ctx.decorative,
|
|
407
|
+
ctx.emit,
|
|
408
|
+
)
|
|
409
|
+
},
|
|
410
|
+
}
|
|
411
|
+
|
|
383
412
|
/**
|
|
384
413
|
* The registry proper — every `DiagramType` is looked up here by the SVG
|
|
385
414
|
* front door (`renderMermaidSVG` in ./index.ts), which has no fallback
|
|
@@ -408,4 +437,5 @@ export const diagramRegistry: Record<DiagramType, AnyDiagramModule> = {
|
|
|
408
437
|
architecture: architectureModule,
|
|
409
438
|
|
|
410
439
|
c4: c4Module,
|
|
440
|
+
pie: pieModule,
|
|
411
441
|
}
|
package/src/styles.ts
CHANGED
|
@@ -7,7 +7,11 @@
|
|
|
7
7
|
// contains font metrics, spacing constants, and stroke widths.
|
|
8
8
|
// ============================================================================
|
|
9
9
|
|
|
10
|
-
import { measureTextWidth } from '@zombie-mermaid/core'
|
|
10
|
+
import { buildStyleBlock, measureTextWidth } from '@zombie-mermaid/core'
|
|
11
|
+
import {
|
|
12
|
+
MONO_FONT_FAMILY as EMBEDDED_MONO_FONT_FAMILY,
|
|
13
|
+
MONO_FONT_FACE_CSS as EMBEDDED_MONO_FONT_FACE_CSS,
|
|
14
|
+
} from './generated/mono-font-subset.ts'
|
|
11
15
|
|
|
12
16
|
/** Average character width in px at the given font size and weight (proportional font) */
|
|
13
17
|
export function estimateTextWidth(
|
|
@@ -116,3 +120,26 @@ export const ARROW_HEAD = {
|
|
|
116
120
|
width: 8,
|
|
117
121
|
height: 5,
|
|
118
122
|
} as const
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* SVG `<style>` block for a diagram: core's `buildStyleBlock` plus, when
|
|
126
|
+
* `hasMonoFont` is set, the self-hosted mono font subset for the `.mono`
|
|
127
|
+
* rule. The subset lives here rather than in `core` because only SVG output
|
|
128
|
+
* embeds it (#1319).
|
|
129
|
+
*/
|
|
130
|
+
export function buildSvgStyleBlock(
|
|
131
|
+
font: string,
|
|
132
|
+
hasMonoFont: boolean,
|
|
133
|
+
nonce?: string,
|
|
134
|
+
): string {
|
|
135
|
+
return buildStyleBlock(
|
|
136
|
+
font,
|
|
137
|
+
hasMonoFont
|
|
138
|
+
? {
|
|
139
|
+
family: EMBEDDED_MONO_FONT_FAMILY,
|
|
140
|
+
faceCss: EMBEDDED_MONO_FONT_FACE_CSS,
|
|
141
|
+
}
|
|
142
|
+
: false,
|
|
143
|
+
nonce,
|
|
144
|
+
)
|
|
145
|
+
}
|
package/src/title-gaps.ts
CHANGED
|
@@ -86,14 +86,29 @@ function segmentHitsBox(a: Point, b: Point, box: TitleTextBox): boolean {
|
|
|
86
86
|
return true
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
-
/**
|
|
89
|
+
/** The box without its `GAP_PADDING` clearance: the text itself. */
|
|
90
|
+
function textOnly(box: TitleTextBox): TitleTextBox {
|
|
91
|
+
return {
|
|
92
|
+
x: box.x + GAP_PADDING,
|
|
93
|
+
y: box.y + GAP_PADDING,
|
|
94
|
+
width: box.width - 2 * GAP_PADDING,
|
|
95
|
+
height: box.height - 2 * GAP_PADDING,
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Whether any segment of `edge` passes through the text of any of the `boxes`.
|
|
101
|
+
* The padding only widens the hole that is cut; an edge that merely passes
|
|
102
|
+
* through the clearance beside the text does not need a gap.
|
|
103
|
+
*/
|
|
90
104
|
export function edgeCrossesTitle(
|
|
91
105
|
edge: PositionedEdge,
|
|
92
106
|
boxes: TitleTextBox[],
|
|
93
107
|
): boolean {
|
|
94
108
|
const pts = edge.points
|
|
109
|
+
const texts = boxes.map(textOnly)
|
|
95
110
|
for (let i = 0; i + 1 < pts.length; i++) {
|
|
96
|
-
if (
|
|
111
|
+
if (texts.some((box) => segmentHitsBox(pts[i]!, pts[i + 1]!, box))) {
|
|
97
112
|
return true
|
|
98
113
|
}
|
|
99
114
|
}
|