From 8632f7b04a9c7c5b2369ee5fccb5c7d85ca032d2 Mon Sep 17 00:00:00 2001 From: tegwick Date: Tue, 26 May 2026 14:43:17 +0200 Subject: [PATCH] Implement CE-WP-0004 T01-T05: citation card export (Markdown + HTML) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per-evidence-item export: click Export → Copy as Markdown / Copy as HTML writes a portable citation card to the clipboard. Cmd/Ctrl+Shift+C exports the active evidence as Markdown. - ADR-0007 locks the Markdown + HTML output formats. - New shared types: CitationCard, openContextUrl(), resolveSourceLabel(). - Engine renderers under src/engine/rendering/: renderCitationCardMarkdown, renderCitationCardHtml — snapshot-tested, escape-safe, BEM classes for HTML. - src/work/useExportEvidence.ts wires engine + renderers + clipboard. - EvidenceSidebar gains an Export popover per row + auto-dismissing toast. - E2E test (tests/integration/citation-card-export-e2e.dom.test.tsx) walks PRD scenario steps 10-11 and asserts the clipboard payload. Co-Authored-By: Claude Opus 4.7 --- .../ADR-0007-citation-card-format.md | 115 ++++++++ src/engine/index.ts | 1 + src/engine/rendering/html.test.ts | 172 ++++++++++++ src/engine/rendering/html.ts | 92 ++++++ src/engine/rendering/index.ts | 8 + src/engine/rendering/markdown.test.ts | 194 +++++++++++++ src/engine/rendering/markdown.ts | 68 +++++ src/shared/citation-card-source.test.ts | 75 +++++ src/shared/citation-card-source.ts | 26 ++ src/shared/citation-card.ts | 35 +++ src/shared/index.ts | 3 + src/shared/open-context-url.test.ts | 32 +++ src/shared/open-context-url.ts | 36 +++ src/work/EvidenceSidebar.dom.test.tsx | 210 ++++++++++++++ src/work/EvidenceSidebar.tsx | 261 ++++++++++++++++-- src/work/index.ts | 6 + src/work/useExportEvidence.ts | 89 ++++++ .../citation-card-export-e2e.dom.test.tsx | 215 +++++++++++++++ workplans/CE-WP-0004-citation-card-export.md | 14 +- 19 files changed, 1617 insertions(+), 35 deletions(-) create mode 100644 docs/decisions/ADR-0007-citation-card-format.md create mode 100644 src/engine/rendering/html.test.ts create mode 100644 src/engine/rendering/html.ts create mode 100644 src/engine/rendering/index.ts create mode 100644 src/engine/rendering/markdown.test.ts create mode 100644 src/engine/rendering/markdown.ts create mode 100644 src/shared/citation-card-source.test.ts create mode 100644 src/shared/citation-card-source.ts create mode 100644 src/shared/citation-card.ts create mode 100644 src/shared/open-context-url.test.ts create mode 100644 src/shared/open-context-url.ts create mode 100644 src/work/EvidenceSidebar.dom.test.tsx create mode 100644 src/work/useExportEvidence.ts create mode 100644 tests/integration/citation-card-export-e2e.dom.test.tsx diff --git a/docs/decisions/ADR-0007-citation-card-format.md b/docs/decisions/ADR-0007-citation-card-format.md new file mode 100644 index 0000000..4c2ae3f --- /dev/null +++ b/docs/decisions/ADR-0007-citation-card-format.md @@ -0,0 +1,115 @@ +# ADR-0007 — Citation card output format (Markdown and HTML) + +- Status: accepted +- Date: 2026-05-25 +- Workplan: CE-WP-0004-T02 (Markdown renderer) and CE-WP-0004-T03 (HTML renderer) +- Spec refs: `wiki/ArchitectureOverview.md` §4.7, §14.1, §14.2, §14.3 + +## Context + +The MVP scenario ends with a user exporting an evidence item as a portable +citation card. Two formats ship in CE-WP-0004: + +- **Markdown** — copied to the clipboard for pasting into notes, emails, + GitHub issues, and so on. Renders well as plain text and as rendered + Markdown. +- **HTML** — copied for pasting into rich-text editors and web pages. + +A third format, the `` Web Component from +`ArchitectureOverview.md` §14.2, is out of scope here and lands in a later +workplan. Its visual presentation should be *equivalent* to the HTML form +but is not constrained to be byte-identical. + +The two formats need a written contract so that: + +1. UI components (T04 sidebar export, future web embeds) can rely on the + exact output structure. +2. Snapshot tests fail loudly if the format drifts. +3. Consumers that style the HTML form know which elements and classes are + stable. + +## Decision + +### Markdown format (CE-WP-0004-T02) + +```markdown +> {quote} + +— *{sourceLabel}* · [Open source]({openContextUrl}) + +{commentary} +``` + +Rules: + +- Each `{quote}` line is rendered with the leading `> ` blockquote marker, + preserving line breaks in the source quote. A single-line quote is one + blockquote line; a multi-line quote becomes multiple `> `-prefixed + lines. +- A blank line follows the blockquote. +- The attribution line uses an em dash (`—`, U+2014) followed by a single + space, the italicised source label, a middle dot (`·`, U+00B7) with + surrounding spaces, and the `[Open source]({openContextUrl})` link. +- The middle dot + link segment is **omitted entirely** when no + `openContextUrl` is provided (which is unusual but possible for + evidence items without an annotation). +- A blank line follows the attribution. +- The optional `{commentary}` paragraph is rendered as-is. When absent + the trailing blank line and commentary paragraph are both omitted. +- The output ends with a single trailing newline. + +Reserved Markdown characters inside the quote are not escaped — the +intent is to reproduce the source text verbatim. The blockquote prefix +already neutralises the most dangerous reflow problems. The +`{sourceLabel}` is escaped to defuse `*`/`_` only; the link target is +URL-encoded by `openContextUrl()`. + +### HTML format (CE-WP-0004-T003) + +A single `