Task-Checkboxen tragen in beiden Renderpfaden einen Namen: docToHtml
setzt aria-label aus dem Aufgabentext, die Editor-NodeView ebenso. Die
NodeView rendert ihr Host-Element jetzt selbst als li (ReactNodeView-
Renderer as/attrs) — TipTaps zusätzliches div-Host-Element zwischen ul
und li brach die Listensemantik; der Wrapper flacht per display:contents
ab, die #137-Pixel-Abstimmung bleibt erhalten (Selektor auf die neue
Tiefe nachgeführt, Ausrichtung nachgemessen: 1px-Versatz unverändert).
Der Wissensgraph-SVG bekommt ein beschreibendes aria-label inklusive
Verweis auf die Backlinks als gleichwertige Listenform. Der
Bild-Alt-Editor existierte bereits (Bild-Controls bei Auswahl) — kein
Änderungsbedarf. Hinweis: gecachte Seiten übernehmen das
Checkbox-Label wie bei jeder docToHtml-Änderung erst mit dem nächsten
Persist ihrer Inhalte.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AGM8jo3hwoV9wsCVGfy8iq
The content-cache renderer (docToHtml) emitted wikilinks without an
href, so on the read-only public page view they rendered as styled but
unclickable text. Emit href="<slug>" — relative to the current page URL,
it resolves to the sibling page under both /public/<pond>/… and the
in-app /p/<pond>/… version-history preview, without the renderer needing
pond context. Slugs are [a-z0-9-], safe as a bare path segment.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EwZ4jR4KFAPvpjWevfUGX1
The powerful end of the plugin spectrum (ADR 0008 extension point `block`):
- Shared schema: the reserved `plugin_block` node — a block atom carrying
pluginId, blockType, and the block data as a JSON object. Its DOM shape
round-trips the full state in data attributes (clipboard-safe), markdown
maps to a reserved fence (```dorfteich-plugin <plugin>/<type> + data
JSON body, fence-escalated when the payload contains backticks), and the
content-cache HTML renders a data-carrying neutral placeholder until the
export fallbacks land (#79).
- Editor: a React NodeView hosts the #73 sandbox — render lifecycle on
mount, an edit affordance switching the frame to the plugin's edit mode,
and the blockData capability persisting through node attrs (a normal
editor transaction, so Yjs replicates it; writes are refused on read-only
editors, and the plugin's own attr echo is suppressed so its edit UI
never resets mid-typing). Collaborator changes re-invoke the current
lifecycle, keeping frames live. The page surface (ids, openPage) flows
through a React context like the wikilink pattern; the toolbar gets an
insert picker fed from the active code plugins' block extension points.
- Fallback: GET /plugins/:id/fallback resolves the manifest fallback from
the stored snapshot — it survives uninstall as a tombstone, image
fallbacks degrade to neutral once assets are gone. Signed-in only.
- e2e plugin-blocks.spec.ts covers all four acceptance criteria: insert →
edit → reload round-trip, live two-user collab, disable → fallback →
re-enable without document mutation, and copy/paste within and across
pages (the markdown clipboard carries the reserved fence).
getBlock (cross-page block embedding) stays deferred as in #74: the
schema has no per-block ids yet.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EwZ4jR4KFAPvpjWevfUGX1
The #24 commit passed ESLint but not the repo's Prettier check (pnpm
lint runs both) — CI caught it after the push. Formatting only, no
behavior change.
ProseMirror schema (headings 1-4, lists incl. task lists, blockquote,
code block, tables via prosemirror-tables, images, hard breaks; bold/
italic/code/strikethrough/link marks) plus docToMarkdown, markdownToDoc,
docToPlainText, docToHtml, and extractOutline built on it. Markdown
parsing extends markdown-it's default preset with a token-stream
transform for GFM task lists and table-cell paragraph wrapping.
docToHtml hand-rolls escaping and link-protocol allowlisting with zero
DOM dependencies, so it runs in the API/collab server as well as the
browser.
Node names `wikilink` and `plugin_block` are reserved for later stories.
Closes#24