Scrutinize is a document viewer for close-reading and annotating essays. Text is generated on demand by DeepSeek's chat model from whatever topic you type in, so you get a fresh document to mark up every time instead of pulling from a fixed corpus. You select a phrase, tag it with an annotation type and a short note, and the tool tracks that span as a highlighted region in the document going forward.
The interesting part is how it turns a flat list of {start, end} annotations back into a segmented document without ever touching the underlying string. Annotations get sorted by start offset, then the content is sliced into alternating plain-text and highlighted-span chunks in a single pass, memoized so it only recomputes when the content or annotation set actually changes:
const highlightedContent = useMemo(() => {
if (annotations.length === 0) return content;
const sorted = [...annotations].sort((a, b) => a.start - b.start);
let lastIdx = 0;
const nodes: React.ReactNode[] = [];
sorted.forEach((ann) => {
if (ann.start > lastIdx) {
nodes.push(content.slice(lastIdx, ann.start));
}
nodes.push(
{content.slice(ann.start, ann.end)}
);
lastIdx = ann.end;
});
if (lastIdx < content.length) {
nodes.push(content.slice(lastIdx));
}
return nodes;
}, [content, annotations, handleHighlightMouseEnter, handleHighlightMouseLeave]);
New selections are checked against existing annotation ranges before they're allowed to land. If a proposed [start, end) overlaps any existing one, the selection just gets dropped instead of creating a nested or conflicting highlight. That keeps the slicing logic above simple: it never has to reason about overlapping spans.