Skip to content

feat(viewer): Markdown notes, preamble & editable titles in Notebook/Report#931

Merged
thinkingfish merged 6 commits into
iopsystems:mainfrom
thinkingfish:feat/notebook-markdown-notes
May 16, 2026
Merged

feat(viewer): Markdown notes, preamble & editable titles in Notebook/Report#931
thinkingfish merged 6 commits into
iopsystems:mainfrom
thinkingfish:feat/notebook-markdown-notes

Conversation

@thinkingfish
Copy link
Copy Markdown
Member

@thinkingfish thinkingfish commented May 16, 2026

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).

  • New 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.
    • 21 node:test cases.
  • Notebook notes: an Edit ⇄ Preview toggle per note (markdownField). Edit is the default mode; click Preview to render, Edit to return to the textarea. Report renders notes as Markdown.
  • Preamble: the old single-line tagline becomes a top-of-page "Overview" field with the same Markdown + toggle treatment; Report and the imported-Selection view render it formatted.
  • Editable chart titles (Notebook): click a title (or the ✎ on hover) to edit it as inline Markdown; the box is prefilled with the current effective title (override or derived breadcrumb) so you tweak from the original. Enter/blur commits; an empty value falls back to the derived title. Report/LoadedSelection render the override read-only; the unavailable-card placeholder uses plain effective text.
  • Backing state is additive: note, tagline, and entry.titleOverride are 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-inline CSS is scoped so element selectors don't leak.
  • Refreshed the mr2-report.parquet demo fixture to exercise the new Markdown content.
  • Out of scope, recorded for later: docs/TODO.md adds a backlog item to derive count/mean/percentiles from a single metriken quantiles() call (not implemented here).

Test plan

  • node --test tests/markdown.test.mjs (21/21: escaping/XSS, links, blocks, lists, code fences, inline mode)
  • full JS suite node --test tests/*.test.mjs
  • cargo build, bash tests/viewer_smoke.sh
  • Manual: note Edit/Preview toggle (edit default); Overview preamble; click-to-edit title prefilled + Markdown render in Report; Save as Report → reload renders Markdown; an older report (plain-text notes/titles) still renders fine

🤖 Generated with Claude Code

- 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'.
@thinkingfish thinkingfish changed the title feat(viewer): Markdown notes + top-of-page preamble in Notebook/Report feat(viewer): Markdown notes, preamble & editable titles in Notebook/Report May 16, 2026
@thinkingfish thinkingfish marked this pull request as ready for review May 16, 2026 15:55
@thinkingfish thinkingfish merged commit 2abee43 into iopsystems:main May 16, 2026
12 checks passed
@thinkingfish thinkingfish deleted the feat/notebook-markdown-notes branch May 16, 2026 16:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant