feat: fork ink and make it work nicely

This commit is contained in:
Brooklyn Nicholson 2026-04-11 11:29:08 -05:00
parent cb79018977
commit 8760faf991
139 changed files with 24952 additions and 140 deletions

View file

@ -0,0 +1,74 @@
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