├── examples
├── circle.txt
├── arrows.txt
├── edge-cases.txt
├── tiny-grids.txt
├── dot-grids.txt
├── circle.svg
├── small-shapes.txt
├── big-shapes.txt
├── small-nodes.txt
├── small-grids.txt
├── overlaps.txt
├── trees.txt
├── line-decorations.txt
├── large-nodes.txt
├── line-ends.txt
├── unicode.txt
├── flow-chart.txt
├── graphics.txt
├── big-grids.txt
├── arrows.svg
├── circuits.txt
├── icons.txt
├── complicated.txt
├── big-shapes.svg
├── small-shapes.svg
├── edge-cases.svg
├── trees.svg
├── big-grids.svg
├── overlaps.svg
├── line-decorations.svg
├── circuits.svg
├── large-nodes.svg
├── small-nodes.svg
├── graphics.svg
├── small-grids.svg
├── flow-chart.svg
├── dot-grids.svg
├── line-ends.svg
└── icons.svg
├── .vscode
└── settings.json
├── .gitignore
├── go.mod
├── .github
└── workflows
│ └── test.yml
├── canvas_test.go
├── index.go
├── LICENSE
├── iter.go
├── go.sum
├── iter_test.go
├── examples_test.go
├── svg.go
└── README.md
/examples/circle.txt:
--------------------------------------------------------------------------------
1 |
2 | .-.
3 | | |
4 | '-'
5 |
6 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "autoHide.autoHidePanel": false
3 | }
4 |
--------------------------------------------------------------------------------
/examples/arrows.txt:
--------------------------------------------------------------------------------
1 | ^
2 | |
3 | <---+--->
4 | |
5 | v
6 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.swp
2 | .DS_Store
3 |
4 | vendor
5 | examples/*.svg
6 |
7 | goat
8 | goat.test
9 |
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/bep/goat
2 |
3 | go 1.17
4 |
5 | require (
6 | github.com/frankban/quicktest v1.14.2
7 | github.com/google/go-cmp v0.5.7
8 | )
9 |
10 | require (
11 | github.com/kr/pretty v0.3.0 // indirect
12 | github.com/kr/text v0.2.0 // indirect
13 | github.com/rogpeppe/go-internal v1.6.1 // indirect
14 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 // indirect
15 | )
16 |
--------------------------------------------------------------------------------
/examples/edge-cases.txt:
--------------------------------------------------------------------------------
1 | +-+ \ \ | / /
2 | + + \ v v v /
3 | +-+ \ .---------. / \ | /
4 | v| |v vvv
5 | +-+ --->| |<--- -->o<--
6 | | | ^| |^ ^^^
7 | +-+ / '---------' \ / | \
8 | / ^ ^ ^ \
9 | / / | \ \
10 |
--------------------------------------------------------------------------------
/examples/tiny-grids.txt:
--------------------------------------------------------------------------------
1 | ┌─┬─┬─┬─┬─┐ ▉▉ ▉▉ ▉▉ ⬢ ⬡ ⬡ ┌┬┬┬┬┬┬┬┬┐ ⁚⁚⁚⁚⁚⁚⁚⁚⁚⁚ ___________ +-+-+-+-+
2 | ├─┼─┼─┼─┼─┤ ▉▉ ▉▉ ⬢ ⬢ ⬡ ⬡ ├┼┼┼┼┼┼┼┼┤ ⁚⁚⁚⁚⁚⁚⁚⁚⁚⁚ |__|__|__|__| +-+-+-+-+
3 | ├─┼─┼─┼─┼─┤ ▉▉ ▉▉ ▉▉ ⬢ ⬢ ⬢ ⬡ ⬡ ├┼┼┼┼┼┼┼┼┤ ⁚⁚⁚⁚⁚⁚⁚⁚⁚⁚ |__|__|__|__| +-+-+-+-+
4 | ├─┼─┼─┼─┼─┤ ▉▉ ▉▉ ⬡ ⬡ ⬡ ⬡ ├┼┼┼┼┼┼┼┼┤ ⁚⁚⁚⁚⁚⁚⁚⁚⁚⁚ |__|__|__|__| +-+-+-+-+
5 | └─┴─┴─┴─┴─┘ ▉▉ ▉▉ ▉▉ ⬡ ⬡ ⬡ └┴┴┴┴┴┴┴┴┘ ⁚⁚⁚⁚⁚⁚⁚⁚⁚⁚ |__|__|__|__| +-+-+-+-+
6 |
--------------------------------------------------------------------------------
/examples/dot-grids.txt:
--------------------------------------------------------------------------------
1 |
2 | o o o o o * * * * * * * o o * o o o * * * o o o · * · · · · · ·
3 | o o o o o * * * * * o o o o * o o o o * * * * * o * * · * * · · · · · ·
4 | o o o o o * * * * * o * o o o o o o o o * * * * * o o o o o · o · · o · · * * ·
5 | o o o o o * * * * * o * o o o o o o o * * * * o * o o · · · · o · · * ·
6 | o o o o o * * * * * * * * * o o o o * * * o * o · · · · · · · *
7 |
8 |
--------------------------------------------------------------------------------
/examples/circle.svg:
--------------------------------------------------------------------------------
1 |
9 |
--------------------------------------------------------------------------------
/.github/workflows/test.yml:
--------------------------------------------------------------------------------
1 | name: Test
2 |
3 | on:
4 | push:
5 | branches: [ master ]
6 | pull_request:
7 | branches: [ master ]
8 | jobs:
9 | build:
10 | strategy:
11 | matrix:
12 | go-version: [1.17.x]
13 | os: [ubuntu-latest, windows-latest]
14 | runs-on: ${{ matrix.os }}
15 | steps:
16 | - name: Install Go
17 | uses: actions/setup-go@v2
18 | with:
19 | go-version: ${{ matrix.go-version }}
20 | - name: Checkout code
21 | uses: actions/checkout@v2
22 | - name: Test
23 | run: go test -race -v .
24 |
--------------------------------------------------------------------------------
/examples/small-shapes.txt:
--------------------------------------------------------------------------------
1 | .---. __ ..
2 | .--. . .-----. \ / .---. .---. ___ ___ | | | )
3 | / \ / \ \ / .-. . ' . | | .---. .---. | | / \ | | '--' ''
4 | \ / / \ \ / | | / \ / \ '---' / / \ \ | | \___/ |___| .. __
5 | '--' '-----' ' '-' '---' /___\ '---' '---' '---' ( | |__|
6 | ''
7 |
--------------------------------------------------------------------------------
/examples/big-shapes.txt:
--------------------------------------------------------------------------------
1 |
2 | .---------. . .-------. .-------. .---------. .-----. .----.
3 | \ / / \ \ \ | | | | / \ / \
4 | \ / / \ \ \ | | | | / \ | |
5 | \ / / \ \ \ | | | | \ / | |
6 | \ / / \ \ \ | | | | \ / \ /
7 | ' '---------' '-------' '-------' '---------' '-----' '----'
8 |
9 |
--------------------------------------------------------------------------------
/examples/small-nodes.txt:
--------------------------------------------------------------------------------
1 |
2 | A 1 2 4 8
3 | A B C *----->o<---->o<----o-----------. o
4 | *-------->o<------->o ^ ^ | ^
5 | ^ / ^ | | | | |
6 | | v \ v v | v |
7 | o----->o---->o<---->* o<--->*<---->o---->*---->o---->o<---->*
8 | D E F G 3 B 5 C 6 7 D
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/examples/small-grids.txt:
--------------------------------------------------------------------------------
1 | ___ ___ .---+---+---+---+---. .---+---+---+---. .---. .---.
2 | ___/ \___/ \ | | | | | | / \ / \ / \ / \ / | +---+ |
3 | / \___/ \___/ +---+---+---+---+---+ +---+---+---+---+ +---+ +---+
4 | \___/ b \___/ \ | | | b | | | \ / \a/ \b/ \ / \ | +---+ |
5 | / a \___/ \___/ +---+---+---+---+---+ +---+---+---+---+ +---+ b +---+
6 | \___/ \___/ \ | | a | | | | / \ / \ / \ / \ / | a +---+ |
7 | \___/ \___/ '---+---+---+---+---' '---+---+---+---' '---' '---'
8 |
9 |
--------------------------------------------------------------------------------
/examples/overlaps.txt:
--------------------------------------------------------------------------------
1 |
2 | .-. .-. .-. .-. .-. .-.
3 | | | | | | | | | | | | |
4 | .---------. .--+---+--. .--+---+--. .--| |--. .--+ +--. .------|--.
5 | | | | | | | | | | | | | | | | | | |
6 | '---------' '--+---+--' '--+---+--' '--| |--' '--+ +--' '--|------'
7 | | | | | | | | | | | | |
8 | '-' '-' '-' '-' '-' '-'
9 |
--------------------------------------------------------------------------------
/examples/trees.txt:
--------------------------------------------------------------------------------
1 |
2 | . . . .--- 1 .-- 1 / 1
3 | / \ | | .---+ .-+ +
4 | / \ .---+---. .--+--. | '--- 2 | '-- 2 / \ 2
5 | + + | | | | ---+ ---+ +
6 | / \ / \ .-+-. .-+-. .+. .+. | .--- 3 | .-- 3 \ / 3
7 | / \ / \ | | | | | | | | '---+ '-+ +
8 | 1 2 3 4 1 2 3 4 1 2 3 4 '--- 4 '-- 4 \ 4
9 |
10 |
--------------------------------------------------------------------------------
/examples/line-decorations.txt:
--------------------------------------------------------------------------------
1 | ________ o * * .--------------.
2 | *---+--. | | o o | ^ \ / | .----------. |
3 | | | '--* -+- | | v / \ / | | <------. | |
4 | | '-----> .---(---' --->*<--- / .+->*<--o----' | | | | |
5 | <--' ^ ^ | | | | | ^ \ | '--------' | |
6 | \/ *-----' o |<----->| '-----' |__| v '------------' |
7 | /\ *---------------'
8 |
--------------------------------------------------------------------------------
/canvas_test.go:
--------------------------------------------------------------------------------
1 | package goat
2 |
3 | import (
4 | "bytes"
5 | "testing"
6 |
7 | qt "github.com/frankban/quicktest"
8 | )
9 |
10 | func TestReadASCII(t *testing.T) {
11 | c := qt.New(t)
12 |
13 | var buf bytes.Buffer
14 |
15 | // TODO: UNICODE
16 | buf.WriteString(" +-->\n")
17 | buf.WriteString(" | å\n")
18 | buf.WriteString(" +----->")
19 |
20 | canvas := NewCanvas(&buf)
21 |
22 | c.Assert(canvas.Width, qt.Equals, 8)
23 | c.Assert(canvas.Height, qt.Equals, 3)
24 |
25 | buf.Reset()
26 | buf.WriteString(" +--> \n")
27 | buf.WriteString(" | å \n")
28 | buf.WriteString(" +----->\n")
29 |
30 | expected := buf.String()
31 |
32 | c.Assert(expected, qt.Equals, canvas.String())
33 | }
34 |
--------------------------------------------------------------------------------
/examples/large-nodes.txt:
--------------------------------------------------------------------------------
1 |
2 | .---. .-. .-. .-. .-.
3 | | A +----->| 1 +<---->| 2 |<----+ 4 +------------------. | 8 |
4 | '---' '-' '+' '-' | '-'
5 | | ^ | ^
6 | v | v |
7 | .-. .-+-. .-. .-+-. .-. .+. .---.
8 | | 3 +---->| B |<----->| 5 +---->| C +---->| 6 +---->| 7 |<---->| D |
9 | '-' '---' '-' '---' '-' '-' '---'
10 |
--------------------------------------------------------------------------------
/examples/line-ends.txt:
--------------------------------------------------------------------------------
1 | o--o *--o / / * o o o o o * * * * o o o o * * * * o o o o * * * *
2 | o--* *--* v v ^ ^ | | | | | | | | \ \ \ \ \ \ \ \ / / / / / / / /
3 | o--> *--> * o / / o * v ' o * v ' o * v \ o * v \ o * v / o * v /
4 | o--- *---
5 | ^ ^ ^ ^ . . . . ^ ^ ^ ^ \ \ \ \ ^ ^ ^ ^ / / / /
6 | | | * o \ \ * o | | | | | | | | \ \ \ \ \ \ \ \ / / / / / / / /
7 | v v ^ ^ v v ^ ^ o * v ' o * v ' o * v \ o * v \ o * v / o * v /
8 | * o | | * o \ \
9 |
10 | <--o <--* <--> <--- ---o ---* ---> ---- *<-- o<-- -->o -->*
11 |
12 |
--------------------------------------------------------------------------------
/examples/unicode.txt:
--------------------------------------------------------------------------------
1 | ↖ ↗ ✶ ✹ ✩ ⓵ ⎲ ░░▒▒▓▓▉▉ ▚▚ ▢ ▢ ⬚ ⬚ ⊕
2 | ▲ ◀━━━━━━━▶ ↙ ↘ ➊ ❶ ➀ ① ➕ ➖ ➗ ❌ ⎳ ╲ ╱ ▚▚ ▢ ▢ ⬚ ⬚ ⊖
3 | ┃ ╭╌╌╌╌╌╌╌╮ ╔═══════╗ ┏━━━━━━━┓ ┏╍╍╍╍╍╍╍┓ ╲ ╱ ░░▒▒▓▓▉▉ ▚▚ ⬣ ⬣ ⎔ ⎔ ⊗
4 | ┃ ╎ ╎ ║ ║ ┃ ┃ ╏ ╏ ⎛ ⎧ ⎡ ╳ ░░▒▒▓▓▉▉ ▚▚ ⬣ ⬣ ⎔ ⎔ ⊘
5 | ┃ ╎ ╎ ║ ║ ┃ ┃ ╏ ╏⋮ ⎜ ⎨ ⎢ ╱ ╲ ░░▒▒▓▓▉▉ ▚▚ ◯ ◯ ⏣ ⏣ ⊙
6 | ▼ ╰╌╌╌╌╌╌╌╯ ╚═══════╝ ┗━━━━━━━┛ ⋱ ┗╍╍╍╍╍╍╍┛⋮ ⎝ ⎩ ⎣╱ ╲ ░░▒▒▓▓▉▉ ▚▚ ◯ ◯ ⏣ ⏣ ⊛
7 | ⋱ ⋮ ◢▉▉◣ ⊜
8 | ∑xᵢ ∫t²dt ⋱ ⋮ ◥▉▉◤
9 |
--------------------------------------------------------------------------------
/examples/flow-chart.txt:
--------------------------------------------------------------------------------
1 | .
2 | .---------. / \
3 | | START | / \ .-+-------+-. ___________
4 | '----+----' .-------. A / \ B | |COMPLEX| | / \ .-.
5 | | | END |<-----+CHOICE +----->| | | +--->+ PREPARATION +--->| X |
6 | v '-------' \ / | |PROCESS| | \___________/ '-'
7 | .---------. \ / '-+---+---+-'
8 | / INPUT / \ /
9 | '-----+---' '
10 | | ^
11 | v |
12 | .-----------. .-----+-----. .-.
13 | | PROCESS +---------------->| PROCESS |<------+ X |
14 | '-----------' '-----------' '-'
15 |
--------------------------------------------------------------------------------
/examples/graphics.txt:
--------------------------------------------------------------------------------
1 | .
2 | 0 3 P * Eye / ^ /
3 | *-------* +y \ +) \ / Reflection
4 | 1 /| 2 /| ^ \ \ \ v
5 | *-------* | | v0 \ v3 --------*--------
6 | | |4 | |7 | *----\-----*
7 | | *-----|-* +-----> +x / v X \ .-.<-------- o
8 | |/ |/ / / o \ | / | Refraction / \
9 | *-------* v / \ +-' / \
10 | 5 6 +z v1 *------------------* v2 | o-----o
11 | v
12 |
--------------------------------------------------------------------------------
/examples/big-grids.txt:
--------------------------------------------------------------------------------
1 | .----. .----.
2 | / \ / \ .-----+-----+-----.
3 | + +----+ +----. | | | | .-----+-----+-----+-----+
4 | \ / \ / \ | | | | / / / / /
5 | +----+ B +----+ + +-----+-----+-----+ +-----+-----+-----+-----+
6 | / \ / \ / | | | | / / / / /
7 | + A +----+ +----+ | | B | | +-----+-----+-----+-----+
8 | \ / \ / \ +-----+-----+-----+ / / A / B / /
9 | '----+ +----+ + | | | | +-----+-----+-----+-----+
10 | \ / \ / | A | | | / / / / /
11 | '----' '----' '-----+-----+-----' '-----+-----+-----+-----+
12 |
13 |
--------------------------------------------------------------------------------
/index.go:
--------------------------------------------------------------------------------
1 | package goat
2 |
3 | // Index represents a position within an ASCII diagram.
4 | type Index struct {
5 | x int
6 | y int
7 | }
8 |
9 | // Pixel represents the on-screen coordinates for an Index.
10 | type Pixel Index
11 |
12 | func (i *Index) asPixel() Pixel {
13 | return Pixel{x: i.x * 8, y: i.y * 16}
14 | }
15 |
16 | func (i *Index) asPixelXY() (int, int) {
17 | p := i.asPixel()
18 | return p.x, p.y
19 | }
20 |
21 | func (i *Index) east() Index {
22 | return Index{i.x + 1, i.y}
23 | }
24 |
25 | func (i *Index) west() Index {
26 | return Index{i.x - 1, i.y}
27 | }
28 |
29 | func (i *Index) north() Index {
30 | return Index{i.x, i.y - 1}
31 | }
32 |
33 | func (i *Index) south() Index {
34 | return Index{i.x, i.y + 1}
35 | }
36 |
37 | func (i *Index) nWest() Index {
38 | return Index{i.x - 1, i.y - 1}
39 | }
40 |
41 | func (i *Index) nEast() Index {
42 | return Index{i.x + 1, i.y - 1}
43 | }
44 |
45 | func (i *Index) sWest() Index {
46 | return Index{i.x - 1, i.y + 1}
47 | }
48 |
49 | func (i *Index) sEast() Index {
50 | return Index{i.x + 1, i.y + 1}
51 | }
52 |
--------------------------------------------------------------------------------
/examples/arrows.svg:
--------------------------------------------------------------------------------
1 |
13 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Bryce Lampe
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/examples/circuits.txt:
--------------------------------------------------------------------------------
1 | ____ *
2 | | |_____.---. |
3 | o _____| )----------)-------.
4 | / \ | '---' | __|__
5 | /___\ | | \ /
6 | | '-------------. | \ /
7 | A ----------------' | | o
8 | .-------------------. o-----)-------' |
9 | | |___.---. | |___.---.
10 | B ---*---.__.---. ___| )--*--.__..---. ____) )----- Y
11 | __| o----*--' '---' ______)) )---' '---'
12 | C -------' '---' | | ''---'
13 | | o
14 | | / \
15 | | /___\
16 | | |
17 | '--------------'
18 |
--------------------------------------------------------------------------------
/examples/icons.txt:
--------------------------------------------------------------------------------
1 | .-. .--------.
2 | .-+ | | |
3 | .--+ '--. |'--------'|
4 | | Server Cloud |<------------------>| Database |
5 | '-------------' | |
6 | ^ ^ '--------'
7 | Internet | | ^
8 | .------------------------' '-------------. |
9 | | | v
10 | v v .------. .------.
11 | .--------. WiFi .--------. Bluetooth .-----. / # # /| / # # /|
12 | | |<------------->| |<---------->| | +------+/| LAN +------+/|
13 | |Windows | | OS X | | iOS | | +/|<--->| +/|
14 | +--------+ +--------+ | | |Ubuntu+/| |Ubuntu+/|
15 | /// ____ \\\ /// ____ \\\ | o | | +/ | +/
16 | '------------' '------------' '-----' '------' '------'
17 | Laptop 1 Laptop 2 Tablet 1 Dedicated Server Rack
18 |
--------------------------------------------------------------------------------
/iter.go:
--------------------------------------------------------------------------------
1 | package goat
2 |
3 | type canvasIterator func(width int, height int) chan Index
4 |
5 | func upDown(width int, height int) chan Index {
6 | c := make(chan Index, width*height)
7 |
8 | go func() {
9 | for w := 0; w < width; w++ {
10 | for h := 0; h < height; h++ {
11 | c <- Index{w, h}
12 | }
13 | }
14 | close(c)
15 | }()
16 |
17 | return c
18 | }
19 |
20 | func leftRight(width int, height int) chan Index {
21 | c := make(chan Index, width*height)
22 |
23 | // Transpose an upDown order.
24 | go func() {
25 | for i := range upDown(height, width) {
26 | c <- Index{i.y, i.x}
27 | }
28 |
29 | close(c)
30 | }()
31 |
32 | return c
33 | }
34 |
35 | func diagDown(width int, height int) chan Index {
36 | c := make(chan Index, width*height)
37 |
38 | go func() {
39 | minSum := -height + 1
40 | maxSum := width
41 |
42 | for sum := minSum; sum <= maxSum; sum++ {
43 | for w := 0; w < width; w++ {
44 | for h := 0; h < height; h++ {
45 | if w-h == sum {
46 | c <- Index{w, h}
47 | }
48 | }
49 | }
50 | }
51 | close(c)
52 | }()
53 |
54 | return c
55 | }
56 |
57 | func diagUp(width int, height int) chan Index {
58 | c := make(chan Index, width*height)
59 |
60 | go func() {
61 | maxSum := width + height - 2
62 |
63 | for sum := 0; sum <= maxSum; sum++ {
64 | for w := 0; w < width; w++ {
65 | for h := 0; h < height; h++ {
66 | if h+w == sum {
67 | c <- Index{w, h}
68 | }
69 | }
70 | }
71 | }
72 | close(c)
73 | }()
74 |
75 | return c
76 | }
77 |
--------------------------------------------------------------------------------
/go.sum:
--------------------------------------------------------------------------------
1 | github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
2 | github.com/frankban/quicktest v1.14.2 h1:SPb1KFFmM+ybpEjPUhCCkZOM5xlovT5UbrMvWnXyBns=
3 | github.com/frankban/quicktest v1.14.2/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps=
4 | github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
5 | github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
6 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
7 | github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
8 | github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
9 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
10 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
11 | github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
12 | github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
13 | github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
14 | github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
15 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
16 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
17 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
18 | gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
19 |
--------------------------------------------------------------------------------
/iter_test.go:
--------------------------------------------------------------------------------
1 | package goat
2 |
3 | import (
4 | "testing"
5 |
6 | qt "github.com/frankban/quicktest"
7 | "github.com/google/go-cmp/cmp"
8 | )
9 |
10 | var eq = qt.CmpEquals(
11 | cmp.Comparer(func(i1, i2 Index) bool {
12 | return i1.x == i2.x && i1.y == i2.y
13 | }),
14 | )
15 |
16 | func TestIterators(t *testing.T) {
17 | c := qt.New(t)
18 |
19 | tests := []struct {
20 | iterator chan Index
21 | expected []Index
22 | }{
23 | // UpDown
24 | // 1 3
25 | // 2 4
26 | {
27 | iterator: upDown(2, 2),
28 | expected: []Index{
29 | {0, 0},
30 | {0, 1},
31 | {1, 0},
32 | {1, 1},
33 | },
34 | },
35 |
36 | // LeftRight
37 | // 1 2
38 | // 3 4
39 | {
40 | iterator: leftRight(2, 2),
41 | expected: []Index{
42 | {0, 0},
43 | {1, 0},
44 | {0, 1},
45 | {1, 1},
46 | },
47 | },
48 |
49 | // DiagUp
50 | // 1 3
51 | // 2 5
52 | // 4 6
53 | {
54 | iterator: diagUp(2, 3),
55 | expected: []Index{
56 | {0, 0}, // x + y == 0
57 | {0, 1}, // x + y == 1
58 | {1, 0}, // x + y == 1
59 | {0, 2}, // x + y == 2
60 | {1, 1}, // x + y == 2
61 | {1, 2}, // x + y == 3
62 | },
63 | },
64 |
65 | // DiagDown
66 | // 2 4 6
67 | // 1 3 5
68 | {
69 | iterator: diagDown(3, 2),
70 | expected: []Index{
71 | {0, 1}, // x - y == -1
72 | {0, 0}, // x - y == 0
73 | {1, 1}, // x - y == 0
74 | {1, 0}, // x - y == 1
75 | {2, 1}, // x - y == 1
76 | {2, 0}, // x - y == 2
77 | },
78 | },
79 | }
80 |
81 | for _, tt := range tests {
82 | result := make([]Index, 0, len(tt.expected))
83 |
84 | for i := range tt.iterator {
85 | result = append(result, i)
86 | }
87 |
88 | c.Assert(result, eq, tt.expected)
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/examples/complicated.txt:
--------------------------------------------------------------------------------
1 | +-------------------+ ^ .---.
2 | | A Box |__.--.__ __.--> | .-. | |
3 | | | '--' v | * |<--- | |
4 | +-------------------+ '-' | |
5 | Round *---(-. |
6 | .-----------------. .-------. .----------. .-------. | | |
7 | | Mixed Rounded | | | / Diagonals \ | | | | | |
8 | | & Square Corners | '--. .--' / \ |---+---| '-)-' .--------.
9 | '--+------------+-' .--. | '-------+--------' | | | | / Search /
10 | | | | | '---. | '-------' | '-+------'
11 | |<---------->| | | | v Interior | ^
12 | ' <---' '----' .-----------. ---. .--- v |
13 | .------------------. Diag line | .-------. +---. \ / . |
14 | | if (a > b) +---. .--->| | | | | Curved line \ / / \ |
15 | | obj->fcn() | \ / | '-------' |<--' + / \ |
16 | '------------------' '--' '--+--------' .--. .--. | .-. +Done?+-'
17 | .---+-----. | ^ |\ | | /| .--+ | | \ /
18 | | | | Join \|/ | | Curved | \| |/ | | \ | \ /
19 | | | +----> o --o-- '-' Vertical '--' '--' '-- '--' + .---.
20 | <--+---+-----' | /|\ | | 3 |
21 | v not:line 'quotes' .-' '---'
22 | .-. .---+--------. / A || B *bold* | ^
23 | | | | Not a dot | <---+---<-- A dash--is not a line v |
24 | '-' '---------+--' / Nor/is this. ---
25 |
--------------------------------------------------------------------------------
/examples_test.go:
--------------------------------------------------------------------------------
1 | package goat
2 |
3 | import (
4 | "bytes"
5 | "flag"
6 | "io"
7 | "io/ioutil"
8 | "os"
9 | "path/filepath"
10 | "strings"
11 | "testing"
12 |
13 | qt "github.com/frankban/quicktest"
14 | )
15 |
16 | var write = flag.Bool("write", false, "write examples to disk")
17 |
18 | func TestExamplesStableOutput(t *testing.T) {
19 | c := qt.New(t)
20 |
21 | var previous string
22 | for i := 0; i < 3; i++ {
23 | in, err := os.Open(filepath.Join(basePath, "circuits.txt"))
24 | if err != nil {
25 | t.Fatal(err)
26 | }
27 | var out bytes.Buffer
28 | BuildAndWriteSVG(in, &out)
29 | in.Close()
30 | if i > 0 && previous != out.String() {
31 | c.Fail()
32 | }
33 | previous = out.String()
34 |
35 | }
36 | }
37 |
38 | func TestExamples(t *testing.T) {
39 | c := qt.New(t)
40 |
41 | filenames, err := filepath.Glob(filepath.Join(basePath, "*.txt"))
42 | c.Assert(err, qt.IsNil)
43 |
44 | var buff *bytes.Buffer
45 |
46 | for _, name := range filenames {
47 | in := getIn(name)
48 | var out io.WriteCloser
49 | if *write {
50 | out = getOut(name)
51 | } else {
52 | if buff == nil {
53 | buff = &bytes.Buffer{}
54 | } else {
55 | buff.Reset()
56 | }
57 | out = struct {
58 | io.Writer
59 | io.Closer
60 | }{
61 | buff,
62 | io.NopCloser(nil),
63 | }
64 | }
65 |
66 | BuildAndWriteSVG(in, out)
67 | in.Close()
68 | out.Close()
69 |
70 | if buff != nil {
71 | golden := getOutString(name)
72 | if buff.String() != golden {
73 | c.Log(buff.Len(), len(golden))
74 | c.Fatalf("Content mismatch for %s", name)
75 |
76 | }
77 | in.Close()
78 | out.Close()
79 | }
80 | }
81 | }
82 |
83 | func BenchmarkComplicated(b *testing.B) {
84 | in := getIn(filepath.FromSlash("examples/complicated.txt"))
85 | b.ResetTimer()
86 | for i := 0; i < b.N; i++ {
87 | BuildAndWriteSVG(in, io.Discard)
88 | }
89 | }
90 |
91 | const basePath string = "examples"
92 |
93 | func getIn(filename string) io.ReadCloser {
94 | in, err := os.Open(filename)
95 | if err != nil {
96 | panic(err)
97 | }
98 | return in
99 | }
100 |
101 | func getOut(filename string) io.WriteCloser {
102 | out, err := os.Create(toSVGFilename(filename))
103 | if err != nil {
104 | panic(err)
105 | }
106 | return out
107 | }
108 |
109 | func getOutString(filename string) string {
110 | b, err := ioutil.ReadFile(toSVGFilename(filename))
111 | if err != nil {
112 | panic(err)
113 | }
114 | b = bytes.ReplaceAll(b, []byte("\r\n"), []byte("\n"))
115 | return string(b)
116 | }
117 |
118 | func toSVGFilename(filename string) string {
119 | return strings.TrimSuffix(filename, filepath.Ext(filename)) + ".svg"
120 | }
121 |
--------------------------------------------------------------------------------
/examples/big-shapes.svg:
--------------------------------------------------------------------------------
1 |
41 |
--------------------------------------------------------------------------------
/examples/small-shapes.svg:
--------------------------------------------------------------------------------
1 |
79 |
--------------------------------------------------------------------------------
/examples/edge-cases.svg:
--------------------------------------------------------------------------------
1 |
70 |
--------------------------------------------------------------------------------
/examples/trees.svg:
--------------------------------------------------------------------------------
1 |
93 |
--------------------------------------------------------------------------------
/examples/big-grids.svg:
--------------------------------------------------------------------------------
1 |
110 |
--------------------------------------------------------------------------------
/examples/overlaps.svg:
--------------------------------------------------------------------------------
1 |
105 |
--------------------------------------------------------------------------------
/svg.go:
--------------------------------------------------------------------------------
1 | package goat
2 |
3 | import (
4 | "bytes"
5 | "fmt"
6 | "io"
7 | )
8 |
9 | type SVG struct {
10 | Body string
11 | Width int
12 | Height int
13 | }
14 |
15 | func (s SVG) String() string {
16 | return fmt.Sprintf("\n",
17 | "diagram",
18 | "http://www.w3.org/2000/svg",
19 | "1.1", s.Height, s.Width, s.Body)
20 | }
21 |
22 | // BuildSVG reads in a newline-delimited ASCII diagram from src and returns a SVG.
23 | func BuildSVG(src io.Reader) SVG {
24 | var buff bytes.Buffer
25 | canvas := NewCanvas(src)
26 | canvas.WriteSVGBody(&buff)
27 | return SVG{
28 | Body: buff.String(),
29 | Width: canvas.widthScreen(),
30 | Height: canvas.heightScreen(),
31 | }
32 | }
33 |
34 | // BuildAndWriteSVG reads in a newline-delimited ASCII diagram from src and writes a
35 | // corresponding SVG diagram to dst.
36 | func BuildAndWriteSVG(src io.Reader, dst io.Writer) {
37 | canvas := NewCanvas(src)
38 |
39 | // Preamble
40 | writeBytes(dst,
41 | "\n")
51 | }
52 |
53 | func writeBytes(out io.Writer, format string, args ...interface{}) {
54 | bytesOut := fmt.Sprintf(format, args...)
55 |
56 | _, err := out.Write([]byte(bytesOut))
57 | if err != nil {
58 | panic(nil)
59 | }
60 | }
61 |
62 | // Draw a straight line as an SVG path.
63 | func (l Line) Draw(out io.Writer) {
64 | start := l.start.asPixel()
65 | stop := l.stop.asPixel()
66 |
67 | // For cases when a vertical line hits a perpendicular like this:
68 | //
69 | // | |
70 | // | or v
71 | // --- ---
72 | //
73 | // We need to nudge the vertical line half a vertical cell in the
74 | // appropriate direction in order to meet up cleanly with the midline of
75 | // the cell next to it.
76 |
77 | // A diagonal segment all by itself needs to be shifted slightly to line
78 | // up with _ baselines:
79 | // _
80 | // \_
81 | //
82 | // TODO make this a method on Line to return accurate pixel
83 | if l.lonely {
84 | switch l.orientation {
85 | case NE:
86 | start.x -= 4
87 | stop.x -= 4
88 | start.y += 8
89 | stop.y += 8
90 | case SE:
91 | start.x -= 4
92 | stop.x -= 4
93 | start.y -= 8
94 | stop.y -= 8
95 | case S:
96 | start.y -= 8
97 | stop.y -= 8
98 | }
99 |
100 | // Half steps
101 | switch l.chop {
102 | case N:
103 | stop.y -= 8
104 | case S:
105 | start.y += 8
106 | }
107 | }
108 |
109 | if l.needsNudgingDown {
110 | stop.y += 8
111 | if l.horizontal() {
112 | start.y += 8
113 | }
114 | }
115 |
116 | if l.needsNudgingLeft {
117 | start.x -= 8
118 | }
119 |
120 | if l.needsNudgingRight {
121 | stop.x += 8
122 | }
123 |
124 | if l.needsTinyNudgingLeft {
125 | start.x -= 4
126 | if l.orientation == NE {
127 | start.y += 8
128 | } else if l.orientation == SE {
129 | start.y -= 8
130 | }
131 | }
132 |
133 | if l.needsTinyNudgingRight {
134 | stop.x += 4
135 | if l.orientation == NE {
136 | stop.y -= 8
137 | } else if l.orientation == SE {
138 | stop.y += 8
139 | }
140 | }
141 |
142 | writeBytes(out,
143 | "\n",
144 | start.x, start.y,
145 | stop.x, stop.y,
146 | )
147 | }
148 |
149 | // Draw a solid triable as an SVG polygon element.
150 | func (t Triangle) Draw(out io.Writer) {
151 | // https://www.w3.org/TR/SVG/shapes.html#PolygonElement
152 |
153 | /*
154 | +-----+-----+
155 | | /|\ |
156 | | / | \ |
157 | x +- / -+- \ -+
158 | | / | \ |
159 | |/ | \|
160 | +-----+-----+
161 | y
162 | */
163 |
164 | x, y := float32(t.start.asPixel().x), float32(t.start.asPixel().y)
165 | r := 0.0
166 |
167 | x0 := x + 8
168 | y0 := y
169 | x1 := x - 4
170 | y1 := y - 0.35*16
171 | x2 := x - 4
172 | y2 := y + 0.35*16
173 |
174 | switch t.orientation {
175 | case N:
176 | r = 270
177 | if t.needsNudging {
178 | x0 += 8
179 | x1 += 8
180 | x2 += 8
181 | }
182 | case NE:
183 | r = 300
184 | x0 += 4
185 | x1 += 4
186 | x2 += 4
187 | if t.needsNudging {
188 | x0 += 6
189 | x1 += 6
190 | x2 += 6
191 | }
192 | case NW:
193 | r = 240
194 | x0 += 4
195 | x1 += 4
196 | x2 += 4
197 | if t.needsNudging {
198 | x0 += 6
199 | x1 += 6
200 | x2 += 6
201 | }
202 | case W:
203 | r = 180
204 | if t.needsNudging {
205 | x0 -= 8
206 | x1 -= 8
207 | x2 -= 8
208 | }
209 | case E:
210 | r = 0
211 | if t.needsNudging {
212 | x0 -= 8
213 | x1 -= 8
214 | x2 -= 8
215 | }
216 | case S:
217 | r = 90
218 | if t.needsNudging {
219 | x0 += 8
220 | x1 += 8
221 | x2 += 8
222 | }
223 | case SW:
224 | r = 120
225 | x0 += 4
226 | x1 += 4
227 | x2 += 4
228 | if t.needsNudging {
229 | x0 += 6
230 | x1 += 6
231 | x2 += 6
232 | }
233 | case SE:
234 | r = 60
235 | x0 += 4
236 | x1 += 4
237 | x2 += 4
238 | if t.needsNudging {
239 | x0 += 6
240 | x1 += 6
241 | x2 += 6
242 | }
243 | }
244 |
245 | writeBytes(out,
246 | "\n",
247 | x0, y0,
248 | x1, y1,
249 | x2, y2,
250 | r,
251 | x, y,
252 | )
253 | }
254 |
255 | // Draw a solid circle as an SVG circle element.
256 | func (c *Circle) Draw(out io.Writer) {
257 | fill := "#fff"
258 |
259 | if c.bold {
260 | fill = "currentColor"
261 | }
262 |
263 | pixel := c.start.asPixel()
264 |
265 | writeBytes(out,
266 | "\n",
267 | pixel.x,
268 | pixel.y,
269 | fill,
270 | )
271 | }
272 |
273 | // Draw a single text character as an SVG text element.
274 | func (t Text) Draw(out io.Writer) {
275 | p := t.start.asPixel()
276 | c := t.contents
277 |
278 | opacity := 0
279 |
280 | // Markdeep special-cases these character and treats them like a
281 | // checkerboard.
282 | switch c {
283 | case "▉":
284 | opacity = -64
285 | case "▓":
286 | opacity = 64
287 | case "▒":
288 | opacity = 128
289 | case "░":
290 | opacity = 191
291 | }
292 |
293 | fill := "currentColor"
294 | if opacity > 0 {
295 | fill = fmt.Sprintf("rgb(%d,%d,%d)", opacity, opacity, opacity)
296 | }
297 |
298 | if opacity != 0 {
299 | writeBytes(out,
300 | "",
301 | p.x-4, p.y-8,
302 | fill,
303 | )
304 | return
305 | }
306 |
307 | // Escape for XML
308 | switch c {
309 | case "&":
310 | c = "&"
311 | case ">":
312 | c = ">"
313 | case "<":
314 | c = "<"
315 | }
316 |
317 | writeBytes(out,
318 | "%s\n",
319 | p.x, p.y+4, c,
320 | )
321 | }
322 |
323 | // Draw a rounded corner as an SVG elliptical arc element.
324 | func (c *RoundedCorner) Draw(out io.Writer) {
325 | // https://www.w3.org/TR/SVG/paths.html#PathDataEllipticalArcCommands
326 |
327 | x, y := c.start.asPixelXY()
328 | startX, startY, endX, endY, sweepFlag := 0, 0, 0, 0, 0
329 |
330 | switch c.orientation {
331 | case NW:
332 | startX = x + 8
333 | startY = y
334 | endX = x - 8
335 | endY = y + 16
336 | case NE:
337 | sweepFlag = 1
338 | startX = x - 8
339 | startY = y
340 | endX = x + 8
341 | endY = y + 16
342 | case SE:
343 | sweepFlag = 1
344 | startX = x + 8
345 | startY = y - 16
346 | endX = x - 8
347 | endY = y
348 | case SW:
349 | startX = x - 8
350 | startY = y - 16
351 | endX = x + 8
352 | endY = y
353 | }
354 |
355 | writeBytes(out,
356 | "\n",
357 | startX,
358 | startY,
359 | sweepFlag,
360 | endX,
361 | endY,
362 | )
363 | }
364 |
365 | // Draw a bridge as an SVG elliptical arc element.
366 | func (b Bridge) Draw(out io.Writer) {
367 | x, y := b.start.asPixelXY()
368 | sweepFlag := 1
369 |
370 | if b.orientation == W {
371 | sweepFlag = 0
372 | }
373 |
374 | writeBytes(out,
375 | "\n",
376 | x, y-8,
377 | sweepFlag,
378 | x, y+8,
379 | )
380 | }
381 |
--------------------------------------------------------------------------------
/examples/line-decorations.svg:
--------------------------------------------------------------------------------
1 |
104 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # GoAT: Go ASCII Tool
2 |
3 | This is a Go implementation of [markdeep.mini.js]'s ASCII diagram
4 | generation.
5 |
6 |
7 | ## TODO
8 |
9 | - Dashed lines signaled by `:` or `=`.
10 | - Bold lines signaled by ???.
11 |
12 | ## Examples
13 |
14 | Here are some SVGs and the ASCII input they were generated from:
15 |
16 | ### Trees
17 |
18 | 
19 |
20 | ```
21 | . . . .--- 1 .-- 1 / 1
22 | / \ | | .---+ .-+ +
23 | / \ .---+---. .--+--. | '--- 2 | '-- 2 / \ 2
24 | + + | | | | ---+ ---+ +
25 | / \ / \ .-+-. .-+-. .+. .+. | .--- 3 | .-- 3 \ / 3
26 | / \ / \ | | | | | | | | '---+ '-+ +
27 | 1 2 3 4 1 2 3 4 1 2 3 4 '--- 4 '-- 4 \ 4
28 | ```
29 |
30 | ### Overlaps
31 |
32 | 
33 |
34 | ```
35 | .-. .-. .-. .-. .-. .-.
36 | | | | | | | | | | | | |
37 | .---------. .--+---+--. .--+---+--. .--| |--. .--+ +--. .------|--.
38 | | | | | | | | | | | | | | | | | | |
39 | '---------' '--+---+--' '--+---+--' '--| |--' '--+ +--' '--|------'
40 | | | | | | | | | | | | |
41 | '-' '-' '-' '-' '-' '-'
42 | ```
43 |
44 | ### Line Decorations
45 |
46 | 
47 |
48 | ```
49 | ________ o * * .--------------.
50 | *---+--. | | o o | ^ \ / | .----------. |
51 | | | '--* -+- | | v / \ / | | <------. | |
52 | | '-----> .---(---' --->*<--- / .+->*<--o----' | | | | |
53 | <--' ^ ^ | | | | | ^ \ | '--------' | |
54 | \/ *-----' o |<----->| '-----' |__| v '------------' |
55 | /\ *---------------'
56 | ```
57 |
58 | ### Line Ends
59 |
60 | 
61 |
62 | ```
63 | o--o *--o / / * o o o o o * * * * o o o o * * * * o o o o * * * *
64 | o--* *--* v v ^ ^ | | | | | | | | \ \ \ \ \ \ \ \ / / / / / / / /
65 | o--> *--> * o / / o * v ' o * v ' o * v \ o * v \ o * v / o * v /
66 | o--- *---
67 | ^ ^ ^ ^ . . . . ^ ^ ^ ^ \ \ \ \ ^ ^ ^ ^ / / / /
68 | | | * o \ \ * o | | | | | | | | \ \ \ \ \ \ \ \ / / / / / / / /
69 | v v ^ ^ v v ^ ^ o * v ' o * v ' o * v \ o * v \ o * v / o * v /
70 | * o | | * o \ \
71 |
72 | <--o <--* <--> <--- ---o ---* ---> ---- *<-- o<-- -->o -->*
73 | ```
74 |
75 | ### Dot Grids
76 |
77 | 
78 |
79 | ```
80 | o o o o o * * * * * * * o o * o o o * * * o o o · * · · · · · ·
81 | o o o o o * * * * * o o o o * o o o o * * * * * o * * · * * · · · · · ·
82 | o o o o o * * * * * o * o o o o o o o o * * * * * o o o o o · o · · o · · * * ·
83 | o o o o o * * * * * o * o o o o o o o * * * * o * o o · · · · o · · * ·
84 | o o o o o * * * * * * * * * o o o o * * * o * o · · · · · · · *
85 | ```
86 |
87 | ### Large Nodes
88 |
89 | 
90 |
91 | ```
92 | .---. .-. .-. .-. .-.
93 | | A +----->| 1 +<---->| 2 |<----+ 4 +------------------. | 8 |
94 | '---' '-' '+' '-' | '-'
95 | | ^ | ^
96 | v | v |
97 | .-. .-+-. .-. .-+-. .-. .+. .---.
98 | | 3 +---->| B |<----->| 5 +---->| C +---->| 6 +---->| 7 |<---->| D |
99 | '-' '---' '-' '---' '-' '-' '---'
100 | ```
101 |
102 | ### Small Grids
103 |
104 | 
105 |
106 | ```
107 | ___ ___ .---+---+---+---+---. .---+---+---+---. .---. .---.
108 | ___/ \___/ \ | | | | | | / \ / \ / \ / \ / | +---+ |
109 | / \___/ \___/ +---+---+---+---+---+ +---+---+---+---+ +---+ +---+
110 | \___/ b \___/ \ | | | b | | | \ / \a/ \b/ \ / \ | +---+ |
111 | / a \___/ \___/ +---+---+---+---+---+ +---+---+---+---+ +---+ b +---+
112 | \___/ \___/ \ | | a | | | | / \ / \ / \ / \ / | a +---+ |
113 | \___/ \___/ '---+---+---+---+---' '---+---+---+---' '---' '---'
114 | ```
115 |
116 | ### Big Grids
117 |
118 | 
119 |
120 | ```
121 | .----. .----.
122 | / \ / \ .-----+-----+-----.
123 | + +----+ +----. | | | | .-----+-----+-----+-----+
124 | \ / \ / \ | | | | / / / / /
125 | +----+ B +----+ + +-----+-----+-----+ +-----+-----+-----+-----+
126 | / \ / \ / | | | | / / / / /
127 | + A +----+ +----+ | | B | | +-----+-----+-----+-----+
128 | \ / \ / \ +-----+-----+-----+ / / A / B / /
129 | '----+ +----+ + | | | | +-----+-----+-----+-----+
130 | \ / \ / | A | | | / / / / /
131 | '----' '----' '-----+-----+-----' '-----+-----+-----+-----+
132 | ```
133 |
134 | ### Complicated
135 |
136 | 
137 |
138 | ```
139 | +-------------------+ ^ .---.
140 | | A Box |__.--.__ __.--> | .-. | |
141 | | | '--' v | * |<--- | |
142 | +-------------------+ '-' | |
143 | Round *---(-. |
144 | .-----------------. .-------. .----------. .-------. | | |
145 | | Mixed Rounded | | | / Diagonals \ | | | | | |
146 | | & Square Corners | '--. .--' / \ |---+---| '-)-' .--------.
147 | '--+------------+-' .--. | '-------+--------' | | | | / Search /
148 | | | | | '---. | '-------' | '-+------'
149 | |<---------->| | | | v Interior | ^
150 | ' <---' '----' .-----------. ---. .--- v |
151 | .------------------. Diag line | .-------. +---. \ / . |
152 | | if (a > b) +---. .--->| | | | | Curved line \ / / \ |
153 | | obj->fcn() | \ / | '-------' |<--' + / \ |
154 | '------------------' '--' '--+--------' .--. .--. | .-. +Done?+-'
155 | .---+-----. | ^ |\ | | /| .--+ | | \ /
156 | | | | Join \|/ | | Curved | \| |/ | | \ | \ /
157 | | | +----> o --o-- '-' Vertical '--' '--' '-- '--' + .---.
158 | <--+---+-----' | /|\ | | 3 |
159 | v not:line 'quotes' .-' '---'
160 | .-. .---+--------. / A || B *bold* | ^
161 | | | | Not a dot | <---+---<-- A dash--is not a line v |
162 | '-' '---------+--' / Nor/is this. ---
163 | ```
164 |
165 | More examples are available [here](examples).
166 |
167 | [markdeep.mini.js]: http://casual-effects.com/markdeep/
168 |
--------------------------------------------------------------------------------
/examples/circuits.svg:
--------------------------------------------------------------------------------
1 |
128 |
--------------------------------------------------------------------------------
/examples/large-nodes.svg:
--------------------------------------------------------------------------------
1 |
105 |
--------------------------------------------------------------------------------
/examples/small-nodes.svg:
--------------------------------------------------------------------------------
1 |
96 |
--------------------------------------------------------------------------------
/examples/graphics.svg:
--------------------------------------------------------------------------------
1 |
119 |
--------------------------------------------------------------------------------
/examples/small-grids.svg:
--------------------------------------------------------------------------------
1 |
165 |
--------------------------------------------------------------------------------
/examples/flow-chart.svg:
--------------------------------------------------------------------------------
1 |
146 |
--------------------------------------------------------------------------------
/examples/dot-grids.svg:
--------------------------------------------------------------------------------
1 |
181 |
--------------------------------------------------------------------------------
/examples/line-ends.svg:
--------------------------------------------------------------------------------
1 |
213 |
--------------------------------------------------------------------------------
/examples/icons.svg:
--------------------------------------------------------------------------------
1 |
234 |
--------------------------------------------------------------------------------