Wikilink node with autocomplete #46

Closed
opened 2026-07-04 14:52:22 +02:00 by fable-5 · 1 comment
Collaborator

Context

Obsidian-style [[page links]] were confirmed in kickoff as in-scope and fit the vision's relation-tree idea.

Scope

Add the reserved wikilink inline node to the shared schema (attrs: targetSlug, displayText): typing [[ opens an autocomplete popup querying pages of the current pond (title match, create-new-page hint for misses), Enter inserts the node; rendering resolves slug → current title live (phantom targets render dashed with tooltip); click navigates (read mode) / opens edit affordance (edit mode); markdown mapping [[slug|text]] in docToMarkdown/markdownToDoc.

Acceptance criteria

  • autocomplete filters as you type and inserts a working link (e2e)
  • renaming the target page's title updates displayed text where no explicit displayText is set
  • phantom link (nonexistent target) renders distinctly and becomes live once the page is created (after #47)
  • markdown round-trip preserves wikilinks

Technical notes

  • ADR 0004 (reserved node), data-model.md (page_links — indexing is #47).
  • Autocomplete endpoint may reuse the pages list; debounce client-side.

Dependencies

Depends on #24, #25.

Size: ~1.5 days


Conventions: English code/comments, clear human-readable code, no hard-coded UI strings (ADR 0012, add de and en), permission checks only via the shared guard (docs/architecture/permissions.md). Read the referenced ADRs before starting.

## Context Obsidian-style `[[page links]]` were confirmed in kickoff as in-scope and fit the vision's relation-tree idea. ## Scope Add the reserved `wikilink` inline node to the shared schema (attrs: targetSlug, displayText): typing `[[` opens an autocomplete popup querying pages of the current pond (title match, create-new-page hint for misses), Enter inserts the node; rendering resolves slug → current title live (phantom targets render dashed with tooltip); click navigates (read mode) / opens edit affordance (edit mode); markdown mapping `[[slug|text]]` in `docToMarkdown`/`markdownToDoc`. ## Acceptance criteria - [ ] autocomplete filters as you type and inserts a working link (e2e) - [ ] renaming the target page's title updates displayed text where no explicit displayText is set - [ ] phantom link (nonexistent target) renders distinctly and becomes live once the page is created (after #47) - [ ] markdown round-trip preserves wikilinks ## Technical notes - ADR 0004 (reserved node), data-model.md (`page_links` — indexing is #47). - Autocomplete endpoint may reuse the pages list; debounce client-side. ## Dependencies Depends on #24, #25. **Size**: ~1.5 days --- *Conventions: English code/comments, clear human-readable code, no hard-coded UI strings (ADR 0012, add `de` **and** `en`), permission checks only via the shared guard (docs/architecture/permissions.md). Read the referenced ADRs before starting.*
fable-5 added this to the M4 — Organization & search milestone 2026-07-04 14:52:22 +02:00
fable-5 added the
frontend
label 2026-07-04 14:52:22 +02:00
Collaborator

Implemented in 7244b89 (Claude Opus 4.8). Pipeline green (CI incl. the new wikilink browser e2e pack; CD deploy Test → smoke → promote Int).

Verified end to end in a real browser (locally against an isolated full stack, and in CI against deploy-identical code): type [[, the autocomplete filters the pond's pages as you type, Enter inserts a wikilink node that renders the target's current title and is not phantom, and the link survives a reload (persisted through the collab server). Markdown round-trip ([[slug]] / [[slug|text]]) and slug parsing are unit-tested in @dorfteich/shared.

Acceptance criteria

  • autocomplete filters as you type and inserts a working link (e2e)
  • renaming the target page's title updates displayed text where no explicit displayText is set — the NodeView shows displayText ?? resolvedTitle ?? slug, resolving live from the pond's pages (WikilinkContext); the autocomplete inserts with displayText: null so matches auto-resolve.
  • phantom link renders distinctly (dashed + tooltip); becomes live once the page is created — the NodeView resolves against the live pond-pages query, so creating the target flips it from phantom to resolved. (Server-side backlink resolution is #47.)
  • markdown round-trip preserves wikilinks (shared unit tests)

Notes

  • Reserved wikilink inline atom added to the shared editor schema (attrs targetSlug, optional displayText); markdown via a markdown-it inline rule + serializer node; plain-text/HTML derivation include the shown text.
  • [[ autocomplete is dependency-free (no @tiptap/suggestion): a React popup positioned via view.coordsAtPos, with ↑/↓/Enter/Esc intercepted in the capture phase so ProseMirror does not act on them while open. Create-new-page hint inserts a phantom link.
  • Schema fidelity between editor and server decoder holds (existing roundtrip test, now with the wikilink node).

Next M4 issue: #47 (wikilink index, backlinks API, phantom resolution).

Implemented in `7244b89` (Claude Opus 4.8). Pipeline green (CI incl. the new **wikilink** browser e2e pack; CD deploy Test → smoke → promote Int). **Verified** end to end in a real browser (locally against an isolated full stack, and in CI against deploy-identical code): type `[[`, the autocomplete filters the pond's pages as you type, Enter inserts a `wikilink` node that renders the target's current title and is not phantom, and the link survives a reload (persisted through the collab server). Markdown round-trip (`[[slug]]` / `[[slug|text]]`) and slug parsing are unit-tested in `@dorfteich/shared`. **Acceptance criteria** - [x] autocomplete filters as you type and inserts a working link (e2e) - [x] renaming the target page's title updates displayed text where no explicit displayText is set — the NodeView shows `displayText ?? resolvedTitle ?? slug`, resolving live from the pond's pages (`WikilinkContext`); the autocomplete inserts with `displayText: null` so matches auto-resolve. - [x] phantom link renders distinctly (dashed + tooltip); **becomes live once the page is created** — the NodeView resolves against the live pond-pages query, so creating the target flips it from phantom to resolved. (Server-side backlink resolution is #47.) - [x] markdown round-trip preserves wikilinks (shared unit tests) **Notes** - Reserved `wikilink` inline atom added to the shared editor schema (attrs `targetSlug`, optional `displayText`); markdown via a markdown-it inline rule + serializer node; plain-text/HTML derivation include the shown text. - `[[` autocomplete is dependency-free (no `@tiptap/suggestion`): a React popup positioned via `view.coordsAtPos`, with ↑/↓/Enter/Esc intercepted in the capture phase so ProseMirror does not act on them while open. Create-new-page hint inserts a phantom link. - Schema fidelity between editor and server decoder holds (existing roundtrip test, now with the wikilink node). Next M4 issue: #47 (wikilink index, backlinks API, phantom resolution).
Sign in to join this conversation.
No project
No Assignees
2 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: stwaidele/dorfteich#46
No description provided.