Commit Graph

2 Commits

Author SHA1 Message Date
MechaCat02
c259d97f04 Do not let a table be the end of a note
A table, code block, quote or list as the last element of a
contenteditable element is a dead end: there is no node after it to put
the caret in, and no key that makes one, so the note simply cannot be
continued below it. Every engine behaves this way. The editor now keeps
an empty paragraph after such a block — it serializes to nothing, so it
never reaches the file, which a test pins down.

Tables got the rest of what they were missing while the cause was in
view: Tab walks the cells and a Tab out of the last one adds a row, the
toolbar button adds a row when the cursor is already in a table (a phone
has no Tab key, and it renames itself so it says which it will do), and
Ctrl/Cmd+Enter opens a paragraph after whatever block the cursor is in.
Empty cells are given a break, because a `<td></td>` with nothing in it
cannot be clicked into in Gecko — a blank cell was uneditable.

Driven in Firefox against a page that reproduces the dead end first.
2026-09-20 13:06:25 +02:00
MechaCat02
534b1b0f58 Write notes as formatted text, store them as Markdown
The editor was a textarea holding raw Markdown, which is the wrong thing
to hand someone taking notes during a lesson: nobody types `##` and `**`
while a teacher is talking. It now shows the note formatted and puts a
toolbar above it — headings, bold, lists, tick boxes, quotes, links,
tables — while the file on disk stays exactly what it was, because that
is what the indexer reads and what outlives this app.

`markdown.js` is the whole translation: `markdownToHtml` on the way in,
`markdownFromDom` on the way out. The property that matters is that the
round trip settles — one pass may tidy a note, a second must change
nothing — because these notes are the only record of what was said in
the room and there is nothing to restore a lossy save from. `editor.js`
checks exactly that before opening a note formatted, and a note it
cannot hold unchanged opens in the Markdown view and says so instead of
being quietly reduced.

No editor library: the content security policy allows no outside script
and the app has no bundler, so this is `contenteditable` and
`execCommand` with a tolerant serializer behind it — an element it does
not model keeps its words and loses its tag. Pasted HTML is converted to
Markdown before it reaches the document, which is the one place where
sanitising and formatting are the same operation.

Tested against `test/mini-dom.ts`, sixty lines of read-only DOM, rather
than a headless browser or a DOM dependency; the toolbar itself was
driven by hand in Firefox. WebKit has still never run it.
2026-09-19 21:24:42 +02:00