feat(viewer): Markdown notes, preamble & editable titles in Notebook/Report#931
Merged
thinkingfish merged 6 commits intoMay 16, 2026
Merged
Conversation
- New dependency-free, XSS-safe renderMarkdown (markdown.js): escapes all input first, then emits a fixed tag whitelist; supports headings, bold/italic, inline + fenced code, ul/ol, blockquote, scheme-validated links. 16 node:test cases. - Per-note Edit ⇄ Preview toggle in Notebook (markdownField helper); Report renders notes as Markdown. New notes open in edit mode. - 'tagline' single-line input becomes a top-of-page 'Overview' preamble field (same Markdown + toggle); Report/LoadedSelection render it as Markdown. No schema change — still a plain string in the selection payload, so existing reports keep working. - editingMarkdown UI state cleared alongside expandedNotes everywhere. - Scoped .md-rendered CSS so element selectors don't leak. - WASM site symlink for markdown.js; version bump to alpha.9.
Invert the markdownField mode: a field is in raw edit mode unless its key is in previewMarkdown (set = opted into preview). New notes and the preamble now open editable; clicking Preview renders, clicking Edit returns to the textarea. Report/LoadedSelection are unaffected (they always render read-only).
- markdown.js gains renderMarkdownInline: escaped + inline formatting (bold/italic/code/links), newlines flattened, no block tags. 5 more node:test cases. - New optional entry.titleOverride (additive to the selection payload + persistence + entry shape; empty = derived breadcrumb title, so old reports are unaffected). - cardTitle(): Notebook click-to-edit single-line input (✎ affordance, Enter/blur commits, blank clears → derived); Report/LoadedSelection render the override as inline Markdown read-only; unavailable-card placeholder uses plain effective text. - editingTitle UI state cleared alongside the note/preview state in removeEntry / clearStore / openInNotebook.
Edit box opens with the override (or derived breadcrumb) text instead of blank, so the user tweaks from the original rather than retyping. Storage semantics unchanged — empty still means 'use derived'.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Per-element styling control in the Notebook/Report — Markdown notes, a top-of-page preamble, and editable chart titles — with no selection-schema change (all fields are additive plain strings, so existing saved reports keep working; the difference is purely render-time).
markdown.js— a tiny, dependency-free, XSS-safe renderer. Every char is HTML-escaped first; transforms only insert a fixed tag whitelist; link hrefs are scheme-validated (http/https/mailto/relative only —javascript:/data:degrade to plain text). Two entry points:renderMarkdown(block): headings, bold/italic, inline + fenced code, ul/ol, blockquote, links.renderMarkdownInline(one-line): inline formatting only, newlines flattened, never a block tag — used for titles.node:testcases.markdownField). Edit is the default mode; click Preview to render, Edit to return to the textarea. Report renders notes as Markdown.taglinebecomes a top-of-page "Overview" field with the same Markdown + toggle treatment; Report and the imported-Selection view render it formatted.note,tagline, andentry.titleOverrideare plain strings in the selection payload + localStorage; old reports with plain-text notes/titles render unchanged. UI-only edit/preview/title-edit state is cleared alongside the existing note state in every reset/clear path..md-rendered/.md-inlineCSS is scoped so element selectors don't leak.mr2-report.parquetdemo fixture to exercise the new Markdown content.docs/TODO.mdadds a backlog item to derive count/mean/percentiles from a single metrikenquantiles()call (not implemented here).Test plan
node --test tests/markdown.test.mjs(21/21: escaping/XSS, links, blocks, lists, code fences, inline mode)node --test tests/*.test.mjscargo build,bash tests/viewer_smoke.sh🤖 Generated with Claude Code