Skip to content
Open
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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ All notable user-visible changes to this project are documented in this file.

### Added

- Added `termdraw compile` for rendering JSONC diagram documents through the termDRAW drawing model without opening the interactive editor.

### Changed

### Fixed
Expand Down
65 changes: 65 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,46 @@
- `@termdraw/opentui` — embeddable OpenTUI components and renderables
- `@termdraw/pi` — Pi package that opens termDRAW in a Pi overlay

## Architecture

```text
╔══════════════════════════════════════════════════════════════════════════════════════════════╗
║ termDRAW workspace ║
║ ┌──────────────────────────────────────────────────────────────────────────────────────────┐ ║
║ │ workspace root │ ║
║ │ package.json scripts: format | lint | test | typecheck | build | smoke:pi │ ║
║ └──────────────────────────────────────────────────────────────────────────────────────────┘ ║
║ ║
║ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ║
║ ┌────────────────────────┐ ┃ packages/opentui ┃ ┌──────────────────────┐ ║
║ │ packages/app │ ┃ ┃ │ packages/pi │ ║
║ │ │ ┃ @termdraw/opentui ┃ │ │ ║
║ │ @termdraw/app │ ┃ ┃ │ @termdraw/pi │ ║
║ │ │ ┃ draw-state.ts ┃ │ │ ║
║ │ src/cli.tsx │ ┃ objects/tools/history ┃ │ overlay.ts │ ║
║ │ │────>┃ ┃─────>│ │ ║
║ │ src/main.tsx │ ┃ app.ts renderable ┃ │ termdraw.island.tsx │ ║
║ │ │ ┃ ┃ │ │ ║
║ │ TermDrawApp │ ┃ app/input.ts keys+mouse ┃ │ onSave bridge │ ║
║ │ │ ┃ ┃ │ │ ║
║ │ │ ┃ app/render.ts canvas ┃ │ │ ║
║ └────────────────────────┘ ┃ ┃ └──────────────────────┘ ║
║ │ ┃ react.ts components ┃ │ ║
║ │ ┃ ┃ │ ║
║ v ┃ ┃ v ║
║ ╔══════════════════════╗ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ╔══════════════════════╗ ║
║ ║ terminal CLI ║ v ║ Pi editor ║ ║
║ ║ stdout / --output ║ ╔════════════════════╗ ║ insert saved art ║ ║
║ ║ ║ ║ saved art ║ ║ ║ ║
║ ╚══════════════════════╝ ║ plain or fenced ║ ╚══════════════════════╝ ║
║ ╚════════════════════╝ ║
╚══════════════════════════════════════════════════════════════════════════════════════════════╝
```

- `packages/app` wraps the full OpenTUI app as the standalone `termdraw` CLI.
- `packages/opentui` owns the reusable editor state, rendering, input handling, React bindings, and text export.
- `packages/pi` embeds the editor through an island bridge and returns saved art to Pi.

## Install the app

Requirements:
Expand Down Expand Up @@ -57,12 +97,37 @@ termdraw --output diagram.txt
# export a fenced Markdown code block
termdraw --fenced > diagram.md

# render a JSONC diagram document without opening the editor
termdraw compile docs/examples/service-flow.diagram.jsonc

# show CLI help
termdraw --help
```

termDRAW! outputs terminal text, not SVG or bitmap graphics.

## Compile diagrams from JSONC

`termdraw compile` renders a compact diagram document through the same retained drawing model used by the interactive editor. It accepts a file path, `-`, or stdin.

```jsonc
{
"version": 1,
"size": [24, 5],
"objects": [
{ "type": "box", "rect": [0, 0, 8, 2], "style": "light", "text": "CLI" },
{ "type": "line", "from": [9, 1], "to": [14, 1], "style": "light", "marker": ">" },
{ "type": "text", "at": [16, 1], "text": "text" },
],
}
```

```text
┌───────┐
│ CLI │─────> text
└───────┘
```

## Use it in Pi

```bash
Expand Down
27 changes: 18 additions & 9 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

197 changes: 197 additions & 0 deletions docs/examples/architecture.diagram.jsonc
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
{
"version": 1,
"size": [96, 31],
"objects": [
{
"type": "box",
"id": "frame",
"rect": [0, 0, 95, 30],
"style": "double",
"text": "termDRAW workspace",
},
{
"type": "box",
"id": "root",
"rect": [2, 2, 93, 5],
"style": "light",
"text": "workspace root",
},
{
"type": "text",
"at": [5, 4],
"text": "package.json scripts: format | lint | test | typecheck | build | smoke:pi",
},
{
"type": "box",
"id": "app",
"rect": [2, 8, 27, 20],
"style": "light",
"text": "packages/app",
},
{
"type": "text",
"at": [5, 11],
"text": "@termdraw/app",
},
{
"type": "text",
"at": [5, 13],
"text": "src/cli.tsx",
},
{
"type": "text",
"at": [5, 15],
"text": "src/main.tsx",
},
{
"type": "text",
"at": [5, 17],
"text": "TermDrawApp",
},
{
"type": "box",
"id": "core",
"rect": [33, 7, 63, 24],
"style": "heavy",
"text": "packages/opentui",
},
{
"type": "text",
"at": [36, 10],
"text": "@termdraw/opentui",
},
{
"type": "text",
"at": [36, 12],
"text": "draw-state.ts",
},
{
"type": "text",
"at": [39, 13],
"text": "objects/tools/history",
},
{
"type": "text",
"at": [36, 15],
"text": "app.ts renderable",
},
{
"type": "text",
"at": [36, 17],
"text": "app/input.ts keys+mouse",
},
{
"type": "text",
"at": [36, 19],
"text": "app/render.ts canvas",
},
{
"type": "text",
"at": [36, 21],
"text": "react.ts components",
},
{
"type": "box",
"id": "pi",
"rect": [70, 8, 93, 20],
"style": "light",
"text": "packages/pi",
},
{
"type": "text",
"at": [73, 11],
"text": "@termdraw/pi",
},
{
"type": "text",
"at": [73, 13],
"text": "overlay.ts",
},
{
"type": "text",
"at": [73, 15],
"text": "termdraw.island.tsx",
},
{
"type": "text",
"at": [73, 17],
"text": "onSave bridge",
},
{
"type": "box",
"id": "cli-output",
"rect": [4, 24, 27, 28],
"style": "double",
"text": "terminal CLI",
},
{
"type": "text",
"at": [7, 26],
"text": "stdout / --output",
},
{
"type": "box",
"id": "saved-art",
"rect": [38, 26, 59, 29],
"style": "double",
"text": "saved art",
},
{
"type": "text",
"at": [41, 28],
"text": "plain or fenced",
},
{
"type": "box",
"id": "pi-output",
"rect": [70, 24, 93, 28],
"style": "double",
"text": "Pi editor",
},
{
"type": "text",
"at": [73, 26],
"text": "insert saved art",
},
{
"type": "line",
"id": "app-core",
"from": [28, 14],
"to": [32, 14],
"style": "light",
"marker": ">",
},
{
"type": "line",
"id": "core-pi",
"from": [64, 14],
"to": [69, 14],
"style": "light",
"marker": ">",
},
{
"type": "line",
"id": "app-output",
"from": [15, 21],
"to": [15, 23],
"style": "light",
"marker": "v",
},
{
"type": "line",
"id": "core-output",
"from": [48, 25],
"to": [48, 25],
"style": "light",
"marker": "v",
},
{
"type": "line",
"id": "pi-output-edge",
"from": [82, 21],
"to": [82, 23],
"style": "light",
"marker": "v",
},
],
}
Loading