Skip to content

Commit d153dce

Browse files
authored
Merge pull request #293 from terrastruct/ascii
ascii export
2 parents 3656aba + acf0555 commit d153dce

256 files changed

Lines changed: 2787 additions & 9616 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

blog/ascii.md

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import CodeBlock from '@theme/CodeBlock';
2+
import Example from '@site/static/d2/ascii-ex.d2';
3+
4+
# ASCII output
5+
6+
In the latest release of D2 (0.7.1), we introduce ASCII outputs.
7+
8+
Any output file with extension `txt` will use the ASCII renderer to write to it.
9+
10+
```shell
11+
d2 in.d2 out.txt
12+
```
13+
14+
<!-- truncate -->
15+
16+
Here is an example of their rendering from the [D2 Vim extension](https://github.com/terrastruct/d2-vim). The user opens a `.d2` file and opens a preview window, which updates upon every save.
17+
18+
![D2 Vim preview](/blog/ascii/preview.gif)
19+
20+
## Code documentation
21+
22+
Perhaps the most useful place for ASCII diagrams is in the source code comments. Small
23+
simple diagrams next to functions or classes can serve to be much clearer than describing
24+
a flow.
25+
26+
Here again the Vim extension demonstrates a functionality to write some d2 code and
27+
replace the selection with the ASCII render.
28+
29+
![D2 Vim replace](/blog/ascii/replace.gif)
30+
31+
## Unicode and standard ASCII
32+
33+
The default character set of ASCII renders is unicode, which has nicer box-drawing
34+
characters. If you'd like true ASCII for maximum portability, you can specify this with
35+
the flag `--ascii-mode=standard`.
36+
37+
## Limitations
38+
39+
:::info Alpha
40+
Note that the ASCII renderer should be considered in alpha stage. There will be many
41+
corner cases, areas of improvements, and outright bugs. If you enjoy using it, we'd
42+
appreciate you taking the time to file any issues you run into:
43+
[https://github.com/terrastruct/d2/issues](https://github.com/terrastruct/d2/issues).
44+
:::
45+
46+
The ASCII renderer is a downscale of the layout determined by the ELK layout engine with
47+
some post-processing to further compact it.
48+
49+
- No styles are supported
50+
- Some will never be, e.g. `animated` and `font` don't make sense in ASCII.
51+
- Some may in the future with limited scope, e.g. colors when rendered to terminal.
52+
- By extension, themes are moot
53+
- Some should be considered TODOs, e.g. `double-border` and `multiple`
54+
- Uneven spacing
55+
- Sometimes the downscaling results in a box with uneven spacing, e.g. a rectangle with
56+
width 5 and the label is 2 chars. Due to discrete coordinate space in ASCII renders, some
57+
outputs may look less even than their SVG counterparts.
58+
59+
## Try it yourself
60+
61+
This is live now in the D2 Playground. Try opening the below code block (click top right
62+
of it).
63+
64+
<CodeBlock className="language-d2" expandeable={true} ascii={true}>
65+
{Example}
66+
</CodeBlock>

ci/examples/examples.sh

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,16 @@ main() {
99

1010
# Create temp directory for extracted files
1111
temp_dir=$(mktemp -d)
12-
trap "rm -rf $temp_dir" EXIT
12+
13+
# Create temp directory for generated SVGs when no args provided
14+
if [ $# -eq 0 ]; then
15+
temp_output_dir=$(mktemp -d)
16+
trap "rm -rf $temp_dir $temp_output_dir" EXIT
17+
output_dir="$temp_output_dir"
18+
else
19+
trap "rm -rf $temp_dir" EXIT
20+
output_dir="./static/img/examples"
21+
fi
1322

1423
# Parse txtar file
1524
current_file=""
@@ -68,12 +77,18 @@ main() {
6877
bigheader "$output_name"
6978

7079
# Generate SVG with appropriate layout
71-
runjob sh_c D2_LAYOUT=$layout d2 --theme=0 -c --pad 10 "$d2_file" "./static/img/examples/$output_name.svg2" &
80+
runjob sh_c D2_LAYOUT=$layout d2 --omit-version --theme=0 -c --pad 10 "$d2_file" "$output_dir/$output_name.svg2" &
7281
done
7382
done
7483

7584
waitjobs
7685

86+
# If no args provided, replace the examples directory with temp directory contents
87+
if [ $# -eq 0 ]; then
88+
rm -rf ./static/img/examples/*
89+
cp "$temp_output_dir"/* ./static/img/examples/
90+
fi
91+
7792
# Generate the examples pages
7893
generate_examples_pages
7994
}

ci/render.sh

Lines changed: 37 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,44 +4,54 @@ set -eu
44
cd -- "$(dirname "$0")/.."
55

66
_normal() {
7-
sh_c d2 --dark-theme=200 -c --pad 0 ./static/d2/${ex}.d2 ./static/img/generated/${ex}.svg2
7+
sh_c d2 --omit-version --dark-theme=200 -c --pad 0 ./static/d2/${ex}.d2 ${output_dir}/${ex}.svg2
88
}
99

10+
1011
_bespoke() {
11-
sh_c d2 --theme=300 --dark-theme=200 -l elk -c --pad 0 ./static/bespoke-d2/terminal-theme.d2 ./static/img/generated/terminal-theme.svg2
12-
sh_c d2 --theme=300 --dark-theme=200 -l elk -c --pad 0 ./static/bespoke-d2/theme-override.d2 ./static/img/generated/theme-override.svg2
13-
sh_c d2 --animate-interval=1400 -l elk -c --pad 0 ./static/bespoke-d2/animated.d2 ./static/img/generated/animated.svg2
14-
sh_c d2 --animate-interval=1400 -c --pad 0 ./static/bespoke-d2/chicken.d2 ./static/img/generated/chicken.svg2
15-
sh_c d2 --pad 50 ./static/bespoke-d2/tiktok.d2 ./static/img/generated/tiktok.pdf
16-
sh_c d2 --pad 0 ./static/bespoke-d2/cat.d2 ./static/img/generated/cat.pdf
17-
sh_c d2 --pad 50 ./static/bespoke-d2/lotr.d2 ./static/img/generated/lotr.pdf
12+
sh_c d2 --omit-version --theme=300 --dark-theme=200 -l elk -c --pad 0 ./static/bespoke-d2/terminal-theme.d2 ${output_dir}/terminal-theme.svg2
13+
sh_c d2 --omit-version --theme=300 --dark-theme=200 -l elk -c --pad 0 ./static/bespoke-d2/theme-override.d2 ${output_dir}/theme-override.svg2
14+
sh_c d2 --omit-version --animate-interval=1400 -l elk -c --pad 0 ./static/bespoke-d2/animated.d2 ${output_dir}/animated.svg2
15+
sh_c d2 --omit-version --animate-interval=1400 -c --pad 0 ./static/bespoke-d2/chicken.d2 ${output_dir}/chicken.svg2
16+
sh_c d2 --omit-version --pad 50 ./static/bespoke-d2/tiktok.d2 ${output_dir}/tiktok.pdf
17+
sh_c d2 --omit-version --pad 0 ./static/bespoke-d2/cat.d2 ${output_dir}/cat.pdf
18+
sh_c d2 --omit-version --pad 50 ./static/bespoke-d2/lotr.d2 ${output_dir}/lotr.pdf
1819

19-
sh_c d2 --pad 50 ./static/bespoke-d2/c4-code.d2 ./static/img/generated/c4.pdf
20+
sh_c d2 --omit-version --pad 50 ./static/bespoke-d2/c4-code.d2 ${output_dir}/c4.pdf
2021

21-
sh_c d2 --animate-interval=1600 -c --pad 50 -l elk ./static/bespoke-d2/tax.d2 ./static/img/generated/tax.svg2
22-
sh_c d2 --animate-interval=1600 -c --pad 0 -l elk ./static/bespoke-d2/pizza.d2 ./static/img/generated/pizza.svg2
23-
sh_c d2 --animate-interval=1600 -c --pad 0 -l elk ./static/bespoke-d2/johnwick.d2 ./static/img/generated/johnwick.svg2
22+
sh_c d2 --omit-version --animate-interval=1600 -c --pad 50 -l elk ./static/bespoke-d2/tax.d2 ${output_dir}/tax.svg2
23+
sh_c d2 --omit-version --animate-interval=1600 -c --pad 0 -l elk ./static/bespoke-d2/pizza.d2 ${output_dir}/pizza.svg2
24+
sh_c d2 --omit-version --animate-interval=1600 -c --pad 0 -l elk ./static/bespoke-d2/johnwick.d2 ${output_dir}/johnwick.svg2
2425

25-
sh_c d2 --animate-interval=400 -c --pad 0 ./static/bespoke-d2/grid-row-dominant.d2 ./static/img/generated/grid-row-dominant.svg2
26-
sh_c d2 --animate-interval=400 -c --pad 0 ./static/bespoke-d2/grid-column-dominant.d2 ./static/img/generated/grid-column-dominant.svg2
26+
sh_c d2 --omit-version --animate-interval=400 -c --pad 0 ./static/bespoke-d2/grid-row-dominant.d2 ${output_dir}/grid-row-dominant.svg2
27+
sh_c d2 --omit-version --animate-interval=400 -c --pad 0 ./static/bespoke-d2/grid-column-dominant.d2 ${output_dir}/grid-column-dominant.svg2
2728

28-
sh_c d2 ./static/bespoke-d2/cult.d2 ./static/img/generated/cult.pptx
29-
sh_c d2 ./static/bespoke-d2/wcc.d2 ./static/img/generated/wcc.pptx
29+
sh_c d2 --omit-version ./static/bespoke-d2/cult.d2 ${output_dir}/cult.pptx
30+
sh_c d2 --omit-version ./static/bespoke-d2/wcc.d2 ${output_dir}/wcc.pptx
3031

31-
sh_c d2 ./static/bespoke-d2/imports-nested.d2 ./static/img/generated/imports-nested.pdf
32+
sh_c d2 --omit-version ./static/bespoke-d2/imports-nested.d2 ${output_dir}/imports-nested.pdf
3233

33-
sh_c d2 ./static/bespoke-d2/triple-glob.d2 ./static/img/generated/triple-glob.pdf
34+
sh_c d2 --omit-version ./static/bespoke-d2/triple-glob.d2 ${output_dir}/triple-glob.pdf
3435

35-
sh_c d2 --sketch ./static/bespoke-d2/grid-nested-connections.d2 ./static/img/generated/grid-nested-connections.svg2
36+
sh_c d2 --omit-version --sketch ./static/bespoke-d2/grid-nested-connections.d2 ${output_dir}/grid-nested-connections.svg2
3637

37-
sh_c d2 --dark-theme=200 -l elk -c --pad 0 ./static/bespoke-d2/classes-3.d2 ./static/img/generated/classes-3.svg2
38+
sh_c d2 --omit-version --dark-theme=200 -l elk -c --pad 0 ./static/bespoke-d2/classes-3.d2 ${output_dir}/classes-3.svg2
3839

39-
sh_c d2 -c --pad 50 ./static/bespoke-d2/styles-animated.d2 ./static/img/generated/styles-animated.svg2
40+
sh_c d2 --omit-version -c --pad 50 ./static/bespoke-d2/styles-animated.d2 ${output_dir}/styles-animated.svg2
4041
}
4142

4243
main() {
4344
job_parseflags "$@"
4445

46+
# Set up output directory - use temp dir if no args, direct output if filtered
47+
if [ $# -eq 0 ]; then
48+
temp_output_dir=$(mktemp -d)
49+
trap "rm -rf $temp_output_dir" EXIT
50+
output_dir="$temp_output_dir"
51+
else
52+
output_dir="./static/img/generated"
53+
fi
54+
4555
for ex in ./static/d2/*.d2; do
4656
ex=${ex#./static/d2/}
4757
ex=${ex%.d2}
@@ -58,6 +68,12 @@ main() {
5868
runjob _bespoke &
5969
fi
6070
waitjobs
71+
72+
# If no args provided, replace the generated directory with temp directory contents
73+
if [ $# -eq 0 ]; then
74+
rm -rf ./static/img/generated/*
75+
cp "$temp_output_dir"/* ./static/img/generated/
76+
fi
6177
}
6278

6379
main "$@"

docs/tour/connections.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ To override the default arrowhead shape or give a label next to arrowheads, defi
113113
- Can be further styled as `style.filled: true`.
114114
- `cf-one`, `cf-one-required` (cf stands for crows foot)
115115
- `cf-many`, `cf-many-required`
116+
- `cross`
116117
:::
117118

118119
:::info

docs/tour/exports.md

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ On the CLI, you may export `.d2` into
88
* [PDF](#pdf)
99
* [PPTX](#pptx)
1010
* [GIF](#gif)
11+
* [ASCII](#ascii)
1112
* [Stdout](#stdout)
1213

1314
## SVG
@@ -102,6 +103,60 @@ For example, show two Scenarios, show a couple of steps. Something that the audi
102103
digest in a loop that lasts a couple of seconds without needing to flip through it
103104
manually.
104105

106+
## ASCII
107+
108+
:::warning Beta
109+
ASCII outputs are new as of 0.7.1. They are to be considered in beta, and many diagrams
110+
may not render correctly.
111+
:::
112+
113+
ASCII exports render diagrams as text-based art, perfect for documentation, terminals, and environments where graphical formats aren't suitable. D2 automatically detects the `.txt` file extension and renders in ASCII format.
114+
115+
```shell
116+
d2 in.d2 out.txt
117+
```
118+
119+
### Character sets
120+
121+
D2 supports two ASCII character modes:
122+
123+
#### Extended mode (default)
124+
Uses Unicode box-drawing characters for cleaner output:
125+
126+
```shell
127+
d2 in.d2 out.txt
128+
```
129+
130+
```
131+
┌───────┐ ┌───────┐
132+
│ Hello │──────▶│ World │
133+
└───────┘ └───────┘
134+
```
135+
136+
#### Standard mode
137+
Uses basic ASCII characters for maximum compatibility:
138+
139+
```shell
140+
d2 --ascii-mode standard in.d2 out.txt
141+
```
142+
143+
```
144+
+-------+ +-------+
145+
| Hello |------>| World |
146+
+-------+ +-------+
147+
```
148+
149+
### Notes
150+
151+
- Renders only with ELK and TALA, due to curved lines not rendering well in ASCII. If
152+
Dagre (or unspecified) is chosen, it will render in ELK.
153+
- Some shapes are supported, like Person, but some shapes are hard to represent cleanly in
154+
ASCII. It's best to avoid using these shapes when the output is ASCII, but if it can't
155+
be avoided, in these cases, an icon on the top-left corner represents what the shape is
156+
meant to be.
157+
- Many styles are moot in ASCII, such as shadow or multiple or animated. It's best to keep
158+
it as simple box and arrow type diagrams.
159+
105160
## Stdout
106161

107162
D2 accepts `-` in place of the input and/or output arguments. SVG is used as the format

docs/tour/fonts.md

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,16 @@ one but not all of the fonts, it will fall back to Source Sans Pro for the missi
2929
For example, if you give a `--font-regular`, `--font-bold`, and `--font-semibold`, then the
3030
italic will remain as Source Sans Pro Italic.
3131

32-
:::info
33-
Do you want to customize the fonts for code or sketch mode? Please raise an Issue on
34-
GitHub. We'll support this if there's demand.
35-
:::
32+
## Mono fonts
33+
34+
If you'd like to customize the mono fonts:
35+
36+
- `--font-regular`
37+
- `--font-italic`
38+
- `--font-bold`
39+
- `--fond-semibold`
40+
41+
## Sketch font
42+
43+
In sketch mode, if you supply a font, it will replace the default hand-drawn font family
44+
instead of Source Sans Pro.

docs/tour/legend.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,17 @@ of shapes to exclude them from the legend.
2323
</CodeBlock>
2424

2525
<div style={{width: "100%"}} className="embedSVG" dangerouslySetInnerHTML={{__html: require('@site/static/img/generated/legend-hidden.svg2')}}></div>
26+
27+
## Rename "legend"
28+
29+
You may rename "legend" by simply giving it a label. This is particularly useful for
30+
non-English diagrams.
31+
32+
```d2
33+
vars: {
34+
d2-legend: "凡例" {
35+
# Legend items...
36+
}
37+
}
38+
# Rest of diagram...
39+
```

docs/tour/man.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,11 @@ OPTIONS
6565
-s, --sketch false
6666
Renders the diagram to look like it was sketched by hand.
6767
68+
--ascii-mode extended
69+
Character set to use for ASCII output (.txt extension or
70+
--stdout-format ascii). Options: standard (basic ASCII) or
71+
extended (Unicode box-drawing characters).
72+
6873
--center flag
6974
Center the SVG in the containing viewbox, such as your
7075
browser screen.
@@ -145,7 +150,7 @@ OPTIONS
145150
146151
--stdout-format string
147152
Set the output format when writing to stdout. Supported
148-
formats are: png, svg. Only used when output is set to stdout
153+
formats are: png, svg, ascii. Only used when output is set to stdout
149154
(-).
150155
151156
--no-xml-tag false
@@ -236,6 +241,9 @@ ENVIRONMENT VARIABLES
236241
D2_STDOUT_FORMAT
237242
See --stdout-format flag.
238243
244+
D2_ASCII_MODE
245+
See --ascii-mode flag.
246+
239247
D2_NO_XML_TAG
240248
See --no-xml-tag flag.
241249

docs/tour/positions.md

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import NearConstant from '@site/static/d2/near-constant.d2';
44
import NearContainer from '@site/static/d2/near-container.d2';
55
import NearExplanation from '@site/static/d2/near-explanation.d2';
66
import NearLabelIcon from '@site/static/d2/near-label-icon.d2';
7+
import BorderLabel from '@site/static/d2/border-label.d2';
8+
import TooltipNear from '@site/static/d2/tooltip-near.d2';
79

810
# Positions
911

@@ -62,7 +64,7 @@ The `near` can be nested to `label` and `icon` to specify their positions.
6264

6365
<div className="embedSVG" dangerouslySetInnerHTML={{__html: require('@site/static/img/generated/near-label-icon.svg2')}}></div>
6466

65-
:::info Extra values
67+
### Outside and border
6668

6769
When positioning labels and icons, in addition to the values that `near` can take
6870
elsewhere, an `outside-` prefix can be added to specify positioning outside the bounding
@@ -76,8 +78,25 @@ box of the shape.
7678

7779

7880
Note that `outside-left-center` is a different order than `center-left`.
79-
:::
8081

82+
You can also add `border-x` prefix to specify the label being on the border.
83+
84+
<CodeBlock className="language-d2">
85+
{BorderLabel}
86+
</CodeBlock>
87+
88+
<div className="embedSVG" dangerouslySetInnerHTML={{__html: require('@site/static/img/generated/border-label.svg2')}}></div>
89+
90+
## Tooltip near
91+
92+
Usually, `tooltip` is a on-hover effect. However, if you specify a `near` field, it will
93+
permanently show.
94+
95+
<CodeBlock className="language-d2">
96+
{TooltipNear}
97+
</CodeBlock>
98+
99+
<div className="embedSVG" dangerouslySetInnerHTML={{__html: require('@site/static/img/generated/tooltip-near.svg2')}}></div>
81100

82101
## Near objects
83102

0 commit comments

Comments
 (0)