From 546087a060c5392f57de77f71abd7c388b6c3b01 Mon Sep 17 00:00:00 2001 From: Jacek Tomaszewski Date: Wed, 2 Sep 2026 07:48:00 +0200 Subject: [PATCH 1/4] feat(cockpit): every box you type markdown into shows how it will read MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A comment goes to GitHub as markdown, so "did that list come out as a list, and where did my backticks go" is a question the cockpit should answer before the Send rather than after it. Now it does, in all four places you write: a comment being edited, a comment being added, the line composer, and the chat input. The preview sits under the box with no tab and no toggle — a Write / Preview pair is two clicks to answer a question you have continuously — and it appears exactly when it has something to say: when the render reads back as something other than what was typed. A one-line note, or two plain paragraphs, get nothing, because a second identical copy of them is noise. A list, a heading, `code`, **bold**, a [link] all lose or move characters on the way through, and those are the drafts worth seeing first. A comment is previewed with its grade badge, since that is the body GitHub gets — the same withGrade() the finished comment, the payload and the export all use. Preview and render share one markdown path for the same reason: a preview that can drift from the real thing is worse than none. Co-Authored-By: Claude Opus 5 (1M context) --- SPEC.md | 10 +++++- web/src/Detail.tsx | 24 ++++++++++---- web/src/Markdown.tsx | 67 +++++++++++++++++++++++++++++++++++--- web/src/markdown.test.ts | 69 ++++++++++++++++++++++++++++++++++++++++ web/src/styles.css | 16 ++++++++++ 5 files changed, 174 insertions(+), 12 deletions(-) create mode 100644 web/src/markdown.test.ts diff --git a/SPEC.md b/SPEC.md index f09b98c..e8a2bae 100644 --- a/SPEC.md +++ b/SPEC.md @@ -1426,6 +1426,14 @@ one is reported over the next. would read as a click the user never made. - Opening a review triggers refresh (§13.2); a refresh failure is reported softly and the draft still reads. +- Every box the user types markdown into (a comment being edited, a comment + being written, a line composer, the chat input) renders that draft as it + will read, below the box, with no switch and no click. The preview MUST be + produced by the same markdown path as the finished render, so it cannot + drift from it, and a comment's preview MUST carry its grade badge (§7.4) — + that is the body GitHub gets. It MUST be suppressed when the render reads + back word-for-word as the source (whitespace runs flattened): a plain note + is told nothing by a second copy of itself. - The review's history renders as a collapsed card at the foot of the review, newest first — it is what you open when a review is not where you expected it, not part of reading one — with a rail jump that opens it on the way. An @@ -1712,7 +1720,7 @@ An implementation conforms when all of the following hold: | §14 GitHub | `src/core/gh.ts`, `src/core/trust.ts`, `src/core/send.ts` | | §15 auto-send | `src/core/autosend.ts` | | §16 HTTP API | `src/server/index.ts` | -| §17 cockpit | `web/src/inbox.ts`, `notify.ts`, `favicon.ts`, `review.ts` | +| §17 cockpit | `web/src/inbox.ts`, `notify.ts`, `favicon.ts`, `review.ts`, `Markdown.tsx` | | §18 CLI | `src/cli/index.ts` | ## Appendix B. Known Divergences in the Reference Implementation (non-normative) diff --git a/web/src/Detail.tsx b/web/src/Detail.tsx index ac6f9aa..676aea9 100644 --- a/web/src/Detail.tsx +++ b/web/src/Detail.tsx @@ -21,7 +21,7 @@ import { } from "./api"; import { highlightDiff } from "./highlight"; import { Icon, IconName, Key } from "./Icon"; -import { Markdown } from "./Markdown"; +import { Markdown, MarkdownPreview } from "./Markdown"; import { walkFrom } from "./inbox"; import { EVENT_LABEL, @@ -166,6 +166,7 @@ function LineComposer({ } }} /> +
{editing ? ( -