diff --git a/CLAUDE.md b/CLAUDE.md index 0fcbed6..bc10949 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -125,7 +125,11 @@ bin/cli.ts ──HTTP──────────┘ cli/{config,client,sync hit would read "my note, Monday" and "what did we do in Deutsch" would match a note whose other five lessons were something else. The files are the truth and the index is a view of them, so `list_notes`/`get_note` read disk and answer - before the first crawl and while Postgres is down. **The one thing anything + before the first crawl and while Postgres is down. `searchNotes` is full + text over those same files, behind `/api/notes/search` and the app's Suche + tab: notes reach the index only on a **full** crawl, so anything written + this week would be missing from it, and the app is exactly where "I wrote + that this morning" is the common case. **The one thing anything here writes** — see Invariants. `docs/NOTES.md` is the guide. - **`untis-history.ts`** — the class register read backwards, which is what puts "what did we actually cover" into the search index. Its whole reason @@ -163,7 +167,11 @@ bin/cli.ts ──HTTP──────────┘ cli/{config,client,sync it against `test/mini-dom.ts`, ~60 lines of read-only DOM, because losing a lesson's notes to a lossy serializer is not a bug anyone can recover from. Pasted HTML goes through Markdown before it reaches the document, which is - where sanitising and formatting are the same operation. + where sanitising and formatting are the same operation. **An element holding + blocks is a block, whatever its tag, and a container's style is not + emphasis** — WebKit wraps a copied selection in one span carrying the computed + style of everything in it, so reading that span as inline made a whole pasted + Apple note bold and flattened it into one paragraph. - **`http/web-auth.ts`** — the app's login, which is a different kind of credential from everything else here: a password a person types, not a token a program was configured with. scrypt at startup, a signed `HttpOnly` / diff --git a/README.md b/README.md index b81de63..6387233 100644 --- a/README.md +++ b/README.md @@ -86,6 +86,10 @@ teachers, rooms, cancellations dropped and substitutions marked. Each heading is indexed as its own lesson, so a search answers "my own note, Deutsch, 18.09.2026" rather than "Friday". +A **Suche** tab searches your own notes straight from the files — no crawl in +between, so a lesson written this morning is findable this morning — and a +result names the lesson it matched in rather than the day. + Writing is **formatted, not Markdown**: headings, bold, lists, tick boxes, quotes, links and tables come from a toolbar, and `MD` shows the Markdown underneath when you want it. The file on disk stays Markdown either way — that diff --git a/docs/NOTES.md b/docs/NOTES.md index f08e930..e2789cf 100644 --- a/docs/NOTES.md +++ b/docs/NOTES.md @@ -105,11 +105,19 @@ tables as tables — and the toolbar above it writes the Markdown. Nobody types | `🔗` `▦` | a link (`Strg`/`Cmd` + K) and a table | | `MD` | the Markdown itself | -`Enter` starts a new paragraph, `Shift+Enter` a new line in the same one. A -paste from a web page or a PDF keeps its structure and loses its fonts, colours -and anything else that is not in the list above — pasted HTML is converted to -Markdown before it reaches the page, which is what keeps a copied page from -bringing its script along. +`Enter` starts a new paragraph, `Shift+Enter` a new line in the same one. In a +table, `Tab` walks the cells and a `Tab` out of the last one adds a row; +`Ctrl`/`Cmd`+`Enter` opens a paragraph after whatever block you are in. + +A paste from a web page, a PDF or Apple Notes keeps its structure and loses its +fonts, colours and anything else that is not in the list above — pasted HTML is +converted to Markdown before it reaches the page, which is what keeps a copied +page from bringing its script along. **A copy from Apple Notes arrives wrapped +in one span carrying the computed style of everything in it**, `font-weight: +700` included; that wrapper is a container, not emphasis, and the blocks inside +it are blocks. Reading it the other way made a whole pasted note bold and +flattened every line into one paragraph, which is the failure +`test/app-markdown.test.ts` now pins down. **The file is still Markdown.** `MD` shows it and lets you edit it directly, which is the way to write something the toolbar has no button for. There is no @@ -122,6 +130,28 @@ so rather than being quietly reduced. `test/app-markdown.test.ts` is what holds that promise up: every construct in this document goes in and comes back out unchanged. +### Suche — the notes themselves + +The **Suche** tab searches your own notes and nothing else. Every word has to +appear, in any order, ignoring case and accents; there is no stemming, so +*Argument* does not find *Argumente*. + +A result names the **lesson**, not the day — `1. LF10 — 08:00–08:45` with the +date beside it — because a day note holds five or six lessons and "Freitag" says +nothing about which one matched. Tapping a day note opens it in the editor; +anything else, such as a note from the Apple Notes import, opens read-only, +since the editor is day-shaped and those notes have no day. + +It reads the **files**, not the index. That is the point: notes reach the +Postgres index only on a full crawl, so a lesson written this morning would not +be there, and "what did I write this week" is most of what anyone searches their +own notes for. A few hundred small files answer instantly, and it keeps working +while Postgres is down — the same reason `list_notes` reads disk. + +The `search` tool in Claude is the other half: it spans the Schulcloud material +and the WebUntis class register as well, at the cost of being only as fresh as +the last crawl. + **Einstellungen** holds the Schulcloud token: how long it has left, and the box to paste a fresh `jwt` cookie into when it expires (the same thing `schulcloud token set` and the older `/token` page do). It also shows the index's state and diff --git a/scripts/smoke.mjs b/scripts/smoke.mjs index cbdc422..a009990 100644 --- a/scripts/smoke.mjs +++ b/scripts/smoke.mjs @@ -740,7 +740,9 @@ console.log('\n== web app =='); ); check( 'the shell loads the app as a module, so its imports resolve', - /