MCPcopy Create free account
hub / github.com/modem-dev/hunk / flattenHighlightedLine

Function flattenHighlightedLine

src/ui/diff/pierre.ts:378–439  ·  view source on GitHub ↗

Flatten one highlighted HAST line into terminal-friendly styled text spans.

(node: HastNode | undefined, theme: AppTheme, emphasisBg: string)

Source from the content-addressed store, hash-verified

376
377/** Flatten one highlighted HAST line into terminal-friendly styled text spans. */
378function flattenHighlightedLine(node: HastNode | undefined, theme: AppTheme, emphasisBg: string) {
379 if (!node) {
380 return [];
381 }
382
383 const cacheKey = `${themeRenderCacheKey(theme)}:${emphasisBg}`;
384 const cachedByTheme = flattenedHighlightedLineCache.get(node);
385 const cached = cachedByTheme?.get(cacheKey);
386 if (cached) {
387 return cached;
388 }
389
390 // Cache hits here are what make revisiting/remounting already-highlighted files cheap:
391 // we skip the full recursive walk and return the already-flattened terminal spans.
392
393 const spans: RenderSpan[] = [];
394 const colorVariable = theme.appearance === "light" ? "--diffs-token-light" : "--diffs-token-dark";
395
396 const visit = (current: HastNode | undefined, inherited: Pick<RenderSpan, "fg" | "bg">) => {
397 if (!current) {
398 return;
399 }
400
401 if (current.type === "text") {
402 // Pierre injects a "\n" placeholder into empty line nodes so they aren't childless.
403 // Strip it the same way cleanDiffLine does for the unhighlighted path, or the literal
404 // newline ends up in the span text and breaks terminal row rendering.
405 mergeSpan(spans, {
406 text: tabify(cleanLastNewline(current.value)),
407 fg: inherited.fg,
408 bg: inherited.bg,
409 });
410 return;
411 }
412
413 const properties = current.properties ?? {};
414 const styles = parseStyleValue(properties.style);
415 const nextStyle: Pick<RenderSpan, "fg" | "bg"> = {
416 // Newer Pierre output can emit direct `color:#...` styles instead of theme CSS variables.
417 fg: normalizeHighlightedColor(
418 styles.get(colorVariable) ?? styles.get("color") ?? inherited.fg,
419 theme,
420 ),
421 // Pierre marks inline word-diff emphasis spans with a data attribute rather than a separate row kind.
422 bg: Object.hasOwn(properties, "data-diff-span") ? emphasisBg : inherited.bg,
423 };
424
425 for (const child of current.children ?? []) {
426 visit(child, nextStyle);
427 }
428 };
429
430 visit(node, {});
431
432 const nextCachedByTheme = cachedByTheme ?? new Map<string, RenderSpan[]>();
433 nextCachedByTheme.set(cacheKey, spans);
434 if (!cachedByTheme) {
435 flattenedHighlightedLineCache.set(node, nextCachedByTheme);

Callers 3

makeSplitCellFunction · 0.85
makeStackCellFunction · 0.85

Calls 2

themeRenderCacheKeyFunction · 0.85
visitFunction · 0.85

Tested by

no test coverage detected