import { escapeAttr, escapeHtml } from './citations.js';
export function createAssistantExporter(options) {
options = options || {};
var exportCacheKey = '';
var exportCacheItems = null;
function invalidate() {
exportCacheKey = '';
exportCacheItems = null;
}
function exportAnswerPdf(state) {
state = state || {};
if (!state.lastAnswer) {
if (typeof options.showToast === 'function') options.showToast('No answer to export', 'error');
return;
}
var exportItems = collectExportItems(state.messages || [], state.lastAnswer, state.lastSources || []);
var cacheKey = buildExportCacheKey(exportItems, state.lastGeneratedImageSrc || '');
var doc = openExportWindow();
if (!doc) {
if (typeof options.showToast === 'function') options.showToast('Allow popups to export PDF', 'error');
return;
}
if (exportCacheKey === cacheKey && exportCacheItems) {
writePrintableChatExport(doc, exportCacheItems, state.lastGeneratedImageSrc || '');
return;
}
exportCacheKey = cacheKey;
exportCacheItems = exportItems;
writePrintableChatExport(doc, exportItems, state.lastGeneratedImageSrc || '');
}
function openExportWindow() {
var doc = window.open('', '_blank', 'width=900,height=1100');
if (!doc) return null;
doc.document.open();
doc.document.write('
Preparing Clinical Assistant ExportPreparing PDF export...
');
doc.document.close();
return doc;
}
function writePrintableChatExport(doc, items, imageSrc) {
if (!doc || doc.closed) return;
items = Array.isArray(items) && items.length ? items : [];
var imageHtml = imageSrc ? 'Generated Image
' : '';
var sections = items.map(function (item, idx) {
var sources = Array.isArray(item.sources) ? item.sources : [];
var heading = item.heading || deriveExportHeading(item.question, idx);
var summary = item.summary || '';
var answer = item.answer || '';
var citedNumbers = extractCitedSourceNumbers([summary, answer].filter(Boolean).join('\n\n'));
var refs = renderExportRefs(sources, idx + 1, citedNumbers);
return '' +
'' + escapeHtml(heading) + '
' +
'Question: ' + escapeHtml(item.question || '') + '
' +
(summary ? 'Summary
' + renderMarkdown(summary, sources, { citationLabel: 'number' }) + '
' : '') +
'Full Generated Answer
' + renderMarkdown(answer, sources, { citationLabel: 'number' }) + '
' +
(refs ? 'References
' + refs + '
' : '') +
'';
}).join('');
var html = 'Clinical Assistant Export' +
'' +
'Clinical Assistant Export
' +
'Export generated ' + escapeHtml(new Date().toLocaleString()) + '
' +
imageHtml +
sections + '';
doc.document.open();
doc.document.write(html);
doc.document.close();
try {
var printBtn = doc.document.getElementById('assistant-export-print');
if (printBtn) printBtn.addEventListener('click', function () { doc.focus(); doc.print(); });
} catch (e) {}
setTimeout(function () { try { doc.focus(); doc.print(); } catch (e) {} }, 500);
}
function renderMarkdown(md, sources, renderOptions) {
if (typeof options.renderMarkdown === 'function') return options.renderMarkdown(md, sources, renderOptions);
return escapeHtml(md);
}
return {
exportAnswerPdf: exportAnswerPdf,
invalidate: invalidate
};
}
function collectExportItems(messages, lastAnswer, lastSources) {
var items = [];
var pendingQuestion = '';
(messages || []).forEach(function (m) {
if (m.role === 'user') {
pendingQuestion = m.content || pendingQuestion;
return;
}
if (m.role !== 'assistant' || !m.content) return;
if (isUtilityAssistantMessage(m.content)) return;
items.push({
question: pendingQuestion || 'Clinical question',
heading: deriveExportHeading(pendingQuestion, items.length),
summary: '',
answer: m.content,
sources: Array.isArray(m.sources) && m.sources.length ? m.sources : lastSources
});
pendingQuestion = '';
});
if (!items.length && lastAnswer) {
items.push({ question: 'Clinical question', heading: 'Clinical Answer', summary: '', answer: lastAnswer, sources: lastSources });
}
return items;
}
function renderExportRefs(sources, sectionNumber, citedNumbers) {
var cited = citedNumbers && citedNumbers.length ? new Set(citedNumbers.map(String)) : null;
return (sources || []).filter(function (s, idx) {
var n = s.number || idx + 1;
return !cited || cited.has(String(n));
}).map(function (s, idx) {
var n = s.number || idx + 1;
var title = s.title || s.resource || 'Untitled source';
var page = s.page || s.page_number || s.pageNumber;
return '[' + n + '] ' + escapeHtml(title) + (page ? ', page ' + escapeHtml(page) : '') + '.';
}).join('');
}
function extractCitedSourceNumbers(text) {
var found = new Set();
String(text || '').replace(/\[(\d+(?:\s*,\s*\d+)*)\]/g, function (_, nums) {
nums.split(',').forEach(function (n) {
n = String(n || '').trim();
if (n) found.add(n);
});
return _;
});
return Array.from(found).sort(function (a, b) { return Number(a) - Number(b); });
}
function deriveExportHeading(question, idx) {
var text = String(question || '').replace(/\s+/g, ' ').trim();
if (!text || /^(what|which|when|why|how|and|also|what dose\??|dose\??)$/i.test(text)) return 'Clinical Question ' + (idx + 1);
return text.replace(/[?!.]+$/, '').slice(0, 90);
}
function isUtilityAssistantMessage(content) {
return /^I prepared the image prompt in the \*\*Image \/ Graph\*\* box/i.test(String(content || ''));
}
export function buildExportCacheKey(items, imageSrc) {
return JSON.stringify({ items: (items || []).map(function (item) {
return { q: item.question, a: item.answer, s: (item.sources || []).map(function (s) { return [s.number, s.title, s.page]; }) };
}), image: imageSrc ? '1' : '' });
}