133 lines
5.8 KiB
Markdown
133 lines
5.8 KiB
Markdown
# JSON Canvas Editor
|
|
|
|
A native desktop editor for the [JSON Canvas](https://jsoncanvas.org) 1.0 file
|
|
format, written in Rust. It runs on Windows and Linux from a single binary and
|
|
reads and writes plain `.canvas` files on the local disk — there is no server,
|
|
no account and no hidden state.
|
|
|
|

|
|
|
|
## What it does
|
|
|
|
**The whole spec.** All four node types (`text`, `file`, `link`, `group`) and
|
|
every edge attribute (`fromSide`/`toSide`, `fromEnd`/`toEnd`, `label`, `color`),
|
|
plus both `canvasColor` forms — the six presets and `#rrggbb` hex.
|
|
The format as this editor reads and writes it is written down in
|
|
[`spec/spec.md`](spec/spec.md), the handful of additions to JSON Canvas 1.0 are
|
|
listed on their own in [`spec/extensions.md`](spec/extensions.md), and the
|
|
original 1.0 spec sits next to them in [`spec/1.0.md`](spec/1.0.md) to diff
|
|
against.
|
|
|
|
**It does not damage files it does not fully understand.** Unknown top-level
|
|
keys, unknown node/edge attributes and even unknown node `type`s are carried
|
|
through a load/save cycle untouched, and attributes are written back in the
|
|
order the spec lists them, so a save produces a small diff rather than a
|
|
reshuffle.
|
|
|
|
**Direct manipulation.**
|
|
|
|
| Gesture | Result |
|
|
| --- | --- |
|
|
| Double-click empty canvas | New text note, ready to type in |
|
|
| Double-click a note | Edit its Markdown in place |
|
|
| Double-click a file/link node | Open it with the system default application |
|
|
| Drag a dot on a node's edge | Draw a connection; drop it on empty canvas to create the node too |
|
|
| Drag a corner or side handle | Resize |
|
|
| Drag a group | Moves the group and everything inside it |
|
|
| Drag on empty canvas | Rubber-band selection (hold <kbd>Shift</kbd> to add) |
|
|
| Middle- or right-drag | Pan |
|
|
| Wheel over a node | Scroll contents that are taller than the node |
|
|
| <kbd>Ctrl</kbd>+wheel | Zoom around the pointer |
|
|
|
|
**Markdown in text nodes**: headings, bold/italic/strikethrough, inline and
|
|
fenced code, quotes, bullet, numbered and task lists, rules, images and links.
|
|
Links are clickable; a link to another `.canvas` file opens it in the editor.
|
|
|
|
**File node previews**: images are rendered inline, text files are previewed as
|
|
Markdown, and a `subpath` such as `#Design` shows just that section of the file.
|
|
Group `background` images are drawn with the fitting their `backgroundStyle`
|
|
asks for (`cover`, `ratio` or `repeat`). Paths are stored relative to the
|
|
canvas, so a canvas plus its files stays portable.
|
|
|
|
**A display text for link nodes**: name a link in the inspector and the canvas
|
|
shows the name instead of the address, with the full URL in its tooltip. It is
|
|
stored as a `label` attribute — the name groups and edges already use — so a
|
|
tool that does not know about it carries it through untouched. This is an
|
|
addition to the format; see [`spec/extensions.md`](spec/extensions.md).
|
|
|
|
**The usual editor comforts**: undo/redo of every change, copy/paste/duplicate,
|
|
grouping, alignment, z-order, a properties inspector, snap-to-grid, light and
|
|
dark themes, and a warning before you lose unsaved work.
|
|
|
|
## Building and running
|
|
|
|
```sh
|
|
cargo run --release # start with an empty canvas
|
|
cargo run --release -- board.canvas
|
|
```
|
|
|
|
The release binary is self-contained:
|
|
|
|
```sh
|
|
cargo build --release # target/release/jsoncanvas-desktop[.exe]
|
|
```
|
|
|
|
* **Windows** — nothing beyond a Rust toolchain (MSVC or GNU).
|
|
* **Linux** — the usual desktop development packages for windowing and
|
|
rendering, e.g. on Debian/Ubuntu:
|
|
|
|
```sh
|
|
sudo apt install build-essential pkg-config libx11-dev libxcursor-dev \
|
|
libxrandr-dev libxi-dev libgl1-mesa-dev libwayland-dev libxkbcommon-dev
|
|
```
|
|
|
|
File dialogs use the XDG desktop portal, so no GTK development packages are
|
|
needed; install `xdg-desktop-portal` and a backend for your desktop if it is
|
|
not already present.
|
|
|
|
Run the tests with `cargo test` (the model, geometry, Markdown and editing logic
|
|
are covered headless — no display required).
|
|
|
|
## Keyboard shortcuts
|
|
|
|
| | |
|
|
| --- | --- |
|
|
| <kbd>Ctrl</kbd>+<kbd>N</kbd> / <kbd>O</kbd> / <kbd>S</kbd> | New, open, save |
|
|
| <kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>S</kbd> | Save as |
|
|
| <kbd>Ctrl</kbd>+<kbd>Z</kbd> / <kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>Z</kbd> | Undo, redo |
|
|
| <kbd>Ctrl</kbd>+<kbd>C</kbd> / <kbd>V</kbd> / <kbd>D</kbd> | Copy, paste, duplicate |
|
|
| <kbd>Ctrl</kbd>+<kbd>A</kbd> | Select everything |
|
|
| <kbd>Ctrl</kbd>+<kbd>G</kbd> | Put the selection in a group |
|
|
| <kbd>Ctrl</kbd>+<kbd>I</kbd> | Show or hide the inspector |
|
|
| <kbd>Delete</kbd> | Delete the selection |
|
|
| <kbd>F2</kbd> | Edit the selected node |
|
|
| <kbd>F</kbd> | Zoom to the selection |
|
|
| <kbd>Escape</kbd> | Stop editing, clear the selection |
|
|
| Arrow keys | Nudge by 1 (<kbd>Shift</kbd>: 10) |
|
|
| <kbd>Ctrl</kbd>+<kbd>0</kbd> / <kbd>1</kbd> | Zoom to fit, actual size |
|
|
|
|
## How it is put together
|
|
|
|
The UI toolkit is [egui](https://github.com/emilk/egui) via `eframe`. An
|
|
infinite canvas is essentially one large custom-painted widget, which is what
|
|
immediate-mode GUI is good at, and it builds to a single binary on both targets
|
|
without a GTK or Qt runtime. Pan and zoom are a transform on a dedicated egui
|
|
layer, so real widgets (the in-place Markdown editor, links) keep working while
|
|
the canvas is scaled.
|
|
|
|
| Module | Responsibility |
|
|
| --- | --- |
|
|
| `model.rs` | The file format: parsing, writing, round-trip fidelity |
|
|
| `document.rs` | Open document: path, dirty state, undo history |
|
|
| `geometry.rs` | Node boxes, edge anchors, Bézier routing, hit testing |
|
|
| `view.rs` | The canvas: painting, selection, and every gesture |
|
|
| `nodes.rs` | Node bodies: Markdown, file previews, links |
|
|
| `markdown.rs` | The Markdown subset used by text nodes |
|
|
| `inspector.rs` | The properties panel |
|
|
| `theme.rs` | Palettes and the six preset colours |
|
|
| `app.rs` | Menus, toolbar, dialogs, file handling, shortcuts |
|
|
|
|
## Licence
|
|
|
|
MIT.
|