feat: author-colored changed/added blocks in review; unchanged blocks render plain
This commit is contained in:
+33
-15
@@ -841,18 +841,26 @@ function renderReviewOp(
|
||||
render: (src: string) => string,
|
||||
colored: (raw: string) => string,
|
||||
src: string,
|
||||
changedHtml?: string,
|
||||
): string {
|
||||
// removed blocks and any changed block (atomic fences diffed whole; non-atomic prose
|
||||
// word-merged) render via renderOp — no author sentinels (deletions neutral, spec §6.7).
|
||||
// `src` is "" for a removed block (no live source — INV-36).
|
||||
// A non-atomic changed prose block is pre-rendered with author-colored ins/del
|
||||
// (changedHtml). Removed blocks and atomic changed fences stay neutral via renderOp
|
||||
// (standalone deletion → neutral, per the adjacency heuristic). `src` is "" for a
|
||||
// removed block (no live source — INV-36).
|
||||
if (op.kind === "changed" && !op.atomic && changedHtml !== undefined) {
|
||||
return `<div class="cw-blk cw-changed"${src}>${changedHtml}</div>`;
|
||||
}
|
||||
if (op.kind === "removed" || op.kind === "changed") return renderOp(op, render, src);
|
||||
return `<div class="cw-blk ${op.kind === "added" ? "cw-added" : "cw-unchanged"}"${src}>${colored(op.block.raw)}</div>`;
|
||||
// "added": use changedHtml (author-colored word-diff from empty before, all insertions).
|
||||
// "unchanged": colored() returns plain render(raw) — color means "changed since baseline".
|
||||
return `<div class="cw-blk ${op.kind === "added" ? "cw-added" : "cw-unchanged"}"${src}>${changedHtml ?? colored(op.block.raw)}</div>`;
|
||||
}
|
||||
|
||||
/**
|
||||
* On-state body (INV-33): the F7 baseline diff — added/changed PROSE author-colored
|
||||
* via colorByAuthor (F9 sentinels), deletions struck — overlaid with F4 pending
|
||||
* proposals as blue cw-proposal blocks (✓/✗). One pass, pure, vscode-free.
|
||||
* On-state body: the F7 baseline diff — added/changed PROSE author-colored via
|
||||
* wordDiffByAuthor (cw-ins-{author}/cw-del-{author} per token), unchanged blocks render plain,
|
||||
* deletions struck neutral — overlaid with F4 pending proposals as blue cw-proposal
|
||||
* blocks (✓/✗). One pass, pure, vscode-free.
|
||||
*
|
||||
* A resolved proposal renders INLINE, right after the current-side block its anchor
|
||||
* falls in (#31) — so "what is Claude proposing, and where?" is answered by
|
||||
@@ -903,11 +911,9 @@ export function renderReview(
|
||||
const ops = diffBlocks(baselineText, landedText);
|
||||
// #48: right after a PIN (baseline reason "pinned") with no changes since, the
|
||||
// panel is fully clean: no change marks (already absent) AND no authorship
|
||||
// coloring, so the pin reads as "this is my clean starting point". Skip
|
||||
// colorByAuthor for every block in this case; data-src mapping and any pending
|
||||
// proposals (review actions, not annotations) are kept below. A baseline advanced
|
||||
// by a machine-landing (accept) is ALSO zero-diff but is NOT pinned — it keeps
|
||||
// its authorship coloring (F10 INV-33), so this is gated on the pin specifically.
|
||||
// coloring, so the pin reads as "this is my clean starting point". Suppress
|
||||
// wordDiffByAuthor for every block in this case; data-src mapping and any pending
|
||||
// proposals (review actions, not annotations) are kept below.
|
||||
const clean = opts.pinned === true && ops.every((o) => o.kind === "unchanged");
|
||||
|
||||
// Map a currentText offset to its landedText offset (account for reverted spans
|
||||
@@ -959,9 +965,21 @@ export function renderReview(
|
||||
for (const op of ops) {
|
||||
const blockIndex = op.kind === "removed" ? -1 : ci;
|
||||
const blk = op.kind === "removed" ? undefined : ranges[ci++];
|
||||
const colored = (raw: string): string =>
|
||||
blk && !clean ? colorByAuthor(raw, blk.start, landedSpans, render) : render(raw);
|
||||
bodyParts.push(renderReviewOp(op, render, colored, srcAttr(blk)));
|
||||
// Only ADDED and CHANGED prose blocks are author-colored (they differ since baseline);
|
||||
// UNCHANGED blocks render plain (color means "changed since baseline").
|
||||
const colored = (raw: string): string => render(raw);
|
||||
// A non-atomic changed prose block: author-colored word diff (ins by author,
|
||||
// del by adjacency). An added block: word diff from empty before — all insertions.
|
||||
// `blk.start` is the landed offset of the after-side text.
|
||||
const changedHtml =
|
||||
blk && !clean
|
||||
? op.kind === "changed" && !op.atomic
|
||||
? render(wordDiffByAuthor(op.before.raw, op.block.raw, blk.start, landedSpans))
|
||||
: op.kind === "added"
|
||||
? render(wordDiffByAuthor("", op.block.raw, blk.start, landedSpans))
|
||||
: undefined
|
||||
: undefined;
|
||||
bodyParts.push(renderReviewOp(op, render, colored, srcAttr(blk), changedHtml));
|
||||
const here = blockIndex >= 0 ? byBlock.get(blockIndex) : undefined;
|
||||
if (here) for (const p of here) bodyParts.push(proposalBlockHtml(p, render));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user