const { test } = require('node:test'); const assert = require('node:assert/strict'); const fs = require('node:fs/promises'); const path = require('node:path'); let modulePromise; async function loadCitationModule() { if (!modulePromise) { modulePromise = fs.readFile(path.join(__dirname, '..', 'public', 'js', 'assistant', 'citations.js'), 'utf8') .then((source) => import('data:text/javascript;charset=utf-8,' + encodeURIComponent(source))); } return modulePromise; } test('mhchem inline delimiters render as KaTeX without eating ordinary backslash prose', async () => { const { renderAssistantMarkdown } = await loadCitationModule(); const expressions = []; const katex = { renderToString(expr, opts) { expressions.push({ expr, display: opts.displayMode }); return '' + expr + ''; } }; const html = renderAssistantMarkdown('Base deficit \\ce{HCO3-} and \\pu{37 C}; a plain \\ce without braces stays text.', [], { katex }); assert.deepEqual(expressions, [{ expr: '\\ce{HCO3-}', display: false }, { expr: '\\pu{37 C}', display: false }]); assert.match(html, /\\ce{HCO3-}<\/span>/); assert.match(html, /\\pu{37 C}<\/span>/); assert.match(html, /without braces stays text/); }); test('without KaTeX the mhchem source stays literal and escaped', async () => { const { renderAssistantMarkdown } = await loadCitationModule(); const html = renderAssistantMarkdown('Base deficit \\ce{HCO3-}.', []); assert.match(html, /\\ce\{HCO3-\}/); assert.doesNotMatch(html, /katex/); }); test('mhchem inside fenced code blocks is never rendered', async () => { const { renderAssistantMarkdown } = await loadCitationModule(); const katex = { renderToString() { throw new Error('code block sent to KaTeX'); } }; const html = renderAssistantMarkdown('```md\n\\ce{H2O} stays literal\n```', [], { katex }); assert.match(html, /\\ce\{H2O\}/); assert.doesNotMatch(html, /katex/); });