UNPKG

astro

Version:

Astro is a modern site builder with web best practices, performance, and DX front-of-mind.

104 lines (103 loc) 2.86 kB
import { markHTMLString, escapeHTML } from "../../escape.js"; import { chunkToString } from "../common.js"; async function renderQueue(queue, destination) { const result = queue.result; const pool = queue.pool; const cache = queue.htmlStringCache; let batchBuffer = ""; let i = 0; while (i < queue.nodes.length) { const node = queue.nodes[i]; try { if (canBatch(node)) { const batchStart = i; while (i < queue.nodes.length && canBatch(queue.nodes[i])) { batchBuffer += renderNodeToString(queue.nodes[i]); i = i + 1; } if (batchBuffer) { const htmlString = cache ? cache.getOrCreate(batchBuffer) : markHTMLString(batchBuffer); destination.write(htmlString); batchBuffer = ""; } if (pool) { for (let j = batchStart; j < i; j++) { pool.release(queue.nodes[j]); } } } else { await renderNode(node, destination, result); if (pool) { pool.release(node); } i = i + 1; } } catch (error) { throw error; } } if (batchBuffer) { const htmlString = cache ? cache.getOrCreate(batchBuffer) : markHTMLString(batchBuffer); destination.write(htmlString); } } function canBatch(node) { return node.type === "text" || node.type === "html-string"; } function renderNodeToString(node) { switch (node.type) { case "text": return node.content ? escapeHTML(node.content) : ""; case "html-string": return node.html || ""; case "component": case "instruction": { return ""; } } } async function renderNode(node, destination, result) { const cache = result._experimentalQueuedRendering?.htmlStringCache; switch (node.type) { case "text": { if (node.content) { const escaped = escapeHTML(node.content); const htmlString = cache ? cache.getOrCreate(escaped) : markHTMLString(escaped); destination.write(htmlString); } break; } case "html-string": { if (node.html) { const htmlString = cache ? cache.getOrCreate(node.html) : markHTMLString(node.html); destination.write(htmlString); } break; } case "instruction": { if (node.instruction) { destination.write(node.instruction); } break; } case "component": { if (node.instance) { let componentHtml = ""; const componentDestination = { write(chunk) { if (chunk instanceof Response) return; componentHtml += chunkToString(result, chunk); } }; await node.instance.render(componentDestination); if (componentHtml) { destination.write(componentHtml); } } break; } } } export { renderQueue };