Export notes as Markdown or PDF
The reason to build this is not a missing feature — it is that trusting a program you maintain alone with years of notes should not mean the notes can only ever be read by that program. Reachable from a note's toolbar, a notebook's context menu, and Account → Alle Notizen exportieren. Markdown carries over everything with an equivalent: headings, lists, quotes, code, tables, and task state as `- [x]`. A link to another note in the same export becomes a relative link to its file; a link to a note outside it degrades to the plain title rather than leaving a dead reference. Notes with images or a drawing arrive as a ZIP so the files travel along, and a multi-note export gets a README index. PDF goes through the browser's print dialog rather than a bundled PDF library — the browser already has a good one, and it is the only format where drawings sit inside the document. Markdown gets them as a PNG beside the text, with a line saying so, because dropping them silently would be the wrong kind of quiet. Two decisions worth recording: - the ZIP writer is eighty lines here rather than a dependency. Note text is small and images are already compressed, so compression bought nothing, and stored entries are a handful of fixed-layout records. - Markdown escaping only covers what changes meaning mid-line, plus a leading list or heading marker. Escaping every character Markdown ever uses turns a sentence into `Hallo\. Alles gut\!`, which defeats the point of choosing a readable format. 42 unit tests on the serialiser and the archive format, plus a browser suite that unpacks a real download and reads the bytes back. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
311e992496
commit
2611d87f8c
14 files changed
+1707
-2
No files matched your search
@@ -18,6 +18,7 @@ A cross-platform note-taking application with rich text editing, freehand drawin
|
||||
- **PDF Import & Annotation** — Import PDFs, overlay drawing/highlighting, persistent annotations
|
||||
- **Notebooks & Folders** — Create notebooks with custom gradient covers, organize notes by folder
|
||||
- **Star/Favorite** — Quick access to important notes
|
||||
- **Export** — Any note, notebook or the whole account as Markdown or PDF, entirely in the browser
|
||||
- **Dark & Light Mode** — Full theme support with refined color schemes
|
||||
|
||||
### Sync & Storage
|
||||
@@ -57,6 +58,7 @@ inknote/
|
||||
│ │ ├── offlineStore.ts # IndexedDB wrapper
|
||||
│ │ ├── search.ts # Local full-text index
|
||||
│ │ ├── hooks/ # Note data, search, layout, history, drag
|
||||
│ │ ├── export/ # Markdown, ZIP and print-to-PDF
|
||||
│ │ ├── ui/ # Sidebar, dialogs, icons, palette
|
||||
│ │ ├── features/notes/ # List, editor pane, version history
|
||||
│ │ ├── features/notebooks/ # Dashboard
|
||||
@@ -65,6 +67,7 @@ inknote/
|
||||
│ ├── public/sw.js # PWA service worker
|
||||
│ ├── nginx.conf # Static serving + API/WS proxy
|
||||
│ └── dockerfile # Web container
|
||||
├── e2e/ # Browser suites — run with ./e2e/run.sh
|
||||
└── readme.md # This file
|
||||
```
|
||||
|
||||
@@ -329,6 +332,7 @@ docker compose -f docker-compose.dev.yml up -d --build # must be running
|
||||
| `search-attachments` | 12 | body-only matches, ranking, umlauts; images as blob URLs, not inline bytes |
|
||||
| `history` | 10 | a large deletion is snapshotted, restoring works, restoring is itself undoable |
|
||||
| `drawing` | 7 | strokes survive the poller, and match across four viewport widths |
|
||||
| `export` | 12 | the downloaded bytes are real Markdown and a real ZIP, unpacked and read back |
|
||||
|
||||
Each suite creates a throwaway account through the admin API and deletes it
|
||||
afterwards, so runs leave the database as they found it. They need an admin to
|
||||
@@ -475,6 +479,40 @@ rows behind.
|
||||
|
||||
---
|
||||
|
||||
## Export
|
||||
|
||||
Notes should not be hostage to this program, so everything can leave it — from a
|
||||
single note up to every note in the account, reachable from the note's toolbar,
|
||||
a notebook's context menu, and Account → *Alle Notizen exportieren*.
|
||||
|
||||
**Markdown** keeps the notes editable elsewhere. Headings, lists, quotes, code,
|
||||
tables and task state all have equivalents and are carried over; a link to
|
||||
another exported note becomes a relative link to its file, and a link to a note
|
||||
outside the export degrades to its plain title rather than a dead reference.
|
||||
A note with images or a drawing arrives as a ZIP so the files travel with it,
|
||||
and a whole notebook gets a `README.md` index grouped by notebook.
|
||||
|
||||
**PDF** goes through the browser's own print dialog rather than a bundled PDF
|
||||
library — every browser already has a good one behind *Save as PDF*, and it
|
||||
handles fonts and page breaks better than anything that would fit in here. This
|
||||
is the format that keeps drawings inside the document.
|
||||
|
||||
Two things Markdown cannot represent, and what happens instead:
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| drawings | rendered to PNG beside the note, with a line in the text saying so |
|
||||
| underline | written as `<u>`, which every Markdown renderer passes through |
|
||||
|
||||
The ZIP writer is [`export/zip.ts`](frontend/src/export/zip.ts) — about eighty
|
||||
lines for stored (uncompressed) entries, rather than a dependency. Note text is
|
||||
small and images are already compressed, so there was nothing to gain by
|
||||
compressing, and this is one fewer thing to keep updated.
|
||||
|
||||
Everything runs in the browser. Nothing is uploaded anywhere to produce a file.
|
||||
|
||||
---
|
||||
|
||||
## Drawings
|
||||
|
||||
Drawings are **vector strokes**, not bitmaps. Every stroke is recorded in one canonical
|
||||
|
||||
Reference in new issue
Block a user