Merge branch 'master' into alixander/flag-env-var

This commit is contained in:
Alexander Wang 2022-11-16 16:31:16 -08:00
commit ff800e1564
No known key found for this signature in database
GPG key ID: D89FA31966BDBECE
35 changed files with 1788 additions and 195 deletions

3
.gitattributes vendored Normal file
View file

@ -0,0 +1,3 @@
d2layouts/d2dagrelayout/dagre.js linguist-vendored
d2layouts/d2elklayout/elk.js linguist-vendored
d2renderers/d2svg/github-markdown.css linguist-vendored

View file

@ -1,2 +1,3 @@
<!-- Please title the PR with a scope prefix like cli: performance improvements. -->
<!-- Please add screenshots or screencasts for ui/autolayout changes. -->
<!-- Remember to update ci/release/changelogs/next.md, the manpage and cli help documentation. -->

View file

@ -20,27 +20,28 @@
<!-- toc -->
- [Quickstart (CLI)](#quickstart-cli)
* [MacOS](#macos)
* [Linux/Windows](#linuxwindows)
- [Quickstart (library)](#quickstart-library)
- [Quickstart](#quickstart)
- [Install](#install)
* [Install script](#install-script)
* [Install from source](#install-from-source)
- [D2 as a library](#d2-as-a-library)
- [Themes](#themes)
- [Fonts](#fonts)
- [Export file types](#export-file-types)
- [Language tooling](#language-tooling)
- [Layout engine](#layout-engine)
- [Plugins](#plugins)
- [Comparison](#comparison)
- [Contributing](#contributing)
- [License](#license)
- [Dependencies](#dependencies)
- [Related](#related)
* [VSCode extension](#vscode-extension)
* [Vim extension](#vim-extension)
* [Misc](#misc)
- [FAQ](#faq)
<!-- tocstop -->
## Quickstart (CLI)
## Quickstart
The most convenient way to use D2 is to just run it as a CLI executable to
produce SVGs from `.d2` files.
@ -55,22 +56,17 @@ d2 --watch in.d2 out.svg
A browser window will open with `out.svg` and live-reload on changes to `in.d2`.
### Install from source
## Install
```sh
go install oss.terrastruct.com/d2
```
### Install
### Install script
The recommended way to install is to run our install script, which will figure out the
best way to install based on your machine. E.g. if D2 is available through a package
manager installed, it will use that package manager.
best way to install based on your machine.
```sh
# With --dryrun the install script will print the commands it will use
# With --dry-run the install script will print the commands it will use
# to install without actually installing so you know what it's going to do.
curl -fsSL https://d2lang.com/install.sh | sh -s -- --dryrun
curl -fsSL https://d2lang.com/install.sh | sh -s -- --dry-run
# If things look good, install for real.
curl -fsSL https://d2lang.com/install.sh | sh -s --
```
@ -83,7 +79,7 @@ and release a docker image.
To uninstall:
```sh
curl -fsSL https://d2lang.com/install.sh | sh -s -- --uninstall --dryrun
curl -fsSL https://d2lang.com/install.sh | sh -s -- --uninstall --dry-run
# If things look good, uninstall for real.
curl -fsSL https://d2lang.com/install.sh | sh -s -- --uninstall
```
@ -91,7 +87,15 @@ curl -fsSL https://d2lang.com/install.sh | sh -s -- --uninstall
> warn: Our binary releases aren't fully portable like normal Go binaries due to the C
> dependency on v8go for executing dagre.
## Quickstart (library)
### Install from source
Alternatively, you can install from source:
```sh
go install oss.terrastruct.com/d2
```
## D2 as a library
In addition to being a runnable CLI tool, D2 can also be used to produce diagrams from
Go programs.
@ -208,10 +212,13 @@ Copyright © 2022 Terrastruct, Inc. Open-source licensed under the Mozilla Publi
[https://github.com/terrastruct/d2-vim](https://github.com/terrastruct/d2-vim)
### Language docs
[https://github.com/terrastruct/d2-docs](https://github.com/terrastruct/d2-docs)
### Misc
- [https://github.com/terrastruct/d2-docs](https://github.com/terrastruct/d2-docs)
- [https://github.com/terrastruct/text-to-diagram-com](https://github.com/terrastruct/text-to-diagram-com)
- [https://github.com/terrastruct/text-to-diagram-site](https://github.com/terrastruct/text-to-diagram-site)
## FAQ
@ -221,10 +228,8 @@ Copyright © 2022 Terrastruct, Inc. Open-source licensed under the Mozilla Publi
- Does D2 need a browser to run?
- No, D2 can run entirely server-side.
- I have a question or need help.
- The best way to get help is to open an Issue, so that it's searchable by others in the
future. If you prefer synchronous or just want to chat, you can pop into the help
channel of the [D2 Discord](https://discord.gg/NF6X8K4eDq) as well.
- I have a feature request or proposal.
- D2 uses Github Issues for everything. Just add a "discussion" label to your Issue.
- The best way to get help is to ask on [D2 Discord](https://discord.gg/NF6X8K4eDq)
- I have a feature request, proposal, or bug report.
- Please open up a Github Issue.
- I have a private inquiry.
- Please reach out at [hi@d2lang.com](hi@d2lang.com).

View file

@ -194,7 +194,7 @@ EOF
if ! manpath | grep -qF "$PREFIX/share/man"; then
logcat >&2 <<EOF
Extend your \$MANPATH to view d2's manpages:
export MANPATH=$PREFIX/share/man\${MANPATH+:\$MANPATH}
export MANPATH=$PREFIX/share/man:\$MANPATH
Then run:
man d2
EOF

View file

@ -5,7 +5,7 @@ cd -- "$(dirname "$0")/../.."
help() {
cat <<EOF
usage: $0 [--rebuild] [--local] [--dry-run] [--run=regex] [--host-only]
usage: $0 [--rebuild] [--local] [--dry-run] [--run=regex] [--host-only] [--lockfile-force]
$0 builds D2 release archives into ./ci/release/build/<version>/d2-<VERSION>-<OS>-<ARCH>.tar.gz
@ -35,6 +35,9 @@ Flags:
--version vX.X.X
Use to overwrite the version detected from git.
--lockfile-force
Forcefully take ownership of remote builder lockfiles.
EOF
}
@ -71,6 +74,10 @@ main() {
flag_nonemptyarg && shift "$FLAGSHIFT"
VERSION=$FLAGARG
;;
lockfile-force)
flag_noarg && shift "$FLAGSHIFT"
LOCKFILE_FORCE=1
;;
'')
shift "$FLAGSHIFT"
break
@ -118,10 +125,10 @@ build() {
macos)
case $ARCH in
amd64)
RHOST=$TSTRUCT_MACOS_AMD64_BUILDER build_rhost_macos
REMOTE_HOST=$TSTRUCT_MACOS_AMD64_BUILDER build_remote_macos
;;
arm64)
RHOST=$TSTRUCT_MACOS_ARM64_BUILDER build_rhost_macos
REMOTE_HOST=$TSTRUCT_MACOS_ARM64_BUILDER build_remote_macos
;;
*)
warn "no builder for OS=$OS ARCH=$ARCH, building locally..."
@ -132,10 +139,10 @@ build() {
linux)
case $ARCH in
amd64)
RHOST=$TSTRUCT_LINUX_AMD64_BUILDER build_rhost_linux
REMOTE_HOST=$TSTRUCT_LINUX_AMD64_BUILDER build_remote_linux
;;
arm64)
RHOST=$TSTRUCT_LINUX_ARM64_BUILDER build_rhost_linux
REMOTE_HOST=$TSTRUCT_LINUX_ARM64_BUILDER build_remote_linux
;;
*)
warn "no builder for OS=$OS ARCH=$ARCH, building locally..."
@ -160,10 +167,12 @@ build_local() {
sh_c ./ci/release/_build.sh
}
build_rhost_macos() {
sh_c ssh "$RHOST" mkdir -p src
sh_c rsync --archive --human-readable --delete ./ "$RHOST:src/d2/"
sh_c ssh -tttt "$RHOST" "DRY_RUN=${DRY_RUN-} \
build_remote_macos() {
sh_c lockfile_ssh "$REMOTE_HOST" .d2-build-lock
trap unlockfile_ssh EXIT
sh_c ssh "$REMOTE_HOST" mkdir -p src
sh_c rsync --archive --human-readable --delete ./ "$REMOTE_HOST:src/d2/"
sh_c ssh "$REMOTE_HOST" "DRY_RUN=${DRY_RUN-} \
HW_BUILD_DIR=$HW_BUILD_DIR \
VERSION=$VERSION \
OS=$OS \
@ -173,13 +182,15 @@ TERM=$TERM \
PATH=\\\"/usr/local/bin:/usr/local/sbin:/opt/homebrew/bin:/opt/homebrew/sbin\\\${PATH+:\\\$PATH}\\\" \
./src/d2/ci/release/_build.sh"
sh_c mkdir -p "$HW_BUILD_DIR"
sh_c rsync --archive --human-readable "$RHOST:src/d2/$ARCHIVE" "$ARCHIVE"
sh_c rsync --archive --human-readable "$REMOTE_HOST:src/d2/$ARCHIVE" "$ARCHIVE"
}
build_rhost_linux() {
sh_c ssh "$RHOST" mkdir -p src
sh_c rsync --archive --human-readable --delete ./ "$RHOST:src/d2/"
sh_c ssh -tttt "$RHOST" "DRY_RUN=${DRY_RUN-} \
build_remote_linux() {
sh_c lockfile_ssh "$REMOTE_HOST" .d2-build-lock
trap unlockfile_ssh EXIT
sh_c ssh "$REMOTE_HOST" mkdir -p src
sh_c rsync --archive --human-readable --delete ./ "$REMOTE_HOST:src/d2/"
sh_c ssh "$REMOTE_HOST" "DRY_RUN=${DRY_RUN-} \
HW_BUILD_DIR=$HW_BUILD_DIR \
VERSION=$VERSION \
OS=$OS \
@ -188,7 +199,7 @@ ARCHIVE=$ARCHIVE \
TERM=$TERM \
./src/d2/ci/release/build_docker.sh"
sh_c mkdir -p "$HW_BUILD_DIR"
sh_c rsync --archive --human-readable "$RHOST:src/d2/$ARCHIVE" "$ARCHIVE"
sh_c rsync --archive --human-readable "$REMOTE_HOST:src/d2/$ARCHIVE" "$ARCHIVE"
}
ssh() {

View file

@ -0,0 +1,61 @@
#!/bin/sh
set -eu
cd -- "$(dirname "$0")/../../.."
. ./ci/sub/lib.sh
help() {
cat <<EOF
usage: $0 [--dry-run] -i keys.pub
$0 copies keys.pub to each builder and then deduplicates its .authorized_keys.
EOF
}
main() {
while :; do
flag_parse "$@"
case "$FLAG" in
h|help)
help
return 0
;;
dry-run)
flag_noarg && shift "$FLAGSHIFT"
DRY_RUN=1
;;
i)
flag_nonemptyarg && shift "$FLAGSHIFT"
KEY_FILE=$FLAGARG
;;
'')
shift "$FLAGSHIFT"
break
;;
*)
flag_errusage "unrecognized flag $FLAGRAW"
;;
esac
done
if [ -z "${KEY_FILE-}" ]; then
echoerr "-i is required"
exit 1
fi
header linux-amd64
REMOTE_HOST=$TSTRUCT_LINUX_AMD64_BUILDER copy_keys
header linux-arm64
REMOTE_HOST=$TSTRUCT_LINUX_ARM64_BUILDER copy_keys
header macos-amd64
REMOTE_HOST=$TSTRUCT_MACOS_AMD64_BUILDER copy_keys
header macos-arm64
REMOTE_HOST=$TSTRUCT_MACOS_ARM64_BUILDER copy_keys
}
copy_keys() {
sh_c ssh-copy-id -fi "$KEY_FILE" "$REMOTE_HOST"
sh_c ssh "$REMOTE_HOST" 'cat .ssh/authorized_keys \| sort -u \> .ssh/authorized_keys.dedup'
sh_c ssh "$REMOTE_HOST" 'cp .ssh/authorized_keys.dedup .ssh/authorized_keys'
sh_c ssh "$REMOTE_HOST" 'rm .ssh/authorized_keys.dedup'
}
main "$@"

View file

@ -41,12 +41,12 @@ main() {
fi
if [ -z "${SKIP_CREATE-}" ]; then
create_rhosts
create_remote_hosts
fi
init_rhosts
init_remote_hosts
}
create_rhosts() {
create_remote_hosts() {
KEY_NAME=$(aws ec2 describe-key-pairs | jq -r .KeyPairs[0].KeyName)
VPC_ID=$(aws ec2 describe-vpcs | jq -r .Vpcs[0].VpcId)
@ -77,7 +77,7 @@ create_rhosts() {
| jq -r '.Reservations[].Instances[].State.Name')
if [ -z "$state" ]; then
sh_c aws ec2 run-instances \
--image-id=ami-0d593311db5abb72b \
--image-id=ami-071e6cafc48327ca2 \
--count=1 \
--instance-type=t2.small \
--security-groups=ssh \
@ -90,8 +90,8 @@ create_rhosts() {
--filters 'Name=instance-state-name,Values=pending,running,stopping,stopped' 'Name=tag:Name,Values=d2-builder-linux-amd64' \
| jq -r '.Reservations[].Instances[].PublicDnsName')
if [ -n "$dnsname" ]; then
log "TSTRUCT_LINUX_AMD64_BUILDER=ec2-user@$dnsname"
export TSTRUCT_LINUX_AMD64_BUILDER=ec2-user@$dnsname
log "TSTRUCT_LINUX_AMD64_BUILDER=admin@$dnsname"
export TSTRUCT_LINUX_AMD64_BUILDER=admin@$dnsname
break
fi
sleep 5
@ -103,7 +103,7 @@ create_rhosts() {
| jq -r '.Reservations[].Instances[].State.Name')
if [ -z "$state" ]; then
sh_c aws ec2 run-instances \
--image-id=ami-0efabcf945ffd8831 \
--image-id=ami-0e67506f183e5ab60 \
--count=1 \
--instance-type=t4g.small \
--security-groups=ssh \
@ -116,8 +116,8 @@ create_rhosts() {
--filters 'Name=instance-state-name,Values=pending,running,stopping,stopped' 'Name=tag:Name,Values=d2-builder-linux-arm64' \
| jq -r '.Reservations[].Instances[].PublicDnsName')
if [ -n "$dnsname" ]; then
log "TSTRUCT_LINUX_ARM64_BUILDER=ec2-user@$dnsname"
export TSTRUCT_LINUX_ARM64_BUILDER=ec2-user@$dnsname
log "TSTRUCT_LINUX_ARM64_BUILDER=admin@$dnsname"
export TSTRUCT_LINUX_ARM64_BUILDER=admin@$dnsname
break
fi
sleep 5
@ -194,15 +194,15 @@ create_rhosts() {
done
}
init_rhosts() {
init_remote_hosts() {
header linux-amd64
RHOST=$TSTRUCT_LINUX_AMD64_BUILDER init_rhost_linux
REMOTE_HOST=$TSTRUCT_LINUX_AMD64_BUILDER init_remote_linux
header linux-arm64
RHOST=$TSTRUCT_LINUX_ARM64_BUILDER init_rhost_linux
REMOTE_HOST=$TSTRUCT_LINUX_ARM64_BUILDER init_remote_linux
header macos-amd64
RHOST=$TSTRUCT_MACOS_AMD64_BUILDER init_rhost_macos
REMOTE_HOST=$TSTRUCT_MACOS_AMD64_BUILDER init_remote_macos
header macos-arm64
RHOST=$TSTRUCT_MACOS_ARM64_BUILDER init_rhost_macos
REMOTE_HOST=$TSTRUCT_MACOS_ARM64_BUILDER init_remote_macos
COLOR=2 header summary
log "export TSTRUCT_LINUX_AMD64_BUILDER=$TSTRUCT_LINUX_AMD64_BUILDER"
@ -211,32 +211,53 @@ init_rhosts() {
log "export TSTRUCT_MACOS_ARM64_BUILDER=$TSTRUCT_MACOS_ARM64_BUILDER"
}
init_rhost_linux() {
init_remote_linux() {
while true; do
if sh_c ssh "$RHOST" :; then
if sh_c ssh "$REMOTE_HOST" :; then
break
fi
sleep 5
done
sh_c ssh "$RHOST" 'sudo yum upgrade -y'
sh_c ssh "$RHOST" 'sudo yum install -y docker'
sh_c ssh "$RHOST" 'sudo systemctl start docker'
sh_c ssh "$RHOST" 'sudo systemctl enable docker'
sh_c ssh "$RHOST" 'sudo usermod -a -G docker ec2-user'
sh_c ssh "$RHOST" 'sudo reboot' || true
sh_c ssh "$REMOTE_HOST" sh -s -- <<EOF
set -eux
export DEBIAN_FRONTEND=noninteractive
sudo -E apt-get update -y
sudo -E apt-get dist-upgrade -y
sudo -E apt-get install -y build-essential rsync
# Docker from https://docs.docker.com/engine/install/debian/
sudo -E apt-get -y install \
ca-certificates \
curl \
gnupg \
lsb-release
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --batch --yes --dearmor -o /etc/apt/keyrings/docker.gpg
echo \
"deb [arch=\$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian \
\$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo -E apt-get update -y
sudo -E apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
sudo groupadd docker || true
sudo usermod -aG docker \$USER
EOF
sh_c ssh "$REMOTE_HOST" 'sudo reboot' || true
}
init_rhost_macos() {
init_remote_macos() {
while true; do
if sh_c ssh "$RHOST" :; then
if sh_c ssh "$REMOTE_HOST" :; then
break
fi
sleep 5
done
sh_c ssh "$RHOST" '": | /bin/bash -c \"\$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\""'
sh_c ssh "$RHOST" 'PATH="/usr/local/bin:/opt/homebrew/bin:\$PATH" brew update'
sh_c ssh "$RHOST" 'PATH="/usr/local/bin:/opt/homebrew/bin:\$PATH" brew upgrade'
sh_c ssh "$RHOST" 'PATH="/usr/local/bin:/opt/homebrew/bin:\$PATH" brew install go'
sh_c ssh "$REMOTE_HOST" '"/bin/bash -c \"\$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\""'
sh_c ssh "$REMOTE_HOST" 'PATH="/usr/local/bin:/opt/homebrew/bin:\$PATH" brew update'
sh_c ssh "$REMOTE_HOST" 'PATH="/usr/local/bin:/opt/homebrew/bin:\$PATH" brew upgrade'
sh_c ssh "$REMOTE_HOST" 'PATH="/usr/local/bin:/opt/homebrew/bin:\$PATH" brew install go'
}
main "$@"

View file

@ -1,43 +0,0 @@
#!/bin/sh
set -eu
cd -- "$(dirname "$0")/../../.."
. ./ci/sub/lib.sh
help() {
cat <<EOF
usage: $0 [--dry-run] [...args]
$0 runs ssh-copy-id on each builder.
args are passed to ssh-copy-id directly.
EOF
}
main() {
while :; do
flag_parse "$@"
case "$FLAG" in
h|help)
help
return 0
;;
dry-run)
flag_noarg && shift "$FLAGSHIFT"
DRY_RUN=1
;;
'')
shift "$FLAGSHIFT"
break
;;
*)
flag_errusage "unrecognized flag $FLAGRAW"
;;
esac
done
sh_c ssh-copy-id "$@" "\$TSTRUCT_LINUX_AMD64_BUILDER"
sh_c ssh-copy-id "$@" "\$TSTRUCT_LINUX_ARM64_BUILDER"
sh_c ssh-copy-id "$@" "\$TSTRUCT_MACOS_AMD64_BUILDER"
sh_c ssh-copy-id "$@" "\$TSTRUCT_MACOS_ARM64_BUILDER"
}
main "$@"

46
ci/release/builders/ssh.sh Executable file
View file

@ -0,0 +1,46 @@
#!/bin/sh
set -eu
cd -- "$(dirname "$0")/../../.."
. ./ci/sub/lib.sh
help() {
cat <<EOF
usage: $0 [--dry-run] [--run=regex] ...
Run a command on every builder instance.
EOF
}
main() {
while :; do
flag_parse "$@"
case "$FLAG" in
h|help)
help
return 0
;;
dry-run)
flag_noarg && shift "$FLAGSHIFT"
DRY_RUN=1
;;
run)
flag_reqarg && shift "$FLAGSHIFT"
JOBFILTER="$FLAGARG"
;;
'')
shift "$FLAGSHIFT"
break
;;
*)
flag_errusage "unrecognized flag $FLAGRAW"
;;
esac
done
REMOTE_HOST=$TSTRUCT_LINUX_AMD64_BUILDER; runjob linux-amd64 ssh "$REMOTE_HOST" "$@"
REMOTE_HOST=$TSTRUCT_LINUX_ARM64_BUILDER; runjob linux-arm64 ssh "$REMOTE_HOST" "$@"
REMOTE_HOST=$TSTRUCT_MACOS_AMD64_BUILDER; runjob macos-amd64 ssh "$REMOTE_HOST" "$@"
REMOTE_HOST=$TSTRUCT_MACOS_ARM64_BUILDER; runjob macos-arm64 ssh "$REMOTE_HOST" "$@"
}
main "$@"

View file

@ -6,7 +6,7 @@ For v0.0.99 we focused on X, Y and Z. Enjoy!
#### Improvements 🔧
- Improves something or the other #9999
- Add table columns indices in edges between SQL Tables so that layout engines can route exactly between them
#### Bugfixes 🔴

View file

@ -0,0 +1 @@
As of v0.0.12, D2 is now open-source!

View file

@ -4,14 +4,14 @@ cd -- "$(dirname "$0")/.."
. ./scripts/lib.sh
main() {
if [ ! -e "${PREFIX-}" ]; then
if [ -z "${PREFIX-}" ]; then
echoerr "\$PREFIX must be set to a unix prefix directory in which to install d2 like /usr/local"
return 1
fi
sh_c mkdir -p "$PREFIX/bin"
sh_c mkdir -p "$PREFIX/share/man/man1"
sh_c install ./bin/d2 "$PREFIX/bin/d2"
sh_c mkdir -p "$PREFIX/share/man/man1"
sh_c install ./man/d2.1 "$PREFIX/share/man/man1"
}

View file

@ -1,5 +1,9 @@
#!/bin/sh
if [ -n "${DEBUG-}" ]; then
set -x
fi
rand() {
seed="$1"
range="$2"

View file

@ -4,7 +4,7 @@ cd -- "$(dirname "$0")/.."
. ./scripts/lib.sh
main() {
if [ ! -e "${PREFIX-}" ]; then
if [ -z "${PREFIX-}" ]; then
echoerr "\$PREFIX must be set to a unix prefix directory from which to uninstall d2 like /usr/local"
return 1
fi

2
ci/sub

@ -1 +1 @@
Subproject commit 670ea5892b60d815f53a52bf31fdb50ef475ee37
Subproject commit df51b90892737ebe9feca3dd982bcdfc7f684834

View file

@ -36,7 +36,7 @@ func run(ctx context.Context, ms *xmain.State) (err error) {
debugFlag := ms.Opts.Bool("DEBUG", "debug", "d", false, "print debug logs.")
layoutFlag := ms.Opts.String("D2_LAYOUT", "layout", "l", "dagre", `the layout engine used.`)
themeFlag := ms.Opts.Int64("D2_THEME", "theme", "t", 0, "the diagram theme ID. For a list of available options, see https://oss.terrastruct.com/d2")
versionFlag := ms.Opts.Bool("", "version", "v", false, "get the version and check for updates")
versionFlag := ms.Opts.Bool("", "version", "v", false, "get the version")
err = ms.Opts.Parse()
if !errors.Is(err, pflag.ErrHelp) && err != nil {
@ -64,7 +64,7 @@ func run(ctx context.Context, ms *xmain.State) (err error) {
if len(ms.Opts.Args()) == 0 {
if versionFlag != nil && *versionFlag {
version.CheckVersion(ctx, ms.Log)
fmt.Println(version.Version)
return nil
}
help(ms)
@ -72,9 +72,10 @@ func run(ctx context.Context, ms *xmain.State) (err error) {
} else if len(ms.Opts.Args()) >= 3 {
return xmain.UsageErrorf("too many arguments passed")
}
if len(ms.Opts.Args()) >= 1 {
if ms.Opts.Arg(0) == "version" {
version.CheckVersion(ctx, ms.Log)
fmt.Println(version.Version)
return nil
}
inputPath = ms.Opts.Arg(0)

View file

@ -1,8 +1,5 @@
// d2ast implements the d2 language's abstract syntax tree.
//
// https://github.com/terrastruct/d2-vscode
// https://terrastruct.com/docs/d2/tour/intro/
//
// Special characters to think about in parser:
// #
// """

View file

@ -680,12 +680,12 @@ func (c *compiler) compileSQLTable(obj *d2graph.Object) {
continue
}
if srcID == absID {
// Frontend isn't aware of container IDs.
d2Col.Reference = strings.TrimPrefix(dstID, parentID+".")
relSrc := strings.TrimPrefix(absID, parentID+".")
e.Attributes.Label.Value = fmt.Sprintf("%s %s %s", relSrc, e.ArrowString(), d2Col.Reference)
// removeContainer() will adjust the edge to point to the table and not inside.
break
e.SrcTableColumnIndex = new(int)
*e.SrcTableColumnIndex = len(obj.SQLTable.Columns)
} else if dstID == absID {
e.DstTableColumnIndex = new(int)
*e.DstTableColumnIndex = len(obj.SQLTable.Columns)
}
}
@ -746,6 +746,14 @@ func flattenContainer(g *d2graph.Graph, obj *d2graph.Object) {
newEdge, _ = g.Root.Connect(e.Src.AbsIDArray(), obj.AbsIDArray(), e.SrcArrow, e.DstArrow, e.Attributes.Label.Value)
}
// TODO more attributes
if e.SrcTableColumnIndex != nil {
newEdge.SrcTableColumnIndex = new(int)
*newEdge.SrcTableColumnIndex = *e.SrcTableColumnIndex
}
if e.DstTableColumnIndex != nil {
newEdge.DstTableColumnIndex = new(int)
*newEdge.DstTableColumnIndex = *e.DstTableColumnIndex
}
newEdge.Attributes.Label = e.Attributes.Label
newEdge.References = e.References
}

View file

@ -1474,6 +1474,32 @@ b`, g.Objects[0].Attributes.Label.Value)
SVP1.style.3d: true`,
expErr: `d2/testdata/d2compiler/TestCompile/3d_oval.d2:2:1: key "3d" can only be applied to squares and rectangles
`,
}, {
name: "edge_column_index",
text: `src: {
shape: sql_table
id: int
dst_id: int
}
dst: {
shape: sql_table
id: int
name: string
}
dst.id <-> src.dst_id
`,
assertions: func(t *testing.T, g *d2graph.Graph) {
srcIndex := g.Edges[0].SrcTableColumnIndex
if srcIndex == nil || *srcIndex != 0 {
t.Fatalf("expected SrcTableColumnIndex to be 0, got %v", srcIndex)
}
dstIndex := g.Edges[0].DstTableColumnIndex
if dstIndex == nil || *dstIndex != 1 {
t.Fatalf("expected DstTableColumnIndex to be 1, got %v", dstIndex)
}
},
},
}

View file

@ -1,6 +1,3 @@
// Package d2compiler implements a parser, compiler and autoformatter for the Terrastruct d2
// diagramming language.
//
// https://github.com/terrastruct/d2-vscode
// https://terrastruct.com/docs/d2/tour/intro/
package d2compiler

View file

@ -607,6 +607,9 @@ type Edge struct {
MinWidth int `json:"minWidth"`
MinHeight int `json:"minHeight"`
SrcTableColumnIndex *int `json:"srcTableColumnIndex,omitempty"`
DstTableColumnIndex *int `json:"dstTableColumnIndex,omitempty"`
LabelDimensions d2target.TextDimensions `json:"label_dimensions"`
LabelPosition *string `json:"labelPosition,omitempty"`
LabelPercentage *float64 `json:"labelPercentage,omitempty"`

View file

@ -0,0 +1,6 @@
dagre.js comes from https://github.com/dagrejs/dagre
Attribution:
MIT License
https://github.com/dagrejs/dagre/blob/master/LICENSE

View file

@ -0,0 +1,6 @@
elk.js comes from https://github.com/kieler/elkjs
Attribution:
EPL License 2.0
https://github.com/kieler/elkjs/blob/master/LICENSE.md

View file

@ -12,7 +12,6 @@ import (
"math"
"rogchap.com/v8go"
v8 "rogchap.com/v8go"
"oss.terrastruct.com/xdefer"
@ -104,7 +103,7 @@ func Layout(ctx context.Context, g *d2graph.Graph) (err error) {
})
global.Set("setTimeout", setTimeout, v8go.ReadOnly)
v8ctx := v8.NewContext(iso, global)
v8ctx := v8go.NewContext(iso, global)
if _, err := v8ctx.RunScript(elkJS, "elk.js"); err != nil {
return err
}

View file

@ -18,9 +18,6 @@ type Neutral struct {
}
type ColorPalette struct {
// So far the palette only contains the colors used in d2 shapes, the full theme includes more colors
// https://www.figma.com/file/n79RbPiHFUTO4PPPdpDu7w/%5BKW%5D-GUI-features?node-id=2268%3A120792
Neutrals Neutral `json:"neutrals"`
// Base Colors: used for containers

View file

@ -831,6 +831,43 @@ a -> md -> b
+setTimeout(seconds int)
}
`,
}, {
name: "sql_tables",
script: `users: {
shape: sql_table
id: int
name: string
email: string
password: string
last_login: datetime
}
products: {
shape: sql_table
id: int
price: decimal
sku: string
name: string
}
orders: {
shape: sql_table
id: int
user_id: int
product_id: int
}
shipments: {
shape: sql_table
id: int
order_id: int
tracking_number: string
status: string
}
users.id <-> orders.user_id
products.id <-> orders.product_id
shipments.order_id <-> orders.id`,
},
}

View file

@ -0,0 +1,396 @@
{
"name": "",
"shapes": [
{
"id": "users",
"type": "sql_table",
"pos": {
"x": 0,
"y": 0
},
"width": 259,
"height": 216,
"level": 1,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#FFFFFF",
"stroke": "#0A0F25",
"shadow": false,
"3d": false,
"multiple": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"fields": null,
"methods": null,
"columns": [
{
"name": "id",
"type": "int",
"constraint": "",
"reference": "orders.user_id"
},
{
"name": "name",
"type": "string",
"constraint": "",
"reference": ""
},
{
"name": "email",
"type": "string",
"constraint": "",
"reference": ""
},
{
"name": "password",
"type": "string",
"constraint": "",
"reference": ""
},
{
"name": "last_login",
"type": "datetime",
"constraint": "",
"reference": ""
}
],
"label": "users",
"fontSize": 20,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 61,
"labelHeight": 36
},
{
"id": "products",
"type": "sql_table",
"pos": {
"x": 319,
"y": 18
},
"width": 290,
"height": 180,
"level": 1,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#FFFFFF",
"stroke": "#0A0F25",
"shadow": false,
"3d": false,
"multiple": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"fields": null,
"methods": null,
"columns": [
{
"name": "id",
"type": "int",
"constraint": "",
"reference": "orders.product_id"
},
{
"name": "price",
"type": "decimal",
"constraint": "",
"reference": ""
},
{
"name": "sku",
"type": "string",
"constraint": "",
"reference": ""
},
{
"name": "name",
"type": "string",
"constraint": "",
"reference": ""
}
],
"label": "products",
"fontSize": 20,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 99,
"labelHeight": 36
},
{
"id": "orders",
"type": "sql_table",
"pos": {
"x": 357,
"y": 316
},
"width": 215,
"height": 144,
"level": 1,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#FFFFFF",
"stroke": "#0A0F25",
"shadow": false,
"3d": false,
"multiple": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"fields": null,
"methods": null,
"columns": [
{
"name": "id",
"type": "int",
"constraint": "",
"reference": ""
},
{
"name": "user_id",
"type": "int",
"constraint": "",
"reference": ""
},
{
"name": "product_id",
"type": "int",
"constraint": "",
"reference": ""
}
],
"label": "orders",
"fontSize": 20,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 74,
"labelHeight": 36
},
{
"id": "shipments",
"type": "sql_table",
"pos": {
"x": 669,
"y": 18
},
"width": 293,
"height": 180,
"level": 1,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#FFFFFF",
"stroke": "#0A0F25",
"shadow": false,
"3d": false,
"multiple": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"fields": null,
"methods": null,
"columns": [
{
"name": "id",
"type": "int",
"constraint": "",
"reference": ""
},
{
"name": "order_id",
"type": "int",
"constraint": "",
"reference": "orders.id"
},
{
"name": "tracking_number",
"type": "string",
"constraint": "",
"reference": ""
},
{
"name": "status",
"type": "string",
"constraint": "",
"reference": ""
}
],
"label": "shipments",
"fontSize": 20,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 116,
"labelHeight": 36
}
],
"connections": [
{
"id": "(users <-> orders)[0]",
"src": "users",
"srcArrow": "triangle",
"srcLabel": "",
"dst": "orders",
"dstArrow": "triangle",
"dstLabel": "",
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"stroke": "#0D32B2",
"label": "",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#676C7E",
"italic": true,
"bold": false,
"underline": false,
"labelWidth": 0,
"labelHeight": 0,
"labelPosition": "",
"labelPercentage": 0,
"route": [
{
"x": 129.5,
"y": 216
},
{
"x": 129.5,
"y": 256
},
{
"x": 174.9,
"y": 282.55844544095663
},
{
"x": 356.5,
"y": 348.7922272047833
}
],
"isCurve": true,
"animated": false,
"tooltip": "",
"icon": null
},
{
"id": "(products <-> orders)[0]",
"src": "products",
"srcArrow": "triangle",
"srcLabel": "",
"dst": "orders",
"dstArrow": "triangle",
"dstLabel": "",
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"stroke": "#0D32B2",
"label": "",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#676C7E",
"italic": true,
"bold": false,
"underline": false,
"labelWidth": 0,
"labelHeight": 0,
"labelPosition": "",
"labelPercentage": 0,
"route": [
{
"x": 464,
"y": 198
},
{
"x": 464,
"y": 252.4
},
{
"x": 464,
"y": 276
},
{
"x": 464,
"y": 316
}
],
"isCurve": true,
"animated": false,
"tooltip": "",
"icon": null
},
{
"id": "(shipments <-> orders)[0]",
"src": "shipments",
"srcArrow": "triangle",
"srcLabel": "",
"dst": "orders",
"dstArrow": "triangle",
"dstLabel": "",
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"stroke": "#0D32B2",
"label": "",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#676C7E",
"italic": true,
"bold": false,
"underline": false,
"labelWidth": 0,
"labelHeight": 0,
"labelPosition": "",
"labelPercentage": 0,
"route": [
{
"x": 815.5,
"y": 198
},
{
"x": 815.5,
"y": 252.4
},
{
"x": 766.7,
"y": 283
},
{
"x": 571.5,
"y": 351
}
],
"isCurve": true,
"animated": false,
"tooltip": "",
"icon": null
}
]
}

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 335 KiB

View file

@ -0,0 +1,385 @@
{
"name": "",
"shapes": [
{
"id": "users",
"type": "sql_table",
"pos": {
"x": 46,
"y": 412
},
"width": 259,
"height": 216,
"level": 1,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#FFFFFF",
"stroke": "#0A0F25",
"shadow": false,
"3d": false,
"multiple": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"fields": null,
"methods": null,
"columns": [
{
"name": "id",
"type": "int",
"constraint": "",
"reference": "orders.user_id"
},
{
"name": "name",
"type": "string",
"constraint": "",
"reference": ""
},
{
"name": "email",
"type": "string",
"constraint": "",
"reference": ""
},
{
"name": "password",
"type": "string",
"constraint": "",
"reference": ""
},
{
"name": "last_login",
"type": "datetime",
"constraint": "",
"reference": ""
}
],
"label": "users",
"fontSize": 20,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 61,
"labelHeight": 36
},
{
"id": "products",
"type": "sql_table",
"pos": {
"x": 15,
"y": 212
},
"width": 290,
"height": 180,
"level": 1,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#FFFFFF",
"stroke": "#0A0F25",
"shadow": false,
"3d": false,
"multiple": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"fields": null,
"methods": null,
"columns": [
{
"name": "id",
"type": "int",
"constraint": "",
"reference": "orders.product_id"
},
{
"name": "price",
"type": "decimal",
"constraint": "",
"reference": ""
},
{
"name": "sku",
"type": "string",
"constraint": "",
"reference": ""
},
{
"name": "name",
"type": "string",
"constraint": "",
"reference": ""
}
],
"label": "products",
"fontSize": 20,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 99,
"labelHeight": 36
},
{
"id": "orders",
"type": "sql_table",
"pos": {
"x": 405,
"y": 230
},
"width": 215,
"height": 144,
"level": 1,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#FFFFFF",
"stroke": "#0A0F25",
"shadow": false,
"3d": false,
"multiple": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"fields": null,
"methods": null,
"columns": [
{
"name": "id",
"type": "int",
"constraint": "",
"reference": ""
},
{
"name": "user_id",
"type": "int",
"constraint": "",
"reference": ""
},
{
"name": "product_id",
"type": "int",
"constraint": "",
"reference": ""
}
],
"label": "orders",
"fontSize": 20,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 74,
"labelHeight": 36
},
{
"id": "shipments",
"type": "sql_table",
"pos": {
"x": 12,
"y": 12
},
"width": 293,
"height": 180,
"level": 1,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#FFFFFF",
"stroke": "#0A0F25",
"shadow": false,
"3d": false,
"multiple": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"fields": null,
"methods": null,
"columns": [
{
"name": "id",
"type": "int",
"constraint": "",
"reference": ""
},
{
"name": "order_id",
"type": "int",
"constraint": "",
"reference": "orders.id"
},
{
"name": "tracking_number",
"type": "string",
"constraint": "",
"reference": ""
},
{
"name": "status",
"type": "string",
"constraint": "",
"reference": ""
}
],
"label": "shipments",
"fontSize": 20,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 116,
"labelHeight": 36
}
],
"connections": [
{
"id": "(users <-> orders)[0]",
"src": "users",
"srcArrow": "triangle",
"srcLabel": "",
"dst": "orders",
"dstArrow": "triangle",
"dstLabel": "",
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"stroke": "#0D32B2",
"label": "",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#676C7E",
"italic": true,
"bold": false,
"underline": false,
"labelWidth": 0,
"labelHeight": 0,
"labelPosition": "",
"labelPercentage": 0,
"route": [
{
"x": 305,
"y": 520
},
{
"x": 355,
"y": 520
},
{
"x": 355,
"y": 338
},
{
"x": 405,
"y": 338
}
],
"animated": false,
"tooltip": "",
"icon": null
},
{
"id": "(products <-> orders)[0]",
"src": "products",
"srcArrow": "triangle",
"srcLabel": "",
"dst": "orders",
"dstArrow": "triangle",
"dstLabel": "",
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"stroke": "#0D32B2",
"label": "",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#676C7E",
"italic": true,
"bold": false,
"underline": false,
"labelWidth": 0,
"labelHeight": 0,
"labelPosition": "",
"labelPercentage": 0,
"route": [
{
"x": 305,
"y": 302
},
{
"x": 405,
"y": 302
}
],
"animated": false,
"tooltip": "",
"icon": null
},
{
"id": "(shipments <-> orders)[0]",
"src": "shipments",
"srcArrow": "triangle",
"srcLabel": "",
"dst": "orders",
"dstArrow": "triangle",
"dstLabel": "",
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"stroke": "#0D32B2",
"label": "",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#676C7E",
"italic": true,
"bold": false,
"underline": false,
"labelWidth": 0,
"labelHeight": 0,
"labelPosition": "",
"labelPercentage": 0,
"route": [
{
"x": 305,
"y": 102
},
{
"x": 355,
"y": 102
},
{
"x": 355,
"y": 266
},
{
"x": 405,
"y": 266
}
],
"animated": false,
"tooltip": "",
"icon": null
}
]
}

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 335 KiB

6
go.mod
View file

@ -8,7 +8,6 @@ require (
github.com/alecthomas/chroma v0.10.0
github.com/fsnotify/fsnotify v1.6.0
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0
github.com/google/go-github v17.0.0+incompatible
github.com/lucasb-eyer/go-colorful v1.2.0
github.com/mazznoer/csscolorparser v0.1.3
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8
@ -21,8 +20,8 @@ require (
golang.org/x/text v0.3.7
gonum.org/v1/plot v0.12.0
nhooyr.io/websocket v1.8.7
oss.terrastruct.com/cmdlog v0.0.0-20221025194258-d3fd7e0b8950
oss.terrastruct.com/diff v1.0.1
oss.terrastruct.com/cmdlog v0.0.0-20221116181457-07977d95ac37
oss.terrastruct.com/diff v1.0.2-0.20221116222035-8bf4dd3ab541
oss.terrastruct.com/xcontext v0.0.0-20221018000442-50fdafb12f4f
oss.terrastruct.com/xdefer v0.0.0-20221017222355-6f3b6e4d1557
oss.terrastruct.com/xjson v0.0.0-20221018000420-4986731c4c4a
@ -40,7 +39,6 @@ require (
github.com/gin-gonic/gin v1.7.7 // indirect
github.com/go-playground/validator/v10 v10.10.0 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/gorilla/websocket v1.4.2 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.13.6 // indirect

12
go.sum
View file

@ -189,10 +189,6 @@ github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY=
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
@ -772,10 +768,10 @@ honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
nhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g=
nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0=
oss.terrastruct.com/cmdlog v0.0.0-20221025194258-d3fd7e0b8950 h1:35gU5c1wwHKhXg58F500d6Ev8s+jqQUg4BiDbx2Zr+g=
oss.terrastruct.com/cmdlog v0.0.0-20221025194258-d3fd7e0b8950/go.mod h1:ROL3yxl2X+S3O+Rls00qdX6aMh+p1dF8IdxDRwDDpsg=
oss.terrastruct.com/diff v1.0.1 h1:WJ0LPXIgj644ne7l9CtDT9sBMDqo1B2/Ir5zdvbxYN8=
oss.terrastruct.com/diff v1.0.1/go.mod h1:cRGe5OvyjX7WWKk7CYh73SoS2tEghpTmAY1IPFWbqgE=
oss.terrastruct.com/cmdlog v0.0.0-20221116181457-07977d95ac37 h1:Xy1JKJHc4hcuwi57s0BvGUY16GjxTtBmLUybsuGDU7E=
oss.terrastruct.com/cmdlog v0.0.0-20221116181457-07977d95ac37/go.mod h1:ROL3yxl2X+S3O+Rls00qdX6aMh+p1dF8IdxDRwDDpsg=
oss.terrastruct.com/diff v1.0.2-0.20221116222035-8bf4dd3ab541 h1:I9B1O1IJ6spivIQxbFRZmbhAwVeLwrcQRR1JbYUOvrI=
oss.terrastruct.com/diff v1.0.2-0.20221116222035-8bf4dd3ab541/go.mod h1:ags2QDy/T6jr69hT6bpmAmhr2H98n9o8Atf3QlUJPiU=
oss.terrastruct.com/xcontext v0.0.0-20221018000442-50fdafb12f4f h1:7voRCwKM7TZkTo9u7hj+uV/zXoVB8czWrTq6MVIh3dg=
oss.terrastruct.com/xcontext v0.0.0-20221018000442-50fdafb12f4f/go.mod h1:Y0coTLsWwX0q3a+/Ndq797t+vWyxm42T49Ik3bzaDKY=
oss.terrastruct.com/xdefer v0.0.0-20221017222355-6f3b6e4d1557 h1:rPbhJbN1q7B4tnppSPoAMwq0t6Pk5SrQDQ5S6uoNNHg=

View file

@ -628,7 +628,7 @@ EOF
if ! manpath | grep -qF "$PREFIX/share/man"; then
logcat >&2 <<EOF
Extend your \$MANPATH to view d2's manpages:
export MANPATH=$PREFIX/share/man\${MANPATH+:\$MANPATH}
export MANPATH=$PREFIX/share/man:\$MANPATH
Then run:
man d2
EOF

View file

@ -1,44 +1,4 @@
package version
import (
"context"
"fmt"
"github.com/google/go-github/github"
"oss.terrastruct.com/cmdlog"
)
// Pre-built binaries will have version set during build time.
var Version = "master (built from source)"
func CheckVersion(ctx context.Context, logger *cmdlog.Logger) {
fmt.Println(Version)
if Version == "master (built from source)" {
return
}
// Install script uses -v to check the version, we shouldn't be checking for
// updates here...
// https://github.com/terrastruct/d2/issues/49#issuecomment-1313229683
return
logger.Info.Printf("Checking for updates...")
latest, err := getLatestVersion(ctx)
if err != nil {
logger.Debug.Printf("Error reaching Github for latest version: %s", err.Error())
} else if Version != "master" && Version != latest {
logger.Info.Printf("A new version of D2 is available: %s -> %s", Version, latest)
}
}
func getLatestVersion(ctx context.Context) (string, error) {
client := github.NewClient(nil)
rep, _, err := client.Repositories.GetLatestRelease(ctx, "terrastruct", "d2")
if err != nil {
return "", err
}
return *rep.TagName, nil
}

View file

@ -0,0 +1,559 @@
{
"graph": {
"ast": {
"range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,0:0:0-13:0:123",
"nodes": [
{
"map_key": {
"range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,0:0:0-4:1:48",
"key": {
"range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,0:0:0-0:3:3",
"path": [
{
"unquoted_string": {
"range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,0:0:0-0:3:3",
"value": [
{
"string": "src",
"raw_string": "src"
}
]
}
}
]
},
"primary": {},
"value": {
"map": {
"range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,0:5:5-4:0:47",
"nodes": [
{
"map_key": {
"range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,1:1:8-1:17:24",
"key": {
"range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,1:1:8-1:6:13",
"path": [
{
"unquoted_string": {
"range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,1:1:8-1:6:13",
"value": [
{
"string": "shape",
"raw_string": "shape"
}
]
}
}
]
},
"primary": {},
"value": {
"unquoted_string": {
"range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,1:8:15-1:17:24",
"value": [
{
"string": "sql_table",
"raw_string": "sql_table"
}
]
}
}
}
},
{
"map_key": {
"range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,2:1:26-2:8:33",
"key": {
"range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,2:1:26-2:3:28",
"path": [
{
"unquoted_string": {
"range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,2:1:26-2:3:28",
"value": [
{
"string": "id",
"raw_string": "id"
}
]
}
}
]
},
"primary": {},
"value": {
"unquoted_string": {
"range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,2:5:30-2:8:33",
"value": [
{
"string": "int",
"raw_string": "int"
}
]
}
}
}
},
{
"map_key": {
"range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,3:1:35-3:12:46",
"key": {
"range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,3:1:35-3:7:41",
"path": [
{
"unquoted_string": {
"range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,3:1:35-3:7:41",
"value": [
{
"string": "dst_id",
"raw_string": "dst_id"
}
]
}
}
]
},
"primary": {},
"value": {
"unquoted_string": {
"range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,3:9:43-3:12:46",
"value": [
{
"string": "int",
"raw_string": "int"
}
]
}
}
}
}
]
}
}
}
},
{
"map_key": {
"range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,6:0:50-10:1:99",
"key": {
"range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,6:0:50-6:3:53",
"path": [
{
"unquoted_string": {
"range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,6:0:50-6:3:53",
"value": [
{
"string": "dst",
"raw_string": "dst"
}
]
}
}
]
},
"primary": {},
"value": {
"map": {
"range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,6:5:55-10:0:98",
"nodes": [
{
"map_key": {
"range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,7:1:58-7:17:74",
"key": {
"range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,7:1:58-7:6:63",
"path": [
{
"unquoted_string": {
"range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,7:1:58-7:6:63",
"value": [
{
"string": "shape",
"raw_string": "shape"
}
]
}
}
]
},
"primary": {},
"value": {
"unquoted_string": {
"range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,7:8:65-7:17:74",
"value": [
{
"string": "sql_table",
"raw_string": "sql_table"
}
]
}
}
}
},
{
"map_key": {
"range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,8:1:76-8:8:83",
"key": {
"range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,8:1:76-8:3:78",
"path": [
{
"unquoted_string": {
"range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,8:1:76-8:3:78",
"value": [
{
"string": "id",
"raw_string": "id"
}
]
}
}
]
},
"primary": {},
"value": {
"unquoted_string": {
"range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,8:5:80-8:8:83",
"value": [
{
"string": "int",
"raw_string": "int"
}
]
}
}
}
},
{
"map_key": {
"range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,9:1:85-9:13:97",
"key": {
"range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,9:1:85-9:5:89",
"path": [
{
"unquoted_string": {
"range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,9:1:85-9:5:89",
"value": [
{
"string": "name",
"raw_string": "name"
}
]
}
}
]
},
"primary": {},
"value": {
"unquoted_string": {
"range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,9:7:91-9:13:97",
"value": [
{
"string": "string",
"raw_string": "string"
}
]
}
}
}
}
]
}
}
}
},
{
"map_key": {
"range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,12:0:101-12:21:122",
"edges": [
{
"range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,12:0:101-12:21:122",
"src": {
"range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,12:0:101-12:7:108",
"path": [
{
"unquoted_string": {
"range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,12:0:101-12:3:104",
"value": [
{
"string": "dst",
"raw_string": "dst"
}
]
}
},
{
"unquoted_string": {
"range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,12:4:105-12:6:107",
"value": [
{
"string": "id",
"raw_string": "id"
}
]
}
}
]
},
"src_arrow": "<",
"dst": {
"range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,12:10:111-12:21:122",
"path": [
{
"unquoted_string": {
"range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,12:11:112-12:14:115",
"value": [
{
"string": "src",
"raw_string": "src"
}
]
}
},
{
"unquoted_string": {
"range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,12:15:116-12:21:122",
"value": [
{
"string": "dst_id",
"raw_string": "dst_id"
}
]
}
}
]
},
"dst_arrow": ">"
}
],
"primary": {},
"value": {}
}
}
]
},
"root": {
"id": "",
"id_val": "",
"label_dimensions": {
"width": 0,
"height": 0
},
"attributes": {
"label": {
"value": ""
},
"style": {},
"near_key": null,
"shape": {
"value": ""
}
}
},
"edges": [
{
"index": 0,
"minWidth": 0,
"minHeight": 0,
"srcTableColumnIndex": 0,
"dstTableColumnIndex": 1,
"label_dimensions": {
"width": 0,
"height": 0
},
"isCurve": false,
"src_arrow": true,
"dst_arrow": true,
"references": [
{
"map_key_edge_index": 0
}
],
"attributes": {
"label": {
"value": ""
},
"style": {},
"near_key": null,
"shape": {
"value": ""
}
}
}
],
"objects": [
{
"id": "src",
"id_val": "src",
"label_dimensions": {
"width": 0,
"height": 0
},
"references": [
{
"key": {
"range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,0:0:0-0:3:3",
"path": [
{
"unquoted_string": {
"range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,0:0:0-0:3:3",
"value": [
{
"string": "src",
"raw_string": "src"
}
]
}
}
]
},
"key_path_index": 0,
"map_key_edge_index": 0
},
{
"key": {
"range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,12:10:111-12:21:122",
"path": [
{
"unquoted_string": {
"range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,12:11:112-12:14:115",
"value": [
{
"string": "src",
"raw_string": "src"
}
]
}
},
{
"unquoted_string": {
"range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,12:15:116-12:21:122",
"value": [
{
"string": "dst_id",
"raw_string": "dst_id"
}
]
}
}
]
},
"key_path_index": 0,
"map_key_edge_index": 0
}
],
"sql_table": {
"columns": [
{
"name": "id",
"type": "int",
"constraint": "",
"reference": ""
},
{
"name": "dst_id",
"type": "int",
"constraint": "",
"reference": ""
}
]
},
"attributes": {
"label": {
"value": "src"
},
"style": {},
"near_key": null,
"shape": {
"value": "sql_table"
}
}
},
{
"id": "dst",
"id_val": "dst",
"label_dimensions": {
"width": 0,
"height": 0
},
"references": [
{
"key": {
"range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,6:0:50-6:3:53",
"path": [
{
"unquoted_string": {
"range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,6:0:50-6:3:53",
"value": [
{
"string": "dst",
"raw_string": "dst"
}
]
}
}
]
},
"key_path_index": 0,
"map_key_edge_index": 0
},
{
"key": {
"range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,12:0:101-12:7:108",
"path": [
{
"unquoted_string": {
"range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,12:0:101-12:3:104",
"value": [
{
"string": "dst",
"raw_string": "dst"
}
]
}
},
{
"unquoted_string": {
"range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,12:4:105-12:6:107",
"value": [
{
"string": "id",
"raw_string": "id"
}
]
}
}
]
},
"key_path_index": 0,
"map_key_edge_index": 0
}
],
"sql_table": {
"columns": [
{
"name": "id",
"type": "int",
"constraint": "",
"reference": "src.dst_id"
},
{
"name": "name",
"type": "string",
"constraint": "",
"reference": ""
}
]
},
"attributes": {
"label": {
"value": "dst"
},
"style": {},
"near_key": null,
"shape": {
"value": "sql_table"
}
}
}
]
},
"err": null
}