0 directories, 46 files

util

Home / tinai / util
/**
 * File export for scratchpads: downloads the rendered scratchpad content as
 * standalone HTML, Markdown, or PDF. HTML and Markdown reuse the clipboard
 * conversion pipeline (extractFormattedContent); equation items are restored
 * to their raw $$..$$ TeX first, since typeset MathJax markup does not
 * survive outside the app. Mermaid diagrams are rasterized once and shared
 * by the PDF embed and the HTML/markdown conversion; the PDF delegates to
 * the shared PDF exporter.
 */

import { extractFormattedContent, rasterize_diagrams, build_export_html } from './format-utils.js';
import { strip_tags } from './dom-utils.js';
import { export_content } from './export-utils.js';
import { exportDocumentPdf } from './pdf-export.js';
import { compute_list_markers } from '../document-model.js';
import { formatEquation } from './conversation-format-utils.js';

/**
 * Builds a detached clone of the rendered scratchpad content with equation
 * items restored to their raw $$..$$ TeX text.
 * @param {Array<Object>} items - The revision's content items.
 * @param {HTMLElement} el - The rendered .div-response-content element.
 * @returns {HTMLElement} The prepared clone.
 */
function prepared_content(items, el) {
	const clone = el.cloneNode(true);
	clone.querySelectorAll('.div-code-expand-btn').forEach(btn => btn.remove());
	const by_guid = new Map((Array.isArray(items) ? items : []).map(item => [item?.guid, item]));
	clone.querySelectorAll('[data-guid]').forEach(node => {
		const item = by_guid.get(node.getAttribute('data-guid'));
		if (item?.type === 'equation') {
			node.textContent = strip_tags(formatEquation({ ...item, caption: '' })).trim();
		}
	});
	return clone;
}

/**
 * Builds the scratchpad content as markdown.
 * @param {Array<Object>} items - The revision's content items.
 * @param {HTMLElement} el - The rendered .div-response-content element.
 * @param {Object} images - Rasterized diagram PNGs keyed by item guid.
 * @returns {Promise<string>} The markdown document.
 */
async function build_scratchpad_markdown(items, el, images) {
	const { text } = await extractFormattedContent(prepared_content(items, el), images);
	return text + '\n';
}

/**
 * Builds the scratchpad content as a standalone HTML5 document.
 * @param {Array<Object>} items - The revision's content items.
 * @param {HTMLElement} el - The rendered .div-response-content element.
 * @param {string} title - The scratchpad title.
 * @param {boolean} mobile - Whether to emit the mobile variant.
 * @param {Object} images - Rasterized diagram PNGs keyed by item guid.
 * @returns {Promise<string>} The HTML5 document.
 */
async function build_scratchpad_html(items, el, title, mobile, images) {
	const { html } = await extractFormattedContent(prepared_content(items, el), images);
	return build_export_html(title, html, mobile);
}

/**
 * Exports the scratchpad in the given format and downloads the file.
 * @param {Array<Object>} items - The revision's content items.
 * @param {HTMLElement} el - The rendered .div-response-content element.
 * @param {string} title - The scratchpad title, used for filename and metadata.
 * @param {string} format - 'html', 'html-mobile', 'markdown', or 'pdf'.
 */
export async function export_scratchpad(items, el, title, format) {
	title = String(title || '').trim() || 'scratchpad';
	const images = await rasterize_diagrams(el, items);
	await export_content(format, title, {
		pdf: () => exportDocumentPdf(items, compute_list_markers(items), title, images),
		html: (mobile) => build_scratchpad_html(items, el, title, mobile, images),
		markdown: () => build_scratchpad_markdown(items, el, images)
	});
}
🌐
scratchpad-export.js ×
Type: Web, text/x-java
3.56 Kilobytes
Last Modified 2026-11-04 09:48:28
⬇ Download File