mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-07 02:51:50 +00:00
74 lines
2.1 KiB
TypeScript
74 lines
2.1 KiB
TypeScript
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
|