Register BASIC with highlight.js (preview mode) and add it to the
code modal language picker. CodeMirror falls back to plain text in
the modal editor as no CM6 BASIC parser is available.
Use the shared title sanitizer for both SSR and client-side title editing
so note titles are cleaned by one function. Also sanitize note titles on
create in the fragments route and add a regression test for formatted
titles.
syncResponsiveMode already called redrawMobileUI() when crossing
desktop→mobile, but the reverse path only hid the mobile app. A session
that started narrow (mobile mode) never called initNavPanel/initEditorPanel
for the desktop form, leaving the preview and CM host with undefined
display states and stale scroll position.
Mirror the pattern: save wasMobile before clobbering _lastSyncWasMobile,
then call initNavPanel()+initEditorPanel() when wasMobile===true.
Both functions are idempotent (guarded by dataset flags) so a repeat
call on an already-initialised form is a no-op.
- Install markdown-it@14.1.1 as server-side renderer (renderMarkdown only)
- Preserve all Joplin extensions: underline (++..++), checkboxes,
blank-line markers, softbreak→<br>, resource URIs, spellcheck attrs,
hx-* strip, fence/code/image/link render overrides
- Fix blank-line round-trip: emptyDiv/emptyP Turndown rules now return
the BL sentinel instead of '<br>' (which line 611 inflated to 4 newlines)
or '' (which made blank-line edits never save)
- Disable CSS scroll anchoring in preview editor so images flow down
naturally when text is typed above them
- Narrow the Notebook + button label and padding in the nav header
- Bump static asset version to 20260501a
Eliminates fragile ad-hoc DOM toggling that allowed two mobile screens to
render simultaneously. All transitions now go through setMobileState()
reducer; renderMobile() is the only function that writes
.mobile-screen-active. assertSingleActiveScreen() self-heals violations
and traces them. Test asserts the architectural invariant in source.
Also: DB session lookup fails closed on transient errors instead of
crashing; mobile back-save uses formHash (not UI badge); single-screen
CSS via display:none/flex (no transforms); resize debounced without
reload; aria-hidden warning fix.
- Add DB index on (owner_id, jop_type, jop_parent_id, jop_updated_time DESC)
- New folderNoteCountsByUserId query: GROUP BY folder, no row data fetched
- New noteHeadersByFolder query: paginated per folder (LIMIT 100)
- navData() now fetches only folders + counts (no note rows on page load)
- navigationFragment: lazy mode renders empty note lists, lazy-loaded on expand
- toggleNavFolder / initNavPanel: htmx fetch on first expand, data-loaded guard
- Add /fragments/folder-notes endpoint for lazy per-folder note pages
- Add folderNotesPageFragment with Load more button for pagination
- Mobile: folders use counts Map, notes use paginated noteHeadersByFolder
- Tests: 129/129 passing