Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions blog/ascii.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import CodeBlock from '@theme/CodeBlock';
import Example from '@site/static/d2/ascii-ex.d2';

# ASCII output

In the latest release of D2 (0.7.1), we introduce ASCII outputs.

Any output file with extension `txt` will use the ASCII renderer to write to it.

```shell
d2 in.d2 out.txt
```

<!-- truncate -->

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.

![D2 Vim preview](/blog/ascii/preview.gif)

## Code documentation

Perhaps the most useful place for ASCII diagrams is in the source code comments. Small
simple diagrams next to functions or classes can serve to be much clearer than describing
a flow.

Here again the Vim extension demonstrates a functionality to write some d2 code and
replace the selection with the ASCII render.

![D2 Vim replace](/blog/ascii/replace.gif)

## Unicode and standard ASCII

The default character set of ASCII renders is unicode, which has nicer box-drawing
characters. If you'd like true ASCII for maximum portability, you can specify this with
the flag `--ascii-mode=standard`.

## Limitations

:::info Alpha
Note that the ASCII renderer should be considered in alpha stage. There will be many
corner cases, areas of improvements, and outright bugs. If you enjoy using it, we'd
appreciate you taking the time to file any issues you run into:
[https://github.com/terrastruct/d2/issues](https://github.com/terrastruct/d2/issues).
:::

The ASCII renderer is a downscale of the layout determined by the ELK layout engine with
some post-processing to further compact it.

- No styles are supported
- Some will never be, e.g. `animated` and `font` don't make sense in ASCII.
- Some may in the future with limited scope, e.g. colors when rendered to terminal.
- By extension, themes are moot
- Some should be considered TODOs, e.g. `double-border` and `multiple`
- Uneven spacing
- Sometimes the downscaling results in a box with uneven spacing, e.g. a rectangle with
width 5 and the label is 2 chars. Due to discrete coordinate space in ASCII renders, some
outputs may look less even than their SVG counterparts.

## Try it yourself

This is live now in the D2 Playground. Try opening the below code block (click top right
of it).

<CodeBlock className="language-d2" expandeable={true} ascii={true}>
{Example}
</CodeBlock>
19 changes: 17 additions & 2 deletions ci/examples/examples.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,16 @@ main() {

# Create temp directory for extracted files
temp_dir=$(mktemp -d)
trap "rm -rf $temp_dir" EXIT

# Create temp directory for generated SVGs when no args provided
if [ $# -eq 0 ]; then
temp_output_dir=$(mktemp -d)
trap "rm -rf $temp_dir $temp_output_dir" EXIT
output_dir="$temp_output_dir"
else
trap "rm -rf $temp_dir" EXIT
output_dir="./static/img/examples"
fi

# Parse txtar file
current_file=""
Expand Down Expand Up @@ -68,12 +77,18 @@ main() {
bigheader "$output_name"

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

waitjobs

# If no args provided, replace the examples directory with temp directory contents
if [ $# -eq 0 ]; then
rm -rf ./static/img/examples/*
cp "$temp_output_dir"/* ./static/img/examples/
fi

# Generate the examples pages
generate_examples_pages
}
Expand Down
58 changes: 37 additions & 21 deletions ci/render.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,44 +4,54 @@ set -eu
cd -- "$(dirname "$0")/.."

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


_bespoke() {
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
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
sh_c d2 --animate-interval=1400 -l elk -c --pad 0 ./static/bespoke-d2/animated.d2 ./static/img/generated/animated.svg2
sh_c d2 --animate-interval=1400 -c --pad 0 ./static/bespoke-d2/chicken.d2 ./static/img/generated/chicken.svg2
sh_c d2 --pad 50 ./static/bespoke-d2/tiktok.d2 ./static/img/generated/tiktok.pdf
sh_c d2 --pad 0 ./static/bespoke-d2/cat.d2 ./static/img/generated/cat.pdf
sh_c d2 --pad 50 ./static/bespoke-d2/lotr.d2 ./static/img/generated/lotr.pdf
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
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
sh_c d2 --omit-version --animate-interval=1400 -l elk -c --pad 0 ./static/bespoke-d2/animated.d2 ${output_dir}/animated.svg2
sh_c d2 --omit-version --animate-interval=1400 -c --pad 0 ./static/bespoke-d2/chicken.d2 ${output_dir}/chicken.svg2
sh_c d2 --omit-version --pad 50 ./static/bespoke-d2/tiktok.d2 ${output_dir}/tiktok.pdf
sh_c d2 --omit-version --pad 0 ./static/bespoke-d2/cat.d2 ${output_dir}/cat.pdf
sh_c d2 --omit-version --pad 50 ./static/bespoke-d2/lotr.d2 ${output_dir}/lotr.pdf

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

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

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

sh_c d2 ./static/bespoke-d2/cult.d2 ./static/img/generated/cult.pptx
sh_c d2 ./static/bespoke-d2/wcc.d2 ./static/img/generated/wcc.pptx
sh_c d2 --omit-version ./static/bespoke-d2/cult.d2 ${output_dir}/cult.pptx
sh_c d2 --omit-version ./static/bespoke-d2/wcc.d2 ${output_dir}/wcc.pptx

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

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

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

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

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

main() {
job_parseflags "$@"

# Set up output directory - use temp dir if no args, direct output if filtered
if [ $# -eq 0 ]; then
temp_output_dir=$(mktemp -d)
trap "rm -rf $temp_output_dir" EXIT
output_dir="$temp_output_dir"
else
output_dir="./static/img/generated"
fi

for ex in ./static/d2/*.d2; do
ex=${ex#./static/d2/}
ex=${ex%.d2}
Expand All @@ -58,6 +68,12 @@ main() {
runjob _bespoke &
fi
waitjobs

# If no args provided, replace the generated directory with temp directory contents
if [ $# -eq 0 ]; then
rm -rf ./static/img/generated/*
cp "$temp_output_dir"/* ./static/img/generated/
fi
}

main "$@"
1 change: 1 addition & 0 deletions docs/tour/connections.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ To override the default arrowhead shape or give a label next to arrowheads, defi
- Can be further styled as `style.filled: true`.
- `cf-one`, `cf-one-required` (cf stands for crows foot)
- `cf-many`, `cf-many-required`
- `cross`
:::

:::info
Expand Down
55 changes: 55 additions & 0 deletions docs/tour/exports.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ On the CLI, you may export `.d2` into
* [PDF](#pdf)
* [PPTX](#pptx)
* [GIF](#gif)
* [ASCII](#ascii)
* [Stdout](#stdout)

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

## ASCII

:::warning Beta
ASCII outputs are new as of 0.7.1. They are to be considered in beta, and many diagrams
may not render correctly.
:::

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.

```shell
d2 in.d2 out.txt
```

### Character sets

D2 supports two ASCII character modes:

#### Extended mode (default)
Uses Unicode box-drawing characters for cleaner output:

```shell
d2 in.d2 out.txt
```

```
┌───────┐ ┌───────┐
│ Hello │──────▶│ World │
└───────┘ └───────┘
```

#### Standard mode
Uses basic ASCII characters for maximum compatibility:

```shell
d2 --ascii-mode standard in.d2 out.txt
```

```
+-------+ +-------+
| Hello |------>| World |
+-------+ +-------+
```

### Notes

- Renders only with ELK and TALA, due to curved lines not rendering well in ASCII. If
Dagre (or unspecified) is chosen, it will render in ELK.
- Some shapes are supported, like Person, but some shapes are hard to represent cleanly in
ASCII. It's best to avoid using these shapes when the output is ASCII, but if it can't
be avoided, in these cases, an icon on the top-left corner represents what the shape is
meant to be.
- Many styles are moot in ASCII, such as shadow or multiple or animated. It's best to keep
it as simple box and arrow type diagrams.

## Stdout

D2 accepts `-` in place of the input and/or output arguments. SVG is used as the format
Expand Down
17 changes: 13 additions & 4 deletions docs/tour/fonts.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,16 @@ one but not all of the fonts, it will fall back to Source Sans Pro for the missi
For example, if you give a `--font-regular`, `--font-bold`, and `--font-semibold`, then the
italic will remain as Source Sans Pro Italic.

:::info
Do you want to customize the fonts for code or sketch mode? Please raise an Issue on
GitHub. We'll support this if there's demand.
:::
## Mono fonts

If you'd like to customize the mono fonts:

- `--font-regular`
- `--font-italic`
- `--font-bold`
- `--fond-semibold`

## Sketch font

In sketch mode, if you supply a font, it will replace the default hand-drawn font family
instead of Source Sans Pro.
14 changes: 14 additions & 0 deletions docs/tour/legend.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,17 @@ of shapes to exclude them from the legend.
</CodeBlock>

<div style={{width: "100%"}} className="embedSVG" dangerouslySetInnerHTML={{__html: require('@site/static/img/generated/legend-hidden.svg2')}}></div>

## Rename "legend"

You may rename "legend" by simply giving it a label. This is particularly useful for
non-English diagrams.

```d2
vars: {
d2-legend: "凡例" {
# Legend items...
}
}
# Rest of diagram...
```
10 changes: 9 additions & 1 deletion docs/tour/man.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@ OPTIONS
-s, --sketch false
Renders the diagram to look like it was sketched by hand.

--ascii-mode extended
Character set to use for ASCII output (.txt extension or
--stdout-format ascii). Options: standard (basic ASCII) or
extended (Unicode box-drawing characters).

--center flag
Center the SVG in the containing viewbox, such as your
browser screen.
Expand Down Expand Up @@ -145,7 +150,7 @@ OPTIONS

--stdout-format string
Set the output format when writing to stdout. Supported
formats are: png, svg. Only used when output is set to stdout
formats are: png, svg, ascii. Only used when output is set to stdout
(-).

--no-xml-tag false
Expand Down Expand Up @@ -236,6 +241,9 @@ ENVIRONMENT VARIABLES
D2_STDOUT_FORMAT
See --stdout-format flag.

D2_ASCII_MODE
See --ascii-mode flag.

D2_NO_XML_TAG
See --no-xml-tag flag.

Expand Down
23 changes: 21 additions & 2 deletions docs/tour/positions.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import NearConstant from '@site/static/d2/near-constant.d2';
import NearContainer from '@site/static/d2/near-container.d2';
import NearExplanation from '@site/static/d2/near-explanation.d2';
import NearLabelIcon from '@site/static/d2/near-label-icon.d2';
import BorderLabel from '@site/static/d2/border-label.d2';
import TooltipNear from '@site/static/d2/tooltip-near.d2';

# Positions

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

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

:::info Extra values
### Outside and border

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


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

You can also add `border-x` prefix to specify the label being on the border.

<CodeBlock className="language-d2">
{BorderLabel}
</CodeBlock>

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

## Tooltip near

Usually, `tooltip` is a on-hover effect. However, if you specify a `near` field, it will
permanently show.

<CodeBlock className="language-d2">
{TooltipNear}
</CodeBlock>

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

## Near objects

Expand Down
Loading