(null);
const html = renderMarkdown(text);
useEffect(() => {
// marked autolinks URLs but leaves them same-tab — open externally
// so a click never navigates the terminal away.
ref.current?.querySelectorAll('a[href]').forEach((a) => {
a.setAttribute('target', '_blank');
a.setAttribute('rel', 'noopener noreferrer');
});
}, [html]);
// eslint-disable-next-line react/no-danger -- sanitized by DOMPurify in renderMarkdown
return ;
}
function DiffBody({ text }: { text: string }) {
const lines = String(text).split('\n');
return (
{lines.map((line, i) => {
const cls = line.startsWith('+ ') ? 'diff-add' : line.startsWith('- ') ? 'diff-del' : 'diff-ctx';
return (
{line}
{'\n'}
);
})}
);
}
export function Row({ row }: { row: TermRow }) {
const cssClass = 'level-' + row.level;
const icon = row.icon != null && row.icon !== '' && {row.icon};
if (row.body == null) {
return (
{icon}
{linkifyToNodes(row.summary)}
);
}
// Empty summary + markdown body → the body itself is the whole row
// (assistant text), no summary prefix line, never collapsible.
if (row.body_format === 'markdown' && row.summary === '') {
return (
{icon}
);
}
return (
{icon}
{row.summary}
{row.body_format === 'diff' && }
{row.body_format === 'markdown' && }
{row.body_format == null && {linkifyToNodes(row.body)}}
);
}