Commit Graph

706 Commits

Author SHA1 Message Date
Test
d07a592750 Merge remote-tracking branch 'origin/main' into task/image-drop-overlay-fix
# Conflicts:
#	tests/smoke/changing-type-data-corruption.spec.ts
#	tests/smoke/fix-note-filename-on-rename.spec.ts
#	tests/smoke/move-note-to-type-folder.spec.ts
2026-03-17 13:55:34 +01:00
Test
412a1e02c7 fix: resolve demo vault path relative to project root — fix smoke test failures
DEFAULT_VAULTS was hard-coded to the main repo path, causing the Vault API
to read stale/duplicate files when running from worktrees. Now uses Vite's
define to inject the correct path at build time. Also fix theme heading
titles (remove redundant "Theme" suffix) and make smoke tests resilient
to Theme-type notes appearing first in the note list.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 13:14:56 +01:00
Test
6dc6b5e515 refactor: improve code health for vault/mod.rs and Editor.tsx — fix CodeScene hotspot score
Extract scan_vault helpers (is_md_file, try_parse_md, scan_root_md_files, scan_protected_folders)
to eliminate deep nesting and reduce cyclomatic complexity. Break up large assertion blocks in tests.
Extract useEditorSetup and useRawModeWithFlush hooks from Editor component to reduce complexity.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 12:07:33 +01:00
Test
fa49251459 feat: persist editor mode (raw/preview) across note switches
Editor mode is now stored as a global preference in VaultConfig instead of
being tracked per-tab. Toggling raw mode persists across tab switches and
app restarts via the editor_mode field in config/ui.config.md.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 11:41:35 +01:00
Test
97513929a3 refactor: extract welcome/loading screens in App.tsx — reduce main component complexity 2026-03-17 07:16:49 +01:00
Test
19bbba9a27 test: add unit tests for useNoteCreation and useNoteRename hooks
39 tests for useNoteCreation covering creation, daily notes, templates,
optimistic revert, and unsaved cleanup. 12 tests for useNoteRename
covering rename operations, toast messages, and error handling.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 23:52:42 +01:00
Test
4d13212ff5 refactor: extract frontmatterOps, update imports for useNoteCreation/useNoteRename split
useNoteActions.ts reduced from 213 to 125 lines by extracting frontmatter
helpers into frontmatterOps.ts and removing re-exports. Consumers now
import directly from the extracted modules.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 23:52:42 +01:00
Test
389424ff84 refactor: split NoteList.tsx god component into focused modules
Extract 7 sub-modules under components/note-list/:
- PinnedCard.tsx, RelationshipGroupSection.tsx, TrashWarningBanner.tsx
- NoteListHeader.tsx, NoteListViews.tsx
- noteListHooks.ts, noteListUtils.ts

NoteList.tsx reduced from 579 → 95 lines. No behavior changes.
All 2152 unit tests pass, 80%+ coverage, lint + typecheck clean.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 19:36:00 +01:00
Test
3f5ac7a9a9 refactor: split useNoteActions into useNoteCreation + useNoteRename — CodeScene 7.92→9.38
Extract note creation (CRUD, daily notes, types, optimistic persistence) into
useNoteCreation and rename operations into useNoteRename. useNoteActions now
composes both hooks plus frontmatter/navigation logic.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 18:31:33 +01:00
Test
08668854b9 fix: flat vault type resolution — remove type/ prefix from links and protected folders
- Type relationship links: [[type/essay]] → [[essay]] (matches flat vault structure)
- PROTECTED_FOLDERS / KEEP_FOLDERS: only attachments, _themes, assets
- TypeSelector navigation: type/slug → slug
- Updated all 14 affected test files
- All 612 Rust tests + 2151 frontend tests pass
2026-03-16 16:19:24 +01:00
Luca Rossi
5a081b06d4 refactor: split DynamicPropertiesPanel into focused sub-components — reduce 699-line catch-all (#197)
Extract PropertyValueCells, TypeSelector, and AddPropertyForm into dedicated
files. Move shared display-mode constants to utils/propertyTypes to satisfy
react-refresh lint rule. All tests pass, no behavior change.

Co-authored-by: Test <test@test.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 07:25:40 +01:00
Test
6a30016e6b fix: correct reloadVault type in useFlatVaultMigration
Accept Promise<unknown> instead of Promise<void> to match the actual
reloadVault return type (Promise<VaultEntry[]>).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 05:06:24 +01:00
Test
6237efe02f feat: add migration wizard for flat vault
On vault load, detects files in non-protected subfolders via
vault_health_check. Shows an amber banner offering to flatten them
to the vault root. After migration, reloads the vault automatically.
The banner can be dismissed without migrating.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 05:06:24 +01:00
Test
aad863ebe3 feat: add dedicated TitleField above editor
Adds a TitleField component between the breadcrumb bar and BlockNote
editor that serves as the primary title editing surface. The H1 block
inside BlockNote is hidden via CSS. The title field:
- Shows the note title in a prominent input field
- Displays the expected filename when it differs from the current one
- Triggers onTitleSync on blur/Enter to rename the file
- Responds to laputa:focus-editor selectTitle events for new notes
- Reverts on Escape or empty input

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 05:06:24 +01:00
Test
38021d231d refactor: reorder wikilink resolution for flat vault
Multi-pass resolution now prioritizes filename stem (strongest) over
alias over title. Removes path-based matching (e.path.endsWith). Legacy
path-style targets like "person/alice" still work by extracting the
last segment "alice" and matching by filename/title.

This matches the flat vault convention where filename IS the note's
identity — filename stem is always slugify(title).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 05:06:24 +01:00
Test
23b632ac9f fix: fall back to sub-heading text when snippet has no paragraph content
Notes with only headings/rules after H1 (e.g. project templates, daily
notes) previously showed empty snippets. Now extract_snippet collects
sub-heading text as fallback. Also hides the snippet div when empty to
avoid blank gaps in the note list. Bumps cache version to 8 for rescan.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 04:42:31 +01:00
Test
5cfc80dad5 fix: render deleted notes banner outside Virtuoso for proper visibility
The banner is now rendered as a flex sibling below the list container,
ensuring it displays correctly in both unit tests (JSDOM) and real
browsers (Playwright/Chromium).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 03:55:52 +01:00
Test
298c82b9b8 feat: show deleted notes in Changes view
When notes are permanently deleted, the Changes note list now shows a
"N notes deleted" banner so the counter matches the visible list items.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 03:42:40 +01:00
Test
ee556aa004 fix: strip list markers from snippets + bump cache version for full rescan
Snippet extraction was including raw list markers (* , - , + , 1. ) in
the preview text, producing ugly leading spaces. Notes whose snippets
were cached before this fix showed stale/incorrect previews.

- Add strip_list_marker() in both Rust and TS to remove bullet/ordered
  list prefixes before snippet assembly
- Trim final snippet to remove leading/trailing whitespace
- Bump CACHE_VERSION 6 → 7 to force full rescan on next vault load,
  ensuring all entries get clean snippets
- Add Rust + Vitest tests for list marker stripping
- Update Playwright smoke test with stricter snippet assertions

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 03:14:58 +01:00
Test
8684b36bba fix: prevent crash when creating note from relationship input
Root cause: handleCreateNoteForRelationship used `await persistNewNote()`
which forced an early React flush. The subsequent frontmatter update
(onAdd/onAddProperty) triggered setTabs in a microtask that collided with
the render batch, causing a radix-ui infinite setState loop
("Maximum update depth exceeded") and a blank white screen.

Two fixes applied:
1. Make handleCreateNoteForRelationship synchronous (fire-and-forget
   persistence) to keep all state updates batched — mirrors the working
   handleCreateNoteImmediate pattern.
2. Defer onAdd/onAddProperty via setTimeout(0) so the frontmatter update
   runs after the tab-switch render completes, avoiding the radix-ui
   ref composition loop.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 02:23:45 +01:00
Test
b03173058c fix: force WebKit reflow for pseudo-elements on theme CSS var changes
WKWebView doesn't auto-invalidate ::before/::after styles when CSS custom
properties change on document.documentElement. Add `void root.offsetHeight`
to force reflow. Also add a version counter in useThemeApplier to prevent
stale async fetches from overwriting live-reload CSS vars.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 01:24:31 +01:00
Test
b3126044e8 refactor: flatten vault structure — simplify migration API and flatten demo vault
- Simplify flatten_vault API to return usize instead of MigrationResult struct
- Add KEEP_FOLDERS: attachments/ and _themes/ alongside type/, config/, theme/
- Use HashSet for collision tracking in unique_filename
- Update wikilinks from path-based [[folder/slug]] to title-based [[slug]]
- Clean up empty directories after flattening
- Flatten demo-vault-v2: move all notes from type-based subfolders to root
- Update smoke tests for flat vault structure
- Remove migrate_to_flat_vault from repair_vault (one-time migration only)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 23:40:47 +01:00
Test
fc1826b0e2 fix: disable Tauri native drag-drop to unblock HTML5 DnD (tabs, blocks)
Root cause: Tauri's dragDropEnabled (default: true) intercepts drag events
at the webview level, preventing HTML5 DnD from working for tab reorder
and BlockNote block handle drag. Setting dragDropEnabled: false lets all
drag events flow through the standard DOM API.

Image drops now use the HTML5 drop handler + uploadImageFile (same as
paste-upload) instead of Tauri's onDragDropEvent + copyImageToVault.
Removed the useInternalDragFlag workaround and padding hack.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 22:37:12 +01:00
Test
698c4cece1 fix: prevent image drop overlay from breaking internal DnD and block handle
Three fixes for the image drop overlay interference:

1. Block handle clipping: Add padding (0 4px) to editor container so
   BlockNote's side menu (42px) fits within the overflow clip edge.
   overflow-y:auto forces overflow-x:auto (CSS spec), which was clipping
   the menu 2px past the container's left boundary.

2. Block handle click interference: Extract isInteractiveTarget() to
   exclude .bn-side-menu from handleContainerClick — prevents the
   container from stealing focus when clicking drag handle or add button.

3. Internal drag isolation: Track document-level dragstart/dragend to
   flag internal HTML5 drags (tabs, blocks). Tauri onDragDropEvent
   handler skips entirely during internal drags to prevent interference.
   Extract useInternalDragFlag() and handleTauriDrop() to keep
   useImageDrop under CodeScene complexity threshold.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 21:38:37 +01:00
Test
b2bb7cf661 feat: title = filename — wikilink resolution + slug collision detection
- Wikilink resolution order: filename stem (primary) → alias → title (fallback)
- Slug collision detection: auto-suffix (-2, -3, etc.) on note creation
- Add slugCollides utility for frontend collision checking
- resolveNewNote accepts entries param for collision-aware creation
- Title editing via H1 heading already triggers file rename (existing flow)
- Update docs/ARCHITECTURE.md with migrate_to_flat_vault command

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 19:50:22 +01:00
Test
112f68c66d feat: flatten vault structure — remove type-based folders
- scan_vault now scans root + system folders (type/, config/, theme/) only
- Type determined purely by frontmatter, no folder inference
- Remove move_note_to_type_folder (Rust command + frontend logic)
- Remove TYPE_FOLDER_MAP — new notes created at vault root
- Add migrate_to_flat_vault command (moves subfolder notes to root,
  updates path-based wikilinks to title-based, cleans empty dirs)
- Migration runs automatically via Cmd+K > Repair Vault
- Update getting_started sample files for flat structure
- Update all tests (611 cargo + 2131 vitest passing)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 19:43:00 +01:00
Luca Rossi
66090688f9 refactor: extract useLayoutPanels hook from App.tsx — reduce god component churn (#195) (#196)
Co-authored-by: Test <test@test.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 07:11:31 +01:00
Luca Rossi
a15f36ec6a refactor: extract useAppNavigation hook from App.tsx — reduce god component churn (#194)
Co-authored-by: Test <test@test.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 07:24:46 +01:00
Luca Rossi
8137125569 refactor: extract useDeleteActions hook from App.tsx — reduce churn surface (#193)
Extract delete/trash management logic (deleteNoteFromDisk, handleDeleteNote,
handleBulkDeletePermanently, handleEmptyTrash, trashedCount, confirmDelete state)
into a focused useDeleteActions hook. Reduces App.tsx from 733 to 672 lines.

Co-authored-by: Test <test@test.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 06:28:19 +01:00
Luca Rossi
9891a29f7f test: extract useBulkActions hook and add unit tests (#192)
useBulkActions was embedded in App.tsx with zero test coverage. It handles
bulk archive, trash, and restore operations — all with partial-failure
semantics and toast messaging.

Extract to src/hooks/useBulkActions.ts and add 15 unit tests covering:
- Plural/singular toast messages ("2 notes archived" vs "1 note archived")
- Partial failures: only successful operations counted in toast
- All-failure case: no toast shown
- Empty array: no operations called, no toast

Risk mitigated: silent bugs in batch operations (wrong count in toast,
toast shown when nothing succeeded, partial failure not handled).

Co-authored-by: Test <test@test.com>
2026-03-12 03:19:32 +01:00
Luca Rossi
6c9b39c0f0 test: add useEditorSaveWithLinks tests, remove dead useDropdownKeyboard (#191)
Co-authored-by: Test <test@test.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-03-12 03:01:39 +01:00
Test
70f984c399 feat: add Playwright smoke tests, data-tab-path attr, store full VaultEntry in closed tab history
- Refactor useClosedTabHistory to store full VaultEntry (not stub) for reliable reopening
- Add data-tab-path attribute to TabItem for precise Playwright selectors
- Add 2 Playwright smoke tests: single close/reopen and empty-history no-op
- Update ARCHITECTURE.md and ABSTRACTIONS.md with closed tab history docs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 00:54:48 +01:00
Test
0d6cce1588 feat: add Cmd+Shift+T shortcut, menu item, and full wiring
Add "Reopen Closed Tab" to File menu with CmdOrCtrl+Shift+T accelerator.
Wire onReopenClosedTab through useAppKeyboard, useMenuEvents,
useAppCommands, and App.tsx.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 00:54:48 +01:00
Test
73278f3baf feat: add closed tab history and reopen-closed-tab support
Introduce useClosedTabHistory hook (LIFO stack, 20-entry cap, dedup)
and integrate it into useTabManagement so handleCloseTab records entries
and handleReopenClosedTab pops them to reopen at original position.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 00:54:23 +01:00
Test
61a145c49b feat: add Empty Trash menu bar item and Playwright smoke test
Add "Empty Trash…" to the Note menu for discoverability and wire
the menu event through useMenuEvents. Add comprehensive Playwright
smoke test covering trash view navigation, Empty Trash button and
command, confirmation dialog, bulk selection context, and trashed
note banner.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 00:33:44 +01:00
Test
9a7369c799 feat: trash management — bulk restore, delete permanently, empty trash
- Add ConfirmDeleteDialog for permanent deletion confirmation
- Update BulkActionBar to show contextual actions (Restore/Delete permanently
  in trash view, Archive/Trash elsewhere)
- Add Empty Trash button in note list header when viewing trash
- Add Empty Trash command to Cmd+K palette
- Add bulk restore, bulk delete permanently, and empty trash handlers
- All permanent deletions require confirmation dialog
- Update mock handlers for batch_delete_notes and empty_trash

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 00:33:44 +01:00
Test
c158cbccff fix: make empty space below editor content clickable to focus editor
Clicking anywhere in the editor container (including empty space below the
last block) now focuses the editor and places the cursor at the end of the
last block. This matches the behavior of Notion, Bear, and Obsidian.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 00:18:58 +01:00
Test
8a48c21445 test: add Playwright smoke test for theme properties defaults
Validates that all 140 CSS custom properties from the expanded
DEFAULT_VAULT_THEME_VARS are applied to the DOM when a theme is
activated, including editor, heading, list, checkbox, inline-style,
code-block, blockquote, table, and horizontal-rule properties.

Also updates mock content and handlers to use the full 140-property
frontmatter, matching the Rust backend output.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 23:28:24 +01:00
Test
7c72494efb fix: write all theme.json defaults to vault theme frontmatter
Previously, only UI chrome colours and 3 editor vars were written to
theme note frontmatter. CSS vars like --lists-bullet-size, --headings-h1-font-size,
etc. remained unset, so EditorTheme.css rules had no effect.

- Expand DEFAULT_VAULT_THEME_VARS from 46 to 140 entries, covering every
  property from theme.json (editor, headings, lists, checkboxes, inline
  styles, code blocks, blockquote, table, horizontal rule, colors)
- Fix missing px suffix on editor-font-size and editor-max-width
- Add missing semantic vars: bg-card, text-tertiary
- Refactor built-in vault themes from const strings to generated functions
  with per-theme colour overrides (DRY, all themes get editor properties)
- Quote var() references in frontmatter to prevent YAML parse issues
- Add regression tests for create_vault_theme and seed_vault_themes

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 23:28:23 +01:00
Test
55519e53ad fix: update note list snippet on save so all notes show preview
The snippet was extracted once at vault load time (Rust backend) and
never updated when content was saved. Notes created or edited during
a session showed stale/empty snippets until the next app restart.

Added extractSnippet() to the frontend (mirroring Rust logic) and
wired it into useEditorSaveWithLinks so snippet + wordCount are
updated alongside outgoingLinks on every save.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 22:38:25 +01:00
Test
fafa4e394b fix: sync raw editor (CodeMirror) content to BlockNote on mode switch
When toggling from raw mode back to BlockNote, the editor now correctly
re-parses content from tab.content instead of using stale cached blocks.

Key changes:
- useEditorTabSwap: detect rawMode true→false transition, invalidate
  block cache, and re-parse from tab.content. Added rawSwapPendingRef
  guard to prevent a second effect run from re-caching stale blocks
  before the deferred doSwap microtask runs.
- useRawMode: added onBeforeRawEnd callback to flush debounced raw
  editor content synchronously before toggling off.
- Editor.tsx: wired rawLatestContentRef and handleBeforeRawEnd to
  ensure the latest raw content reaches tab.content before the swap.
- RawEditorView: exposed latestContentRef so parent can read the
  latest keystroke content without waiting for the 500ms debounce.
- EditorContent: threaded rawLatestContentRef through to RawEditorView.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 22:14:20 +01:00
Test
ab02aa5e96 feat: wire create-open relationship note to all panel contexts 2026-03-11 21:25:20 +01:00
Test
4dd27cf0c3 feat: add 'Create & open' option to relationship input dropdowns
When typing a non-existent note title in the relationship target input,
a 'Create & open' option now appears at the bottom of the dropdown.
Selecting it creates the note, adds the wikilink, and opens the new note.

- Added SearchDropdownWithCreate with create option
- Modified InlineAddNote and NoteTargetInput to support create flow
- Added onCreateAndOpenNote prop to DynamicRelationshipsPanel
- Keyboard accessible (arrow keys + Enter)
- 6 new tests covering create-and-open behavior

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 21:25:20 +01:00
Test
c499ef30f0 fix: case-insensitive type entry lookup + Playwright smoke test
buildTypeEntryMap now stores both original title and lowercase key so
isA: 'config' matches type entry titled 'Config'. Adds Playwright smoke
test that blocks the vault API to test against mock data fixtures.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 21:24:51 +01:00
Test
b3bf2bf76e fix: sidebar section header reflects type icon, color, and label
- Add GearSix icon ('gear-six') to icon registry — was missing, causing
  Config type to show FileText fallback instead of its configured icon
- Add 'gray' to ACCENT_COLORS palette with CSS variables — was missing,
  causing Config type color to fall back to muted foreground
- Extract sidebar section logic to utils/sidebarSections.ts for testability
- Add Config type + instance to mock entries for browser dev mode
- Add tests: icon resolution, gray color, sidebar section builder

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 21:24:51 +01:00
Test
13622bc236 test: add real filesystem vault integration tests
Replace mock vault approach with real filesystem I/O for integration
tests. Each test copies tests/fixtures/test-vault/ to a temp directory,
overrides mock handlers to point at it, and verifies actual file
operations through the vite dev server middleware.

Tests cover: vault loading, archive/trash filtering, note creation,
rename with filesystem update, wikilink cascade on rename, relationship
display, and real file content loading.

Also extends vite.config.ts vault API middleware with write endpoints
(save, rename, delete, search, entry) and fixes getBool to handle
YAML 1.2 string values like "Yes"/"yes" (js-yaml 4.x compatibility).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 21:24:44 +01:00
Test
75ca18d4d0 test: unit tests for rename-wikilink-update feature
- handleRenameNote passes entry title as old_title to Rust
- handleUpdateFrontmatter triggers rename on title key change
- non-title keys don't trigger rename
- null old_title when entry not found

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 19:47:46 +01:00
Test
47c408dc50 feat: wire H1 sync and frontmatter title change to full rename flow
handleTitleSync now saves pending content and calls rename_note
(which renames the file and updates wikilinks) instead of only
updating in-memory state. handleUpdateFrontmatter also triggers
rename when the title: key is changed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 19:47:46 +01:00
Test
0ee6e76d10 fix: post-process BlockNote serializer to remove extra blank lines
blocksToMarkdownLossy() inserts blank lines between every block, making
tight lists loose and polluting git history. Add compactMarkdown() that
collapses inter-list-item blanks and excessive blank line runs while
preserving code blocks and intentional paragraph spacing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 19:38:05 +01:00
Test
61760c4a41 fix: unify wikilink resolution and disambiguate duplicate titles
- Create resolveEntry() in wikilink.ts: single case-insensitive resolution
  function that handles title, alias, filename stem, path suffix, and
  pipe syntax matching
- Replace findEntryByTarget (case-sensitive) and entryMatchesTarget
  (hardcoded /Laputa/ path) with unified resolveEntry
- Fix attachClickHandlers to insert path|title pipe syntax when multiple
  candidates share the same title (disambiguation)
- Update ai-context.ts resolveTarget to use unified resolution
- Add comprehensive tests for resolveEntry and disambiguation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 19:12:05 +01:00