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.
- package/CHANGELOG.md +149 -4
- package/LICENSES/Apache-2.0.txt +202 -0
- package/README.md +25 -32
- package/THIRD_PARTY_NOTICES.md +29 -0
- package/assets/fonts/FONT-LICENSES.md +9 -5
- package/assets/fonts/Inter-Bold.ttf +0 -0
- package/assets/fonts/Inter-Medium.ttf +0 -0
- package/assets/fonts/Inter-Regular.ttf +0 -0
- package/assets/fonts/Inter-SemiBold.ttf +0 -0
- package/dist/agent-core.d.ts +463 -0
- package/dist/agent-core.js +397 -0
- package/dist/agent.d.ts +81 -1822
- package/dist/agent.js +336 -36839
- package/dist/agentic-mermaid-mcp.js +7 -37908
- package/dist/am.js +33638 -36261
- 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 -32836
- 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 +70 -43
- package/server.json +41 -0
- 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 -602
- package/Instructions_for_agents.md +0 -83
- package/TODO.md +0 -662
- package/assets/hero.png +0 -0
- package/dist/index-x2Cj1dVv.d.ts +0 -1089
- 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 -203
- 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 -71
- 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-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 -433
- package/docs/design/families/journey-usage-research.md +0 -423
- package/docs/design/families/journey.md +0 -125
- 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 -496
- 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 -118
- 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 -212
- 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 -364
- package/src/agent/er-body.ts +0 -224
- package/src/agent/facts.ts +0 -337
- package/src/agent/families-builtin.ts +0 -934
- package/src/agent/families.ts +0 -232
- package/src/agent/family-layouts.ts +0 -826
- package/src/agent/flowchart-body.ts +0 -372
- package/src/agent/flowchart-unsupported.ts +0 -243
- package/src/agent/gantt-body.ts +0 -495
- package/src/agent/index.ts +0 -10
- package/src/agent/journey-body.ts +0 -414
- 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 -439
- package/src/agent/parse.ts +0 -223
- package/src/agent/pie-body.ts +0 -270
- package/src/agent/png.ts +0 -117
- 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 -979
- package/src/agent/verify.ts +0 -571
- 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 -189
- 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 -128
- package/src/ascii/types.ts +0 -312
- package/src/ascii/validate.ts +0 -120
- package/src/ascii/width.ts +0 -81
- 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 -1117
- package/src/cli/init-agent.ts +0 -147
- 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/font-manifest.ts +0 -27
- 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 -520
- package/src/journey/parser.ts +0 -218
- package/src/journey/renderer.ts +0 -811
- 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 -387
- 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 -72
- 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 -639
- 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 -454
- 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/journey/types.ts
DELETED
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
// ============================================================================
|
|
2
|
-
// Journey diagram types
|
|
3
|
-
//
|
|
4
|
-
// Models Mermaid user journey diagrams in parsed and positioned form.
|
|
5
|
-
// Journey diagrams group scored tasks into optional sections with per-task actors.
|
|
6
|
-
// ============================================================================
|
|
7
|
-
|
|
8
|
-
import type { PositionedDiagram } from '../types.ts'
|
|
9
|
-
|
|
10
|
-
/** Parsed journey diagram — logical structure from Mermaid text */
|
|
11
|
-
export interface JourneyDiagram {
|
|
12
|
-
/** Optional diagram title */
|
|
13
|
-
title?: string
|
|
14
|
-
/** Optional accessibility title from Mermaid accTitle */
|
|
15
|
-
accessibilityTitle?: string
|
|
16
|
-
/** Optional accessibility description from Mermaid accDescr */
|
|
17
|
-
accessibilityDescription?: string
|
|
18
|
-
/** Ordered sections in input order */
|
|
19
|
-
sections: JourneySection[]
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export interface JourneySection {
|
|
23
|
-
id: string
|
|
24
|
-
/** Optional section label. Undefined means an implicit / ungrouped section. */
|
|
25
|
-
label?: string
|
|
26
|
-
tasks: JourneyTask[]
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export interface JourneyTask {
|
|
30
|
-
id: string
|
|
31
|
-
text: string
|
|
32
|
-
/** Satisfaction score on a 1..5 scale */
|
|
33
|
-
score: number
|
|
34
|
-
/** Optional actors attached to the task */
|
|
35
|
-
actors: string[]
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
// ============================================================================
|
|
39
|
-
// Positioned journey diagram — ready for SVG rendering
|
|
40
|
-
// ============================================================================
|
|
41
|
-
|
|
42
|
-
export interface PositionedJourneyDiagram extends PositionedDiagram {
|
|
43
|
-
width: number
|
|
44
|
-
height: number
|
|
45
|
-
title?: PositionedJourneyTitle
|
|
46
|
-
accessibilityTitle?: string
|
|
47
|
-
accessibilityDescription?: string
|
|
48
|
-
actors: PositionedJourneyActor[]
|
|
49
|
-
scoreGuide: PositionedJourneyScoreGuide
|
|
50
|
-
sections: PositionedJourneySection[]
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
export interface PositionedJourneyTitle {
|
|
54
|
-
text: string
|
|
55
|
-
x: number
|
|
56
|
-
y: number
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export interface PositionedJourneySection {
|
|
60
|
-
id: string
|
|
61
|
-
label?: string
|
|
62
|
-
x: number
|
|
63
|
-
y: number
|
|
64
|
-
width: number
|
|
65
|
-
height: number
|
|
66
|
-
labelX: number
|
|
67
|
-
labelY: number
|
|
68
|
-
/** Whether to render a section span for this section. */
|
|
69
|
-
framed: boolean
|
|
70
|
-
/** Height of the section span. 0 when there is no visible span. */
|
|
71
|
-
headerHeight: number
|
|
72
|
-
tasks: PositionedJourneyTask[]
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
export interface PositionedJourneyActor {
|
|
76
|
-
label: string
|
|
77
|
-
x: number
|
|
78
|
-
y: number
|
|
79
|
-
colorIndex: number
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
export interface PositionedJourneyScoreGuide {
|
|
83
|
-
x: number
|
|
84
|
-
y: number
|
|
85
|
-
width: number
|
|
86
|
-
height: number
|
|
87
|
-
ticks: PositionedJourneyScoreTick[]
|
|
88
|
-
baseline: PositionedJourneyBaseline
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
export interface PositionedJourneyScoreTick {
|
|
92
|
-
score: number
|
|
93
|
-
x1: number
|
|
94
|
-
x2: number
|
|
95
|
-
y: number
|
|
96
|
-
labelX: number
|
|
97
|
-
labelY: number
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
export interface PositionedJourneyBaseline {
|
|
101
|
-
x1: number
|
|
102
|
-
y1: number
|
|
103
|
-
x2: number
|
|
104
|
-
y2: number
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
export interface PositionedJourneyTask {
|
|
108
|
-
id: string
|
|
109
|
-
sectionId: string
|
|
110
|
-
text: string
|
|
111
|
-
score: number
|
|
112
|
-
actors: string[]
|
|
113
|
-
x: number
|
|
114
|
-
y: number
|
|
115
|
-
width: number
|
|
116
|
-
height: number
|
|
117
|
-
textX: number
|
|
118
|
-
textY: number
|
|
119
|
-
centerX: number
|
|
120
|
-
track: PositionedJourneyTrack
|
|
121
|
-
marker: PositionedJourneyScoreMarker
|
|
122
|
-
actorDots: PositionedJourneyActorDot[]
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
export interface PositionedJourneyTrack {
|
|
126
|
-
x: number
|
|
127
|
-
y1: number
|
|
128
|
-
y2: number
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
export interface PositionedJourneyScoreMarker {
|
|
132
|
-
cx: number
|
|
133
|
-
cy: number
|
|
134
|
-
r: number
|
|
135
|
-
score: number
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
export interface PositionedJourneyActorDot {
|
|
139
|
-
label: string
|
|
140
|
-
colorIndex: number
|
|
141
|
-
x: number
|
|
142
|
-
y: number
|
|
143
|
-
r: number
|
|
144
|
-
}
|
package/src/layout/geometry.ts
DELETED
|
@@ -1,182 +0,0 @@
|
|
|
1
|
-
// Shared geometry kernel for the layout pipeline
|
|
2
|
-
// (docs/design/system/layout-pass-pipeline.md §4 step 2 / OQ-D1).
|
|
3
|
-
//
|
|
4
|
-
// Leaf module: depends only on core types, so the relocated post-ELK passes in
|
|
5
|
-
// ./passes/* can import these helpers WITHOUT importing layout-engine.ts — which
|
|
6
|
-
// is what keeps the dependency one-directional (layout-engine -> passes -> geometry)
|
|
7
|
-
// and free of import cycles.
|
|
8
|
-
import type { Direction, MermaidSubgraph, Point, PositionedGroup, PositionedNode } from '../types.ts'
|
|
9
|
-
|
|
10
|
-
export const DEFAULTS = {
|
|
11
|
-
font: 'Inter',
|
|
12
|
-
padding: 40,
|
|
13
|
-
nodeSpacing: 28,
|
|
14
|
-
layerSpacing: 48,
|
|
15
|
-
mergeEdges: true,
|
|
16
|
-
thoroughness: 3,
|
|
17
|
-
} as const
|
|
18
|
-
|
|
19
|
-
export function flattenGroupBounds(groups: PositionedGroup[]): Array<{ x: number; y: number; right: number; bottom: number }> {
|
|
20
|
-
const bounds: Array<{ x: number; y: number; right: number; bottom: number }> = []
|
|
21
|
-
for (const g of groups) {
|
|
22
|
-
bounds.push({ x: g.x, y: g.y, right: g.x + g.width, bottom: g.y + g.height })
|
|
23
|
-
bounds.push(...flattenGroupBounds(g.children))
|
|
24
|
-
}
|
|
25
|
-
return bounds
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export function polylineLength(points: Point[]): number {
|
|
29
|
-
let totalLength = 0
|
|
30
|
-
for (let i = 1; i < points.length; i++) {
|
|
31
|
-
const dx = points[i]!.x - points[i - 1]!.x
|
|
32
|
-
const dy = points[i]!.y - points[i - 1]!.y
|
|
33
|
-
totalLength += Math.sqrt(dx * dx + dy * dy)
|
|
34
|
-
}
|
|
35
|
-
return totalLength
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export function pointAtPathDistance(points: Point[], distance: number): { point: Point; segmentIndex: number; pathDistance: number } {
|
|
39
|
-
if (points.length === 0) return { point: { x: 0, y: 0 }, segmentIndex: 0, pathDistance: 0 }
|
|
40
|
-
if (points.length === 1) return { point: points[0]!, segmentIndex: 0, pathDistance: 0 }
|
|
41
|
-
|
|
42
|
-
const target = Math.max(0, Math.min(polylineLength(points), distance))
|
|
43
|
-
let remaining = target
|
|
44
|
-
let walked = 0
|
|
45
|
-
for (let i = 1; i < points.length; i++) {
|
|
46
|
-
const dx = points[i]!.x - points[i - 1]!.x
|
|
47
|
-
const dy = points[i]!.y - points[i - 1]!.y
|
|
48
|
-
const segLen = Math.sqrt(dx * dx + dy * dy)
|
|
49
|
-
if (segLen === 0) continue
|
|
50
|
-
if (remaining <= segLen) {
|
|
51
|
-
const t = remaining / segLen
|
|
52
|
-
return {
|
|
53
|
-
point: {
|
|
54
|
-
x: points[i - 1]!.x + t * dx,
|
|
55
|
-
y: points[i - 1]!.y + t * dy,
|
|
56
|
-
},
|
|
57
|
-
segmentIndex: i,
|
|
58
|
-
pathDistance: walked + remaining,
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
remaining -= segLen
|
|
62
|
-
walked += segLen
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
return { point: points[points.length - 1]!, segmentIndex: points.length - 1, pathDistance: walked }
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Calculate the midpoint along a polyline path.
|
|
70
|
-
* Walks the path to find the point at half the total length.
|
|
71
|
-
*/
|
|
72
|
-
export function calculatePathMidpoint(points: Point[]): Point {
|
|
73
|
-
return pointAtPathDistance(points, polylineLength(points) / 2).point
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
export function layoutFlow(direction: Direction): {
|
|
77
|
-
isHorizontal: boolean
|
|
78
|
-
main: 'x' | 'y'
|
|
79
|
-
cross: 'x' | 'y'
|
|
80
|
-
sign: 1 | -1
|
|
81
|
-
sourceSide: 'N' | 'E' | 'S' | 'W'
|
|
82
|
-
targetSide: 'N' | 'E' | 'S' | 'W'
|
|
83
|
-
} {
|
|
84
|
-
if (direction === 'LR') return { isHorizontal: true, main: 'x', cross: 'y', sign: 1, sourceSide: 'E', targetSide: 'W' }
|
|
85
|
-
if (direction === 'RL') return { isHorizontal: true, main: 'x', cross: 'y', sign: -1, sourceSide: 'W', targetSide: 'E' }
|
|
86
|
-
if (direction === 'BT') return { isHorizontal: false, main: 'y', cross: 'x', sign: -1, sourceSide: 'N', targetSide: 'S' }
|
|
87
|
-
return { isHorizontal: false, main: 'y', cross: 'x', sign: 1, sourceSide: 'S', targetSide: 'N' }
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
export function positionedNodeCenter(node: PositionedNode): Point {
|
|
91
|
-
return { x: node.x + node.width / 2, y: node.y + node.height / 2 }
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
export function nodeMainStart(node: PositionedNode, direction: Direction): number {
|
|
95
|
-
const f = layoutFlow(direction)
|
|
96
|
-
return node[f.main]
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
export function nodeCrossStart(node: PositionedNode, direction: Direction): number {
|
|
100
|
-
const f = layoutFlow(direction)
|
|
101
|
-
return node[f.cross]
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
export function nodeCrossSize(node: PositionedNode, direction: Direction): number {
|
|
105
|
-
return layoutFlow(direction).isHorizontal ? node.height : node.width
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
export function nodeMainSize(node: PositionedNode, direction: Direction): number {
|
|
109
|
-
return layoutFlow(direction).isHorizontal ? node.width : node.height
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
export function nodeCrossCenter(node: PositionedNode, direction: Direction): number {
|
|
113
|
-
return nodeCrossStart(node, direction) + nodeCrossSize(node, direction) / 2
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
export function nodeMainCenter(node: PositionedNode, direction: Direction): number {
|
|
117
|
-
return nodeMainStart(node, direction) + nodeMainSize(node, direction) / 2
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
export function rectsOverlap(a: { x: number; y: number; width: number; height: number }, b: { x: number; y: number; width: number; height: number }, pad = 0): boolean {
|
|
121
|
-
return a.x < b.x + b.width + pad && a.x + a.width + pad > b.x && a.y < b.y + b.height + pad && a.y + a.height + pad > b.y
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
/** Margin routing info for cross-hierarchy edges */
|
|
125
|
-
export interface MarginInfo {
|
|
126
|
-
leftX: number
|
|
127
|
-
rightX: number
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
/** Find a subgraph by ID in a nested structure */
|
|
131
|
-
export function findSubgraph(subgraphs: MermaidSubgraph[], id: string): MermaidSubgraph | undefined {
|
|
132
|
-
for (const sg of subgraphs) {
|
|
133
|
-
if (sg.id === id) return sg
|
|
134
|
-
const found = findSubgraph(sg.children, id)
|
|
135
|
-
if (found) return found
|
|
136
|
-
}
|
|
137
|
-
return undefined
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
type LayoutDebugEnv = {
|
|
141
|
-
APL_DEBUG?: string
|
|
142
|
-
APL_NO_CENTER?: string
|
|
143
|
-
APL_NO_FACET?: string
|
|
144
|
-
APL_NO_SVERTEX?: string
|
|
145
|
-
// Disable the alignLabeledSourcePort pass (a labelled single-edge source is
|
|
146
|
-
// left exiting off its mid-port, as it was before that pass). For before/after
|
|
147
|
-
// evidence and bisecting, matching the other APL_NO_* pass switches.
|
|
148
|
-
APL_NO_LABELED_SOURCE_PORT?: string
|
|
149
|
-
// Label-decoupling (opt-in, validated): when set, edge labels are NOT handed
|
|
150
|
-
// to ELK, so a label cannot displace its target node off the edge's port lane
|
|
151
|
-
// (the sym A->B mid-port fix). Default is off — ELK still reserves a label
|
|
152
|
-
// cell — until the bent-duplicate-label route-contract regression is resolved.
|
|
153
|
-
// See the layout-engine label-injection sites and the decoupling write-up.
|
|
154
|
-
APL_DECOUPLE_LABELS?: string
|
|
155
|
-
// DISABLE co-ranking of a mixed-label fan-in (default ON). When a fan-in hub
|
|
156
|
-
// has sibling edges where some are labeled and some are not, the labeled edge
|
|
157
|
-
// reserves an extra label-dummy rank so its source lands one rank EARLIER
|
|
158
|
-
// than the unlabeled sibling's source — an asymmetric fan-in the centering
|
|
159
|
-
// can't square up. By default each unlabeled sibling edge gets a layout-only
|
|
160
|
-
// balancing label (a single space, sized to the widest labeled sibling) so
|
|
161
|
-
// ELK reserves the SAME dummy rank and every source co-ranks;
|
|
162
|
-
// centerPeerBarycenters then drops its labeled-edge exclusion for that
|
|
163
|
-
// now-co-ranked hub so it can center on the squared-up peers, and the spokes
|
|
164
|
-
// converge as symmetric doglegs (marked bundle-owned, so the bend is treated
|
|
165
|
-
// as justified — see route-contracts findRouteHitches and the layout-rubric
|
|
166
|
-
// justified-bend exemption). The balancing label is never rendered — readback
|
|
167
|
-
// keys off the Mermaid edge's own label, which stays undefined. Set this to
|
|
168
|
-
// restore the pre-co-rank base geometry (so before/after stays bisectable);
|
|
169
|
-
// matches the other APL_NO_* pass switches. See the layout-engine
|
|
170
|
-
// label-injection sites and centerPeerBarycenters.
|
|
171
|
-
APL_NO_CORANK_FANIN?: string
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
export function layoutEnvFlag(name: keyof LayoutDebugEnv): boolean {
|
|
175
|
-
const env = (globalThis as typeof globalThis & { process?: { env?: LayoutDebugEnv } }).process?.env
|
|
176
|
-
const value = env?.[name]
|
|
177
|
-
return value === '1' || value === 'true'
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
export function layoutDebug(...args: unknown[]): void {
|
|
181
|
-
if (layoutEnvFlag('APL_DEBUG')) console.error(...args)
|
|
182
|
-
}
|
package/src/layout/pass.ts
DELETED
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
// The LayoutPass abstraction — see docs/design/system/layout-pass-pipeline.md.
|
|
2
|
-
//
|
|
3
|
-
// Generic over the concrete context so this module has NO dependency on the
|
|
4
|
-
// layout engine (and therefore cannot create an import cycle). The concrete
|
|
5
|
-
// `LayoutPassContext` and the `LAYOUT_PIPELINE` manifest live in
|
|
6
|
-
// `src/layout-engine.ts`, where the per-pass functions are in scope.
|
|
7
|
-
//
|
|
8
|
-
// In production `runPipeline` is a thin dispatcher: each pass mutates the shared
|
|
9
|
-
// context in place, byte-identical to the former hand-wired sequence. The
|
|
10
|
-
// cross-pass invariants (§3) are enforced only when `checkInvariants` is set, so
|
|
11
|
-
// they ride debug/CI and never the production render path.
|
|
12
|
-
|
|
13
|
-
export type PassEffect = 'extract' | 'positions' | 'dimensions' | 'edges' | 'translate'
|
|
14
|
-
export type Determinism = 'pure-order' | 'fixed-point' | 'in-place'
|
|
15
|
-
export type RubricMetric = 'hard' | 'crossings' | 'bends' | 'straight' | 'portRate' | 'symErr'
|
|
16
|
-
|
|
17
|
-
/** Per-metric direction/budget for the ratchet (§3.3, resolves OQ-B1). */
|
|
18
|
-
export type MetricBudget = 'improve-only' | { worsenBy: number }
|
|
19
|
-
|
|
20
|
-
/** The minimal shape `runPipeline` needs to enforce the freeze invariant (§3.2). */
|
|
21
|
-
export interface PassContextBase {
|
|
22
|
-
frozen: boolean
|
|
23
|
-
nodes: ReadonlyArray<{ x: number; y: number; width: number; height: number }>
|
|
24
|
-
edges?: ReadonlyArray<{
|
|
25
|
-
points?: ReadonlyArray<{ x: number; y: number }>
|
|
26
|
-
routeCertificate?: unknown
|
|
27
|
-
}>
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export interface LayoutPass<C extends PassContextBase> {
|
|
31
|
-
/** Stable id; the route-contracts §8 pipeline line is generated from `doc`. */
|
|
32
|
-
id: string
|
|
33
|
-
doc: string
|
|
34
|
-
/** Partial-order deps (ids that must run earlier). Checked in debug mode. */
|
|
35
|
-
after: string[]
|
|
36
|
-
/** Geometry channels this pass writes — drives the freeze invariant (§3.2). */
|
|
37
|
-
mutates: PassEffect[]
|
|
38
|
-
/** Per-metric direction/budget (the ratchet, §3.3); enforced only in debug/CI. */
|
|
39
|
-
mayChangeMetrics?: Partial<Record<RubricMetric, MetricBudget>>
|
|
40
|
-
determinism: Determinism
|
|
41
|
-
/** After this pass, node geometry is frozen (the route-contract pass). */
|
|
42
|
-
freezesNodes?: boolean
|
|
43
|
-
/** When present and false, the pass is skipped (e.g. bundling without mergeEdges). */
|
|
44
|
-
enabled?: (ctx: C) => boolean
|
|
45
|
-
run: (ctx: C) => void
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export interface RunOptions<C extends PassContextBase> {
|
|
49
|
-
/** Debug/CI only: enforce ordering + freeze invariants (O(n) per mover). */
|
|
50
|
-
checkInvariants?: boolean
|
|
51
|
-
/** Debug/CI only: called after each pass that actually ran (e.g. to measure the ratchet). */
|
|
52
|
-
onAfterPass?: (pass: LayoutPass<C>, ctx: C) => void
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/** Post-freeze a pass may only translate the whole graph or rewrite edges (§3.2). */
|
|
56
|
-
const freezeSafe = (mutates: PassEffect[]): boolean =>
|
|
57
|
-
mutates.every(m => m === 'translate' || m === 'edges')
|
|
58
|
-
|
|
59
|
-
const routeKey = (edge: { points?: ReadonlyArray<{ x: number; y: number }> }): string =>
|
|
60
|
-
edge.points?.map(p => `${p.x},${p.y}`).join('|') ?? ''
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Run `passes` over `ctx` in array order. The array IS the execution path; with
|
|
64
|
-
* `checkInvariants` the runner also enforces the §3 contract (ordering + freeze).
|
|
65
|
-
*/
|
|
66
|
-
export function runPipeline<C extends PassContextBase>(
|
|
67
|
-
ctx: C,
|
|
68
|
-
passes: ReadonlyArray<LayoutPass<C>>,
|
|
69
|
-
opts: RunOptions<C> = {},
|
|
70
|
-
): void {
|
|
71
|
-
const ran = new Set<string>()
|
|
72
|
-
for (const pass of passes) {
|
|
73
|
-
if (pass.enabled && !pass.enabled(ctx)) {
|
|
74
|
-
ran.add(pass.id)
|
|
75
|
-
continue
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
if (opts.checkInvariants) {
|
|
79
|
-
for (const dep of pass.after) {
|
|
80
|
-
if (!ran.has(dep)) {
|
|
81
|
-
throw new Error(`LayoutPass ordering: '${pass.id}' must run after '${dep}', which has not run`)
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// Freeze invariant (§3.2): after the route-contract pass only a whole-graph
|
|
87
|
-
// translation (or an edge rewrite) may run; a positions/dimensions move is illegal.
|
|
88
|
-
const guardFreeze = opts.checkInvariants === true && ctx.frozen && !freezeSafe(pass.mutates)
|
|
89
|
-
const before = guardFreeze
|
|
90
|
-
? ctx.nodes.map(n => ({ x: n.x, y: n.y, width: n.width, height: n.height }))
|
|
91
|
-
: undefined
|
|
92
|
-
const beforeEdges = opts.checkInvariants === true && ctx.frozen && pass.mutates.includes('edges') && ctx.edges
|
|
93
|
-
? ctx.edges.map(routeKey)
|
|
94
|
-
: undefined
|
|
95
|
-
|
|
96
|
-
pass.run(ctx)
|
|
97
|
-
|
|
98
|
-
if (before) {
|
|
99
|
-
for (let i = 0; i < before.length; i++) {
|
|
100
|
-
const a = before[i]
|
|
101
|
-
const b = ctx.nodes[i]
|
|
102
|
-
if (!a || !b) continue
|
|
103
|
-
if (a.x !== b.x || a.y !== b.y || a.width !== b.width || a.height !== b.height) {
|
|
104
|
-
throw new Error(
|
|
105
|
-
`LayoutPass freeze: '${pass.id}' moved node geometry after the route-contract freeze ` +
|
|
106
|
-
`(only translate/edge passes are allowed; declare 'translate' in mutates if this is a uniform shift)`,
|
|
107
|
-
)
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
if (beforeEdges && ctx.edges) {
|
|
113
|
-
for (let i = 0; i < beforeEdges.length; i++) {
|
|
114
|
-
const edge = ctx.edges[i]
|
|
115
|
-
if (!edge) continue
|
|
116
|
-
if (beforeEdges[i] !== routeKey(edge) && edge.routeCertificate === undefined) {
|
|
117
|
-
throw new Error(
|
|
118
|
-
`LayoutPass certificate: '${pass.id}' rewrote edge geometry after the route-contract freeze ` +
|
|
119
|
-
'without re-issuing routeCertificate',
|
|
120
|
-
)
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
if (pass.freezesNodes) ctx.frozen = true
|
|
126
|
-
ran.add(pass.id)
|
|
127
|
-
opts.onAfterPass?.(pass, ctx)
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
/** A pipeline is well-formed iff its array order is a topological order of `after`. */
|
|
132
|
-
export function assertTopologicalOrder<C extends PassContextBase>(passes: ReadonlyArray<LayoutPass<C>>): void {
|
|
133
|
-
const seen = new Set<string>()
|
|
134
|
-
for (const pass of passes) {
|
|
135
|
-
for (const dep of pass.after) {
|
|
136
|
-
if (!seen.has(dep)) {
|
|
137
|
-
throw new Error(`LayoutPass pipeline order: '${pass.id}' precedes its dependency '${dep}'`)
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
seen.add(pass.id)
|
|
141
|
-
}
|
|
142
|
-
}
|