Skip to content

Commit 79592e9

Browse files
authored
Merge pull request #135 from jongalloway/copilot/add-wireframe-dsl-parser
Add WireframeDslParser for markdown-ui-dsl wireframe diagrams
2 parents 3ad7cd2 + a7c207b commit 79592e9

16 files changed

Lines changed: 2404 additions & 15 deletions

README.md

Lines changed: 78 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ Representative snapshot fixtures from the E2E suite. Click any thumbnail to open
1212
<!-- markdownlint-disable MD033 -->
1313
<h3>Diagram Types</h3>
1414

15-
DiagramForge currently supports more than a dozen diagram types across Mermaid and the conceptual DSL. This gallery is representative, not complete, and includes a few icon-enabled examples. See [Supported syntax](#supported-syntax) and [Conceptual DSL](#conceptual-dsl) below for the full set and syntax details.
15+
DiagramForge currently supports more than a dozen diagram types across Mermaid, the Conceptual DSL, and the Wireframe DSL. This gallery is representative, not complete, and includes a few icon-enabled examples. See [Supported syntax](#supported-syntax), [Conceptual DSL](#conceptual-dsl), and [Wireframe DSL](#wireframe-dsl) below for the full set and syntax details.
1616

1717
<table cellpadding="12" width="100%">
1818
<tr>
@@ -138,6 +138,20 @@ DiagramForge currently supports more than a dozen diagram types across Mermaid a
138138
<br />
139139
<sub>Snake Timeline (Dracula)</sub>
140140
</td>
141+
<td align="center" valign="top" width="33%">
142+
<a href="https://github.com/jongalloway/DiagramForge/blob/main/tests/DiagramForge.E2ETests/Fixtures/wireframe-form.expected.svg">
143+
<img src="https://raw.githubusercontent.com/jongalloway/DiagramForge/main/tests/DiagramForge.E2ETests/Fixtures/wireframe-form.expected.svg" alt="Wireframe form dialog" height="96" />
144+
</a>
145+
<br />
146+
<sub>Wireframe Form</sub>
147+
</td>
148+
<td align="center" valign="top" width="33%">
149+
<a href="https://github.com/jongalloway/DiagramForge/blob/main/tests/DiagramForge.E2ETests/Fixtures/wireframe-dashboard.expected.svg">
150+
<img src="https://raw.githubusercontent.com/jongalloway/DiagramForge/main/tests/DiagramForge.E2ETests/Fixtures/wireframe-dashboard.expected.svg" alt="Wireframe dashboard (Dracula)" height="96" />
151+
</a>
152+
<br />
153+
<sub>Wireframe Dashboard (Dracula)</sub>
154+
</td>
141155
</tr>
142156
</table>
143157

@@ -278,7 +292,7 @@ That's the whole API.
278292

279293
Most diagram-as-code tools assume a browser. Mermaid.js needs a JavaScript engine to run at all — and even once you've stood up headless Chrome and extracted the SVG, you find that it renders text via `<foreignObject>` wrapping HTML `<div>`s instead of native `<text>` elements. That's fine in a web page. It's a blank box in Inkscape, a parse error in Illustrator, and a mess when you try to drop it into a PowerPoint slide. See mermaid-js/mermaid [#2688](https://github.com/mermaid-js/mermaid/issues/2688), [#1845](https://github.com/mermaid-js/mermaid/issues/1845), [#1923](https://github.com/mermaid-js/mermaid/issues/1923), [#2169](https://github.com/mermaid-js/mermaid/issues/2169).
280294

281-
DiagramForge aims lower and hits harder: a **subset** of Mermaid, rendered to **actual** SVG. Flowcharts, block diagrams, sequence diagrams, state diagrams, mindmaps, timelines, Venn diagrams, architecture diagrams, and XY charts — the output opens anywhere.
295+
DiagramForge aims lower and hits harder: a **subset** of Mermaid, rendered to **actual** SVG. Flowcharts, block diagrams, sequence diagrams, state diagrams, mindmaps, timelines, Venn diagrams, architecture diagrams, XY charts, and low-fidelity wireframes — the output opens anywhere.
282296

283297
- **Real SVG.** Native `<text>` elements. No `<foreignObject>`, no embedded HTML, no CSS-in-SVG. Opens in Inkscape, imports into PowerPoint and Keynote, renders with librsvg.
284298
- **Pure .NET.** `net10.0`, zero native dependencies, zero runtime package dependencies. No headless browser, no Node, no shelling out.
@@ -316,7 +330,7 @@ string svg = renderer.Render(diagramText);
316330
File.WriteAllText("out.svg", svg);
317331
```
318332

319-
The renderer auto-detects the syntax from the input. No need to tell it whether it's Mermaid or Conceptual DSL.
333+
The renderer auto-detects the syntax from the input. No need to tell it whether it's Mermaid, Conceptual DSL, or Wireframe DSL.
320334

321335
### With a custom theme
322336

@@ -343,7 +357,7 @@ See [doc/theming.md](doc/theming.md) for the full `Theme` property surface and [
343357

344358
### With diagram frontmatter
345359

346-
Diagram files can embed a small frontmatter block ahead of Mermaid or Conceptual DSL content:
360+
Diagram files can embed a small frontmatter block ahead of Mermaid, Conceptual DSL, or Wireframe DSL content:
347361

348362
```text
349363
---
@@ -784,6 +798,7 @@ Rule of thumb: if the diagram is already easy to describe as Mermaid, use Mermai
784798
| Central concept with surrounding pillars / capabilities (3–8 items) | Conceptual DSL | `diagram: radial\ncenter: Platform\nitems:\n - Security\n - Reliability\n - Observability` |
785799
| Concentric strategy / segmentation target | Conceptual DSL | `diagram: target\ncenter: Launch\nrings:\n - Inner ring: Pricing and messaging\n - Outer ring: Audience reach` |
786800
| Visual step-by-step journey / snake timeline (3+ steps) | Conceptual DSL | `diagram: snake\ntitle: Journey\nsteps:\n - Start: Begin here\n - Middle: Keep going\n - End: Arrive` |
801+
| Low-fidelity UI mockup / wireframe sketch | Wireframe DSL | `wireframe: Settings\n::: HEADER :::\n # Settings\n--- END ---\n[ text: Name ]\n[ Save ](#save)` |
787802

788803
Planned conceptual additions are aimed at presentation-native graphics that Mermaid does not cover idiomatically, such as tree hierarchies / org charts.
789804

@@ -919,6 +934,64 @@ steps:
919934

920935
Requires at least 3 steps. Each step follows the format `Label: Description` — the description is optional. Icons use the standard `icon:pack:name` prefix.
921936

937+
### Wireframe DSL
938+
939+
Low-fidelity wireframe diagrams based on the [markdown-ui-dsl](https://github.com/MegaByteMark/markdown-ui-dsl) syntax. The first non-frontmatter line must start with `wireframe`.
940+
941+
DiagramForge implements a focused subset of the DSL — enough to sketch forms, dashboards, and component showcases as static, theme-able SVG.
942+
943+
#### Supported components
944+
945+
| Component | Syntax | Example |
946+
| --- | --- | --- |
947+
| Header | `::: HEADER :::`…`--- END ---` | `::: HEADER :::\n # Page Title\n--- END ---` |
948+
| Card | `::: CARD: Label :::`…`--- END ---` | `::: CARD: Users :::\n ## 1,240\n Total\n--- END ---` |
949+
| Row layout | `=== ROW ===`…`--- END ---` | `=== ROW ===\n [ OK ](#ok)\n [ Cancel ]\n--- END ---` |
950+
| Button (primary) | `[ Label ](#link)` | `[ Submit ](#save)` |
951+
| Button (secondary) | `[ Label ]` | `[ Cancel ]` |
952+
| Text input | `[ text: placeholder ]` | `[ text: Email address ]` |
953+
| Checkbox | `[x]` / `[ ]` + label | `[x] Accept terms` |
954+
| Radio button | `(x)` / `( )` + label | `(x) Yearly` |
955+
| Toggle | `[on]` / `[off]` + label | `[on] Dark Mode` |
956+
| Dropdown | `[v] Label {options}` | `[v] Country {USA, UK, Canada}` |
957+
| Tab bar | `\|[ Active ]\| Tab2 \| Tab3 \|` | `\|[ Overview ]\| Settings \|` |
958+
| Badge (inline) | `(( Label )) text` | `(( New )) 3 notifications` |
959+
| Heading | `# Heading` or `## Heading` | `# Recent Activity` |
960+
| Body text | plain text line | `Status: Cannot Reproduce` |
961+
| Divider | `***` | `***` |
962+
| Image placeholder | `[ IMG: description ]` | `[ IMG: Profile photo ]` |
963+
964+
#### Example
965+
966+
```text
967+
wireframe: Settings Dialog
968+
::: HEADER :::
969+
# Preferences
970+
--- END ---
971+
[ text: Display name ]
972+
[v] Theme {Light, Dark, System}
973+
[x] Send notifications
974+
( ) Daily digest
975+
(x) Real-time
976+
***
977+
=== ROW ===
978+
[ Save ](#save)
979+
[ Cancel ]
980+
--- END ---
981+
```
982+
983+
All wireframe colors are derived from the active theme's `BackgroundColor`, `TextColor`, `SubtleTextColor`, and `AccentColor`, so every built-in theme (including dark themes) works automatically. Use [frontmatter](#with-diagram-frontmatter) to pick a theme:
984+
985+
```text
986+
---
987+
theme: dracula
988+
---
989+
wireframe: Dashboard
990+
::: HEADER :::
991+
# Mission Control
992+
--- END ---
993+
```
994+
922995
## Architecture
923996

924997
```mermaid
@@ -945,7 +1018,7 @@ Parsers produce a syntax-independent `Diagram` (nodes, edges, groups, labels, la
9451018

9461019
## Roadmap
9471020

948-
See [`doc/prd.md`](doc/prd.md) for the full plan. Short version: more Mermaid diagram types, more conceptual layouts, theme packs, eventually D2 and DOT parsers.
1021+
See [`doc/prd.md`](doc/prd.md) for the full plan. Short version: more Mermaid diagram types, more conceptual layouts, wireframe enhancements, theme packs, eventually D2 and DOT parsers.
9491022

9501023
For analysis of which SmartArt-style conceptual diagrams are most worth adding next, see [`doc/smartart-analysis.md`](doc/smartart-analysis.md).
9511024

doc/prd.md

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# Product Requirements Document (PRD)
2+
23
## Project: Markdown‑Driven Diagram Rendering Engine (Text → SVG)
34

45
---
@@ -38,7 +39,7 @@ Clients (e.g., MarpToPptx, Obsidian plugins, CLI tools) are responsible for extr
3839
- Provide a **pluggable parser architecture** for future syntaxes (e.g., D2, DOT).
3940
- Remain **independent of any specific client** (Marp, PPTX, web apps, etc.).
4041
- Support for themes and palletes, both built-in and user supplied.
41-
- Leverage existing ecosystem. Refer to https://github.com/mermaid-js/mermaid for specification and transpile open source code (with attribution) if possible.
42+
- Leverage existing ecosystem. Refer to <https://github.com/mermaid-js/mermaid> for specification and transpile open source code (with attribution) if possible.
4243

4344
### 2.2 Non‑Goals
4445

@@ -148,7 +149,26 @@ Examples that remain good candidates for the Conceptual DSL:
148149
- Radial / hub-and-spoke
149150
- Pillars / stacked segments
150151

151-
### 5.3 Future Diagram Types (not in v1)
152+
### 5.3 Wireframe DSL
153+
154+
Low-fidelity wireframe diagrams based on the [markdown-ui-dsl](https://github.com/MegaByteMark/markdown-ui-dsl) syntax. The wireframe parser implements a focused subset of the DSL to render UI mockups as self-contained SVG.
155+
156+
Supported component subset:
157+
158+
- Container primitives: column, row, card, header, footer
159+
- Form elements: text input, checkbox, radio button, toggle, dropdown
160+
- Navigation: tab bar (active/inactive states)
161+
- Content: heading, body text, badge (inline with trailing text), image placeholder, divider
162+
- Actions: button (primary via link syntax, secondary via plain brackets)
163+
- Layout: `=== ROW ===` for horizontal arrangement, `::: CARD :::` for grouped content, `***` dividers, indent-based nesting
164+
165+
Selection rule:
166+
167+
- Use the wireframe DSL when the goal is a quick, theme-able, low-fidelity UI sketch inside a slide or document.
168+
- The wireframe DSL is not a UI framework; it renders static SVG of standard UI widget shapes.
169+
- All wireframe colors are derived from the four semantic theme properties (`BackgroundColor`, `TextColor`, `SubtleTextColor`, `AccentColor`) via `WireframePalette`, so every built-in theme works out of the box including dark themes.
170+
171+
### 5.4 Future Diagram Types (not in v1)
152172

153173
- D2 subset
154174
- Architecture diagrams

scripts/Build-Gallery.ps1

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ foreach ($file in $svgFiles) {
112112
$label = Get-FriendlyLabel $themeName
113113
}
114114
else {
115-
$labelSeed = $fixtureName -replace '^mermaid-', '' -replace '^conceptual-', 'Conceptual '
115+
$labelSeed = $fixtureName -replace '^mermaid-', '' -replace '^conceptual-', 'Conceptual ' -replace '^wireframe-', 'Wireframe '
116116
$label = (($labelSeed -split '-') | ForEach-Object {
117117
if ($_.Length -le 2) {
118118
$_.ToUpperInvariant()
@@ -124,13 +124,13 @@ foreach ($file in $svgFiles) {
124124
}
125125

126126
$entries += [PSCustomObject]@{
127-
File = $file
128-
Width = $width
129-
Height = $height
130-
Label = $label
131-
Theme = $themeName
127+
File = $file
128+
Width = $width
129+
Height = $height
130+
Label = $label
131+
Theme = $themeName
132132
IsThemeShowcase = $isThemeShowcase
133-
Content = (Get-Content -LiteralPath $file.FullName -Raw)
133+
Content = (Get-Content -LiteralPath $file.FullName -Raw)
134134
}
135135
}
136136

src/DiagramForge/DiagramRenderer.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using DiagramForge.Models;
66
using DiagramForge.Parsers.Conceptual;
77
using DiagramForge.Parsers.Mermaid;
8+
using DiagramForge.Parsers.Wireframe;
89
using DiagramForge.Rendering;
910

1011
namespace DiagramForge;
@@ -56,7 +57,7 @@ public sealed class DiagramRenderer
5657
/// </summary>
5758
public DiagramRenderer()
5859
: this(
59-
parsers: [new MermaidParser(), new ConceptualDslParser()],
60+
parsers: [new MermaidParser(), new ConceptualDslParser(), new WireframeDslParser()],
6061
layoutEngine: new DefaultLayoutEngine(),
6162
svgRenderer: new SvgRenderer(),
6263
defaultTheme: Theme.Default)

0 commit comments

Comments
 (0)