agentic-mermaid 0.1.1 → 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.
- package/CHANGELOG.md +144 -4
- package/LICENSES/Apache-2.0.txt +202 -0
- package/README.md +25 -32
- package/THIRD_PARTY_NOTICES.md +29 -0
- package/dist/agent-core.d.ts +463 -0
- package/dist/agent-core.js +397 -0
- package/dist/agent.d.ts +73 -1868
- package/dist/agent.js +336 -37325
- package/dist/agentic-mermaid-mcp.js +7 -38399
- package/dist/am.js +33632 -40445
- package/dist/chunk-4QECACIA.js +4702 -0
- package/dist/chunk-CDPKJ2BQ.js +37 -0
- package/dist/chunk-QKDLMOJJ.js +3487 -0
- package/dist/chunk-WI35L7IR.js +615 -0
- package/dist/chunk-WN3YDOBG.js +149 -0
- package/dist/chunk-ZYMMKQ3I.js +62637 -0
- package/dist/index-D54dqSdC.d.ts +6777 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +310 -33014
- package/dist/mcp-cli-SBQSTJFC.js +17 -0
- package/docs/README.md +14 -6
- package/docs/schemas/style-spec.schema.json +1221 -30
- package/examples/styles/catalog.json +54 -0
- package/examples/styles/cloudflare-workers-inspired-prototype.mmd +9 -0
- package/examples/styles/cloudflare-workers-inspired-prototype.style.json +110 -0
- package/examples/styles/cupertino-prototype.mmd +10 -0
- package/examples/styles/cupertino-prototype.style.json +63 -0
- package/examples/styles/mid-century-report.style.json +2 -2
- package/examples/styles/star-chart-atlas.style.json +2 -1
- package/examples/styles/transit-route-map.style.json +2 -2
- package/examples/styles/vercel-inspired-prototype.mmd +6 -0
- package/examples/styles/vercel-inspired-prototype.style.json +87 -0
- package/package.json +68 -43
- package/server.json +2 -2
- package/skills/agentic-mermaid-diagram-workflow/SKILL.md +17 -36
- package/skills/agentic-mermaid-diagram-workflow/references/cli.md +4 -5
- package/skills/agentic-mermaid-diagram-workflow/references/code-mode.md +15 -31
- package/skills/agentic-mermaid-diagram-workflow/references/sequence.md +10 -14
- package/skills/agentic-mermaid-live-editor/SKILL.md +100 -206
- package/AGENT_NATIVE.md +0 -607
- package/Instructions_for_agents.md +0 -89
- package/TODO.md +0 -684
- package/assets/hero.png +0 -0
- package/dist/index-wjRjbsP-.d.ts +0 -1102
- package/docs/agent-api-cookbook.md +0 -308
- package/docs/agent-mutation-policy.md +0 -104
- package/docs/agent-workflow-examples.md +0 -46
- package/docs/api.md +0 -211
- package/docs/ascii.md +0 -103
- package/docs/assets/improvements/box-start-connector.png +0 -0
- package/docs/assets/improvements/comment-dropped-lint.png +0 -0
- package/docs/assets/improvements/er-content-loss.png +0 -0
- package/docs/assets/improvements/fan-in-trunks.png +0 -0
- package/docs/assets/improvements/gantt-family.png +0 -0
- package/docs/assets/improvements/gantt-milestone-clamp.png +0 -0
- package/docs/assets/improvements/gantt-verify-seam.png +0 -0
- package/docs/assets/improvements/subgraph-container-edges.png +0 -0
- package/docs/assets/improvements/wrapper-frontmatter.png +0 -0
- package/docs/assets/improvements/wrapper-init-directive.png +0 -0
- package/docs/assets/improvements/wrapper-leading-comment.png +0 -0
- package/docs/assets/style-cookbook/mid-century-report.png +0 -0
- package/docs/assets/style-cookbook/star-chart-atlas.png +0 -0
- package/docs/assets/style-cookbook/transit-route-map.png +0 -0
- package/docs/comparison.md +0 -94
- package/docs/config.md +0 -105
- package/docs/contributing/adding-diagram-types.md +0 -144
- package/docs/contributing/diagram-family-citizenship.matrix.json +0 -2127
- package/docs/contributing/diagram-family-citizenship.md +0 -82
- package/docs/contributing/harvesting-upstream-tests.md +0 -126
- package/docs/contributing/lessons-learned.md +0 -276
- package/docs/contributing/releasing.md +0 -82
- package/docs/contributing/visual-review-evidence.md +0 -53
- package/docs/custom-style-cookbook.md +0 -154
- package/docs/design/families/README.md +0 -26
- package/docs/design/families/architecture-beta.md +0 -48
- package/docs/design/families/flowchart-parser-conformance.md +0 -22
- package/docs/design/families/gantt-research.md +0 -137
- package/docs/design/families/gantt.md +0 -329
- package/docs/design/families/journey-agentic-cards-before.png +0 -0
- package/docs/design/families/journey-experience-curve-implementation.png +0 -0
- package/docs/design/families/journey-mermaid-classic-implementation.png +0 -0
- package/docs/design/families/journey-mermaid-classic-prototype.png +0 -0
- package/docs/design/families/journey-mermaid-classic-prototype.svg +0 -163
- package/docs/design/families/journey-mermaid-classic-prototype.svg.png +0 -0
- package/docs/design/families/journey-migration-parity.md +0 -439
- package/docs/design/families/journey-section-overlap-after.png +0 -0
- package/docs/design/families/journey-section-overlap-before.png +0 -0
- package/docs/design/families/journey-usage-research.md +0 -423
- package/docs/design/families/journey.md +0 -153
- package/docs/design/families/xychart.md +0 -85
- package/docs/design/system/README.md +0 -45
- package/docs/design/system/abstraction-audit.md +0 -224
- package/docs/design/system/abstraction-recommendations.md +0 -655
- package/docs/design/system/architecture.mmd +0 -29
- package/docs/design/system/architecture.svg +0 -137
- package/docs/design/system/layout-guarantees-and-robustness.md +0 -351
- package/docs/design/system/layout-rubric.md +0 -138
- package/docs/design/system/route-contracts.md +0 -848
- package/docs/design/system/source-preservation-ladder.md +0 -52
- package/docs/design/system/styles-rollout.md +0 -216
- package/docs/design/system/ugly-layouts.md +0 -119
- package/docs/diagram-families.md +0 -193
- package/docs/features.md +0 -147
- package/docs/fork-differences.md +0 -130
- package/docs/getting-started.md +0 -175
- package/docs/issue-derived-test-cases.md +0 -156
- package/docs/layout-characterization/README.md +0 -245
- package/docs/layout-characterization/contact-sheet-families.md +0 -498
- package/docs/layout-characterization/contact-sheet.md +0 -638
- package/docs/layout-characterization/properties.md +0 -281
- package/docs/layout-characterization/visual-quality.md +0 -160
- package/docs/layout-characterization/visual-snapshots/architecture.svg +0 -79
- package/docs/layout-characterization/visual-snapshots/class.svg +0 -60
- package/docs/layout-characterization/visual-snapshots/er.svg +0 -61
- package/docs/layout-characterization/visual-snapshots/flowchart.svg +0 -58
- package/docs/layout-characterization/visual-snapshots/gantt.svg +0 -52
- package/docs/layout-characterization/visual-snapshots/journey.svg +0 -98
- package/docs/layout-characterization/visual-snapshots/pie.svg +0 -36
- package/docs/layout-characterization/visual-snapshots/quadrant.svg +0 -47
- package/docs/layout-characterization/visual-snapshots/sequence.svg +0 -59
- package/docs/layout-characterization/visual-snapshots/state.svg +0 -52
- package/docs/layout-characterization/visual-snapshots/timeline.svg +0 -64
- package/docs/layout-characterization/visual-snapshots/xychart.svg +0 -97
- package/docs/mcp-code-mode-rationale.md +0 -101
- package/docs/mcp-http-transport.md +0 -223
- package/docs/mermaid-layout-complaints.md +0 -837
- package/docs/mutation-testing.md +0 -206
- package/docs/project/divergences.md +0 -98
- package/docs/project/dogfooding-docs-strategy.md +0 -66
- package/docs/project/hosted-mcp-cloudflare-plan.md +0 -338
- package/docs/project/lessons-learned.md +0 -1019
- package/docs/project/remove-role-styling-plan.md +0 -176
- package/docs/quality.md +0 -215
- package/docs/react.md +0 -97
- package/docs/style-authoring.md +0 -133
- package/docs/testing-strategy.md +0 -335
- package/docs/theming.md +0 -162
- package/examples/agent-improve-auth-flow.ts +0 -206
- package/examples/agent-loop.ts +0 -53
- package/examples/mcp-vs-cli-complex-diagrams.ts +0 -133
- package/llms.txt +0 -104
- package/skill-evals/README.md +0 -77
- package/skill-evals/fixtures/architecture-cache/input.mmd +0 -5
- package/skill-evals/fixtures/class-payment/input.mmd +0 -4
- package/skill-evals/fixtures/er-orders/input.mmd +0 -10
- package/skill-evals/fixtures/flowchart-cache/input.mmd +0 -3
- package/skill-evals/fixtures/gantt-release/input.mmd +0 -7
- package/skill-evals/fixtures/journey-checkout/input.mmd +0 -6
- package/skill-evals/fixtures/pie-exports/input.mmd +0 -5
- package/skill-evals/fixtures/quadrant-priorities/input.mmd +0 -11
- package/skill-evals/fixtures/sequence-retry/input.mmd +0 -8
- package/skill-evals/fixtures/state-lifecycle/input.mmd +0 -5
- package/skill-evals/fixtures/timeline-release/input.mmd +0 -6
- package/skill-evals/fixtures/xychart-growth/input.mmd +0 -5
- package/skill-evals/shared-benchmark.json +0 -510
- package/src/agent/analyze.ts +0 -157
- package/src/agent/apply.ts +0 -146
- package/src/agent/architecture-body.ts +0 -458
- package/src/agent/certificates.ts +0 -110
- package/src/agent/class-body.ts +0 -319
- package/src/agent/core.ts +0 -207
- package/src/agent/create.ts +0 -106
- package/src/agent/describe.ts +0 -368
- package/src/agent/er-body.ts +0 -224
- package/src/agent/facts.ts +0 -360
- package/src/agent/families-builtin.ts +0 -920
- package/src/agent/families.ts +0 -232
- package/src/agent/family-layouts.ts +0 -832
- package/src/agent/flowchart-body.ts +0 -372
- package/src/agent/flowchart-unsupported.ts +0 -243
- package/src/agent/font-coverage.ts +0 -288
- package/src/agent/gantt-body.ts +0 -495
- package/src/agent/index.ts +0 -10
- package/src/agent/journey-body.ts +0 -374
- package/src/agent/label-metrics.ts +0 -28
- package/src/agent/layout-to-rendered.ts +0 -63
- package/src/agent/mutate.ts +0 -97
- package/src/agent/mutation-ops.ts +0 -51
- package/src/agent/op-schema.ts +0 -443
- package/src/agent/parse.ts +0 -223
- package/src/agent/pie-body.ts +0 -270
- package/src/agent/png.ts +0 -171
- package/src/agent/quadrant-body.ts +0 -336
- package/src/agent/quality.ts +0 -363
- package/src/agent/readability-audit.ts +0 -92
- package/src/agent/rendered-route-audit.ts +0 -61
- package/src/agent/sequence-body.ts +0 -345
- package/src/agent/serialize.ts +0 -214
- package/src/agent/state-body.ts +0 -589
- package/src/agent/structural-count.ts +0 -150
- package/src/agent/timeline-body.ts +0 -280
- package/src/agent/trace-log.ts +0 -43
- package/src/agent/types.ts +0 -995
- package/src/agent/verify.ts +0 -603
- package/src/agent/xychart-body.ts +0 -472
- package/src/architecture/config.ts +0 -282
- package/src/architecture/layout.ts +0 -496
- package/src/architecture/parser.ts +0 -375
- package/src/architecture/renderer.ts +0 -611
- package/src/architecture/types.ts +0 -113
- package/src/ascii/ansi.ts +0 -423
- package/src/ascii/architecture.ts +0 -210
- package/src/ascii/canvas.ts +0 -443
- package/src/ascii/class-diagram.ts +0 -697
- package/src/ascii/converter.ts +0 -475
- package/src/ascii/draw.ts +0 -1693
- package/src/ascii/edge-bundling.ts +0 -328
- package/src/ascii/edge-routing.ts +0 -330
- package/src/ascii/er-diagram.ts +0 -439
- package/src/ascii/gantt.ts +0 -276
- package/src/ascii/grid.ts +0 -747
- package/src/ascii/index.ts +0 -196
- package/src/ascii/journey.ts +0 -169
- package/src/ascii/meta.ts +0 -244
- package/src/ascii/multiline-utils.ts +0 -80
- package/src/ascii/pathfinder.ts +0 -301
- package/src/ascii/pie.ts +0 -67
- package/src/ascii/quadrant.ts +0 -158
- package/src/ascii/reverse.ts +0 -216
- package/src/ascii/sequence.ts +0 -499
- package/src/ascii/shapes/circle.ts +0 -27
- package/src/ascii/shapes/corners.ts +0 -143
- package/src/ascii/shapes/diamond.ts +0 -27
- package/src/ascii/shapes/hexagon.ts +0 -27
- package/src/ascii/shapes/index.ts +0 -106
- package/src/ascii/shapes/rectangle.ts +0 -168
- package/src/ascii/shapes/rounded.ts +0 -27
- package/src/ascii/shapes/special.ts +0 -332
- package/src/ascii/shapes/stadium.ts +0 -110
- package/src/ascii/shapes/state.ts +0 -192
- package/src/ascii/shapes/types.ts +0 -73
- package/src/ascii/timeline.ts +0 -141
- package/src/ascii/types.ts +0 -312
- package/src/ascii/validate.ts +0 -120
- package/src/ascii/width.ts +0 -81
- package/src/ascii/wrap.ts +0 -131
- package/src/ascii/xychart.ts +0 -919
- package/src/browser.ts +0 -29
- package/src/class/layout.ts +0 -240
- package/src/class/parser.ts +0 -332
- package/src/class/renderer.ts +0 -638
- package/src/class/types.ts +0 -129
- package/src/cli/agent-instructions.ts +0 -1
- package/src/cli/am-bin.ts +0 -6
- package/src/cli/exit-codes.ts +0 -18
- package/src/cli/index.ts +0 -1132
- package/src/cli/init-agent.ts +0 -147
- package/src/cli/run-entrypoint.ts +0 -10
- package/src/color-resolver.ts +0 -152
- package/src/elk-instance.ts +0 -114
- package/src/er/layout.ts +0 -187
- package/src/er/parser.ts +0 -226
- package/src/er/renderer.ts +0 -792
- package/src/er/types.ts +0 -99
- package/src/family-rubric.ts +0 -425
- package/src/font-manifest.ts +0 -31
- package/src/gantt/layout.ts +0 -365
- package/src/gantt/parser.ts +0 -282
- package/src/gantt/pipeline.ts +0 -27
- package/src/gantt/renderer.ts +0 -414
- package/src/gantt/schedule.ts +0 -513
- package/src/gantt/types.ts +0 -255
- package/src/index.ts +0 -368
- package/src/journey/layout.ts +0 -554
- package/src/journey/parse-core.ts +0 -251
- package/src/journey/parser.ts +0 -101
- package/src/journey/renderer.ts +0 -917
- package/src/journey/types.ts +0 -144
- package/src/layout/geometry.ts +0 -182
- package/src/layout/pass.ts +0 -142
- package/src/layout/passes/index.ts +0 -3916
- package/src/layout-engine.ts +0 -1565
- package/src/layout-rubric.ts +0 -659
- package/src/mcp/artifacts.ts +0 -137
- package/src/mcp/dynamic-harness.ts +0 -31
- package/src/mcp/dynamic-modules.d.ts +0 -7
- package/src/mcp/facade.ts +0 -608
- package/src/mcp/harness-runtime.ts +0 -203
- package/src/mcp/hosted-server.ts +0 -468
- package/src/mcp/mcp-bin.ts +0 -3
- package/src/mcp/mcp-cli.ts +0 -82
- package/src/mcp/protocol.ts +0 -13
- package/src/mcp/sandbox.ts +0 -195
- package/src/mcp/sdk-decl.ts +0 -391
- package/src/mcp/server.ts +0 -362
- package/src/mcp/tool-surface.ts +0 -146
- package/src/mermaid-source.ts +0 -655
- package/src/multiline-utils.ts +0 -228
- package/src/parser.ts +0 -1031
- package/src/pie/layout.ts +0 -168
- package/src/pie/parser.ts +0 -136
- package/src/pie/renderer.ts +0 -234
- package/src/pie/types.ts +0 -82
- package/src/quadrant/layout.ts +0 -191
- package/src/quadrant/parser.ts +0 -183
- package/src/quadrant/renderer.ts +0 -322
- package/src/quadrant/types.ts +0 -113
- package/src/render-family-hooks.ts +0 -244
- package/src/renderer.ts +0 -1099
- package/src/route-contracts.ts +0 -2723
- package/src/scene/backend.ts +0 -76
- package/src/scene/fidelity.ts +0 -183
- package/src/scene/hybrid-backend.ts +0 -174
- package/src/scene/ir.ts +0 -181
- package/src/scene/marks.ts +0 -127
- package/src/scene/rough-backend.ts +0 -378
- package/src/scene/seed.ts +0 -46
- package/src/scene/style-registry.ts +0 -556
- package/src/sequence/layout.ts +0 -456
- package/src/sequence/parser.ts +0 -255
- package/src/sequence/renderer.ts +0 -604
- package/src/sequence/types.ts +0 -154
- package/src/shape-clipping.ts +0 -351
- package/src/shared/accessibility-directives.ts +0 -22
- package/src/shared/batched.ts +0 -61
- package/src/shared/color-math.ts +0 -93
- package/src/shared/svg-a11y.ts +0 -29
- package/src/shared/syntax-error.ts +0 -17
- package/src/shared/unicode-ranges.ts +0 -135
- package/src/styles.ts +0 -318
- package/src/svg-paths.ts +0 -28
- package/src/text-metrics.ts +0 -248
- package/src/theme.ts +0 -710
- package/src/timeline/layout.ts +0 -381
- package/src/timeline/parser.ts +0 -215
- package/src/timeline/renderer.ts +0 -538
- package/src/timeline/types.ts +0 -105
- package/src/types.ts +0 -462
- package/src/website-worker-modules.d.ts +0 -18
- package/src/xychart/axis-utils.ts +0 -109
- package/src/xychart/colors.ts +0 -124
- package/src/xychart/config.ts +0 -88
- package/src/xychart/layout.ts +0 -656
- package/src/xychart/parser.ts +0 -504
- package/src/xychart/renderer.ts +0 -640
- package/src/xychart/types.ts +0 -282
package/src/multiline-utils.ts
DELETED
|
@@ -1,228 +0,0 @@
|
|
|
1
|
-
// ============================================================================
|
|
2
|
-
// Multi-line Text Rendering Utilities
|
|
3
|
-
//
|
|
4
|
-
// Shared utilities for rendering multi-line text in SVG using <tspan> elements.
|
|
5
|
-
// Supports inline formatting: <b>, <i>, <u>, <s> mapped to SVG attributes.
|
|
6
|
-
// Used across all diagram types (flowcharts, state, sequence, class, ER).
|
|
7
|
-
// ============================================================================
|
|
8
|
-
|
|
9
|
-
import { LINE_HEIGHT_RATIO } from './text-metrics.ts'
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Normalize label text: strip surrounding quotes, convert <br> tags and
|
|
13
|
-
* literal \n sequences to newline characters. Strips unsupported HTML tags
|
|
14
|
-
* but preserves formatting tags (<b>, <i>, <u>, <s>) for SVG rendering.
|
|
15
|
-
*/
|
|
16
|
-
export function normalizeBrTags(label: string): string {
|
|
17
|
-
// Strip surrounding double quotes (Mermaid uses them for special chars in labels)
|
|
18
|
-
const unquoted = label.startsWith('"') && label.endsWith('"') ? label.slice(1, -1) : label
|
|
19
|
-
return unquoted
|
|
20
|
-
.replace(/<br\s*\/?>/gi, '\n')
|
|
21
|
-
.replace(/\\n/g, '\n')
|
|
22
|
-
.replace(/<\/?(?:sub|sup|small|mark)\s*>/gi, '')
|
|
23
|
-
// Markdown formatting → HTML tags (order matters: ** before *)
|
|
24
|
-
.replace(/\*\*(.+?)\*\*/g, '<b>$1</b>')
|
|
25
|
-
.replace(/(?<!\*)\*([^\s*](?:[^*]*[^\s*])?)\*(?!\*)/g, '<i>$1</i>')
|
|
26
|
-
.replace(/~~(.+?)~~/g, '<s>$1</s>')
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Strip all inline formatting tags from text, keeping only plain text.
|
|
31
|
-
* Used for text measurement where tag characters shouldn't affect width.
|
|
32
|
-
*/
|
|
33
|
-
export function stripFormattingTags(text: string): string {
|
|
34
|
-
return text.replace(/<\/?(?:b|strong|i|em|u|s|del)\s*>/gi, '')
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Escape special XML characters in text content.
|
|
39
|
-
*/
|
|
40
|
-
export function escapeXml(text: string): string {
|
|
41
|
-
return text
|
|
42
|
-
.replace(/&/g, '&')
|
|
43
|
-
.replace(/</g, '<')
|
|
44
|
-
.replace(/>/g, '>')
|
|
45
|
-
.replace(/"/g, '"')
|
|
46
|
-
.replace(/'/g, ''')
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Escape text for use inside a double-quoted XML attribute. The escape set is
|
|
51
|
-
* the same one escapeXml uses — a superset of what attributes strictly need —
|
|
52
|
-
* so element text and attribute values stay consistent everywhere.
|
|
53
|
-
*/
|
|
54
|
-
export function escapeAttr(text: string): string {
|
|
55
|
-
return escapeXml(text)
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// ============================================================================
|
|
59
|
-
// Inline formatting: <b>, <i>, <u>, <s> → SVG tspan attributes
|
|
60
|
-
// ============================================================================
|
|
61
|
-
|
|
62
|
-
interface StyledSegment {
|
|
63
|
-
text: string
|
|
64
|
-
bold: boolean
|
|
65
|
-
italic: boolean
|
|
66
|
-
underline: boolean
|
|
67
|
-
strikethrough: boolean
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/** Regex to match opening/closing formatting tags */
|
|
71
|
-
const FORMAT_TAG_REGEX = /<(\/)?(?:(b|strong)|(i|em)|(u)|(s|del))\s*>/gi
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Parse a line of text into styled segments based on inline formatting tags.
|
|
75
|
-
* Supports nesting: `<b>bold <i>both</i> bold</b>`.
|
|
76
|
-
*/
|
|
77
|
-
function parseInlineFormatting(line: string): StyledSegment[] {
|
|
78
|
-
const segments: StyledSegment[] = []
|
|
79
|
-
let bold = false, italic = false, underline = false, strikethrough = false
|
|
80
|
-
let lastIndex = 0
|
|
81
|
-
|
|
82
|
-
// Reset lastIndex for global regex
|
|
83
|
-
FORMAT_TAG_REGEX.lastIndex = 0
|
|
84
|
-
|
|
85
|
-
let match: RegExpExecArray | null
|
|
86
|
-
while ((match = FORMAT_TAG_REGEX.exec(line)) !== null) {
|
|
87
|
-
// Capture text before this tag
|
|
88
|
-
if (match.index > lastIndex) {
|
|
89
|
-
segments.push({ text: line.slice(lastIndex, match.index), bold, italic, underline, strikethrough })
|
|
90
|
-
}
|
|
91
|
-
lastIndex = match.index + match[0].length
|
|
92
|
-
|
|
93
|
-
const isClosing = Boolean(match[1])
|
|
94
|
-
// match[2] = b|strong, match[3] = i|em, match[4] = u, match[5] = s|del
|
|
95
|
-
if (match[2]) bold = !isClosing
|
|
96
|
-
else if (match[3]) italic = !isClosing
|
|
97
|
-
else if (match[4]) underline = !isClosing
|
|
98
|
-
else if (match[5]) strikethrough = !isClosing
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// Remaining text after last tag
|
|
102
|
-
if (lastIndex < line.length) {
|
|
103
|
-
segments.push({ text: line.slice(lastIndex), bold, italic, underline, strikethrough })
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
return segments
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/** Check if a line contains any formatting tags */
|
|
110
|
-
const HAS_FORMAT_TAGS = /<\/?(?:b|strong|i|em|u|s|del)\s*>/i
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* Render a line's content as SVG, with inline formatting applied as tspan attributes.
|
|
114
|
-
* Returns raw SVG content (no wrapping tspan — caller provides positioning).
|
|
115
|
-
*/
|
|
116
|
-
function renderLineContent(line: string): string {
|
|
117
|
-
// Fast path: no formatting tags
|
|
118
|
-
if (!HAS_FORMAT_TAGS.test(line)) return escapeXml(line)
|
|
119
|
-
|
|
120
|
-
const segments = parseInlineFormatting(line)
|
|
121
|
-
if (segments.length === 0) return ''
|
|
122
|
-
|
|
123
|
-
// If all segments are unstyled, just escape
|
|
124
|
-
const allPlain = segments.every(s => !s.bold && !s.italic && !s.underline && !s.strikethrough)
|
|
125
|
-
if (allPlain) return segments.map(s => escapeXml(s.text)).join('')
|
|
126
|
-
|
|
127
|
-
return segments.map(seg => {
|
|
128
|
-
const escaped = escapeXml(seg.text)
|
|
129
|
-
if (!seg.bold && !seg.italic && !seg.underline && !seg.strikethrough) return escaped
|
|
130
|
-
|
|
131
|
-
const attrs: string[] = []
|
|
132
|
-
if (seg.bold) attrs.push('font-weight="bold"')
|
|
133
|
-
if (seg.italic) attrs.push('font-style="italic"')
|
|
134
|
-
// SVG text-decoration can combine values
|
|
135
|
-
const deco: string[] = []
|
|
136
|
-
if (seg.underline) deco.push('underline')
|
|
137
|
-
if (seg.strikethrough) deco.push('line-through')
|
|
138
|
-
if (deco.length) attrs.push(`text-decoration="${deco.join(' ')}"`)
|
|
139
|
-
|
|
140
|
-
return `<tspan ${attrs.join(' ')}>${escaped}</tspan>`
|
|
141
|
-
}).join('')
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
// ============================================================================
|
|
145
|
-
// Multi-line text rendering
|
|
146
|
-
// ============================================================================
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* Render a multi-line text element with proper vertical centering.
|
|
150
|
-
*
|
|
151
|
-
* For single-line text, returns a simple <text> element.
|
|
152
|
-
* For multi-line text (containing \n), returns <text> with <tspan> children.
|
|
153
|
-
* Inline formatting tags (<b>, <i>, <u>, <s>) are rendered as SVG attributes.
|
|
154
|
-
*
|
|
155
|
-
* @param text - The text to render (may contain \n and formatting tags)
|
|
156
|
-
* @param cx - Center x coordinate
|
|
157
|
-
* @param cy - Center y coordinate
|
|
158
|
-
* @param fontSize - Font size in pixels
|
|
159
|
-
* @param attrs - Additional SVG attributes (e.g., 'text-anchor="middle" fill="var(--_text)"')
|
|
160
|
-
* @param baselineShift - Baseline shift for vertical alignment (default 0.35)
|
|
161
|
-
* @returns SVG text element string
|
|
162
|
-
*/
|
|
163
|
-
export function renderMultilineText(
|
|
164
|
-
text: string,
|
|
165
|
-
cx: number,
|
|
166
|
-
cy: number,
|
|
167
|
-
fontSize: number,
|
|
168
|
-
attrs: string,
|
|
169
|
-
baselineShift: number = 0.35
|
|
170
|
-
): string {
|
|
171
|
-
const lines = text.split('\n')
|
|
172
|
-
|
|
173
|
-
// Single line — simple text element
|
|
174
|
-
if (lines.length === 1) {
|
|
175
|
-
const dy = fontSize * baselineShift
|
|
176
|
-
return `<text x="${cx}" y="${cy}" ${attrs} dy="${dy}">${renderLineContent(text)}</text>`
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
// Multi-line — use tspan elements with vertical centering
|
|
180
|
-
const lineHeight = fontSize * LINE_HEIGHT_RATIO
|
|
181
|
-
// First line dy: shift up by (n-1)/2 line heights, then add baseline shift
|
|
182
|
-
const firstDy = -((lines.length - 1) / 2) * lineHeight + fontSize * baselineShift
|
|
183
|
-
|
|
184
|
-
const tspans = lines.map((line, i) => {
|
|
185
|
-
const dy = i === 0 ? firstDy : lineHeight
|
|
186
|
-
return `<tspan x="${cx}" dy="${dy}">${renderLineContent(line)}</tspan>`
|
|
187
|
-
}).join('')
|
|
188
|
-
|
|
189
|
-
return `<text x="${cx}" y="${cy}" ${attrs}>${tspans}</text>`
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
/**
|
|
193
|
-
* Render a multi-line text element with a background rectangle (pill).
|
|
194
|
-
*
|
|
195
|
-
* Used for edge labels that need a background for readability.
|
|
196
|
-
*
|
|
197
|
-
* @param text - The text to render (may contain \n)
|
|
198
|
-
* @param cx - Center x coordinate
|
|
199
|
-
* @param cy - Center y coordinate
|
|
200
|
-
* @param textWidth - Pre-calculated text width (max line width)
|
|
201
|
-
* @param textHeight - Pre-calculated text height (lines × lineHeight)
|
|
202
|
-
* @param fontSize - Font size in pixels
|
|
203
|
-
* @param padding - Padding around text
|
|
204
|
-
* @param textAttrs - SVG attributes for the text element
|
|
205
|
-
* @param bgAttrs - SVG attributes for the background rect
|
|
206
|
-
* @returns SVG elements string (rect + text)
|
|
207
|
-
*/
|
|
208
|
-
export function renderMultilineTextWithBackground(
|
|
209
|
-
text: string,
|
|
210
|
-
cx: number,
|
|
211
|
-
cy: number,
|
|
212
|
-
textWidth: number,
|
|
213
|
-
textHeight: number,
|
|
214
|
-
fontSize: number,
|
|
215
|
-
padding: number,
|
|
216
|
-
textAttrs: string,
|
|
217
|
-
bgAttrs: string
|
|
218
|
-
): string {
|
|
219
|
-
const bgWidth = textWidth + padding * 2
|
|
220
|
-
const bgHeight = textHeight + padding * 2
|
|
221
|
-
|
|
222
|
-
const rect = `<rect x="${cx - bgWidth / 2}" y="${cy - bgHeight / 2}" ` +
|
|
223
|
-
`width="${bgWidth}" height="${bgHeight}" ${bgAttrs} />`
|
|
224
|
-
|
|
225
|
-
const textEl = renderMultilineText(text, cx, cy, fontSize, textAttrs)
|
|
226
|
-
|
|
227
|
-
return `${rect}\n${textEl}`
|
|
228
|
-
}
|