π File detail
ink/squash-text-nodes.ts
π§© .tsπ 93 linesπΎ 2,293 bytesπ text
β Back to All Filesπ― Use case
This file lives under βink/β, which covers Ink terminal UI (layouts, TTY IO, keyboard, renderer components). On the API surface it exposes StyledSegment and squashTextNodesToSegments β mainly functions, hooks, or classes. It composes internal code from dom and styles (relative imports).
Generated from folder role, exports, dependency roots, and inline comments β not hand-reviewed for every path.
π§ Inline summary
import type { DOMElement } from './dom.js' import type { TextStyles } from './styles.js' /** * A segment of text with its associated styles.
π€ Exports (heuristic)
StyledSegmentsquashTextNodesToSegmentsdefault
π₯οΈ Source preview
import type { DOMElement } from './dom.js'
import type { TextStyles } from './styles.js'
/**
* A segment of text with its associated styles.
* Used for structured rendering without ANSI string transforms.
*/
export type StyledSegment = {
text: string
styles: TextStyles
hyperlink?: string
}
/**
* Squash text nodes into styled segments, propagating styles down through the tree.
* This allows structured styling without relying on ANSI string transforms.
*/
export function squashTextNodesToSegments(
node: DOMElement,
inheritedStyles: TextStyles = {},
inheritedHyperlink?: string,
out: StyledSegment[] = [],
): StyledSegment[] {
const mergedStyles = node.textStyles
? { ...inheritedStyles, ...node.textStyles }
: inheritedStyles
for (const childNode of node.childNodes) {
if (childNode === undefined) {
continue
}
if (childNode.nodeName === '#text') {
if (childNode.nodeValue.length > 0) {
out.push({
text: childNode.nodeValue,
styles: mergedStyles,
hyperlink: inheritedHyperlink,
})
}
} else if (
childNode.nodeName === 'ink-text' ||
childNode.nodeName === 'ink-virtual-text'
) {
squashTextNodesToSegments(
childNode,
mergedStyles,
inheritedHyperlink,
out,
)
} else if (childNode.nodeName === 'ink-link') {
const href = childNode.attributes['href'] as string | undefined
squashTextNodesToSegments(
childNode,
mergedStyles,
href || inheritedHyperlink,
out,
)
}
}
return out
}
/**
* Squash text nodes into a plain string (without styles).
* Used for text measurement in layout calculations.
*/
function squashTextNodes(node: DOMElement): string {
let text = ''
for (const childNode of node.childNodes) {
if (childNode === undefined) {
continue
}
if (childNode.nodeName === '#text') {
text += childNode.nodeValue
} else if (
childNode.nodeName === 'ink-text' ||
childNode.nodeName === 'ink-virtual-text'
) {
text += squashTextNodes(childNode)
} else if (childNode.nodeName === 'ink-link') {
text += squashTextNodes(childNode)
}
}
return text
}
export default squashTextNodes