/** * Pulpie WebUI - UI Renderer * * Renders extraction results, stats, Markdown, Reader preview, and block inspection elements. */ import { marked } from 'marked'; import DOMPurify from 'dompurify'; /** * Display extraction results and statistics in the UI. * * @param {Object} data - Extraction results payload * @param {Object} elements - References to DOM elements */ export function displayResults(data, elements) { elements.resultsCard.style.display = 'block'; elements.pageTitleDisplay.textContent = data.title; elements.sourceUrlDisplay.textContent = data.sourceUrl ? `Source: ${data.sourceUrl}` : ''; // Calculate statistics const totalBlocks = data.blocks.length; const keptCount = data.rawPredictions.filter((p) => p === 1).length; const retentionPct = totalBlocks > 0 ? ((keptCount / totalBlocks) * 100).toFixed(1) : 0; elements.statKeptBlocks.textContent = `${keptCount} / ${totalBlocks}`; elements.statRetention.textContent = `${retentionPct}%`; elements.statTokens.textContent = data.totalTokens.toLocaleString(); if (elements.statTimeLabel) { elements.statTimeLabel.textContent = data.provider === 'wasm' ? 'WASM Time' : 'WebGPU Time'; } elements.statGpuTime.textContent = `${data.inferenceTimeMs} ms`; // Reader View (Sanitized HTML) const renderedHtml = DOMPurify.sanitize(marked.parse(data.markdown)); elements.readerContent.innerHTML = renderedHtml; // Raw Markdown & Clean HTML elements.markdownContent.textContent = data.markdown; elements.htmlContent.textContent = data.cleanHtml; // Render individual inspected blocks renderBlockInspector(data.blocks, data.itemIds, data.labels, elements.blockInspectorList); // Smooth scroll elements.resultsCard.scrollIntoView({ behavior: 'smooth', block: 'start' }); } /** * Populate individual block inspection cards in the Block Inspector tab. * * @param {string[]} blocks - Raw block HTML snippets * @param {string[]} itemIds - Array of _item_id strings * @param {Record} labels - Mapping of item_id -> predicted label * @param {HTMLElement} container - DOM container for block items */ export function renderBlockInspector(blocks, itemIds, labels, container) { container.innerHTML = ''; for (let i = 0; i < blocks.length; i++) { const id = itemIds[i]; const isMain = labels[id] === 'main'; const itemEl = document.createElement('div'); itemEl.className = `inspector-item ${isMain ? 'is-main' : 'is-other'}`; const header = document.createElement('div'); header.className = 'inspector-header'; header.innerHTML = ` Block #${id} ${isMain ? 'MAIN CONTENT' : 'BOILERPLATE'} `; const code = document.createElement('div'); code.className = 'inspector-code'; code.textContent = blocks[i].slice(0, 300) + (blocks[i].length > 300 ? '...' : ''); itemEl.appendChild(header); itemEl.appendChild(code); container.appendChild(itemEl); } }