F10: interactive track-changes review in the markdown preview (#29) #30
@@ -351,6 +351,22 @@ function sentinelsToSpans(html: string): string {
|
||||
.split(SENT.human.close).join("</span>");
|
||||
}
|
||||
|
||||
/**
|
||||
* Color one prose block's HTML by F3 author spans (PUA-sentinel technique,
|
||||
* salvaged from F9 renderAuthorship). `blockStart` is the block's char offset in
|
||||
* the source so spans map correctly. Pure; deterministic.
|
||||
*/
|
||||
export function colorByAuthor(
|
||||
raw: string,
|
||||
blockStart: number,
|
||||
spans: AuthorSpan[],
|
||||
render: (src: string) => string,
|
||||
): string {
|
||||
const overlapping = spans.filter((s) => s.end > blockStart && s.start < blockStart + raw.length);
|
||||
const injected = injectSentinels(raw, blockStart, overlapping);
|
||||
return sentinelsToSpans(render(injected));
|
||||
}
|
||||
|
||||
/**
|
||||
* Pure authorship render (INV-26/28): the CURRENT text with each F3-attributed
|
||||
* span colored by author. Prose blocks get inline `<span class="cw-by-*">`;
|
||||
@@ -379,8 +395,7 @@ export function renderAuthorship(
|
||||
if (!badge) return `<div class="cw-blk">${inner}</div>`;
|
||||
return `<div class="cw-blk ${badge.cls}"><span class="cw-badge">${badge.label}</span>${inner}</div>`;
|
||||
}
|
||||
const injected = injectSentinels(b.raw, b.start, overlapping);
|
||||
return `<div class="cw-blk">${sentinelsToSpans(safe(injected))}</div>`;
|
||||
return `<div class="cw-blk">${colorByAuthor(b.raw, b.start, overlapping, safe)}</div>`;
|
||||
})
|
||||
.join("\n");
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { splitBlocks, splitBlocksWithRanges, diffBlocks, renderTrackChanges, renderAuthorship, type AuthorSpan } from "../src/trackChangesModel";
|
||||
import { describe, it, test, expect } from "vitest";
|
||||
import { splitBlocks, splitBlocksWithRanges, diffBlocks, renderTrackChanges, renderAuthorship, colorByAuthor, type AuthorSpan } from "../src/trackChangesModel";
|
||||
|
||||
describe("splitBlocks", () => {
|
||||
it("splits prose paragraphs on blank lines, dropping empties", () => {
|
||||
@@ -235,6 +235,17 @@ describe("renderAuthorship", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("colorByAuthor", () => {
|
||||
test("colorByAuthor wraps human-authored prose in cw-by-human spans", () => {
|
||||
const raw = "hello world";
|
||||
const spans: AuthorSpan[] = [{ start: 0, end: 5, author: "human" }];
|
||||
const render = (src: string) => `<p>${src}</p>`;
|
||||
const html = colorByAuthor(raw, 0, spans, render);
|
||||
expect(html).toContain('<span class="cw-by-human">hello</span>');
|
||||
expect(html).toContain("world");
|
||||
});
|
||||
});
|
||||
|
||||
import { renderTrackChanges as rtc2 } from "../src/trackChangesModel";
|
||||
|
||||
describe("renderTrackChanges — intra-diagram mermaid (#22)", () => {
|
||||
|
||||
Reference in New Issue
Block a user