opentui-markdown-render 0.0.0-stage → 0.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/LICENSE +21 -0
- package/NOTICE +27 -0
- package/README.md +223 -2
- package/bin/otmd.tsx +99 -0
- package/native/Cargo.lock +3708 -0
- package/native/Cargo.toml +28 -0
- package/native/build.rs +3 -0
- package/native/src/lib.rs +880 -0
- package/package.json +67 -4
- package/prebuilds/linux-x64-gnu/opentui_markdown_render.node +4 -0
- package/src/app.tsx +180 -0
- package/src/cli.ts +63 -0
- package/src/config/index.ts +46 -0
- package/src/config/load.ts +337 -0
- package/src/config/resolve.ts +36 -0
- package/src/config/theme.ts +110 -0
- package/src/config/types.ts +105 -0
- package/src/core/document.ts +44 -0
- package/src/core/frame.ts +144 -0
- package/src/core/image.ts +9 -0
- package/src/core/index.ts +6 -0
- package/src/core/layout.ts +27 -0
- package/src/core/math.ts +170 -0
- package/src/core/parse.ts +208 -0
- package/src/core/tables.ts +58 -0
- package/src/graphics.ts +85 -0
- package/src/headings.ts +77 -0
- package/src/index.ts +107 -0
- package/src/math/index.ts +86 -0
- package/src/math/native.ts +39 -0
- package/src/math/renderer.ts +84 -0
- package/src/math/validate.ts +44 -0
- package/src/media.tsx +267 -0
- package/src/merman/class/dagre-layout.ts +171 -0
- package/src/merman/class/diagram.ts +8 -0
- package/src/merman/class/drawing.ts +343 -0
- package/src/merman/class/labels.ts +38 -0
- package/src/merman/class/layout.ts +531 -0
- package/src/merman/class/parser.ts +308 -0
- package/src/merman/class/render-grid.ts +18 -0
- package/src/merman/class/style.ts +27 -0
- package/src/merman/class/types.ts +57 -0
- package/src/merman/core/canvas.ts +228 -0
- package/src/merman/core/color/style.ts +56 -0
- package/src/merman/core/drawing.ts +307 -0
- package/src/merman/core/geometry.ts +347 -0
- package/src/merman/core/mermaid.ts +38 -0
- package/src/merman/core/render-grid.ts +51 -0
- package/src/merman/core/spatial.ts +243 -0
- package/src/merman/core/text-lines.ts +32 -0
- package/src/merman/core/text.ts +44 -0
- package/src/merman/detect.ts +19 -0
- package/src/merman/diagnostics.ts +16 -0
- package/src/merman/diagram.ts +268 -0
- package/src/merman/flowchart/drawing.ts +433 -0
- package/src/merman/flowchart/labels.ts +144 -0
- package/src/merman/flowchart/layout.ts +1057 -0
- package/src/merman/flowchart/options.ts +12 -0
- package/src/merman/flowchart/parser.ts +477 -0
- package/src/merman/flowchart/render.ts +10 -0
- package/src/merman/flowchart/routing.ts +1429 -0
- package/src/merman/flowchart/style.ts +79 -0
- package/src/merman/flowchart/types.ts +63 -0
- package/src/merman/gantt/diagram.ts +8 -0
- package/src/merman/gantt/drawing.ts +193 -0
- package/src/merman/gantt/parser.ts +198 -0
- package/src/merman/gantt/render-grid.ts +17 -0
- package/src/merman/gantt/style.ts +36 -0
- package/src/merman/gantt/types.ts +45 -0
- package/src/merman/gitgraph/diagram.ts +8 -0
- package/src/merman/gitgraph/drawing.ts +234 -0
- package/src/merman/gitgraph/parser.ts +234 -0
- package/src/merman/gitgraph/render-grid.ts +17 -0
- package/src/merman/gitgraph/style.ts +37 -0
- package/src/merman/gitgraph/types.ts +36 -0
- package/src/merman/palette.ts +60 -0
- package/src/merman/sequence/diagram.ts +8 -0
- package/src/merman/sequence/drawing.ts +288 -0
- package/src/merman/sequence/options.ts +8 -0
- package/src/merman/sequence/parser.ts +303 -0
- package/src/merman/sequence/placement.ts +692 -0
- package/src/merman/sequence/render-grid.ts +22 -0
- package/src/merman/sequence/style.ts +81 -0
- package/src/merman/sequence/types.ts +74 -0
- package/src/merman/state/diagram.ts +8 -0
- package/src/merman/state/drawing.ts +363 -0
- package/src/merman/state/endpoint.ts +15 -0
- package/src/merman/state/layout.ts +1134 -0
- package/src/merman/state/note.ts +59 -0
- package/src/merman/state/options.ts +11 -0
- package/src/merman/state/parser.ts +245 -0
- package/src/merman/state/render-grid.ts +22 -0
- package/src/merman/state/routing.ts +1522 -0
- package/src/merman/state/search.ts +103 -0
- package/src/merman/state/style.ts +52 -0
- package/src/merman/state/types.ts +63 -0
- package/src/merman/state/visible-model.ts +77 -0
- package/src/merman/timeline/diagram.ts +8 -0
- package/src/merman/timeline/drawing.ts +109 -0
- package/src/merman/timeline/parser.ts +119 -0
- package/src/merman/timeline/render-grid.ts +17 -0
- package/src/merman/timeline/style.ts +36 -0
- package/src/merman/timeline/types.ts +31 -0
- package/src/merman.ts +3 -0
- package/src/statusline.tsx +183 -0
- package/src/theme/colors.ts +11 -0
- package/src/theme/defaults.ts +190 -0
- package/src/theme/index.ts +7 -0
- package/src/theme/load.ts +39 -0
- package/src/theme/resolve.ts +167 -0
- package/src/theme/syntax.ts +96 -0
- package/src/theme/types.ts +151 -0
- package/src/view/code.tsx +27 -0
- package/src/view/document-slots.ts +111 -0
- package/src/view/document-table.tsx +98 -0
- package/src/view/document.tsx +195 -0
- package/src/view/frame.tsx +83 -0
- package/src/view/inline-flow.tsx +113 -0
- package/src/view/inline-layout.ts +149 -0
- package/src/view/inline-math.ts +42 -0
- package/src/view/inline-style.ts +103 -0
- package/src/view/math.tsx +85 -0
- package/src/view/mermaid.tsx +128 -0
- package/src/view/table.ts +100 -0
- package/themes/dark.json +32 -0
- package/themes/example.jsonc +98 -0
- package/themes/light.json +32 -0
- package/themes/solarized-dark.json +32 -0
- package/themes/solarized-light.json +32 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { DiagramPoint } from "../core/geometry.js"
|
|
2
|
+
import type { StateDiagramNote } from "./types.js"
|
|
3
|
+
|
|
4
|
+
interface NoteBounds {
|
|
5
|
+
left: number
|
|
6
|
+
top: number
|
|
7
|
+
width: number
|
|
8
|
+
height: number
|
|
9
|
+
centerY: number
|
|
10
|
+
note: StateDiagramNote
|
|
11
|
+
connector?: StateDiagramNoteConnector
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
interface TargetBounds {
|
|
15
|
+
left: number
|
|
16
|
+
top: number
|
|
17
|
+
width: number
|
|
18
|
+
height: number
|
|
19
|
+
centerY: number
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface StateDiagramNoteConnector {
|
|
23
|
+
points: readonly DiagramPoint[]
|
|
24
|
+
connectorY: number
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function stateDiagramNoteConnector(
|
|
28
|
+
bounds: NoteBounds,
|
|
29
|
+
target: TargetBounds,
|
|
30
|
+
): StateDiagramNoteConnector {
|
|
31
|
+
if (bounds.connector) return bounds.connector
|
|
32
|
+
const noteX = bounds.note.position === "right" ? bounds.left - 1 : bounds.left + bounds.width
|
|
33
|
+
const targetX = bounds.note.position === "right" ? target.left + target.width : target.left - 1
|
|
34
|
+
const targetBottom = target.top + target.height - 1
|
|
35
|
+
const noteBottom = bounds.top + bounds.height - 1
|
|
36
|
+
const noteAbove = noteBottom < target.top
|
|
37
|
+
const noteBelow = bounds.top > targetBottom
|
|
38
|
+
|
|
39
|
+
if (noteAbove || noteBelow) {
|
|
40
|
+
const connectorY = bounds.centerY
|
|
41
|
+
return {
|
|
42
|
+
connectorY,
|
|
43
|
+
points: [
|
|
44
|
+
{ x: targetX, y: noteAbove ? target.top - 1 : targetBottom + 1 },
|
|
45
|
+
{ x: targetX, y: connectorY },
|
|
46
|
+
{ x: noteX, y: connectorY },
|
|
47
|
+
],
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const connectorY = Math.max(bounds.top + 1, Math.min(target.centerY, bounds.top + bounds.height - 2))
|
|
52
|
+
return {
|
|
53
|
+
connectorY,
|
|
54
|
+
points: [
|
|
55
|
+
{ x: targetX, y: connectorY },
|
|
56
|
+
{ x: noteX, y: connectorY },
|
|
57
|
+
],
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { BorderStyle } from "@opentui/core"
|
|
2
|
+
import type { StateDiagramArrowHeadStyle } from "./types.js"
|
|
3
|
+
|
|
4
|
+
export const DEFAULT_STATE_DIAGRAM_MIN_STATE_GAP = 5
|
|
5
|
+
export const DEFAULT_STATE_BORDER_STYLE = "rounded" satisfies BorderStyle
|
|
6
|
+
export const DEFAULT_STATE_ARROW_HEAD_STYLE = "filled" satisfies StateDiagramArrowHeadStyle
|
|
7
|
+
|
|
8
|
+
export function normalizeStateMinStateGap(value: number | undefined): number {
|
|
9
|
+
if (value === undefined || !Number.isFinite(value)) return DEFAULT_STATE_DIAGRAM_MIN_STATE_GAP
|
|
10
|
+
return Math.max(1, Math.trunc(value))
|
|
11
|
+
}
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
import { decodeMermaidText, firstMeaningfulMermaidLine, numberedMermaidLines } from "../core/mermaid.js"
|
|
2
|
+
import { splitDiagramLines } from "../core/text-lines.js"
|
|
3
|
+
import { MermaidSyntaxError } from "../diagnostics.js"
|
|
4
|
+
import { normalizeStateDiagramEndpoint, stateDiagramEndMarkerId, stateDiagramStartMarkerId } from "./endpoint.js"
|
|
5
|
+
import type {
|
|
6
|
+
StateDiagram,
|
|
7
|
+
StateDiagramCompositeState,
|
|
8
|
+
StateDiagramDirection,
|
|
9
|
+
StateDiagramNote,
|
|
10
|
+
StateDiagramState,
|
|
11
|
+
StateDiagramTransition,
|
|
12
|
+
} from "./types.js"
|
|
13
|
+
|
|
14
|
+
const DEFAULT_DIRECTION = "LR" satisfies StateDiagramDirection
|
|
15
|
+
const STATE_RE = /^state\s+"([^"]+)"\s+as\s+(\S+)$/i
|
|
16
|
+
const STATE_DECLARE_RE = /^state\s+([A-Za-z_][A-Za-z0-9_.-]*)$/i
|
|
17
|
+
const STATE_DESCRIPTION_RE = /^([A-Za-z_][A-Za-z0-9_.-]*)\s*:\s*(.+)$/
|
|
18
|
+
const COMPOSITE_STATE_RE = /^state\s+(?:"([^"]+)"\s+as\s+)?(\S+)\s*\{$/i
|
|
19
|
+
const CHOICE_STATE_RE = /^state\s+(\S+)\s+<<choice>>$/i
|
|
20
|
+
const PARALLEL_STATE_RE = /^state\s+(\S+)\s+<<(fork|join)>>$/i
|
|
21
|
+
const TRANSITION_RE = /^(\[\*\]|[^\s:]+)\s*-->\s*(\[\*\]|[^\s:]+)(?:\s*:\s*(.*))?$/
|
|
22
|
+
const DIRECTION_RE = /^direction\s+(TB|TD|BT|LR|RL)$/i
|
|
23
|
+
const NOTE_INLINE_RE = /^note\s+(left|right)\s+of\s+(\S+)\s*:\s*(.*)$/i
|
|
24
|
+
const NOTE_START_RE = /^note\s+(left|right)\s+of\s+(\S+)\s*$/i
|
|
25
|
+
const NOTE_END_RE = /^end\s+note$/i
|
|
26
|
+
|
|
27
|
+
function normalizeDirection(value?: string): StateDiagramDirection {
|
|
28
|
+
const upper = value?.toUpperCase()
|
|
29
|
+
if (upper === "TB" || upper === "TD" || upper === "BT" || upper === "LR" || upper === "RL") return upper
|
|
30
|
+
return DEFAULT_DIRECTION
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function isMermaidHeader(line: string): boolean {
|
|
34
|
+
return line.toLowerCase() === "statediagram-v2" || line.toLowerCase() === "statediagram"
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function ensureState(
|
|
38
|
+
states: Map<string, StateDiagramState>,
|
|
39
|
+
id: string,
|
|
40
|
+
label = id,
|
|
41
|
+
kind: StateDiagramState["kind"] = "state",
|
|
42
|
+
parentId?: string,
|
|
43
|
+
): void {
|
|
44
|
+
const existing = states.get(id)
|
|
45
|
+
if (existing) {
|
|
46
|
+
if (existing.label === existing.id && label !== id) existing.label = label
|
|
47
|
+
if (parentId && !existing.parentId) existing.parentId = parentId
|
|
48
|
+
if (kind !== "state") {
|
|
49
|
+
existing.kind = kind
|
|
50
|
+
existing.label = label
|
|
51
|
+
}
|
|
52
|
+
return
|
|
53
|
+
}
|
|
54
|
+
states.set(id, parentId ? { id, label, kind, parentId } : { id, label, kind })
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function resolveCompositeTransitionEndpoint(
|
|
58
|
+
id: string,
|
|
59
|
+
markerId: (scope?: string) => string,
|
|
60
|
+
compositeIds: ReadonlySet<string>,
|
|
61
|
+
states: Map<string, StateDiagramState>,
|
|
62
|
+
): string {
|
|
63
|
+
if (!compositeIds.has(id)) return id
|
|
64
|
+
const marker = markerId(id)
|
|
65
|
+
return states.has(marker) ? marker : id
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function resolveCompositeTransitions(
|
|
69
|
+
transitions: readonly StateDiagramTransition[],
|
|
70
|
+
compositeIds: ReadonlySet<string>,
|
|
71
|
+
states: Map<string, StateDiagramState>,
|
|
72
|
+
): StateDiagramTransition[] {
|
|
73
|
+
return transitions.map((transition) => ({
|
|
74
|
+
from: resolveCompositeTransitionEndpoint(transition.from, stateDiagramEndMarkerId, compositeIds, states),
|
|
75
|
+
to: resolveCompositeTransitionEndpoint(transition.to, stateDiagramStartMarkerId, compositeIds, states),
|
|
76
|
+
label: transition.label,
|
|
77
|
+
}))
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export function isMermaidStateDiagram(content: string): boolean {
|
|
81
|
+
return isMermaidHeader(firstMeaningfulMermaidLine(content) ?? "")
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export function parseMermaidStateDiagram(content: string): StateDiagram {
|
|
85
|
+
const states = new Map<string, StateDiagramState>()
|
|
86
|
+
const transitions: StateDiagramTransition[] = []
|
|
87
|
+
const composites: StateDiagramCompositeState[] = []
|
|
88
|
+
const notes: StateDiagramNote[] = []
|
|
89
|
+
const parentStack: Array<{ id: string; lineNumber: number; sourceLine: string }> = []
|
|
90
|
+
let pendingNote:
|
|
91
|
+
| { target: string; position: "left" | "right"; lines: string[]; lineNumber: number; sourceLine: string }
|
|
92
|
+
| undefined
|
|
93
|
+
let direction: StateDiagramDirection = DEFAULT_DIRECTION
|
|
94
|
+
|
|
95
|
+
for (const source of numberedMermaidLines(content)) {
|
|
96
|
+
const line = source.text
|
|
97
|
+
if (pendingNote) {
|
|
98
|
+
if (NOTE_END_RE.test(line)) {
|
|
99
|
+
notes.push({
|
|
100
|
+
target: pendingNote.target,
|
|
101
|
+
position: pendingNote.position,
|
|
102
|
+
lines: pendingNote.lines.map(decodeMermaidText),
|
|
103
|
+
})
|
|
104
|
+
pendingNote = undefined
|
|
105
|
+
} else if (line || pendingNote.lines.length > 0) {
|
|
106
|
+
pendingNote.lines.push(line)
|
|
107
|
+
}
|
|
108
|
+
continue
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (!line || line.startsWith("%%") || isMermaidHeader(line)) continue
|
|
112
|
+
|
|
113
|
+
if (line === "}") {
|
|
114
|
+
if (parentStack.length === 0) {
|
|
115
|
+
throw new MermaidSyntaxError("state", source.lineNumber, line, 'Unexpected "}" without an open composite state')
|
|
116
|
+
}
|
|
117
|
+
parentStack.pop()
|
|
118
|
+
continue
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const parentId = parentStack[parentStack.length - 1]?.id
|
|
122
|
+
|
|
123
|
+
const directionMatch = line.match(DIRECTION_RE)
|
|
124
|
+
if (directionMatch) {
|
|
125
|
+
if (parentStack.length > 0) {
|
|
126
|
+
throw new MermaidSyntaxError("state", source.lineNumber, line, "Composite-local direction is not supported")
|
|
127
|
+
}
|
|
128
|
+
direction = normalizeDirection(directionMatch[1])
|
|
129
|
+
continue
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const inlineNoteMatch = line.match(NOTE_INLINE_RE)
|
|
133
|
+
if (inlineNoteMatch) {
|
|
134
|
+
notes.push({
|
|
135
|
+
position: inlineNoteMatch[1]!.toLowerCase() as "left" | "right",
|
|
136
|
+
target: inlineNoteMatch[2]!,
|
|
137
|
+
lines: splitDiagramLines(decodeMermaidText(inlineNoteMatch[3]!.trim())),
|
|
138
|
+
})
|
|
139
|
+
continue
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const noteMatch = line.match(NOTE_START_RE)
|
|
143
|
+
if (noteMatch) {
|
|
144
|
+
pendingNote = {
|
|
145
|
+
position: noteMatch[1]!.toLowerCase() as "left" | "right",
|
|
146
|
+
target: noteMatch[2]!,
|
|
147
|
+
lines: [],
|
|
148
|
+
lineNumber: source.lineNumber,
|
|
149
|
+
sourceLine: line,
|
|
150
|
+
}
|
|
151
|
+
continue
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const compositeMatch = line.match(COMPOSITE_STATE_RE)
|
|
155
|
+
if (compositeMatch) {
|
|
156
|
+
const id = compositeMatch[2]!
|
|
157
|
+
composites.push({
|
|
158
|
+
id,
|
|
159
|
+
label: decodeMermaidText(compositeMatch[1] ?? id),
|
|
160
|
+
...(parentId ? { parentId } : {}),
|
|
161
|
+
})
|
|
162
|
+
parentStack.push({ id, lineNumber: source.lineNumber, sourceLine: line })
|
|
163
|
+
continue
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const stateMatch = line.match(STATE_RE)
|
|
167
|
+
if (stateMatch) {
|
|
168
|
+
ensureState(states, stateMatch[2]!, decodeMermaidText(stateMatch[1]!), "state", parentId)
|
|
169
|
+
continue
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const declaration = line.match(STATE_DECLARE_RE)
|
|
173
|
+
if (declaration) {
|
|
174
|
+
ensureState(states, declaration[1]!, declaration[1]!, "state", parentId)
|
|
175
|
+
continue
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const description = line.match(STATE_DESCRIPTION_RE)
|
|
179
|
+
if (description) {
|
|
180
|
+
ensureState(states, description[1]!, decodeMermaidText(description[2]!), "state", parentId)
|
|
181
|
+
continue
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const choiceMatch = line.match(CHOICE_STATE_RE)
|
|
185
|
+
if (choiceMatch) {
|
|
186
|
+
ensureState(states, choiceMatch[1]!, "", "choice", parentId)
|
|
187
|
+
continue
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const parallelMatch = line.match(PARALLEL_STATE_RE)
|
|
191
|
+
if (parallelMatch) {
|
|
192
|
+
ensureState(states, parallelMatch[1]!, "", parallelMatch[2]!.toLowerCase() as "fork" | "join", parentId)
|
|
193
|
+
continue
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
const transitionMatch = line.match(TRANSITION_RE)
|
|
197
|
+
if (transitionMatch) {
|
|
198
|
+
const rawFrom = transitionMatch[1]!
|
|
199
|
+
const rawTo = transitionMatch[2]!
|
|
200
|
+
if (rawFrom.includes("-->") || rawTo.includes("-->")) {
|
|
201
|
+
throw new MermaidSyntaxError("state", source.lineNumber, line)
|
|
202
|
+
}
|
|
203
|
+
const from = normalizeStateDiagramEndpoint(rawFrom, "from", parentId)
|
|
204
|
+
const to = normalizeStateDiagramEndpoint(rawTo, "to", parentId)
|
|
205
|
+
ensureState(states, from, rawFrom === "[*]" ? "●" : from, rawFrom === "[*]" ? "start" : "state", parentId)
|
|
206
|
+
ensureState(states, to, rawTo === "[*]" ? "◎" : to, rawTo === "[*]" ? "end" : "state", parentId)
|
|
207
|
+
transitions.push({ from, to, label: decodeMermaidText(transitionMatch[3]?.trim() ?? "") })
|
|
208
|
+
continue
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
throw new MermaidSyntaxError("state", source.lineNumber, line)
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if (pendingNote) {
|
|
215
|
+
throw new MermaidSyntaxError(
|
|
216
|
+
"state",
|
|
217
|
+
pendingNote.lineNumber,
|
|
218
|
+
pendingNote.sourceLine,
|
|
219
|
+
'Unclosed note; expected "end note"',
|
|
220
|
+
)
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
const unclosedComposite = parentStack[parentStack.length - 1]
|
|
224
|
+
if (unclosedComposite) {
|
|
225
|
+
throw new MermaidSyntaxError(
|
|
226
|
+
"state",
|
|
227
|
+
unclosedComposite.lineNumber,
|
|
228
|
+
unclosedComposite.sourceLine,
|
|
229
|
+
'Unclosed composite state; expected "}"',
|
|
230
|
+
)
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
if (composites.length === 0) {
|
|
234
|
+
return { direction, states: [...states.values()], transitions, composites, notes }
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
const compositeIds = new Set(composites.map((composite) => composite.id))
|
|
238
|
+
return {
|
|
239
|
+
direction,
|
|
240
|
+
states: [...states.values()].filter((state) => !compositeIds.has(state.id)),
|
|
241
|
+
transitions: resolveCompositeTransitions(transitions, compositeIds, states),
|
|
242
|
+
composites,
|
|
243
|
+
notes,
|
|
244
|
+
}
|
|
245
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { RGBA, StyledText } from "@opentui/core"
|
|
2
|
+
import type { DiagramCanvas } from "../core/canvas.js"
|
|
3
|
+
import { renderDiagramGridStyledTextByStyle } from "../core/render-grid.js"
|
|
4
|
+
import type { StateStyleColors } from "./style.js"
|
|
5
|
+
import type { StateCellStyle } from "./types.js"
|
|
6
|
+
|
|
7
|
+
export type StateGrid = DiagramCanvas<StateCellStyle>
|
|
8
|
+
|
|
9
|
+
export function renderStateGridText(grid: StateGrid): string {
|
|
10
|
+
return grid.toString({ trimTop: true, trimBottom: true })
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function renderStateGridStyledText(
|
|
14
|
+
grid: StateGrid,
|
|
15
|
+
colors: StateStyleColors,
|
|
16
|
+
backgrounds?: Partial<Record<StateCellStyle, RGBA>>,
|
|
17
|
+
): StyledText {
|
|
18
|
+
return renderDiagramGridStyledTextByStyle(grid, colors, backgrounds, {
|
|
19
|
+
trimTop: true,
|
|
20
|
+
trimBottom: true,
|
|
21
|
+
})
|
|
22
|
+
}
|