source dump of claude code
at main 92 lines 2.3 kB view raw
1import type { DOMElement } from './dom.js' 2import type { TextStyles } from './styles.js' 3 4/** 5 * A segment of text with its associated styles. 6 * Used for structured rendering without ANSI string transforms. 7 */ 8export type StyledSegment = { 9 text: string 10 styles: TextStyles 11 hyperlink?: string 12} 13 14/** 15 * Squash text nodes into styled segments, propagating styles down through the tree. 16 * This allows structured styling without relying on ANSI string transforms. 17 */ 18export function squashTextNodesToSegments( 19 node: DOMElement, 20 inheritedStyles: TextStyles = {}, 21 inheritedHyperlink?: string, 22 out: StyledSegment[] = [], 23): StyledSegment[] { 24 const mergedStyles = node.textStyles 25 ? { ...inheritedStyles, ...node.textStyles } 26 : inheritedStyles 27 28 for (const childNode of node.childNodes) { 29 if (childNode === undefined) { 30 continue 31 } 32 33 if (childNode.nodeName === '#text') { 34 if (childNode.nodeValue.length > 0) { 35 out.push({ 36 text: childNode.nodeValue, 37 styles: mergedStyles, 38 hyperlink: inheritedHyperlink, 39 }) 40 } 41 } else if ( 42 childNode.nodeName === 'ink-text' || 43 childNode.nodeName === 'ink-virtual-text' 44 ) { 45 squashTextNodesToSegments( 46 childNode, 47 mergedStyles, 48 inheritedHyperlink, 49 out, 50 ) 51 } else if (childNode.nodeName === 'ink-link') { 52 const href = childNode.attributes['href'] as string | undefined 53 squashTextNodesToSegments( 54 childNode, 55 mergedStyles, 56 href || inheritedHyperlink, 57 out, 58 ) 59 } 60 } 61 62 return out 63} 64 65/** 66 * Squash text nodes into a plain string (without styles). 67 * Used for text measurement in layout calculations. 68 */ 69function squashTextNodes(node: DOMElement): string { 70 let text = '' 71 72 for (const childNode of node.childNodes) { 73 if (childNode === undefined) { 74 continue 75 } 76 77 if (childNode.nodeName === '#text') { 78 text += childNode.nodeValue 79 } else if ( 80 childNode.nodeName === 'ink-text' || 81 childNode.nodeName === 'ink-virtual-text' 82 ) { 83 text += squashTextNodes(childNode) 84 } else if (childNode.nodeName === 'ink-link') { 85 text += squashTextNodes(childNode) 86 } 87 } 88 89 return text 90} 91 92export default squashTextNodes