JSON canvas initial
This commit is contained in:
@@ -12,6 +12,8 @@ Minimal self-hosted personal wiki. Folders are pages.
|
||||
|
||||
- **Wikilinks** link between pages with `[[Page Name]]` syntax. When a page is renamed or moved, all wikilinks pointing to it are rewritten automatically to reflect the new path.
|
||||
|
||||
- **Canvases** an infinite pan/zoom board stored as a [JSON Canvas](https://jsoncanvas.org/) `.canvas` file next to the page's `index.md`. Canvases in a folder appear as tabs above the page content, so a canvas is an alternative *view* of the page rather than a separate document. See the [Canvases](#canvases) section.
|
||||
|
||||
- **Movie import** import movie entries via the OMDb API. Fetches title, year, runtime, genre, director, cast, plot, and poster, and pre-fills a new page with that metadata.
|
||||
|
||||
- **Special folder types** folders can opt into custom rendering (e.g. a photo diary with calendar navigation). See the [Special Folder Types](#special-folder-types) section for details.
|
||||
@@ -106,6 +108,76 @@ They resolve against the year page rather than separate per-day URLs:
|
||||
|
||||
Legacy `YYYY/MM/` and `YYYY/MM/DD/` URLs (no longer the canonical form) redirect to the matching anchor on the year page.
|
||||
|
||||
## Canvases
|
||||
|
||||
A canvas is a `<Name>.canvas` file in a page folder holding a
|
||||
[JSON Canvas 1.0](https://jsoncanvas.org/spec/1.0/) document. Every canvas in a
|
||||
folder renders as a tab above that page's content, and the page itself is the
|
||||
first tab — so a page and its diagrams are one thing with several views.
|
||||
|
||||
| URL | What it does |
|
||||
|------|-------------|
|
||||
| `<page>/?canvas=<Name>` | the canvas view (canonical) |
|
||||
| `<page>/<Name>.canvas` | redirects to the canonical form |
|
||||
| `<page>/<Name>.canvas?raw` | the file itself |
|
||||
|
||||
Create one from the **NEW CANVAS** action or the `+` in the tab strip.
|
||||
|
||||
### Nodes
|
||||
|
||||
All four spec node types render:
|
||||
|
||||
| Type | Rendered as |
|
||||
|------|-------------|
|
||||
| `text` | markdown, rendered server-side — wikilinks, `![[embeds]]`, tables and task lists all behave as they do on a page |
|
||||
| `file` | a transclusion of another wiki path: markdown pages (narrowed to a heading when `subpath` is set), images, video, PDFs |
|
||||
| `link` | a card for an external URL |
|
||||
| `group` | a labelled frame; dragging it carries the nodes inside it |
|
||||
|
||||
Node content is rendered by the server and cached in the browser by *content*,
|
||||
so the whole canvas arrives pre-rendered in the initial page load (no per-node
|
||||
requests) and undo/redo of a text edit costs nothing.
|
||||
|
||||
### Controls
|
||||
|
||||
| Gesture | Action |
|
||||
|---------|--------|
|
||||
| drag background | pan |
|
||||
| ctrl/⌘ + wheel, or pinch | zoom |
|
||||
| shift + drag background | marquee select |
|
||||
| drag a node | move it (snaps to a 20px grid; hold alt to bypass) |
|
||||
| drag a corner handle | resize |
|
||||
| drag a side port | draw an edge to another node |
|
||||
| double-click a node | edit it |
|
||||
| double-click empty space | new text node there |
|
||||
|
||||
Keys: `Ctrl+S` save · `Ctrl+Z` / `Ctrl+Shift+Z` undo/redo · `Del` delete
|
||||
selection · `Ctrl+A` select all · arrows nudge (shift for single pixels) ·
|
||||
`T`/`F`/`L`/`G` add a node · `+`/`-`/`0` zoom, `9` fit · `Esc` cancel.
|
||||
|
||||
Undo covers the whole session; a drag or resize is one entry no matter how many
|
||||
events it spanned.
|
||||
|
||||
### Saving
|
||||
|
||||
Saving is explicit (**SAVE**, or `Ctrl+S`) and uploads the whole document. The
|
||||
server parses and validates it before writing anything, so a malformed payload
|
||||
can never land on disk, and four things are checked in order:
|
||||
|
||||
1. the JSON parses into the spec's shape;
|
||||
2. node ids are unique, every edge endpoint resolves, and enums/colours/sizes are in range;
|
||||
3. the `X-Canvas-Version` token matches the file on disk — a mismatch is a `409` and you are asked whether to reload or overwrite;
|
||||
4. a save that would empty a populated canvas is refused until you confirm it.
|
||||
|
||||
The previous contents are kept beside the file as `.<Name>.canvas.bak`, and the
|
||||
write itself is atomic. Leaving the page with unsaved changes prompts first.
|
||||
|
||||
Moving or renaming a page rewrites the canvases that point at it — both the
|
||||
`[[wikilinks]]` inside text nodes and the paths of file nodes and group
|
||||
backgrounds — the same way it rewrites links in `index.md`.
|
||||
|
||||
Canvas *contents* are not searchable; only the file name is indexed.
|
||||
|
||||
## Quick-Add Bookmarklet
|
||||
|
||||
Replace `wiki.host` with your wiki host and `/Topics/Bookmarks/` with the destination page (one bookmarklet per target):
|
||||
|
||||
Reference in New Issue
Block a user