# Feature: Markdown-Editor Verbesserungen ## Motivation Der Wiki-Editor in Ka-Note basiert auf **Tiptap v3** (ProseMirror). Für Nutzer die primär mit Tastatur und Maus arbeiten fehlten: - Ein schneller Weg in den Edit-Modus (ohne Button-Klick) - Kontextuelle Formatierungshilfe beim Schreiben (Slash-Menü) - Schnell-Formatierung bei Textauswahl (Bubble Menu) Referenz-UI: UpNote (Slash-Menü, mobiler Toolbar-Bereich). --- ## Umgesetzte Features ### 1. Doppelklick → Edit-Modus **Datei:** `ka-note/client/src/routes/wiki/[id]/+page.svelte` Im Read-Modus aktiviert ein Doppelklick auf den Inhaltsbereich oder den Seitentitel den Editor. - Titel (``, Zeile ~118): `ondblclick={() => editing = true}` - Content-Container (`
`, Zeile ~202): `ondblclick={() => editing = true}` + `cursor-text` - Einfacher Klick auf `[[Wikilinks]]` → Navigation (unverändert) - Doppelklick auf Linktext → öffnet Editor (kein Konflikt, da Browser-Doppelklick = Textauswahl, nicht Click-Event auf Anchor) --- ### 2. Slash-Command-Menü (`/`) **Datei:** `ka-note/client/src/lib/editor/tiptapSlashCommand.ts` Tippt man `/` am Zeilenanfang oder nach einem Leerzeichen, erscheint ein Kontext-Menü mit Block-Befehlen. #### Verfügbare Befehle | Icon | Label | Tiptap-Command | |------|-------|----------------| | `H1` | Heading 1 | `toggleHeading({ level: 1 })` | | `H2` | Heading 2 | `toggleHeading({ level: 2 })` | | `H3` | Heading 3 | `toggleHeading({ level: 3 })` | | `•–` | Bullet List | `toggleBulletList()` | | `1.` | Ordered List | `toggleOrderedList()` | | `` `x` `` | Code (inline) | `toggleCode()` | | ` ``` ` | Code Block | `toggleCodeBlock()` | | `❝` | Blockquote | `toggleBlockquote()` | | `⊞` | Table (3×3) | `insertTable({ rows: 3, cols: 3, withHeaderRow: true })` | | `—` | Divider | `setHorizontalRule()` | #### Verhalten - Trigger: `/` nach Whitespace oder am Zeilenanfang - Typing filtert die Liste (Label + Keywords, deutsch + englisch) - Arrow Up/Down → navigieren, Enter → ausführen, Escape → schließen - Mausklick auf Eintrag → ausführen - Vor Ausführung: `/` + getippter Query-Text werden gelöscht (`deleteRange`) - URLs wie `https://example.com` triggern das Menü **nicht** (`:` vor `/` bricht den Scan ab) #### Architektur Exakt das gleiche ProseMirror Plugin-Pattern wie `tiptapMention.ts` und `tiptapWikiLink.ts`: - `Extension.create()` mit `addProseMirrorPlugins()` - Rückwärts-Scan im `update(view)`-Hook - DOM-Dropdown in `.ka-editor-wrapper` (renutzt `.mention-dropdown`/`.mention-item`/`.mention-item-active` aus `mention.css`) - `pointerdown` + `preventDefault()` für Klick-Handling ohne Fokusverlust --- ### 3. Bubble Menu (Textauswahl-Toolbar) **Extension:** `@tiptap/extension-bubble-menu` (Tiptap v3, floating-ui-basiert) Bei Textauswahl erscheint eine Mini-Toolbar mit: | Button | Funktion | |--------|----------| | **B** | Bold toggle | | *I* | Italic toggle | | H2 | Heading 2 toggle | | ↗ | Link setzen/entfernen (`window.prompt`) | - Buttons werden aktiv (blau) wenn der Cursor im entsprechenden Mark/Node sitzt - Verschwindet automatisch wenn Auswahl aufgehoben wird - Nicht aktiv bei Bild-Auswahl (`!e.isActive('image')`) - `onpointerdown` + `preventDefault()` verhindert Fokusverlust im Editor #### Tiptap v3 BubbleMenu API v3 nutzt `@floating-ui/dom` für Positionierung (kein tippy.js mehr). Visibility wird über `element.style.visibility` gesteuert (nicht `display`). Der `element`-Prop erwartet einen DOM-Node — in Svelte via `bind:this={bubbleMenuEl}`. --- ## Neue Tiptap-Extensions (Table) Für das Table-Slash-Command wurden hinzugefügt: - `@tiptap/extension-table` - `@tiptap/extension-table-row` - `@tiptap/extension-table-cell` - `@tiptap/extension-table-header` Konfiguration: `Table.configure({ resizable: false })` **Hinweis:** `tiptap-markdown` v0.9 serialisiert Tabellen als GFM (`| col | col |`). Beim ersten produktiven Einsatz verifizieren dass Round-Trip (Edit → Save → reOpen) korrekt funktioniert. --- ## Geänderte / neue Dateien | Datei | Änderung | |-------|----------| | `client/src/routes/wiki/[id]/+page.svelte` | `ondblclick` auf Titel-Span + Content-Container | | `client/src/lib/components/MarkdownEditor.svelte` | 7 neue Imports, `bubbleMenuEl`-Variable, 6 neue Extensions, Bubble-Menu-Template | | `client/src/lib/editor/tiptapSlashCommand.ts` | Neu — Slash-Command Extension | | `client/src/lib/editor/editor.css` | Neu — Slash-Icon + Bubble-Menu-Styles | --- ## Nicht umgesetzt (bewusste Entscheidung) - **Feste Toolbar**: Passt nicht zum minimalistischen UI-Stil; Bubble Menu ist ausreichend für Desktop - **Mobile Keyboard-Toolbar**: Separates Thema — erfordert `visualViewport`-Handling für iOS; bei Bedarf als eigenes Feature - **Link-inline-Dialog**: `window.prompt` als MVP; langfristig ein kleines Svelte-Popover - **Tabellen-Resize**: `resizable: false` — die Resize-Handles brauchen zusätzliches CSS-Styling --- ## Bekannte Einschränkungen - `/code` (inline) — nach dem Löschen des Slash-Texts gibt es keine Auswahl; das Code-Mark wird als "stored mark" für den nächsten Tipp-Vorgang aktiviert (Tiptap-Standardverhalten) - Bubble Menu Link-Button nutzt `window.prompt` — blockiert kurz den Browser