40 lines
1.6 KiB
TypeScript
40 lines
1.6 KiB
TypeScript
/**
|
|
* Shared rendering utilities used by the Rendering node and output views.
|
|
* Pure functions only; no React or node-specific logic.
|
|
*/
|
|
|
|
/** Extract <think>...</think> blocks from HTML/markdown; return main (with blocks removed) and think for collapsible. */
|
|
export function parseThinkSections(html: string): { main: string; think: string } {
|
|
const thinkRegex = /<think>([\s\S]*?)<\/think>/gi
|
|
const thinkParts: string[] = []
|
|
let match
|
|
while ((match = thinkRegex.exec(html)) !== null) thinkParts.push(match[1].trim())
|
|
const think = thinkParts.join('\n\n')
|
|
const main = html.replace(thinkRegex, '').replace(/\n{3,}/g, '\n\n').trim()
|
|
return { main, think }
|
|
}
|
|
|
|
/** Process SVG HTML for viewport display (aspect ratio, fill container). */
|
|
export function processSvgDisplay(html: string): string {
|
|
let out = html
|
|
out = out.replace(/\bpreserveAspectRatio\s*=\s*["']none["']/gi, 'preserveAspectRatio="xMidYMid meet"')
|
|
out = out.replace(/\bwidth\s*=\s*["'][^"']*["']/i, 'width="100%"')
|
|
out = out.replace(/\bheight\s*=\s*["'][^"']*["']/i, 'height="100%"')
|
|
out = out.replace(/\bstyle\s*=\s*["']([^"']*)["']/i, (_, style) => {
|
|
const overridden = style.replace(/\b(width|height):[^;]+/gi, '$1:100%')
|
|
return `style="${overridden}"`
|
|
})
|
|
return out
|
|
}
|
|
|
|
/** Strip Nunjucks/template syntax for raw view. */
|
|
export function stripTemplateSyntax(text: string): string {
|
|
return text
|
|
.replace(/\{%[\s\S]*?%\}/g, '')
|
|
.replace(/\{\{[\s\S]*?\}\}/g, '')
|
|
.replace(/\{#[\s\S]*?#\}/g, '')
|
|
.replace(/(\r?\n)\s*(\r?\n)/g, '$1$2')
|
|
.replace(/^\s*\n|\n\s*$/g, (m) => (m === '\n' ? '\n' : ''))
|
|
.trim()
|
|
}
|