@diagrammo/dgmo 0.8.19 ā 0.8.21
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/cli.cjs +92 -131
- package/dist/editor.cjs +13 -1
- package/dist/editor.cjs.map +1 -1
- package/dist/editor.js +13 -1
- package/dist/editor.js.map +1 -1
- package/dist/highlight.cjs +13 -1
- package/dist/highlight.cjs.map +1 -1
- package/dist/highlight.js +13 -1
- package/dist/highlight.js.map +1 -1
- package/dist/index.cjs +4524 -1511
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +427 -186
- package/dist/index.d.ts +427 -186
- package/dist/index.js +4526 -1503
- package/dist/index.js.map +1 -1
- package/docs/guide/chart-mindmap.md +198 -0
- package/docs/guide/chart-sequence.md +23 -1
- package/docs/guide/chart-wireframe.md +100 -0
- package/docs/guide/index.md +8 -0
- package/docs/language-reference.md +210 -2
- package/package.json +22 -9
- package/src/boxes-and-lines/collapse.ts +21 -3
- package/src/boxes-and-lines/layout.ts +51 -9
- package/src/boxes-and-lines/parser.ts +16 -4
- package/src/boxes-and-lines/renderer.ts +121 -23
- package/src/boxes-and-lines/types.ts +1 -0
- package/src/c4/parser.ts +8 -7
- package/src/class/parser.ts +6 -0
- package/src/cli.ts +1 -9
- package/src/completion.ts +26 -0
- package/src/d3.ts +169 -266
- package/src/dgmo-router.ts +103 -5
- package/src/diagnostics.ts +16 -6
- package/src/echarts.ts +43 -10
- package/src/editor/keywords.ts +12 -0
- package/src/er/parser.ts +22 -2
- package/src/gantt/renderer.ts +2 -2
- package/src/graph/flowchart-parser.ts +89 -52
- package/src/graph/layout.ts +73 -9
- package/src/graph/state-collapse.ts +78 -0
- package/src/graph/state-parser.ts +60 -35
- package/src/graph/state-renderer.ts +139 -34
- package/src/index.ts +41 -16
- package/src/infra/parser.ts +9 -2
- package/src/kanban/renderer.ts +305 -59
- package/src/mindmap/collapse.ts +88 -0
- package/src/mindmap/layout.ts +605 -0
- package/src/mindmap/parser.ts +379 -0
- package/src/mindmap/renderer.ts +543 -0
- package/src/mindmap/text-wrap.ts +207 -0
- package/src/mindmap/types.ts +55 -0
- package/src/palettes/color-utils.ts +4 -12
- package/src/palettes/index.ts +0 -4
- package/src/render.ts +31 -20
- package/src/sequence/parser.ts +7 -2
- package/src/sequence/renderer.ts +141 -21
- package/src/sharing.ts +2 -0
- package/src/sitemap/layout.ts +35 -12
- package/src/sitemap/renderer.ts +1 -6
- package/src/utils/arrows.ts +180 -11
- package/src/utils/d3-types.ts +4 -0
- package/src/utils/export-container.ts +3 -2
- package/src/utils/legend-constants.ts +0 -4
- package/src/utils/legend-d3.ts +1 -0
- package/src/utils/legend-layout.ts +2 -2
- package/src/utils/parsing.ts +2 -0
- package/src/utils/time-ticks.ts +213 -0
- package/src/wireframe/layout.ts +460 -0
- package/src/wireframe/parser.ts +956 -0
- package/src/wireframe/renderer.ts +1293 -0
- package/src/wireframe/types.ts +110 -0
- package/src/branding.ts +0 -67
- package/src/dgmo-mermaid.ts +0 -262
- package/src/palettes/mermaid-bridge.ts +0 -220
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
# Mind Map
|
|
2
|
+
|
|
3
|
+
```dgmo
|
|
4
|
+
mindmap Product Strategy
|
|
5
|
+
|
|
6
|
+
Research
|
|
7
|
+
User Interviews
|
|
8
|
+
Surveys | description: Quarterly NPS survey
|
|
9
|
+
Focus Groups
|
|
10
|
+
Competitor Analysis
|
|
11
|
+
Feature Matrix
|
|
12
|
+
Pricing Review
|
|
13
|
+
Development
|
|
14
|
+
MVP Features
|
|
15
|
+
Auth System
|
|
16
|
+
description: Handle login, signup, OAuth flows
|
|
17
|
+
Dashboard
|
|
18
|
+
Nice-to-haves | collapsed: true
|
|
19
|
+
Dark Mode
|
|
20
|
+
Export PDF
|
|
21
|
+
Go-to-Market
|
|
22
|
+
Launch Plan
|
|
23
|
+
Blog Post
|
|
24
|
+
Demo Video | description: 2-min product walkthrough
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Overview
|
|
28
|
+
|
|
29
|
+
Mind maps visualize hierarchical information radiating from a central concept. Each branch represents a subtopic, with deeper nesting for finer detail. Mind maps are useful for brainstorming, project planning, knowledge organization, and breaking down complex topics.
|
|
30
|
+
|
|
31
|
+
**Interactive features:** Click nodes to navigate to their source line. Collapse and expand subtrees by clicking nodes with children. Toggle tag group coloring and depth-based coloring via the legend controls.
|
|
32
|
+
|
|
33
|
+
## Syntax
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
mindmap Title
|
|
37
|
+
|
|
38
|
+
Node
|
|
39
|
+
Child Node
|
|
40
|
+
Grandchild
|
|
41
|
+
Another Child
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
The first line declares the chart type. The title becomes the root node. Indentation establishes the parent-child hierarchy.
|
|
45
|
+
|
|
46
|
+
## Nodes
|
|
47
|
+
|
|
48
|
+
Every non-blank, non-directive line is a node. Nesting is set by indentation:
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
mindmap Root
|
|
52
|
+
Level 1a
|
|
53
|
+
Level 2a
|
|
54
|
+
Level 2b
|
|
55
|
+
Level 1b
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Node Colors
|
|
59
|
+
|
|
60
|
+
Add a color suffix in parentheses:
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
Important Topic(red)
|
|
64
|
+
Sub-topic(blue)
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Descriptions
|
|
68
|
+
|
|
69
|
+
Nodes can have descriptions shown as secondary text. Two forms:
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
// Pipe form (single line)
|
|
73
|
+
Surveys | description: Quarterly NPS survey
|
|
74
|
+
|
|
75
|
+
// Indented form (before children)
|
|
76
|
+
Auth System
|
|
77
|
+
description: Handle login, signup, and OAuth flows
|
|
78
|
+
Login Page
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Collapse Default
|
|
82
|
+
|
|
83
|
+
Set a node's default collapsed state with pipe metadata:
|
|
84
|
+
|
|
85
|
+
```
|
|
86
|
+
Nice-to-haves | collapsed: true
|
|
87
|
+
Dark Mode
|
|
88
|
+
Export PDF
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Collapsed nodes show a drill-bar indicating hidden children. Click to expand.
|
|
92
|
+
|
|
93
|
+
## Multi-Root
|
|
94
|
+
|
|
95
|
+
Omit the title to create multiple independent root trees:
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
mindmap
|
|
99
|
+
|
|
100
|
+
Q1 Goals
|
|
101
|
+
Ship MVP
|
|
102
|
+
Hire designers
|
|
103
|
+
Q2 Goals
|
|
104
|
+
Launch marketing
|
|
105
|
+
Expand team
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
The diagram title is inferred from the first root's label.
|
|
109
|
+
|
|
110
|
+
## Pipe Metadata
|
|
111
|
+
|
|
112
|
+
Attach metadata after `|` with comma-separated `key: value` pairs:
|
|
113
|
+
|
|
114
|
+
```
|
|
115
|
+
Node | priority: High, status: Done
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Tag values, descriptions, and `collapsed` are all set via pipe metadata.
|
|
119
|
+
|
|
120
|
+
## Tag Groups
|
|
121
|
+
|
|
122
|
+
Tag groups define color-coded categories. They appear before content and follow the standard tag syntax:
|
|
123
|
+
|
|
124
|
+
```
|
|
125
|
+
mindmap Root
|
|
126
|
+
|
|
127
|
+
tag Priority p
|
|
128
|
+
High(red)
|
|
129
|
+
Medium(yellow)
|
|
130
|
+
Low(green)
|
|
131
|
+
|
|
132
|
+
Task A | p: High
|
|
133
|
+
Task B | p: Low
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
- The alias (`p`) provides a shorthand for metadata keys
|
|
137
|
+
- The active tag group colors nodes by their tag value
|
|
138
|
+
- Click a tag group name in the legend to activate or deactivate it
|
|
139
|
+
|
|
140
|
+
## Options
|
|
141
|
+
|
|
142
|
+
| Option | Effect |
|
|
143
|
+
|--------|--------|
|
|
144
|
+
| `active-tag GroupName` | Set the default active tag group |
|
|
145
|
+
| `hide-descriptions` | Hide description text on all nodes |
|
|
146
|
+
|
|
147
|
+
Options are placed on their own line before content:
|
|
148
|
+
|
|
149
|
+
```
|
|
150
|
+
mindmap Root
|
|
151
|
+
|
|
152
|
+
tag Priority p
|
|
153
|
+
High(red)
|
|
154
|
+
Low(green)
|
|
155
|
+
|
|
156
|
+
active-tag Priority
|
|
157
|
+
hide-descriptions
|
|
158
|
+
|
|
159
|
+
Task A | p: High
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## Complete Example
|
|
163
|
+
|
|
164
|
+
```dgmo
|
|
165
|
+
mindmap Product Strategy(blue)
|
|
166
|
+
|
|
167
|
+
tag Priority p
|
|
168
|
+
High(red)
|
|
169
|
+
Medium(yellow)
|
|
170
|
+
Low(green)
|
|
171
|
+
|
|
172
|
+
tag Department d
|
|
173
|
+
Engineering(blue)
|
|
174
|
+
Design(purple)
|
|
175
|
+
Marketing(orange)
|
|
176
|
+
|
|
177
|
+
active-tag Priority
|
|
178
|
+
|
|
179
|
+
Research | d: Marketing
|
|
180
|
+
User Interviews | p: High
|
|
181
|
+
Surveys | description: Quarterly NPS survey
|
|
182
|
+
Focus Groups
|
|
183
|
+
Competitor Analysis | d: Engineering
|
|
184
|
+
Feature Matrix
|
|
185
|
+
Pricing Review
|
|
186
|
+
Development | p: High, d: Engineering
|
|
187
|
+
MVP Features
|
|
188
|
+
Auth System
|
|
189
|
+
description: Handle login, signup, OAuth flows
|
|
190
|
+
Dashboard
|
|
191
|
+
Nice-to-haves | p: Low, collapsed: true
|
|
192
|
+
Dark Mode
|
|
193
|
+
Export PDF
|
|
194
|
+
Go-to-Market | d: Marketing
|
|
195
|
+
Launch Plan
|
|
196
|
+
Blog Post
|
|
197
|
+
Demo Video | description: 2-min product walkthrough
|
|
198
|
+
```
|
|
@@ -103,7 +103,29 @@ PaymentGW is a networking aka "Payment Gateway"
|
|
|
103
103
|
OrderDB position -1
|
|
104
104
|
```
|
|
105
105
|
|
|
106
|
-
|
|
106
|
+
## Participant Ordering
|
|
107
|
+
|
|
108
|
+
Participants are laid out left-to-right based on **first appearance in messages** ā the first participant mentioned gets the leftmost column.
|
|
109
|
+
|
|
110
|
+
**Position values:**
|
|
111
|
+
- `0` = leftmost, `1` = second from left, etc.
|
|
112
|
+
- `-1` = rightmost, `-2` = second from right
|
|
113
|
+
- If two participants target the same slot, the later one shifts to the nearest free position
|
|
114
|
+
|
|
115
|
+
**Groups affect ordering:** members of the same group always stay adjacent (see [Groups](#groups) below). The group is placed where its first member would naturally appear.
|
|
116
|
+
|
|
117
|
+
**Priority (highest wins):**
|
|
118
|
+
1. Explicit `position N`
|
|
119
|
+
2. Group adjacency
|
|
120
|
+
3. First appearance in messages
|
|
121
|
+
|
|
122
|
+
```
|
|
123
|
+
// Example: force the database to the far right
|
|
124
|
+
sequence
|
|
125
|
+
User -placeOrder-> OrderService
|
|
126
|
+
OrderService -save-> OrderDB
|
|
127
|
+
OrderDB position -1
|
|
128
|
+
```
|
|
107
129
|
|
|
108
130
|
## Messages
|
|
109
131
|
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# Wireframe
|
|
2
|
+
|
|
3
|
+
```dgmo
|
|
4
|
+
wireframe Login Page
|
|
5
|
+
|
|
6
|
+
[Header]
|
|
7
|
+
Acme App
|
|
8
|
+
nav
|
|
9
|
+
Home | active
|
|
10
|
+
About
|
|
11
|
+
Pricing
|
|
12
|
+
|
|
13
|
+
[Main]
|
|
14
|
+
# Sign In
|
|
15
|
+
|
|
16
|
+
Email [user@example.com]
|
|
17
|
+
Password [****] | password
|
|
18
|
+
|
|
19
|
+
<x> Remember me
|
|
20
|
+
|
|
21
|
+
(Sign In)
|
|
22
|
+
(Forgot Password?) | ghost
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
New here? (Create Account) | ghost
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Overview
|
|
30
|
+
|
|
31
|
+
Wireframe diagrams use **visual-mnemonic syntax** where bracket characters communicate the element type. The source text reads as a wireframe even before rendering.
|
|
32
|
+
|
|
33
|
+
## Elements
|
|
34
|
+
|
|
35
|
+
| Syntax | Element |
|
|
36
|
+
|--------|---------|
|
|
37
|
+
| `[text]` (no children) | Text input |
|
|
38
|
+
| `[Name]` (with children) | Group / region |
|
|
39
|
+
| `(Label)` | Button |
|
|
40
|
+
| `{A \| B \| C}` | Dropdown |
|
|
41
|
+
| `<x>` / `< >` | Checkbox |
|
|
42
|
+
| `(*) Label` / `( ) Label` | Radio button |
|
|
43
|
+
| `# Text` | Heading |
|
|
44
|
+
| `## Text` | Subheading |
|
|
45
|
+
| `---` | Divider |
|
|
46
|
+
| `- text` | List item |
|
|
47
|
+
|
|
48
|
+
## Keywords
|
|
49
|
+
|
|
50
|
+
`nav`, `tabs`, `table`, `image`, `modal`, `skeleton`, `alert`, `progress`, `chart`
|
|
51
|
+
|
|
52
|
+
- `image round` / `image wide` ā shape hints
|
|
53
|
+
- `chart line` / `chart bar` / `chart pie` ā chart silhouettes
|
|
54
|
+
- `progress 60` ā percentage bar
|
|
55
|
+
- `table 5x4` ā skeleton table with dimensions
|
|
56
|
+
|
|
57
|
+
## States
|
|
58
|
+
|
|
59
|
+
Pipe metadata flags on elements:
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
(Submit) | disabled
|
|
63
|
+
(Delete) | destructive
|
|
64
|
+
(Cancel) | ghost
|
|
65
|
+
[Email] | password
|
|
66
|
+
[Notes] | textarea
|
|
67
|
+
<x> Dark mode | toggle
|
|
68
|
+
[Cards] | horizontal
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Layout
|
|
72
|
+
|
|
73
|
+
- **Desktop** (default): 1200px, top-level regions side-by-side
|
|
74
|
+
- **Mobile**: `mobile` keyword, 375px vertical stacking
|
|
75
|
+
- **Smart sizing**: `sidebar` gets ~25%, `main` fills remaining
|
|
76
|
+
- `| horizontal` on any group arranges children in a row
|
|
77
|
+
|
|
78
|
+
## Multi-Element Lines
|
|
79
|
+
|
|
80
|
+
Two or more spaces between elements on one line:
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
Email [user@example.com] // label + field
|
|
84
|
+
(-) 1 (+) // inline stepper
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Tables
|
|
88
|
+
|
|
89
|
+
```dgmo
|
|
90
|
+
wireframe Data
|
|
91
|
+
|
|
92
|
+
table
|
|
93
|
+
Name, Email, Role
|
|
94
|
+
John, john@, Admin
|
|
95
|
+
Sally, sally@, Editor
|
|
96
|
+
|
|
97
|
+
// Skeleton shorthand:
|
|
98
|
+
table 5x4
|
|
99
|
+
Name, Email, Role, Status
|
|
100
|
+
```
|
package/docs/guide/index.md
CHANGED
|
@@ -4,6 +4,14 @@ Diagrammo is a diagram editor for creating charts and diagrams with a simple pla
|
|
|
4
4
|
|
|
5
5
|
Learn more at **[diagrammo.app](https://diagrammo.app)**.
|
|
6
6
|
|
|
7
|
+
## DGMO and Diagrammo
|
|
8
|
+
|
|
9
|
+
**DGMO** is the plain-text markup language you write. **Diagrammo** is the app you write it in.
|
|
10
|
+
|
|
11
|
+
Think of it like Markdown and your editor ā Markdown is the syntax, and you can write it anywhere. DGMO works the same way: it's a `.dgmo` text file that describes a diagram. You can create and edit `.dgmo` files in the Diagrammo desktop app, the online editor, Obsidian (via plugin), or any text editor. The `dgmo` CLI renders them from the terminal, and the `@diagrammo/dgmo` npm package lets you render them programmatically.
|
|
12
|
+
|
|
13
|
+
The name "DGMO" is shorthand for "Diagrammo" ā shorter to type, easier to use as a file extension and command name.
|
|
14
|
+
|
|
7
15
|
## Getting Started
|
|
8
16
|
|
|
9
17
|
- **Create a new file** using the file tree on the left, or press **Cmd + N**
|
|
@@ -20,7 +20,8 @@
|
|
|
20
20
|
14. [Timeline Diagrams](#14-timeline-diagrams)
|
|
21
21
|
15. [Data Charts](#15-data-charts)
|
|
22
22
|
16. [Visualizations](#16-visualizations)
|
|
23
|
-
17. [
|
|
23
|
+
17. [Wireframe Diagrams](#17-wireframe-diagrams)
|
|
24
|
+
18. [Colon Usage Summary](#18-colon-usage-summary)
|
|
24
25
|
|
|
25
26
|
---
|
|
26
27
|
|
|
@@ -114,6 +115,79 @@ no-option-name // off
|
|
|
114
115
|
- Bare keyword = on; `no-` prefix = off
|
|
115
116
|
- Must appear before diagram content
|
|
116
117
|
|
|
118
|
+
### 1.9 In-Arrow Message Labels
|
|
119
|
+
|
|
120
|
+
An **in-arrow label** is the text embedded inside an arrow between the opening delimiter and the arrow token, as in `A -label-> B`.
|
|
121
|
+
|
|
122
|
+
```
|
|
123
|
+
A -label-> B
|
|
124
|
+
^ ^---^ ^^
|
|
125
|
+
| | ||
|
|
126
|
+
| | |+- destination id
|
|
127
|
+
| | +- arrow token
|
|
128
|
+
| +- label text (plain, no markdown)
|
|
129
|
+
+- opening delimiter (matches arrow type)
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
**Chart types that support in-arrow labels**: sequence, flowchart, state, infra, c4, er, class, boxes-and-lines.
|
|
133
|
+
|
|
134
|
+
#### Cheat sheet
|
|
135
|
+
|
|
136
|
+
```
|
|
137
|
+
// happy-path: labels are plain text with punctuation allowed
|
|
138
|
+
A -location[]-> B // label = "location[]"
|
|
139
|
+
A -a[b]c-> B // label = "a[b]c"
|
|
140
|
+
A -{json}-> B // label = "{json}"
|
|
141
|
+
|
|
142
|
+
// unicode: all scripts and emoji preserved verbatim
|
|
143
|
+
A -cafƩ-> B
|
|
144
|
+
A -ę„ę¬čŖ-> B
|
|
145
|
+
A -š-> B
|
|
146
|
+
|
|
147
|
+
// punctuation is literal ā no markdown interpretation
|
|
148
|
+
A -(parenthetical)-> B // label = "(parenthetical)" (NOT a color)
|
|
149
|
+
A -*emphasis*-> B // label = "*emphasis*" (NOT bold)
|
|
150
|
+
A -`code`-> B // label = "`code`" (NOT a code span)
|
|
151
|
+
|
|
152
|
+
// forbidden: -> and ~> substrings inside a label
|
|
153
|
+
A -uses -> chain-> B // ERROR (E_ARROW_SUBSTRING_IN_LABEL)
|
|
154
|
+
// migration: move the label to the post-colon form
|
|
155
|
+
A -> B: uses -> chain // works for charts that accept post-colon labels
|
|
156
|
+
|
|
157
|
+
// migration from pre-gauntlet (legacy) syntax
|
|
158
|
+
A -Makes calls [HTTP]-> B // label is now the FULL "Makes calls [HTTP]"
|
|
159
|
+
A -Makes calls-> B | tech: HTTP // preferred: technology on target metadata
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
#### Character-set contract
|
|
163
|
+
|
|
164
|
+
- **Allowed**: any Unicode codepoint except the forbidden list below. Brackets `[] {} ()`, pipes `|`, quotes `"' `, backticks, punctuation, digits, emoji, ZWJ sequences, combining marks ā all pass through as literal characters.
|
|
165
|
+
- **Forbidden substrings**: `->` and `~>`. These terminate the arrow. If you need them inside a label, use the post-colon form (`A -> B: uses -> to chain`) on chart types that support it; there is no escape mechanism.
|
|
166
|
+
- **Forbidden characters**: C0 control characters U+0000āU+001F except U+0009 (tab), and U+007F (DEL). Silent renderer breakage and log-injection surface ā no legitimate use case.
|
|
167
|
+
- **Whitespace**: leading and trailing whitespace is trimmed; internal whitespace runs (including tabs, non-breaking spaces, and zero-width spaces) are **preserved**, never collapsed.
|
|
168
|
+
- **Plain text only**: no markdown interpretation. `*foo*` renders as `*foo*`, not italicized. `[label](url)` renders as literal `[label](url)`, not a hyperlink. Clickable URLs belong in notes, not in in-arrow labels.
|
|
169
|
+
- **HTML-safe**: all renderers emit label text as a DOM text node. `<script>alert(1)</script>` renders as literal text ā the entire label is a sequence of codepoints, not a markup fragment.
|
|
170
|
+
|
|
171
|
+
#### Color suffix (flowchart and state only)
|
|
172
|
+
|
|
173
|
+
```
|
|
174
|
+
A -(red)-> B // colored edge, no label
|
|
175
|
+
A -(notacolor)-> B // label = "(notacolor)" (fall-through)
|
|
176
|
+
A -(red) uses-> B // label = "(red) uses" (combined form not supported)
|
|
177
|
+
A -red-> B // label = "red" (bare word is always a label)
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
A parenthesized palette color is only recognized when the entire label between the opening `-` and the arrow token is exactly `(colorName)` and `colorName` is one of the 11 names in §1.5. Any other content falls through to the label. To combine a color and a label, use the post-colon or pipe-metadata form instead.
|
|
181
|
+
|
|
182
|
+
#### Migrating from pre-gauntlet syntax
|
|
183
|
+
|
|
184
|
+
Two legacy forms changed with this spec:
|
|
185
|
+
|
|
186
|
+
1. **C4 trailing `[technology]` sugar is removed.** A C4 arrow like `-Makes calls [HTTPS]-> API` used to extract `HTTPS` as the technology annotation. The full `Makes calls [HTTPS]` is now the label. Use the post-colon or pipe form for technology: `-Makes calls-> API | tech: HTTPS`.
|
|
187
|
+
2. **Bare palette color suffixes are a literal label.** `A -red-> B` on flowchart/state used to be accepted as a bare color suffix in some surfaces. It is now always a label with text `red`. To color an edge, use the `-(red)->` parens form.
|
|
188
|
+
|
|
189
|
+
No code migration is required for in-arrow label character escaping ā any label that was valid before remains valid, with one exception: if your label happened to contain the literal substring `->` or `~>`, the parser now rejects it with `E_ARROW_SUBSTRING_IN_LABEL`. Move those labels to the post-colon form.
|
|
190
|
+
|
|
117
191
|
---
|
|
118
192
|
|
|
119
193
|
## 2. Sequence Diagrams
|
|
@@ -1253,7 +1327,141 @@ Navigator 0.85 0.8
|
|
|
1253
1327
|
|
|
1254
1328
|
---
|
|
1255
1329
|
|
|
1256
|
-
## 17.
|
|
1330
|
+
## 17. Wireframe Diagrams
|
|
1331
|
+
|
|
1332
|
+
Wireframe diagrams use **visual-mnemonic syntax** where bracket characters communicate element type.
|
|
1333
|
+
|
|
1334
|
+
### Declaration
|
|
1335
|
+
|
|
1336
|
+
```
|
|
1337
|
+
wireframe Page Title
|
|
1338
|
+
```
|
|
1339
|
+
|
|
1340
|
+
### Form Factor
|
|
1341
|
+
|
|
1342
|
+
```
|
|
1343
|
+
mobile
|
|
1344
|
+
```
|
|
1345
|
+
|
|
1346
|
+
Switches to narrow vertical layout (375px). Desktop (1200px, horizontal regions) is the default.
|
|
1347
|
+
|
|
1348
|
+
### Visual-Mnemonic Elements
|
|
1349
|
+
|
|
1350
|
+
| Syntax | Element | Example |
|
|
1351
|
+
|--------|---------|---------|
|
|
1352
|
+
| `[text]` (leaf) | Text input | `[Email address]` |
|
|
1353
|
+
| `[Name]` (with children) | Group/region | `[Sidebar]` + indented children |
|
|
1354
|
+
| `(Label)` | Button | `(Submit)` |
|
|
1355
|
+
| `{A \| B \| C}` | Dropdown/select | `{Small \| Medium \| Large}` |
|
|
1356
|
+
| `<x>` / `< >` | Checkbox | `<x> Remember me` |
|
|
1357
|
+
| `(*) Label` / `( ) Label` | Radio button | `(*) Option A` |
|
|
1358
|
+
| `# Text` / `## Text` | Heading | `# Sign In` |
|
|
1359
|
+
| `---` | Divider | `---` |
|
|
1360
|
+
| `- text` | List item | `- Electronics` |
|
|
1361
|
+
| Bare text | Text/paragraph | `Welcome to our app` |
|
|
1362
|
+
|
|
1363
|
+
### Keyword Elements
|
|
1364
|
+
|
|
1365
|
+
| Keyword | Type | Parameters |
|
|
1366
|
+
|---------|------|------------|
|
|
1367
|
+
| `nav` | Block | Children are nav items |
|
|
1368
|
+
| `tabs` | Block | Children are tab labels |
|
|
1369
|
+
| `table` | Block | Comma-separated rows; first = header |
|
|
1370
|
+
| `table RxC` | Skeleton table | `table 5x4` + optional header row |
|
|
1371
|
+
| `image` | Leaf | `round`, `wide` hints |
|
|
1372
|
+
| `modal Title` | Block | Rendered as separate panel below |
|
|
1373
|
+
| `skeleton` | Block | Children render as grey placeholders |
|
|
1374
|
+
| `alert` | Block | Optional semantic state |
|
|
1375
|
+
| `progress N` | Leaf | Value 0-100: `progress 60` |
|
|
1376
|
+
| `chart type` | Leaf | `chart line`, `chart bar`, `chart pie` |
|
|
1377
|
+
|
|
1378
|
+
### Pipe Metadata (States)
|
|
1379
|
+
|
|
1380
|
+
Wireframe uses flag keywords (not `key: value`):
|
|
1381
|
+
|
|
1382
|
+
```
|
|
1383
|
+
(Submit) | disabled
|
|
1384
|
+
(Delete) | destructive
|
|
1385
|
+
(Cancel) | ghost
|
|
1386
|
+
[Email] | password
|
|
1387
|
+
[Notes] | textarea
|
|
1388
|
+
[Cards] | horizontal
|
|
1389
|
+
[Advanced] | collapsed
|
|
1390
|
+
[Messages] | scrollable
|
|
1391
|
+
<x> Dark mode | toggle
|
|
1392
|
+
```
|
|
1393
|
+
|
|
1394
|
+
Available states: `disabled`, `active`, `selected`, `empty`, `ghost`, `destructive`, `success`, `warning`, `info`, `scrollable`, `collapsed`, `toggle`, `password`, `textarea`, `horizontal`, `primary`.
|
|
1395
|
+
|
|
1396
|
+
Free-text annotations after states: `[Email] | required, validates email format`.
|
|
1397
|
+
|
|
1398
|
+
### Multi-Element Lines
|
|
1399
|
+
|
|
1400
|
+
Two or more spaces between segments create separate elements:
|
|
1401
|
+
|
|
1402
|
+
```
|
|
1403
|
+
Email [user@example.com] // label + field (2 segments)
|
|
1404
|
+
(-) 1 (+) // 3 inline items
|
|
1405
|
+
$299.99 ~~$349.99~~ // 2 inline texts
|
|
1406
|
+
```
|
|
1407
|
+
|
|
1408
|
+
- **2 segments** (bare text + element): label-for-element pairing
|
|
1409
|
+
- **3+ segments**: inline items, no label pairing
|
|
1410
|
+
- **Single space = same element**: `Cart (3)` is one text element
|
|
1411
|
+
|
|
1412
|
+
### Group Disambiguation
|
|
1413
|
+
|
|
1414
|
+
- `[Name]` with indented children = group/container
|
|
1415
|
+
- `[Name]` with no children = text input
|
|
1416
|
+
- `[Name] | horizontal/scrollable/collapsed` = group (even without children)
|
|
1417
|
+
|
|
1418
|
+
### Table Syntax
|
|
1419
|
+
|
|
1420
|
+
Explicit rows (comma-separated, first row = header):
|
|
1421
|
+
|
|
1422
|
+
```
|
|
1423
|
+
table
|
|
1424
|
+
Name, Email, Role
|
|
1425
|
+
John, john@, Admin
|
|
1426
|
+
Sally, sally@, Editor
|
|
1427
|
+
```
|
|
1428
|
+
|
|
1429
|
+
Skeleton shorthand:
|
|
1430
|
+
|
|
1431
|
+
```
|
|
1432
|
+
table 5x4
|
|
1433
|
+
Name, Email, Role, Status
|
|
1434
|
+
```
|
|
1435
|
+
|
|
1436
|
+
### Layout Model
|
|
1437
|
+
|
|
1438
|
+
- Desktop: 1200px wide, top-level regions arrange horizontally
|
|
1439
|
+
- Mobile: 375px wide, all regions stack vertically
|
|
1440
|
+
- Smart sizing: `sidebar` ā ~25%, `main`/`content` ā fill, `header`/`footer` ā full width
|
|
1441
|
+
- `| horizontal` on groups arranges children in a row
|
|
1442
|
+
|
|
1443
|
+
### Example
|
|
1444
|
+
|
|
1445
|
+
```
|
|
1446
|
+
wireframe Login Page
|
|
1447
|
+
|
|
1448
|
+
[Header]
|
|
1449
|
+
nav
|
|
1450
|
+
Home | active
|
|
1451
|
+
Settings
|
|
1452
|
+
|
|
1453
|
+
[Main]
|
|
1454
|
+
# Sign In
|
|
1455
|
+
Email [user@example.com]
|
|
1456
|
+
Password [****] | password
|
|
1457
|
+
<x> Remember me
|
|
1458
|
+
(Sign In)
|
|
1459
|
+
(Forgot Password?) | ghost
|
|
1460
|
+
```
|
|
1461
|
+
|
|
1462
|
+
---
|
|
1463
|
+
|
|
1464
|
+
## 18. Colon Usage Summary
|
|
1257
1465
|
|
|
1258
1466
|
### Constructs Where Colons Are REQUIRED
|
|
1259
1467
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@diagrammo/dgmo",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.21",
|
|
4
4
|
"description": "DGMO diagram markup language ā parser, renderer, and color system",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -55,10 +55,12 @@
|
|
|
55
55
|
],
|
|
56
56
|
"sideEffects": false,
|
|
57
57
|
"scripts": {
|
|
58
|
-
"
|
|
58
|
+
"codegen": "lezer-generator src/editor/dgmo.grammar -o src/editor/dgmo.grammar.js",
|
|
59
|
+
"prebuild": "rm -rf dist && pnpm codegen",
|
|
59
60
|
"build": "tsup",
|
|
60
61
|
"typecheck": "tsc --noEmit",
|
|
61
62
|
"dev": "tsup --watch",
|
|
63
|
+
"pretest": "pnpm codegen",
|
|
62
64
|
"test": "vitest run",
|
|
63
65
|
"test:watch": "vitest",
|
|
64
66
|
"gallery": "pnpm build && node scripts/generate-gallery.mjs",
|
|
@@ -69,7 +71,13 @@
|
|
|
69
71
|
"check:duplication": "jscpd ./src",
|
|
70
72
|
"check:deadcode": "knip",
|
|
71
73
|
"check:spelling": "cspell \"src/**/*.ts\" \"tests/**/*.ts\"",
|
|
74
|
+
"check:all": "pnpm check:deadcode && pnpm check:spelling && pnpm check:duplication && pnpm check:circular && pnpm check:deps && pnpm check:security && pnpm build && pnpm check:publish && pnpm check:types",
|
|
75
|
+
"check:circular": "madge --circular --extensions ts src/ --json | node -e \"const c=JSON.parse(require('fs').readFileSync('/dev/stdin','utf8')); const n=c.length; if(n>7){console.error('New circular deps found ('+n+' > 7 known type-only cycles)');process.exit(1)}else if(n>0){console.log(n+' known type-only/dynamic cycles (safe)')}else{console.log('No circular dependencies')}\"",
|
|
76
|
+
"check:deps": "depcheck --ignores='@codemirror/language,@lezer/*,husky,lint-staged,tsup'",
|
|
77
|
+
"check:security": "pnpm audit --prod",
|
|
78
|
+
"check:publish": "publint",
|
|
72
79
|
"check:size": "pnpm build && du -sh dist/ && echo '---' && ls -lh dist/*.js dist/*.cjs",
|
|
80
|
+
"check:types": "attw --pack . --ignore-rules no-resolution",
|
|
73
81
|
"postinstall": "node -e \"console.log('\\nš” Claude Code user? Run: dgmo --install-claude-skill\\n')\"",
|
|
74
82
|
"prepare": "husky"
|
|
75
83
|
},
|
|
@@ -83,10 +91,11 @@
|
|
|
83
91
|
"d3-selection": "^3.0.0",
|
|
84
92
|
"d3-shape": "^3.2.0",
|
|
85
93
|
"echarts": "^6.0.0",
|
|
86
|
-
"jsdom": "^29.0.
|
|
94
|
+
"jsdom": "^29.0.2",
|
|
87
95
|
"lz-string": "^1.5.0"
|
|
88
96
|
},
|
|
89
97
|
"devDependencies": {
|
|
98
|
+
"@arethetypeswrong/cli": "^0.18.2",
|
|
90
99
|
"@codemirror/language": "^6.12.3",
|
|
91
100
|
"@eslint/js": "^10.0.1",
|
|
92
101
|
"@lezer/generator": "^1.8.0",
|
|
@@ -97,18 +106,22 @@
|
|
|
97
106
|
"@types/d3-selection": "^3.0.11",
|
|
98
107
|
"@types/d3-shape": "^3.1.8",
|
|
99
108
|
"@types/jsdom": "^28.0.1",
|
|
100
|
-
"cspell": "^
|
|
109
|
+
"cspell": "^10.0.0",
|
|
110
|
+
"depcheck": "^1.4.7",
|
|
101
111
|
"esbuild": "^0.28.0",
|
|
102
112
|
"eslint": "^10.2.0",
|
|
113
|
+
"eslint-plugin-security": "^4.0.0",
|
|
103
114
|
"husky": "^9.1.7",
|
|
104
|
-
"jscpd": "^4.0.
|
|
105
|
-
"knip": "^6.3.
|
|
115
|
+
"jscpd": "^4.0.9",
|
|
116
|
+
"knip": "^6.3.1",
|
|
106
117
|
"lint-staged": "^16.4.0",
|
|
107
|
-
"
|
|
118
|
+
"madge": "^8.0.0",
|
|
119
|
+
"prettier": "^3.8.2",
|
|
120
|
+
"publint": "^0.3.18",
|
|
108
121
|
"tsup": "^8.5.1",
|
|
109
122
|
"typescript": "^6.0.2",
|
|
110
|
-
"typescript-eslint": "^8.58.
|
|
111
|
-
"vitest": "^4.1.
|
|
123
|
+
"typescript-eslint": "^8.58.1",
|
|
124
|
+
"vitest": "^4.1.4"
|
|
112
125
|
},
|
|
113
126
|
"lint-staged": {
|
|
114
127
|
"*.ts": [
|
|
@@ -40,12 +40,28 @@ export function collapseBoxesAndLines(
|
|
|
40
40
|
const nodeToGroup = new Map<string, string>();
|
|
41
41
|
const collapsedChildCounts = new Map<string, number>();
|
|
42
42
|
|
|
43
|
+
// Recursively collect all descendants of a group (including sub-group children)
|
|
44
|
+
function collectDescendants(groupLabel: string): string[] {
|
|
45
|
+
const group = groupByLabel.get(groupLabel);
|
|
46
|
+
if (!group) return [];
|
|
47
|
+
const descendants: string[] = [];
|
|
48
|
+
for (const child of group.children) {
|
|
49
|
+
descendants.push(child);
|
|
50
|
+
// If child is itself a group, collect its descendants too
|
|
51
|
+
if (groupByLabel.has(child)) {
|
|
52
|
+
descendants.push(...collectDescendants(child));
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return descendants;
|
|
56
|
+
}
|
|
57
|
+
|
|
43
58
|
for (const groupLabel of collapsedGroups) {
|
|
44
59
|
const group = groupByLabel.get(groupLabel);
|
|
45
60
|
if (!group) continue;
|
|
46
61
|
const groupId = `__group_${groupLabel}`;
|
|
47
62
|
|
|
48
|
-
|
|
63
|
+
const allDescendants = collectDescendants(groupLabel);
|
|
64
|
+
for (const child of allDescendants) {
|
|
49
65
|
nodeToGroup.set(child, groupId);
|
|
50
66
|
}
|
|
51
67
|
collapsedChildCounts.set(groupLabel, group.children.length);
|
|
@@ -67,8 +83,10 @@ export function collapseBoxesAndLines(
|
|
|
67
83
|
edges.push({ ...edge, source: src, target: tgt });
|
|
68
84
|
}
|
|
69
85
|
|
|
70
|
-
// Keep only groups that are not collapsed
|
|
71
|
-
const groups = parsed.groups.filter(
|
|
86
|
+
// Keep only groups that are not collapsed and not inside a collapsed group
|
|
87
|
+
const groups = parsed.groups.filter(
|
|
88
|
+
(g) => !collapsedGroups.has(g.label) && !nodeToGroup.has(g.label)
|
|
89
|
+
);
|
|
72
90
|
|
|
73
91
|
return {
|
|
74
92
|
parsed: { ...parsed, nodes, edges, groups },
|