Rebuild the memo editor as a single CodeMirror 6 "decorated source"
editor. The document is the raw markdown, stored verbatim and styled in
place (markers stay visible), so the editor never serializes a tree back
to markdown — removing the round-trip fidelity bug class (inline images,
setext headings, ordered-list indentation, HTML entities) that the old
editor needed per-case patches for.
- MemoEditor/Editor: CodeMirror 6 + lang-markdown (GFM). Tokens, heading
lines, #tag/@mention, and the autocomplete popover are styled in plain
CSS (Editor/editor.css) with theme tokens, not a CSS-in-JS theme.
- Tab/Shift-Tab nest/outdent list items (marker-aware, ordered items
renumbered so nesting is CommonMark-valid); Escape blurs; #tag
autocomplete sourced from useTagCounts.
- Focus-mode toolbar reimplemented as markdown-text ops; active state read
from the Lezer tree via the backend-agnostic formatting/commands catalog.
- Remove the old serialize-back-to-markdown editor (its Editor dir,
PlainEditor, the editor-mode system) and its now-unused dependencies
(marked, textarea-caret, and the rich-text editor packages).
- Consolidate toolbar components under Toolbar/. Read-only MemoContent
rendering is unchanged.
Behavior-preserving restructure of the MemoEditor subsystem for simplicity
and extensibility:
- Add a data-driven command catalog (editorCommands.ts) as the single source
for formatting verbs; the toolbar, active-state hook, and WYSIWYG handle all
derive from it, so adding a verb is a one-file change.
- Add a createSuggestionExtension factory; TagSuggestion consumes it, so new
`/` or `@` triggers reuse the shared popup in ~10 lines.
- Collapse FormattingController into a single EditorController with an optional
`formatting` capability; PlainEditor is an honest textarea fallback (no faked
formatting); replace stringly-typed isActive with typed getActiveFormats.
- Move audio-recorder state out of the reducer into useAudioRecorder, keeping a
single recorderBusy flag in the store.
- Convert the editor context to an external store (useSyncExternalStore) with
per-slice subscriptions, so typing no longer re-renders the toolbar, insert
menu, or metadata.
- Extract the shared #tag lexing grammar (tag-grammar.ts) used by both the
editor tokenizer and the remark renderer.
- Remove dead reducer actions/cases and fix a preview blob-URL leak on the
upload path.
Add tests for the command catalog, suggestion factory, and autosave.
- Remove shared memo-metadata folder
- Move metadata display components (AttachmentList, LocationDisplay, RelationList) to MemoView/components/metadata
- Move attachment types and utilities (LocalFile, AttachmentItem, toAttachmentItems) to MemoEditor/types/attachment
- Simplify AttachmentList and AttachmentCard to work directly with Attachment proto
- Update all imports across MemoEditor and MemoView components
- Better separation of concerns: MemoView handles display, MemoEditor handles local files + attachments