/**
* Reusable markdown processing utility extracted from MessageBubble
* for use in legal documents and other content
*/
function escapeHtml(input: string): string {
return String(input)
.replace(/&/g, '&')
.replace(//g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
}
export const processMarkdown = (text: string): string => {
let processed = text || '';
processed = processed.replace(/\\\[([\s\S]*?)\\\]/g, (_, math) => {
const cleanMath = math.trim()
.replace(/\\text\{([^}]+)\}/g, '$1')
.replace(/\\,/g, ' ')
.replace(/\\/g, '');
return `
${cleanMath}
`;
});
processed = processed.replace(/\\\(([\s\S]*?)\\\)/g, (_, math) => {
const cleanMath = math.trim()
.replace(/\\text\{([^}]+)\}/g, '$1')
.replace(/\\,/g, ' ')
.replace(/\\/g, '');
return `${cleanMath}`;
});
processed = processed.replace(/\$\$([^$]+)\$\$/g, (_, math) => {
return `${math.trim()}
`;
});
processed = processed.replace(/\$([^$]+)\$/g, (_, math) => {
return `${math}`;
});
processed = processed.replace(/`([^`]+)`/g, (_, code) => {
return `${escapeHtml(
code
)}`;
});
processed = processed.replace(/\*\*([^*]+)\*\*/g, '$1');
processed = processed.replace(/__([^_]+)__/g, '$1');
processed = processed.replace(/\*([^*]+)\*/g, '$1');
processed = processed.replace(/_([^_]+)_/g, '$1');
processed = processed.replace(
/!\[([^\]]*)\]\(([^)]+)\)/g,
(_m, alt, url) =>
`
`
);
processed = processed.replace(
/\[([^\]]+)\]\(([^)]+)\)/g,
'$1'
);
processed = processed.replace(/^#### (.*$)/gm, '$1
');
processed = processed.replace(/^### (.*$)/gm, '$1
');
processed = processed.replace(/^## (.*$)/gm, '$1
');
processed = processed.replace(/^# (.*$)/gm, '$1
');
processed = processed.replace(
/(^|\n)((?:\s*[-*]\s+.+\n?)+)/gm,
(_m: string, lead: string, block: string) => {
const items = block
.trimEnd()
.split(/\n/)
.filter(Boolean)
.map((line: string) => line.replace(/^\s*[-*]\s+/, ''))
.map((inner: string) => `${inner}`)
.join('');
return `${lead}`;
}
);
processed = processed.replace(
/(^|\n)((?:\s*\d+\.\s+.+\n?)+)/gm,
(_m: string, lead: string, block: string) => {
const items = block
.trimEnd()
.split(/\n/)
.filter(Boolean)
.map((line: string) => line.replace(/^\s*\d+\.\s+/, ''))
.map((inner: string) => `${inner}`)
.join('');
return `${lead}${items}
`;
}
);
processed = processed.replace(/\n{2,}/g, '
');
processed = processed
.replace(/<\/li>
/g, '')
.replace(/<\/ul>
/g, '')
.replace(/<\/ol>
/g, '');
return processed;
};