Skip to content

Commit 4f9f036

Browse files
Merge pull request #37 from rmsz005/feature/sequence-diagrams
Sequence diagram support
2 parents 86da8c0 + a4c5c36 commit 4f9f036

40 files changed

Lines changed: 2513 additions & 86 deletions

.dockerignore

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Git
2+
.git
3+
.gitignore
4+
5+
# Build artifacts
6+
mermaid-ascii
7+
build/
8+
*.tar.gz
9+
10+
# Documentation
11+
README.md
12+
LICENSE
13+
docs/
14+
*.md
15+
16+
# Development files
17+
.vscode/
18+
.idea/
19+
*.swp
20+
*.swo
21+
*~
22+
23+
# Nix files
24+
flake.nix
25+
flake.lock
26+
27+
# Other package files
28+
PKGBUILD
29+
scripts/
30+
31+
# Test artifacts
32+
*.test
33+
coverage.out
34+
35+
36+

Dockerfile

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
FROM golang:1.25-alpine AS builder
2+
WORKDIR /build
3+
COPY go.mod go.sum ./
4+
RUN go mod download
5+
COPY . .
6+
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o mermaid-ascii .
7+
8+
FROM alpine:latest
9+
RUN apk --no-cache add ca-certificates
10+
RUN addgroup -g 1000 mermaid && \
11+
adduser -D -u 1000 -G mermaid mermaid
12+
13+
WORKDIR /app
14+
COPY --from=builder /build/mermaid-ascii /usr/local/bin/mermaid-ascii
15+
COPY --from=builder /build/templates /app/templates
16+
RUN chown -R mermaid:mermaid /app
17+
18+
USER mermaid
19+
EXPOSE 3001
20+
ENTRYPOINT ["mermaid-ascii"]
21+
CMD ["--help"]
22+
23+
24+

Dockerfile.test

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
FROM golang:1.25-alpine AS test
2+
WORKDIR /app
3+
RUN apk add --no-cache git
4+
COPY go.mod go.sum ./
5+
RUN go mod download
6+
COPY . .
7+
RUN go test ./... -v
8+
CMD ["echo", "Tests passed!"]
9+
10+
11+

Makefile

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,21 @@ clean:
3434
uninstall:
3535
$(RM) $(targets)
3636

37+
.PHONY: test
38+
test:
39+
go test ./... -v
40+
41+
.PHONY: docker-build
42+
docker-build:
43+
docker build -t mermaid-ascii:latest .
44+
45+
.PHONY: docker-test
46+
docker-test:
47+
docker build --target test -t mermaid-ascii:test -f Dockerfile.test .
48+
49+
.PHONY: docker-run
50+
docker-run:
51+
docker run -i mermaid-ascii:latest
52+
3753
dev:
3854
air

README.md

Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,150 @@ $ cat test.mermaid | mermaid-ascii --ascii
198198
| |
199199
+---+
200200

201+
# Using Docker
202+
$ docker build -t mermaid-ascii .
203+
$ echo 'sequenceDiagram
204+
Alice->>Bob: Hello
205+
Bob-->>Alice: Hi' | docker run -i mermaid-ascii -f -
206+
┌───────┐ ┌─────┐
207+
│ Alice │ │ Bob │
208+
└───┬───┘ └──┬──┘
209+
│ │
210+
│ Hello │
211+
├───────────►│
212+
│ │
213+
│ Hi │
214+
│◄┈┈┈┈┈┈┈┈┈┈┈┤
215+
│ │
216+
217+
# Graph diagrams work too
218+
$ echo 'graph LR
219+
A-->B-->C' | docker run -i mermaid-ascii -f -
220+
┌───┐ ┌───┐ ┌───┐
221+
│ │ │ │ │ │
222+
│ A ├────►│ B ├────►│ C │
223+
│ │ │ │ │ │
224+
└───┘ └───┘ └───┘
225+
226+
# Run web interface
227+
$ docker run -p 3001:3001 mermaid-ascii web --port 3001
228+
# Then visit http://localhost:3001
229+
```
230+
231+
### Sequence Diagrams
232+
233+
Sequence diagrams are also fully supported! They visualize message flows between participants over time.
234+
235+
```bash
236+
# Simple sequence diagram
237+
$ cat sequence.mermaid
238+
sequenceDiagram
239+
Alice->>Bob: Hello Bob!
240+
Bob-->>Alice: Hi Alice!
241+
$ mermaid-ascii -f sequence.mermaid
242+
┌───────┐ ┌─────┐
243+
│ Alice │ │ Bob │
244+
└───┬───┘ └──┬──┘
245+
│ │
246+
│ Hello Bob!
247+
├───────────►│
248+
│ │
249+
│ Hi Alice!
250+
│◄┈┈┈┈┈┈┈┈┈┈┈┤
251+
│ │
252+
253+
# Solid arrows (->>) and dotted arrows (-->>)
254+
$ cat sequence.mermaid
255+
sequenceDiagram
256+
Client->>Server: Request
257+
Server-->>Client: Response
258+
$ mermaid-ascii -f sequence.mermaid
259+
┌────────┐ ┌────────┐
260+
│ Client │ │ Server │
261+
└───┬────┘ └───┬────┘
262+
│ │
263+
│ Request │
264+
├─────────────►│
265+
│ │
266+
│ Response │
267+
│◄┈┈┈┈┈┈┈┈┈┈┈┈┈┤
268+
│ │
269+
270+
# Multiple participants
271+
$ cat sequence.mermaid
272+
sequenceDiagram
273+
Alice->>Bob: Hello!
274+
Bob->>Charlie: Forward message
275+
Charlie-->>Alice: Got it!
276+
$ mermaid-ascii -f sequence.mermaid
277+
┌───────┐ ┌─────┐ ┌─────────┐
278+
│ Alice │ │ Bob │ │ Charlie │
279+
└───┬───┘ └──┬──┘ └────┬────┘
280+
│ │ │
281+
│ Hello! │ │
282+
├───────────►│ │
283+
│ │ │
284+
│ │ Forward message
285+
│ ├─────────────►│
286+
│ │ │
287+
│ Got it!
288+
│◄┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┤
289+
│ │ │
290+
291+
# Self-messages
292+
$ cat sequence.mermaid
293+
sequenceDiagram
294+
Alice->>Alice: Think
295+
Alice->>Bob: Hello
296+
$ mermaid-ascii -f sequence.mermaid
297+
┌───────┐ ┌─────┐
298+
│ Alice │ │ Bob │
299+
└───┬───┘ └──┬──┘
300+
│ │
301+
│ Think │
302+
├──┐ │
303+
│ │ │
304+
│◄─┘ │
305+
│ │
306+
│ Hello │
307+
├───────────►│
308+
│ │
309+
310+
# Explicit participant declarations with aliases
311+
$ cat sequence.mermaid
312+
sequenceDiagram
313+
participant A as Alice
314+
participant B as Bob
315+
A->>B: Message from Alice
316+
B-->>A: Reply to Alice
317+
$ mermaid-ascii -f sequence.mermaid
318+
┌───────┐ ┌─────┐
319+
│ Alice │ │ Bob │
320+
└───┬───┘ └──┬──┘
321+
│ │
322+
│ Message from Alice
323+
├───────────►│
324+
│ │
325+
│ Reply to Alice
326+
│◄┈┈┈┈┈┈┈┈┈┈┈┤
327+
│ │
328+
329+
# ASCII mode for sequence diagrams
330+
$ cat sequence.mermaid | mermaid-ascii --ascii
331+
+-------+ +-----+
332+
| Alice | | Bob |
333+
+---+---+ +--+--+
334+
| |
335+
| Hello Bob! |
336+
+----------->|
337+
| |
338+
| Hi Alice! |
339+
|<...........+
340+
| |
341+
342+
```
343+
344+
```bash
201345
$ mermaid-ascii --help
202346
Generate ASCII diagrams from mermaid code.
203347

@@ -360,6 +504,31 @@ $ mermaid-ascii -f ./test.mermaid --coords
360504

361505
Note that with `--coords` enabled, the grid-coords shown show the starting location of the coord, not the center of the coord. This is why `(1,0)` is next to `(0,0)` instead of in the center of the `A` node.
362506

507+
## Supported Diagram Types
508+
509+
### Graphs / Flowcharts ✅
510+
- [x] Graph directions (`graph LR` and `graph TD`)
511+
- [x] Labelled edges (like `A -->|label| B`)
512+
- [x] Multiple arrows on one line (like `A --> B --> C`)
513+
- [x] `A & B` syntax
514+
- [x] `classDef` and `class` for colored output
515+
- [x] Prevent arrows overlapping nodes
516+
- [ ] `subgraph` support
517+
- [ ] Shapes other than rectangles
518+
- [ ] Diagonal arrows
519+
520+
### Sequence Diagrams ✅
521+
- [x] Basic message syntax (`A->>B: message`)
522+
- [x] Solid arrows (`->>`) and dotted arrows (`-->>`)
523+
- [x] Self-messages (`A->>A: think`)
524+
- [x] Participant declarations (`participant Alice`)
525+
- [x] Participant aliases (`participant A as Alice`)
526+
- [x] Unicode support (emojis, CJK characters, etc.)
527+
- [x] Both ASCII and Unicode rendering modes
528+
- [ ] Activation boxes
529+
- [ ] Notes (`Note left of Alice: text`)
530+
- [ ] Loops, alt, opt blocks
531+
363532
## TODOs
364533

365534
The baseline components for Mermaid work, but there are a lot of things that are not supported yet. Here's a list of things that are not yet supported:
@@ -381,3 +550,13 @@ The baseline components for Mermaid work, but there are a lot of things that are
381550
- [ ] Diagonal arrows
382551
- [ ] Place nodes in a more compact way
383552
- [ ] Prevent rendering more than X characters wide (like default 80 for terminal width)
553+
554+
### Sequence Diagram Improvements
555+
556+
- [ ] Activation boxes (activate/deactivate)
557+
- [ ] Notes (`Note left of Alice: text`)
558+
- [ ] Loops, alt, opt, and par blocks
559+
560+
### General
561+
562+
- [ ] Support for more diagram types (class diagrams, state diagrams, etc.)

cmd/diagram.go

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
package cmd
2+
3+
import (
4+
"fmt"
5+
"strings"
6+
7+
"github.com/AlexanderGrooff/mermaid-ascii/internal/diagram"
8+
"github.com/AlexanderGrooff/mermaid-ascii/internal/sequence"
9+
)
10+
11+
func DiagramFactory(input string) (diagram.Diagram, error) {
12+
input = strings.TrimSpace(input)
13+
14+
if sequence.IsSequenceDiagram(input) {
15+
return &SequenceDiagram{}, nil
16+
}
17+
18+
lines := strings.Split(input, "\n")
19+
for _, line := range lines {
20+
trimmed := strings.TrimSpace(line)
21+
if trimmed == "" || strings.HasPrefix(trimmed, "%%") {
22+
continue
23+
}
24+
if strings.HasPrefix(trimmed, "graph ") || strings.HasPrefix(trimmed, "flowchart ") {
25+
return &GraphDiagram{}, nil
26+
}
27+
if !strings.HasPrefix(trimmed, "%%") {
28+
return &GraphDiagram{}, nil
29+
}
30+
}
31+
32+
return &GraphDiagram{}, nil
33+
}
34+
35+
type SequenceDiagram struct {
36+
parsed *sequence.SequenceDiagram
37+
}
38+
39+
func (sd *SequenceDiagram) Parse(input string) error {
40+
parsed, err := sequence.Parse(input)
41+
if err != nil {
42+
return err
43+
}
44+
sd.parsed = parsed
45+
return nil
46+
}
47+
48+
func (sd *SequenceDiagram) Render(config *diagram.Config) (string, error) {
49+
if sd.parsed == nil {
50+
return "", fmt.Errorf("sequence diagram not parsed: call Parse() before Render()")
51+
}
52+
return sequence.Render(sd.parsed, config)
53+
}
54+
55+
func (sd *SequenceDiagram) Type() string {
56+
return "sequence"
57+
}
58+
59+
type GraphDiagram struct {
60+
properties *graphProperties
61+
}
62+
63+
func (gd *GraphDiagram) Parse(input string) error {
64+
properties, err := mermaidFileToMap(input, "cli")
65+
if err != nil {
66+
return err
67+
}
68+
gd.properties = properties
69+
return nil
70+
}
71+
72+
func (gd *GraphDiagram) Render(config *diagram.Config) (string, error) {
73+
if gd.properties == nil {
74+
return "", fmt.Errorf("graph diagram not parsed: call Parse() before Render()")
75+
}
76+
77+
if config == nil {
78+
config = diagram.DefaultConfig()
79+
}
80+
81+
styleType := config.StyleType
82+
if styleType == "" {
83+
styleType = "cli"
84+
}
85+
gd.properties.styleType = styleType
86+
87+
return drawMap(gd.properties), nil
88+
}
89+
90+
func (gd *GraphDiagram) Type() string {
91+
return "graph"
92+
}

0 commit comments

Comments
 (0)