achi-html-stream 1.0.2 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,2 +1,2 @@
1
- var achiHTML=(function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});function t(e){return String(e).replace(/[&<>"']/g,e=>{switch(e){case`&`:return`&amp;`;case`<`:return`&lt;`;case`>`:return`&gt;`;case`"`:return`&quot;`;case`'`:return`&#39;`;default:return e}})}function n(e){let n=e.length;for(;n--;){let r=e[n];typeof r==`string`&&(e[n]=t(r))}return e}var r=class{html;constructor(e){this.html=e}};let i=function*(){}.constructor,a=new WeakMap;function o(e,t){let n=`yield \`${e[0]}\``,i=t.length;for(let a=0;a<i;a++){let i=t[a];typeof i==`string`?n+=`+escapeHTML(args[${a}])+\`${e[a+1]}\``:i instanceof r?n+=`+args[${a}].html+\`${e[a+1]}\``:i instanceof Error||typeof i==`number`?n+=`+args[${a}]+\`${e[a+1]}\``:Array.isArray(i)?n+=`; yield * sanitizeArray(args[${a}]); yield \`${e[a+1]}\``:i?.[Symbol.iterator]?n+=`; yield * args[${a}]; yield \`${e[a+1]}\``:n+=`; yield args[${a}]; yield \`${e[a+1]}\``}return n}function s(e,t){let n=o(e,t);return new i(`escapeHTML`,`sanitizeArray`,`args`,n)}function c(e,...r){let i=a.get(e);return i?i(t,n,r):(i=s(e,r),a.set(e,i),i(t,n,r))}function*l(e,...i){let a=e[0],o=i.length;for(let s=0;s<o;s++){let o=i[s];typeof o==`string`?a+=t(o):o instanceof r?a+=o.html:o instanceof Error||typeof o==`number`?a+=o:Array.isArray(o)?(a&&=(yield a,``),yield*n(o)):o?.[Symbol.iterator]?(a&&=(yield a,``),yield*o):yield o,a+=e[s+1]}a&&=(yield a,``)}async function u(e){try{return await e}catch(e){return e instanceof Promise?u(e):e}}async function d(e,t){let n=e.getReader();try{for(;;){let e=await n.read();if(e.done)return;t.enqueue(e.value)}}catch(e){t.enqueue(e)}finally{n.releaseLock()}}function*f(e,i){let a=``;for(let o of e)if(typeof o==`string`)a+=o;else if(o instanceof r)a+=o.html;else if(o instanceof Error||typeof o==`number`)a+=o;else if(o instanceof Promise){a&&=(i.enqueue(a),``);let e=yield o;if(typeof e==`string`)a+=t(e);else if(e instanceof r)a+=e.html;else if(e instanceof Error||typeof e==`number`)a+=e;else if(Array.isArray(e))a&&=(i.enqueue(a),``),yield*f(n(e),i);else if(e?.[Symbol.iterator])a&&=(i.enqueue(a),``),yield*f(e,i);else if(e==null)continue;else a&&=(i.enqueue(a),``),yield e}else if(Array.isArray(o))a&&=(i.enqueue(a),``),yield*f(n(o),i);else if(o?.[Symbol.iterator])a&&=(i.enqueue(a),``),yield*f(o,i);else if(o==null)continue;else a&&=(i.enqueue(a),``),yield o;a&&=(i.enqueue(a),``)}function p(e){return new ReadableStream({start(t){let n=f(e,t);return r(n);async function r(e=void 0){let i=n.next(e);try{if(i.value instanceof Promise)return r(await u(i.value));if(i.value instanceof Response)return await d(i.value.body.pipeThrough(new TextDecoderStream),t),r();if(i.value instanceof ReadableStream)return await d(i.value,t),r();if(i.value instanceof Request){let e=(await fetch(i.value)).body;return e&&await d(e.pipeThrough(new TextDecoderStream),t),r()}}catch(e){return t.enqueue(e),r()}t.close()}}})}async function m(e){try{let t=p(e).getReader(),n=``;for(;;){let e=await t.read();if(e.done){t.releaseLock();break}n+=e.value}return n}catch(e){throw e}}function h(e,t={},n=200,r=`OK`){let i=Object.assign({"Content-Type":`text/html; charset=utf-8`},t);return new Response(p(e).pipeThrough(new TextEncoderStream),{headers:i,status:n,statusText:r})}return e.UnSafeHTML=r,e.escapeHTML=t,e.html=c,e.liveHTML=l,e.render=h,e.renderAsString=m,e.renderStream=p,e})({});
1
+ var achiHTML=(function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});function t(e){return String(e).replace(/[&<>"']/g,e=>{switch(e){case`&`:return`&amp;`;case`<`:return`&lt;`;case`>`:return`&gt;`;case`"`:return`&quot;`;case`'`:return`&#39;`;default:return e}})}function n(e){let n=e.length;for(;n--;){let r=e[n];typeof r==`string`&&(e[n]=t(r))}return e}var r=class{html;constructor(e){this.html=e}};let i=function*(){}.constructor,a=new WeakMap;function o(e,t){let n=`yield \`${e[0]}\``,i=t.length;for(let a=0;a<i;a++){let i=t[a];typeof i==`string`?n+=`+escapeHTML(args[${a}])+\`${e[a+1]}\``:i instanceof r?n+=`+args[${a}].html+\`${e[a+1]}\``:i instanceof Error||typeof i==`number`?n+=`+args[${a}]+\`${e[a+1]}\``:Array.isArray(i)?n+=`; yield * sanitizeArray(args[${a}]); yield \`${e[a+1]}\``:i?.[Symbol.iterator]?n+=`; yield * args[${a}]; yield \`${e[a+1]}\``:n+=`; yield args[${a}]; yield \`${e[a+1]}\``}return n}function s(e,t){let n=o(e,t);return new i(`escapeHTML`,`sanitizeArray`,`args`,n)}function c(e,...r){let i=a.get(e);return i?i(t,n,r):(i=s(e,r),a.set(e,i),i(t,n,r))}function*l(e,...i){let a=e[0],o=i.length;for(let s=0;s<o;s++){let o=i[s];typeof o==`string`?a+=t(o):o instanceof r?a+=o.html:o instanceof Error||typeof o==`number`?a+=o:Array.isArray(o)?(a&&=(yield a,``),yield*n(o)):o?.[Symbol.iterator]?(a&&=(yield a,``),yield*o):yield o,a+=e[s+1]}a&&=(yield a,``)}async function u(e){try{return await e}catch(e){return e instanceof Promise?u(e):e}}async function d(e,t){let n=e.getReader();try{for(;;){let e=await n.read();if(e.done)return;t.enqueue(e.value)}}catch(e){t.enqueue(e)}finally{n.releaseLock()}}function*f(e,i){let a=``;for(let o of e)if(typeof o==`string`)a+=o;else if(o instanceof r)a+=o.html;else if(o instanceof Error||typeof o==`number`)a+=o;else if(o instanceof Promise){a&&=(i.enqueue(a),``);let e=yield o;if(typeof e==`string`)a+=t(e);else if(e instanceof r)a+=e.html;else if(e instanceof Error||typeof e==`number`)a+=e;else if(Array.isArray(e))a&&=(i.enqueue(a),``),yield*f(n(e),i);else if(e?.[Symbol.iterator])a&&=(i.enqueue(a),``),yield*f(e,i);else if(e==null)continue;else a&&=(i.enqueue(a),``),yield e}else if(Array.isArray(o))a&&=(i.enqueue(a),``),yield*f(n(o),i);else if(o?.[Symbol.iterator])a&&=(i.enqueue(a),``),yield*f(o,i);else if(o==null)continue;else a&&=(i.enqueue(a),``),yield o;a&&=(i.enqueue(a),``)}function p(e){return new ReadableStream({start(t){let n=f(e,t);return r(n);async function r(e=void 0){let i=n.next(e);try{if(i.value instanceof Promise)return r(await u(i.value));if(i.value instanceof Response)return await d(i.value.body.pipeThrough(new TextDecoderStream),t),r();if(i.value instanceof ReadableStream)return await d(i.value,t),r();if(i.value instanceof Request){let e=(await fetch(i.value)).body;return e&&await d(e.pipeThrough(new TextDecoderStream),t),r()}}catch(e){return t.enqueue(e),r()}t.close()}}})}async function m(e){try{let t=p(e).getReader(),n=``;for(;;){let e=await t.read();if(e.done){t.releaseLock();break}n+=e.value}return n}catch(e){throw e}}function h(e,t={},n=200,r=`OK`){let i=Object.assign({"Content-Type":`text/html; charset=utf-8`,"X-Accel-Buffering":`no`},t);return new Response(p(e).pipeThrough(new TextEncoderStream),{headers:i,status:n,statusText:r})}return e.UnSafeHTML=r,e.escapeHTML=t,e.html=c,e.liveHTML=l,e.render=h,e.renderAsString=m,e.renderStream=p,e})({});
2
2
  //# sourceMappingURL=index.iife.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.iife.js","names":[],"sources":["../../src/utils/escapehtml.ts","../../src/utils/sanitizeArray.ts","../../src/utils/UnSafeHTML.ts","../../src/html/cachehtml.ts","../../src/html/livehtml.ts","../../src/utils/promisedValue.ts","../../src/utils/streamHTML.ts","../../src/html/html.ts","../../src/index.browser.ts"],"sourcesContent":["/**\n * Escapes HTML special characters in a string to prevent XSS attacks and ensure proper rendering in HTML.\n *\n * @param {string} str - The string to escape\n *\n * @returns {string} - The escaped string\n */\nexport function escapeHTML(str: string): string {\n return String(str).replace(/[&<>\"']/g, (char: string) => {\n switch (char) {\n case \"&\":\n return \"&amp;\";\n case \"<\":\n return \"&lt;\";\n case \">\":\n return \"&gt;\";\n case '\"':\n return \"&quot;\";\n case \"'\":\n return \"&#39;\";\n default:\n return char;\n }\n });\n}\n","import { escapeHTML } from \"./escapehtml\";\n\nexport function sanitizeArray(values: any[]): any[] {\n let index = values.length;\n while (index--) {\n let value = values[index];\n if (typeof value == \"string\") {\n values[index] = escapeHTML(value);\n }\n }\n return values;\n}\n","export class UnSafeHTML {\n public html: string;\n /**\n * Creates unsafe html that will not be escaped\n *\n * @param {string} html - string containing unsafe html\n */\n constructor(html: string) {\n this.html = html;\n }\n}\n","import { escapeHTML } from \"../utils/escapehtml\";\nimport { sanitizeArray } from \"../utils/sanitizeArray\";\nimport { UnSafeHTML } from \"../utils/UnSafeHTML\";\n\ntype GeneratorFunctionConstructor = new (\n ...args: string[]\n) => (...args: any[]) => Generator<any, any, any>;\nconst TemplateConstructor = function* () {}\n .constructor as GeneratorFunctionConstructor,\n templateCache = new WeakMap();\n\n/**\n * A function that generates the source code for a compiled HTML template function.\n *\n * @param {String[]} templates\n * @param {Array} values\n * @returns {string} source code of the compiled template function that can be called with the appropriate arguments to produce the final HTML output based on the provided templates and values.\n */\nfunction generateTemplateSourceCode(\n templates: TemplateStringsArray,\n values: TemplateValues[],\n): string {\n let sourceCode = `yield \\`${templates[0]}\\``,\n length = values.length;\n for (let index = 0; index < length; index++) {\n let value = values[index];\n if (typeof value == \"string\") {\n sourceCode += `+escapeHTML(args[${index}])+\\`${templates[index + 1]}\\``;\n } else if (value instanceof UnSafeHTML) {\n sourceCode += `+args[${index}].html+\\`${templates[index + 1]}\\``;\n } else if (value instanceof Error || typeof value == \"number\") {\n sourceCode += `+args[${index}]+\\`${templates[index + 1]}\\``;\n } else if (Array.isArray(value)) {\n sourceCode += `; yield * sanitizeArray(args[${index}]); yield \\`${templates[index + 1]}\\``;\n } else if ((value as any)?.[Symbol.iterator]) {\n sourceCode += `; yield * args[${index}]; yield \\`${templates[index + 1]}\\``;\n } else {\n sourceCode += `; yield args[${index}]; yield \\`${templates[index + 1]}\\``;\n }\n }\n return sourceCode;\n}\n/**\n * compiles an HTML template into a function that can be cached and reused with different values. It generates source code for the template by processing the provided templates and values, handling various types of values such as strings, UnSafeHTML instances, errors, numbers, arrays, and iterables. The generated source code is then used to create a new function using the TemplateConstructor, which can be called with the appropriate arguments to produce the final HTML output. This approach allows for efficient rendering of HTML templates while ensuring that string values are properly escaped to prevent XSS vulnerabilities.\n *\n * @param {String[]} templates\n * @param {Array} values\n * @returns {GeneratorFunction} A generator function that can be called with the appropriate arguments to produce the final HTML output based on the provided templates and values.\n */\nfunction compileTemplate(\n templates: TemplateStringsArray,\n values: TemplateValues[],\n) {\n let sourceCode = generateTemplateSourceCode(templates, values);\n return new TemplateConstructor(\n \"escapeHTML\",\n \"sanitizeArray\",\n \"args\",\n sourceCode,\n );\n}\n/**\n * A function that renders an HTML template with caching capabilities. It checks if a compiled template function already exists in the cache for the given templates. If it does, it calls the cached function with the provided values and returns the result. If not, it compiles a new template function using the compileTemplate function, stores it in the cache, and then calls it with the provided values. This allows for efficient rendering of HTML templates while ensuring that string values are properly escaped to prevent XSS vulnerabilities.\n *\n * @param {String[]} templates\n * @param {...(String|UnSafeHTML|Error|number|Array|Iterable)} values\n * @returns {GeneratorFunction} A generator function that can be called with the appropriate arguments to produce the final HTML output based on the provided templates and values.\n */\nfunction cachableHTML(\n templates: TemplateStringsArray,\n ...values: TemplateValues[]\n) {\n let template = templateCache.get(templates);\n if (template) {\n return template(escapeHTML, sanitizeArray, values);\n }\n template = compileTemplate(templates, values);\n templateCache.set(templates, template);\n return template(escapeHTML, sanitizeArray, values);\n}\n\nexport { cachableHTML };\n","import { UnSafeHTML } from \"../utils/UnSafeHTML\";\nimport { escapeHTML } from \"../utils/escapehtml\";\nimport { sanitizeArray } from \"../utils/sanitizeArray\";\n\n/**\n * A generator function that processes an HTML template without caching. It handles various types of values, including strings, UnSafeHTML instances, errors, numbers, promises, arrays, and iterables. The function ensures that string values are properly escaped to prevent XSS vulnerabilities, while allowing UnSafeHTML instances to be included as-is. It also supports asynchronous values by yielding promises and waiting for their resolution before processing them further.\n *\n * @export\n * @param {String[]} templates\n * @param {...TemplateValues} values\n * @returns {Generator} A generator that yields processed HTML content as a stream.\n */\nexport function* liveHTML(\n templates: TemplateStringsArray,\n ...values: TemplateValues[]\n) {\n let cache = templates[0],\n length = values.length;\n for (let index = 0; index < length; index++) {\n let value = values[index];\n if (typeof value == \"string\") {\n cache += escapeHTML(value);\n } else if (value instanceof UnSafeHTML) {\n cache += value.html;\n } else if (value instanceof Error || typeof value == \"number\") {\n cache += value;\n } else if (Array.isArray(value)) {\n if (cache) {\n yield cache;\n cache = \"\";\n }\n yield* sanitizeArray(value);\n } else if ((value as any)?.[Symbol.iterator]) {\n if (cache) {\n yield cache;\n cache = \"\";\n }\n yield* value as Generator;\n } else {\n yield value;\n }\n cache += templates[index + 1];\n }\n if (cache) {\n yield cache;\n cache = \"\";\n }\n}\n","export async function promisedValue(value: Promise<any>): Promise<any> {\n try {\n return await value;\n } catch (error) {\n if (error instanceof Promise) {\n return promisedValue(error);\n } else {\n return error;\n }\n }\n}\n","export async function streamHTML(\n readable: ReadableStream<string>,\n controller: ReadableStreamDefaultController,\n) {\n const stream: ReadableStreamDefaultReader = readable.getReader();\n try {\n while (true) {\n let data = await stream.read();\n if (data.done) {\n return;\n }\n controller.enqueue(data.value);\n }\n } catch (error) {\n controller.enqueue(error);\n } finally {\n stream.releaseLock();\n }\n}\n","import { UnSafeHTML } from \"../utils/UnSafeHTML\";\nimport { escapeHTML } from \"../utils/escapehtml\";\nimport { sanitizeArray } from \"../utils/sanitizeArray\";\nimport { promisedValue } from \"../utils/promisedValue\";\nimport { streamHTML } from \"../utils/streamHTML\";\n\n/**\n * A generator function that processes an HTML template with embedded values and yields the resulting HTML as a stream. It handles various types of values, including strings, UnSafeHTML instances, errors, numbers, promises, arrays, and iterables. The function ensures that string values are properly escaped to prevent XSS vulnerabilities, while allowing UnSafeHTML instances to be included as-is. It also supports asynchronous values by yielding promises and waiting for their resolution before processing them further.\n *\n * @param {Generator} templateGenerator\n * @param {ReadableStreamDefaultController} controller\n * @returns {IterableIterator<string>} An iterator that yields the resulting HTML as a stream.\n */\nfunction* processHTML(\n templateGenerator: Generator | Array<TemplateValues>,\n controller: ReadableStreamDefaultController<string>,\n): any {\n let cache: string = \"\";\n for (const value of templateGenerator) {\n if (typeof value == \"string\") {\n cache += value;\n } else if (value instanceof UnSafeHTML) {\n cache += value.html;\n } else if (value instanceof Error || typeof value == \"number\") {\n cache += value;\n } else if (value instanceof Promise) {\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n let resolvedValue = yield value;\n if (typeof resolvedValue == \"string\") {\n cache += escapeHTML(resolvedValue);\n } else if (resolvedValue instanceof UnSafeHTML) {\n cache += resolvedValue.html;\n } else if (\n resolvedValue instanceof Error ||\n typeof resolvedValue == \"number\"\n ) {\n cache += resolvedValue;\n } else if (Array.isArray(resolvedValue)) {\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n yield* processHTML(sanitizeArray(resolvedValue), controller);\n } else if (resolvedValue?.[Symbol.iterator]) {\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n yield* processHTML(resolvedValue, controller);\n } else if (resolvedValue == undefined) {\n continue;\n } else {\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n let resolvedValues = yield resolvedValue;\n void resolvedValues\n }\n } else if (Array.isArray(value)) {\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n yield* processHTML(sanitizeArray(value), controller);\n } else if (value?.[Symbol.iterator]) {\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n yield* processHTML(value, controller);\n } else if (value == undefined) {\n continue;\n } else {\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n let resolvedValue = yield value;\n void resolvedValue\n }\n }\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n}\n\n/**\n * A function that renders an HTML template generator and returns a ReadableStream that yields the resulting HTML as a stream. It uses the processHTML generator function to process the template and handle various types of values, including promises and streams, while ensuring that string values are properly escaped to prevent XSS vulnerabilities.\n *\n * @param {Generator} generator - The HTML template generator to render.\n * @returns {ReadableStream} A ReadableStream that yields the resulting HTML as a stream.\n */\nfunction renderStream(generator: Generator) {\n return new ReadableStream<string>({\n start(controller) {\n let templateGenerator = processHTML(generator, controller);\n return startHTMLStream(templateGenerator);\n async function startHTMLStream(\n value:\n | undefined\n | Promise<any>\n | Request\n | ReadableStream\n | Response = undefined,\n ) {\n let data = templateGenerator.next(value);\n try {\n if (data.value instanceof Promise) {\n let resolvedValue = await promisedValue(data.value);\n return startHTMLStream(resolvedValue);\n } else if (data.value instanceof Response) {\n await streamHTML(data.value.body.pipeThrough(new TextDecoderStream()), controller);\n return startHTMLStream();\n } else if (data.value instanceof ReadableStream) {\n await streamHTML(data.value, controller);\n return startHTMLStream();\n } else if (data.value instanceof Request) {\n let response:Response = await fetch(data.value),\n stream = response.body;\n if (stream) {\n await streamHTML(stream.pipeThrough(new TextDecoderStream()), controller);\n }\n return startHTMLStream();\n }\n } catch (error) {\n controller.enqueue(error as string);\n return startHTMLStream();\n }\n controller.close();\n }\n },\n });\n}\n/**\n * renders an HTML template generator and returns a promise that resolves to the resulting HTML as a string.\n *\n * @async\n * @param {Generator} generator\n * @returns {Promise<string>} A promise that resolves to the resulting HTML as a string.\n */\nasync function renderAsString(generator: Generator): Promise<string> {\n try {\n let readable = renderStream(generator).getReader(),\n html = \"\";\n while (true) {\n let data = await readable.read();\n if (data.done) {\n readable.releaseLock();\n break;\n }\n html += data.value;\n }\n return html;\n } catch (error) {\n throw error;\n }\n}\nexport { renderStream, renderAsString };\n","import { cachableHTML } from \"./html/cachehtml\";\nimport { liveHTML } from \"./html/livehtml\";\nimport { UnSafeHTML } from \"./utils/UnSafeHTML\";\nimport { renderStream, renderAsString } from \"./html/html\";\nimport { escapeHTML } from \"./utils/escapehtml\";\n\n/**\n * Renders an HTML template and sends it as a response\n *\n * @param {HTMLTemplate} template - HTML template to render\n * @param {{}} [headers={}] - Headers to send with the response\n * @param {number} [status=200] - HTTP status code\n * @param {string} [statusText='OK'] - HTTP status text\n * @returns {Response} - The rendered HTML response\n */\nfunction render(\n template: Generator,\n headers = {},\n status = 200,\n statusText = \"OK\",\n): Response {\n let responseHeaders = Object.assign(\n { \"Content-Type\": \"text/html; charset=utf-8\" },\n headers,\n );\n return new Response(\n renderStream(template).pipeThrough(new TextEncoderStream()),\n { headers: responseHeaders, status, statusText },\n );\n}\nexport {\n render,\n renderAsString,\n renderStream,\n liveHTML,\n cachableHTML as html,\n UnSafeHTML,\n escapeHTML,\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.iife.js","names":[],"sources":["../../src/utils/escapehtml.ts","../../src/utils/sanitizeArray.ts","../../src/utils/UnSafeHTML.ts","../../src/html/cachehtml.ts","../../src/html/livehtml.ts","../../src/utils/promisedValue.ts","../../src/utils/streamHTML.ts","../../src/html/html.ts","../../src/index.browser.ts"],"sourcesContent":["/**\n * Escapes HTML special characters in a string to prevent XSS attacks and ensure proper rendering in HTML.\n *\n * @param {string} str - The string to escape\n *\n * @returns {string} - The escaped string\n */\nexport function escapeHTML(str: string): string {\n return String(str).replace(/[&<>\"']/g, (char: string) => {\n switch (char) {\n case \"&\":\n return \"&amp;\";\n case \"<\":\n return \"&lt;\";\n case \">\":\n return \"&gt;\";\n case '\"':\n return \"&quot;\";\n case \"'\":\n return \"&#39;\";\n default:\n return char;\n }\n });\n}\n","import { escapeHTML } from \"./escapehtml\";\n\nexport function sanitizeArray(values: any[]): any[] {\n let index = values.length;\n while (index--) {\n let value = values[index];\n if (typeof value == \"string\") {\n values[index] = escapeHTML(value);\n }\n }\n return values;\n}\n","export class UnSafeHTML {\n public html: string;\n /**\n * Creates unsafe html that will not be escaped\n *\n * @param {string} html - string containing unsafe html\n */\n constructor(html: string) {\n this.html = html;\n }\n}\n","import { escapeHTML } from \"../utils/escapehtml\";\nimport { sanitizeArray } from \"../utils/sanitizeArray\";\nimport { UnSafeHTML } from \"../utils/UnSafeHTML\";\n\ntype GeneratorFunctionConstructor = new (\n ...args: string[]\n) => (...args: any[]) => Generator<any, any, any>;\nconst TemplateConstructor = function* () {}\n .constructor as GeneratorFunctionConstructor,\n templateCache = new WeakMap();\n\n/**\n * A function that generates the source code for a compiled HTML template function.\n *\n * @param {String[]} templates\n * @param {Array} values\n * @returns {string} source code of the compiled template function that can be called with the appropriate arguments to produce the final HTML output based on the provided templates and values.\n */\nfunction generateTemplateSourceCode(\n templates: TemplateStringsArray,\n values: TemplateValues[],\n): string {\n let sourceCode = `yield \\`${templates[0]}\\``,\n length = values.length;\n for (let index = 0; index < length; index++) {\n let value = values[index];\n if (typeof value == \"string\") {\n sourceCode += `+escapeHTML(args[${index}])+\\`${templates[index + 1]}\\``;\n } else if (value instanceof UnSafeHTML) {\n sourceCode += `+args[${index}].html+\\`${templates[index + 1]}\\``;\n } else if (value instanceof Error || typeof value == \"number\") {\n sourceCode += `+args[${index}]+\\`${templates[index + 1]}\\``;\n } else if (Array.isArray(value)) {\n sourceCode += `; yield * sanitizeArray(args[${index}]); yield \\`${templates[index + 1]}\\``;\n } else if ((value as any)?.[Symbol.iterator]) {\n sourceCode += `; yield * args[${index}]; yield \\`${templates[index + 1]}\\``;\n } else {\n sourceCode += `; yield args[${index}]; yield \\`${templates[index + 1]}\\``;\n }\n }\n return sourceCode;\n}\n/**\n * compiles an HTML template into a function that can be cached and reused with different values. It generates source code for the template by processing the provided templates and values, handling various types of values such as strings, UnSafeHTML instances, errors, numbers, arrays, and iterables. The generated source code is then used to create a new function using the TemplateConstructor, which can be called with the appropriate arguments to produce the final HTML output. This approach allows for efficient rendering of HTML templates while ensuring that string values are properly escaped to prevent XSS vulnerabilities.\n *\n * @param {String[]} templates\n * @param {Array} values\n * @returns {GeneratorFunction} A generator function that can be called with the appropriate arguments to produce the final HTML output based on the provided templates and values.\n */\nfunction compileTemplate(\n templates: TemplateStringsArray,\n values: TemplateValues[],\n) {\n let sourceCode = generateTemplateSourceCode(templates, values);\n return new TemplateConstructor(\n \"escapeHTML\",\n \"sanitizeArray\",\n \"args\",\n sourceCode,\n );\n}\n/**\n * A function that renders an HTML template with caching capabilities. It checks if a compiled template function already exists in the cache for the given templates. If it does, it calls the cached function with the provided values and returns the result. If not, it compiles a new template function using the compileTemplate function, stores it in the cache, and then calls it with the provided values. This allows for efficient rendering of HTML templates while ensuring that string values are properly escaped to prevent XSS vulnerabilities.\n *\n * @param {String[]} templates\n * @param {...(String|UnSafeHTML|Error|number|Array|Iterable)} values\n * @returns {GeneratorFunction} A generator function that can be called with the appropriate arguments to produce the final HTML output based on the provided templates and values.\n */\nfunction cachableHTML(\n templates: TemplateStringsArray,\n ...values: TemplateValues[]\n) {\n let template = templateCache.get(templates);\n if (template) {\n return template(escapeHTML, sanitizeArray, values);\n }\n template = compileTemplate(templates, values);\n templateCache.set(templates, template);\n return template(escapeHTML, sanitizeArray, values);\n}\n\nexport { cachableHTML };\n","import { UnSafeHTML } from \"../utils/UnSafeHTML\";\nimport { escapeHTML } from \"../utils/escapehtml\";\nimport { sanitizeArray } from \"../utils/sanitizeArray\";\n\n/**\n * A generator function that processes an HTML template without caching. It handles various types of values, including strings, UnSafeHTML instances, errors, numbers, promises, arrays, and iterables. The function ensures that string values are properly escaped to prevent XSS vulnerabilities, while allowing UnSafeHTML instances to be included as-is. It also supports asynchronous values by yielding promises and waiting for their resolution before processing them further.\n *\n * @export\n * @param {String[]} templates\n * @param {...TemplateValues} values\n * @returns {Generator} A generator that yields processed HTML content as a stream.\n */\nexport function* liveHTML(\n templates: TemplateStringsArray,\n ...values: TemplateValues[]\n) {\n let cache = templates[0],\n length = values.length;\n for (let index = 0; index < length; index++) {\n let value = values[index];\n if (typeof value == \"string\") {\n cache += escapeHTML(value);\n } else if (value instanceof UnSafeHTML) {\n cache += value.html;\n } else if (value instanceof Error || typeof value == \"number\") {\n cache += value;\n } else if (Array.isArray(value)) {\n if (cache) {\n yield cache;\n cache = \"\";\n }\n yield* sanitizeArray(value);\n } else if ((value as any)?.[Symbol.iterator]) {\n if (cache) {\n yield cache;\n cache = \"\";\n }\n yield* value as Generator;\n } else {\n yield value;\n }\n cache += templates[index + 1];\n }\n if (cache) {\n yield cache;\n cache = \"\";\n }\n}\n","export async function promisedValue(value: Promise<any>): Promise<any> {\n try {\n return await value;\n } catch (error) {\n if (error instanceof Promise) {\n return promisedValue(error);\n } else {\n return error;\n }\n }\n}\n","export async function streamHTML(\n readable: ReadableStream<string>,\n controller: ReadableStreamDefaultController,\n) {\n const stream: ReadableStreamDefaultReader = readable.getReader();\n try {\n while (true) {\n let data = await stream.read();\n if (data.done) {\n return;\n }\n controller.enqueue(data.value);\n }\n } catch (error) {\n controller.enqueue(error);\n } finally {\n stream.releaseLock();\n }\n}\n","import { UnSafeHTML } from \"../utils/UnSafeHTML\";\nimport { escapeHTML } from \"../utils/escapehtml\";\nimport { sanitizeArray } from \"../utils/sanitizeArray\";\nimport { promisedValue } from \"../utils/promisedValue\";\nimport { streamHTML } from \"../utils/streamHTML\";\n\n/**\n * A generator function that processes an HTML template with embedded values and yields the resulting HTML as a stream. It handles various types of values, including strings, UnSafeHTML instances, errors, numbers, promises, arrays, and iterables. The function ensures that string values are properly escaped to prevent XSS vulnerabilities, while allowing UnSafeHTML instances to be included as-is. It also supports asynchronous values by yielding promises and waiting for their resolution before processing them further.\n *\n * @param {Generator} templateGenerator\n * @param {ReadableStreamDefaultController} controller\n * @returns {IterableIterator<string>} An iterator that yields the resulting HTML as a stream.\n */\nfunction* processHTML(\n templateGenerator: Generator | Array<TemplateValues>,\n controller: ReadableStreamDefaultController<string>,\n): any {\n let cache: string = \"\";\n for (const value of templateGenerator) {\n if (typeof value == \"string\") {\n cache += value;\n } else if (value instanceof UnSafeHTML) {\n cache += value.html;\n } else if (value instanceof Error || typeof value == \"number\") {\n cache += value;\n } else if (value instanceof Promise) {\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n let resolvedValue = yield value;\n if (typeof resolvedValue == \"string\") {\n cache += escapeHTML(resolvedValue);\n } else if (resolvedValue instanceof UnSafeHTML) {\n cache += resolvedValue.html;\n } else if (\n resolvedValue instanceof Error ||\n typeof resolvedValue == \"number\"\n ) {\n cache += resolvedValue;\n } else if (Array.isArray(resolvedValue)) {\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n yield* processHTML(sanitizeArray(resolvedValue), controller);\n } else if (resolvedValue?.[Symbol.iterator]) {\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n yield* processHTML(resolvedValue, controller);\n } else if (resolvedValue == undefined) {\n continue;\n } else {\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n let resolvedValues = yield resolvedValue;\n void resolvedValues\n }\n } else if (Array.isArray(value)) {\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n yield* processHTML(sanitizeArray(value), controller);\n } else if (value?.[Symbol.iterator]) {\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n yield* processHTML(value, controller);\n } else if (value == undefined) {\n continue;\n } else {\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n let resolvedValue = yield value;\n void resolvedValue\n }\n }\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n}\n\n/**\n * A function that renders an HTML template generator and returns a ReadableStream that yields the resulting HTML as a stream. It uses the processHTML generator function to process the template and handle various types of values, including promises and streams, while ensuring that string values are properly escaped to prevent XSS vulnerabilities.\n *\n * @param {Generator} generator - The HTML template generator to render.\n * @returns {ReadableStream} A ReadableStream that yields the resulting HTML as a stream.\n */\nfunction renderStream(generator: Generator) {\n return new ReadableStream<string>({\n start(controller) {\n let templateGenerator = processHTML(generator, controller);\n return startHTMLStream(templateGenerator);\n async function startHTMLStream(\n value:\n | undefined\n | Promise<any>\n | Request\n | ReadableStream\n | Response = undefined,\n ) {\n let data = templateGenerator.next(value);\n try {\n if (data.value instanceof Promise) {\n let resolvedValue = await promisedValue(data.value);\n return startHTMLStream(resolvedValue);\n } else if (data.value instanceof Response) {\n await streamHTML(data.value.body.pipeThrough(new TextDecoderStream()), controller);\n return startHTMLStream();\n } else if (data.value instanceof ReadableStream) {\n await streamHTML(data.value, controller);\n return startHTMLStream();\n } else if (data.value instanceof Request) {\n let response:Response = await fetch(data.value),\n stream = response.body;\n if (stream) {\n await streamHTML(stream.pipeThrough(new TextDecoderStream()), controller);\n }\n return startHTMLStream();\n }\n } catch (error) {\n controller.enqueue(error as string);\n return startHTMLStream();\n }\n controller.close();\n }\n },\n });\n}\n/**\n * renders an HTML template generator and returns a promise that resolves to the resulting HTML as a string.\n *\n * @async\n * @param {Generator} generator\n * @returns {Promise<string>} A promise that resolves to the resulting HTML as a string.\n */\nasync function renderAsString(generator: Generator): Promise<string> {\n try {\n let readable = renderStream(generator).getReader(),\n html = \"\";\n while (true) {\n let data = await readable.read();\n if (data.done) {\n readable.releaseLock();\n break;\n }\n html += data.value;\n }\n return html;\n } catch (error) {\n throw error;\n }\n}\nexport { renderStream, renderAsString };\n","import { cachableHTML } from \"./html/cachehtml\";\nimport { liveHTML } from \"./html/livehtml\";\nimport { UnSafeHTML } from \"./utils/UnSafeHTML\";\nimport { renderStream, renderAsString } from \"./html/html\";\nimport { escapeHTML } from \"./utils/escapehtml\";\n\n/**\n * Renders an HTML template and sends it as a response\n *\n * @param {HTMLTemplate} template - HTML template to render\n * @param {{}} [headers={}] - Headers to send with the response\n * @param {number} [status=200] - HTTP status code\n * @param {string} [statusText='OK'] - HTTP status text\n * @returns {Response} - The rendered HTML response\n */\nfunction render(\n template: Generator,\n headers = {},\n status = 200,\n statusText = \"OK\",\n): Response {\n let responseHeaders = Object.assign(\n { \"Content-Type\": \"text/html; charset=utf-8\",\"X-Accel-Buffering\": \"no\" },\n headers,\n );\n return new Response(\n renderStream(template).pipeThrough(new TextEncoderStream()),\n { headers: responseHeaders, status, statusText },\n );\n}\nexport {\n render,\n renderAsString,\n renderStream,\n liveHTML,\n cachableHTML as html,\n UnSafeHTML,\n escapeHTML,\n};\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- function e(e){return String(e).replace(/[&<>"']/g,e=>{switch(e){case`&`:return`&amp;`;case`<`:return`&lt;`;case`>`:return`&gt;`;case`"`:return`&quot;`;case`'`:return`&#39;`;default:return e}})}function t(t){let n=t.length;for(;n--;){let r=t[n];typeof r==`string`&&(t[n]=e(r))}return t}var n=class{html;constructor(e){this.html=e}};const r=function*(){}.constructor,i=new WeakMap;function a(e,t){let r=`yield \`${e[0]}\``,i=t.length;for(let a=0;a<i;a++){let i=t[a];typeof i==`string`?r+=`+escapeHTML(args[${a}])+\`${e[a+1]}\``:i instanceof n?r+=`+args[${a}].html+\`${e[a+1]}\``:i instanceof Error||typeof i==`number`?r+=`+args[${a}]+\`${e[a+1]}\``:Array.isArray(i)?r+=`; yield * sanitizeArray(args[${a}]); yield \`${e[a+1]}\``:i?.[Symbol.iterator]?r+=`; yield * args[${a}]; yield \`${e[a+1]}\``:r+=`; yield args[${a}]; yield \`${e[a+1]}\``}return r}function o(e,t){let n=a(e,t);return new r(`escapeHTML`,`sanitizeArray`,`args`,n)}function s(n,...r){let a=i.get(n);return a?a(e,t,r):(a=o(n,r),i.set(n,a),a(e,t,r))}function*c(r,...i){let a=r[0],o=i.length;for(let s=0;s<o;s++){let o=i[s];typeof o==`string`?a+=e(o):o instanceof n?a+=o.html:o instanceof Error||typeof o==`number`?a+=o:Array.isArray(o)?(a&&=(yield a,``),yield*t(o)):o?.[Symbol.iterator]?(a&&=(yield a,``),yield*o):yield o,a+=r[s+1]}a&&=(yield a,``)}async function l(e){try{return await e}catch(e){return e instanceof Promise?l(e):e}}async function u(e,t){let n=e.getReader();try{for(;;){let e=await n.read();if(e.done)return;t.enqueue(e.value)}}catch(e){t.enqueue(e)}finally{n.releaseLock()}}function*d(r,i){let a=``;for(let o of r)if(typeof o==`string`)a+=o;else if(o instanceof n)a+=o.html;else if(o instanceof Error||typeof o==`number`)a+=o;else if(o instanceof Promise){a&&=(i.enqueue(a),``);let r=yield o;if(typeof r==`string`)a+=e(r);else if(r instanceof n)a+=r.html;else if(r instanceof Error||typeof r==`number`)a+=r;else if(Array.isArray(r))a&&=(i.enqueue(a),``),yield*d(t(r),i);else if(r?.[Symbol.iterator])a&&=(i.enqueue(a),``),yield*d(r,i);else if(r==null)continue;else a&&=(i.enqueue(a),``),yield r}else if(Array.isArray(o))a&&=(i.enqueue(a),``),yield*d(t(o),i);else if(o?.[Symbol.iterator])a&&=(i.enqueue(a),``),yield*d(o,i);else if(o==null)continue;else a&&=(i.enqueue(a),``),yield o;a&&=(i.enqueue(a),``)}function f(e){return new ReadableStream({start(t){let n=d(e,t);return r(n);async function r(e=void 0){let i=n.next(e);try{if(i.value instanceof Promise)return r(await l(i.value));if(i.value instanceof Response)return await u(i.value.body.pipeThrough(new TextDecoderStream),t),r();if(i.value instanceof ReadableStream)return await u(i.value,t),r();if(i.value instanceof Request){let e=(await fetch(i.value)).body;return e&&await u(e.pipeThrough(new TextDecoderStream),t),r()}}catch(e){return t.enqueue(e),r()}t.close()}}})}async function p(e){try{let t=f(e).getReader(),n=``;for(;;){let e=await t.read();if(e.done){t.releaseLock();break}n+=e.value}return n}catch(e){throw e}}function m(e,t={},n=200,r=`OK`){let i=Object.assign({"Content-Type":`text/html; charset=utf-8`},t);return new Response(f(e).pipeThrough(new TextEncoderStream),{headers:i,status:n,statusText:r})}export{n as UnSafeHTML,e as escapeHTML,s as html,c as liveHTML,m as render,p as renderAsString,f as renderStream};
1
+ function e(e){return String(e).replace(/[&<>"']/g,e=>{switch(e){case`&`:return`&amp;`;case`<`:return`&lt;`;case`>`:return`&gt;`;case`"`:return`&quot;`;case`'`:return`&#39;`;default:return e}})}function t(t){let n=t.length;for(;n--;){let r=t[n];typeof r==`string`&&(t[n]=e(r))}return t}var n=class{html;constructor(e){this.html=e}};const r=function*(){}.constructor,i=new WeakMap;function a(e,t){let r=`yield \`${e[0]}\``,i=t.length;for(let a=0;a<i;a++){let i=t[a];typeof i==`string`?r+=`+escapeHTML(args[${a}])+\`${e[a+1]}\``:i instanceof n?r+=`+args[${a}].html+\`${e[a+1]}\``:i instanceof Error||typeof i==`number`?r+=`+args[${a}]+\`${e[a+1]}\``:Array.isArray(i)?r+=`; yield * sanitizeArray(args[${a}]); yield \`${e[a+1]}\``:i?.[Symbol.iterator]?r+=`; yield * args[${a}]; yield \`${e[a+1]}\``:r+=`; yield args[${a}]; yield \`${e[a+1]}\``}return r}function o(e,t){let n=a(e,t);return new r(`escapeHTML`,`sanitizeArray`,`args`,n)}function s(n,...r){let a=i.get(n);return a?a(e,t,r):(a=o(n,r),i.set(n,a),a(e,t,r))}function*c(r,...i){let a=r[0],o=i.length;for(let s=0;s<o;s++){let o=i[s];typeof o==`string`?a+=e(o):o instanceof n?a+=o.html:o instanceof Error||typeof o==`number`?a+=o:Array.isArray(o)?(a&&=(yield a,``),yield*t(o)):o?.[Symbol.iterator]?(a&&=(yield a,``),yield*o):yield o,a+=r[s+1]}a&&=(yield a,``)}async function l(e){try{return await e}catch(e){return e instanceof Promise?l(e):e}}async function u(e,t){let n=e.getReader();try{for(;;){let e=await n.read();if(e.done)return;t.enqueue(e.value)}}catch(e){t.enqueue(e)}finally{n.releaseLock()}}function*d(r,i){let a=``;for(let o of r)if(typeof o==`string`)a+=o;else if(o instanceof n)a+=o.html;else if(o instanceof Error||typeof o==`number`)a+=o;else if(o instanceof Promise){a&&=(i.enqueue(a),``);let r=yield o;if(typeof r==`string`)a+=e(r);else if(r instanceof n)a+=r.html;else if(r instanceof Error||typeof r==`number`)a+=r;else if(Array.isArray(r))a&&=(i.enqueue(a),``),yield*d(t(r),i);else if(r?.[Symbol.iterator])a&&=(i.enqueue(a),``),yield*d(r,i);else if(r==null)continue;else a&&=(i.enqueue(a),``),yield r}else if(Array.isArray(o))a&&=(i.enqueue(a),``),yield*d(t(o),i);else if(o?.[Symbol.iterator])a&&=(i.enqueue(a),``),yield*d(o,i);else if(o==null)continue;else a&&=(i.enqueue(a),``),yield o;a&&=(i.enqueue(a),``)}function f(e){return new ReadableStream({start(t){let n=d(e,t);return r(n);async function r(e=void 0){let i=n.next(e);try{if(i.value instanceof Promise)return r(await l(i.value));if(i.value instanceof Response)return await u(i.value.body.pipeThrough(new TextDecoderStream),t),r();if(i.value instanceof ReadableStream)return await u(i.value,t),r();if(i.value instanceof Request){let e=(await fetch(i.value)).body;return e&&await u(e.pipeThrough(new TextDecoderStream),t),r()}}catch(e){return t.enqueue(e),r()}t.close()}}})}async function p(e){try{let t=f(e).getReader(),n=``;for(;;){let e=await t.read();if(e.done){t.releaseLock();break}n+=e.value}return n}catch(e){throw e}}function m(e,t={},n=200,r=`OK`){let i=Object.assign({"Content-Type":`text/html; charset=utf-8`,"X-Accel-Buffering":`no`},t);return new Response(f(e).pipeThrough(new TextEncoderStream),{headers:i,status:n,statusText:r})}export{n as UnSafeHTML,e as escapeHTML,s as html,c as liveHTML,m as render,p as renderAsString,f as renderStream};
2
2
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../src/utils/escapehtml.ts","../../src/utils/sanitizeArray.ts","../../src/utils/UnSafeHTML.ts","../../src/html/cachehtml.ts","../../src/html/livehtml.ts","../../src/utils/promisedValue.ts","../../src/utils/streamHTML.ts","../../src/html/html.ts","../../src/index.browser.ts"],"sourcesContent":["/**\n * Escapes HTML special characters in a string to prevent XSS attacks and ensure proper rendering in HTML.\n *\n * @param {string} str - The string to escape\n *\n * @returns {string} - The escaped string\n */\nexport function escapeHTML(str: string): string {\n return String(str).replace(/[&<>\"']/g, (char: string) => {\n switch (char) {\n case \"&\":\n return \"&amp;\";\n case \"<\":\n return \"&lt;\";\n case \">\":\n return \"&gt;\";\n case '\"':\n return \"&quot;\";\n case \"'\":\n return \"&#39;\";\n default:\n return char;\n }\n });\n}\n","import { escapeHTML } from \"./escapehtml\";\n\nexport function sanitizeArray(values: any[]): any[] {\n let index = values.length;\n while (index--) {\n let value = values[index];\n if (typeof value == \"string\") {\n values[index] = escapeHTML(value);\n }\n }\n return values;\n}\n","export class UnSafeHTML {\n public html: string;\n /**\n * Creates unsafe html that will not be escaped\n *\n * @param {string} html - string containing unsafe html\n */\n constructor(html: string) {\n this.html = html;\n }\n}\n","import { escapeHTML } from \"../utils/escapehtml\";\nimport { sanitizeArray } from \"../utils/sanitizeArray\";\nimport { UnSafeHTML } from \"../utils/UnSafeHTML\";\n\ntype GeneratorFunctionConstructor = new (\n ...args: string[]\n) => (...args: any[]) => Generator<any, any, any>;\nconst TemplateConstructor = function* () {}\n .constructor as GeneratorFunctionConstructor,\n templateCache = new WeakMap();\n\n/**\n * A function that generates the source code for a compiled HTML template function.\n *\n * @param {String[]} templates\n * @param {Array} values\n * @returns {string} source code of the compiled template function that can be called with the appropriate arguments to produce the final HTML output based on the provided templates and values.\n */\nfunction generateTemplateSourceCode(\n templates: TemplateStringsArray,\n values: TemplateValues[],\n): string {\n let sourceCode = `yield \\`${templates[0]}\\``,\n length = values.length;\n for (let index = 0; index < length; index++) {\n let value = values[index];\n if (typeof value == \"string\") {\n sourceCode += `+escapeHTML(args[${index}])+\\`${templates[index + 1]}\\``;\n } else if (value instanceof UnSafeHTML) {\n sourceCode += `+args[${index}].html+\\`${templates[index + 1]}\\``;\n } else if (value instanceof Error || typeof value == \"number\") {\n sourceCode += `+args[${index}]+\\`${templates[index + 1]}\\``;\n } else if (Array.isArray(value)) {\n sourceCode += `; yield * sanitizeArray(args[${index}]); yield \\`${templates[index + 1]}\\``;\n } else if ((value as any)?.[Symbol.iterator]) {\n sourceCode += `; yield * args[${index}]; yield \\`${templates[index + 1]}\\``;\n } else {\n sourceCode += `; yield args[${index}]; yield \\`${templates[index + 1]}\\``;\n }\n }\n return sourceCode;\n}\n/**\n * compiles an HTML template into a function that can be cached and reused with different values. It generates source code for the template by processing the provided templates and values, handling various types of values such as strings, UnSafeHTML instances, errors, numbers, arrays, and iterables. The generated source code is then used to create a new function using the TemplateConstructor, which can be called with the appropriate arguments to produce the final HTML output. This approach allows for efficient rendering of HTML templates while ensuring that string values are properly escaped to prevent XSS vulnerabilities.\n *\n * @param {String[]} templates\n * @param {Array} values\n * @returns {GeneratorFunction} A generator function that can be called with the appropriate arguments to produce the final HTML output based on the provided templates and values.\n */\nfunction compileTemplate(\n templates: TemplateStringsArray,\n values: TemplateValues[],\n) {\n let sourceCode = generateTemplateSourceCode(templates, values);\n return new TemplateConstructor(\n \"escapeHTML\",\n \"sanitizeArray\",\n \"args\",\n sourceCode,\n );\n}\n/**\n * A function that renders an HTML template with caching capabilities. It checks if a compiled template function already exists in the cache for the given templates. If it does, it calls the cached function with the provided values and returns the result. If not, it compiles a new template function using the compileTemplate function, stores it in the cache, and then calls it with the provided values. This allows for efficient rendering of HTML templates while ensuring that string values are properly escaped to prevent XSS vulnerabilities.\n *\n * @param {String[]} templates\n * @param {...(String|UnSafeHTML|Error|number|Array|Iterable)} values\n * @returns {GeneratorFunction} A generator function that can be called with the appropriate arguments to produce the final HTML output based on the provided templates and values.\n */\nfunction cachableHTML(\n templates: TemplateStringsArray,\n ...values: TemplateValues[]\n) {\n let template = templateCache.get(templates);\n if (template) {\n return template(escapeHTML, sanitizeArray, values);\n }\n template = compileTemplate(templates, values);\n templateCache.set(templates, template);\n return template(escapeHTML, sanitizeArray, values);\n}\n\nexport { cachableHTML };\n","import { UnSafeHTML } from \"../utils/UnSafeHTML\";\nimport { escapeHTML } from \"../utils/escapehtml\";\nimport { sanitizeArray } from \"../utils/sanitizeArray\";\n\n/**\n * A generator function that processes an HTML template without caching. It handles various types of values, including strings, UnSafeHTML instances, errors, numbers, promises, arrays, and iterables. The function ensures that string values are properly escaped to prevent XSS vulnerabilities, while allowing UnSafeHTML instances to be included as-is. It also supports asynchronous values by yielding promises and waiting for their resolution before processing them further.\n *\n * @export\n * @param {String[]} templates\n * @param {...TemplateValues} values\n * @returns {Generator} A generator that yields processed HTML content as a stream.\n */\nexport function* liveHTML(\n templates: TemplateStringsArray,\n ...values: TemplateValues[]\n) {\n let cache = templates[0],\n length = values.length;\n for (let index = 0; index < length; index++) {\n let value = values[index];\n if (typeof value == \"string\") {\n cache += escapeHTML(value);\n } else if (value instanceof UnSafeHTML) {\n cache += value.html;\n } else if (value instanceof Error || typeof value == \"number\") {\n cache += value;\n } else if (Array.isArray(value)) {\n if (cache) {\n yield cache;\n cache = \"\";\n }\n yield* sanitizeArray(value);\n } else if ((value as any)?.[Symbol.iterator]) {\n if (cache) {\n yield cache;\n cache = \"\";\n }\n yield* value as Generator;\n } else {\n yield value;\n }\n cache += templates[index + 1];\n }\n if (cache) {\n yield cache;\n cache = \"\";\n }\n}\n","export async function promisedValue(value: Promise<any>): Promise<any> {\n try {\n return await value;\n } catch (error) {\n if (error instanceof Promise) {\n return promisedValue(error);\n } else {\n return error;\n }\n }\n}\n","export async function streamHTML(\n readable: ReadableStream<string>,\n controller: ReadableStreamDefaultController,\n) {\n const stream: ReadableStreamDefaultReader = readable.getReader();\n try {\n while (true) {\n let data = await stream.read();\n if (data.done) {\n return;\n }\n controller.enqueue(data.value);\n }\n } catch (error) {\n controller.enqueue(error);\n } finally {\n stream.releaseLock();\n }\n}\n","import { UnSafeHTML } from \"../utils/UnSafeHTML\";\nimport { escapeHTML } from \"../utils/escapehtml\";\nimport { sanitizeArray } from \"../utils/sanitizeArray\";\nimport { promisedValue } from \"../utils/promisedValue\";\nimport { streamHTML } from \"../utils/streamHTML\";\n\n/**\n * A generator function that processes an HTML template with embedded values and yields the resulting HTML as a stream. It handles various types of values, including strings, UnSafeHTML instances, errors, numbers, promises, arrays, and iterables. The function ensures that string values are properly escaped to prevent XSS vulnerabilities, while allowing UnSafeHTML instances to be included as-is. It also supports asynchronous values by yielding promises and waiting for their resolution before processing them further.\n *\n * @param {Generator} templateGenerator\n * @param {ReadableStreamDefaultController} controller\n * @returns {IterableIterator<string>} An iterator that yields the resulting HTML as a stream.\n */\nfunction* processHTML(\n templateGenerator: Generator | Array<TemplateValues>,\n controller: ReadableStreamDefaultController<string>,\n): any {\n let cache: string = \"\";\n for (const value of templateGenerator) {\n if (typeof value == \"string\") {\n cache += value;\n } else if (value instanceof UnSafeHTML) {\n cache += value.html;\n } else if (value instanceof Error || typeof value == \"number\") {\n cache += value;\n } else if (value instanceof Promise) {\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n let resolvedValue = yield value;\n if (typeof resolvedValue == \"string\") {\n cache += escapeHTML(resolvedValue);\n } else if (resolvedValue instanceof UnSafeHTML) {\n cache += resolvedValue.html;\n } else if (\n resolvedValue instanceof Error ||\n typeof resolvedValue == \"number\"\n ) {\n cache += resolvedValue;\n } else if (Array.isArray(resolvedValue)) {\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n yield* processHTML(sanitizeArray(resolvedValue), controller);\n } else if (resolvedValue?.[Symbol.iterator]) {\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n yield* processHTML(resolvedValue, controller);\n } else if (resolvedValue == undefined) {\n continue;\n } else {\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n let resolvedValues = yield resolvedValue;\n void resolvedValues\n }\n } else if (Array.isArray(value)) {\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n yield* processHTML(sanitizeArray(value), controller);\n } else if (value?.[Symbol.iterator]) {\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n yield* processHTML(value, controller);\n } else if (value == undefined) {\n continue;\n } else {\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n let resolvedValue = yield value;\n void resolvedValue\n }\n }\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n}\n\n/**\n * A function that renders an HTML template generator and returns a ReadableStream that yields the resulting HTML as a stream. It uses the processHTML generator function to process the template and handle various types of values, including promises and streams, while ensuring that string values are properly escaped to prevent XSS vulnerabilities.\n *\n * @param {Generator} generator - The HTML template generator to render.\n * @returns {ReadableStream} A ReadableStream that yields the resulting HTML as a stream.\n */\nfunction renderStream(generator: Generator) {\n return new ReadableStream<string>({\n start(controller) {\n let templateGenerator = processHTML(generator, controller);\n return startHTMLStream(templateGenerator);\n async function startHTMLStream(\n value:\n | undefined\n | Promise<any>\n | Request\n | ReadableStream\n | Response = undefined,\n ) {\n let data = templateGenerator.next(value);\n try {\n if (data.value instanceof Promise) {\n let resolvedValue = await promisedValue(data.value);\n return startHTMLStream(resolvedValue);\n } else if (data.value instanceof Response) {\n await streamHTML(data.value.body.pipeThrough(new TextDecoderStream()), controller);\n return startHTMLStream();\n } else if (data.value instanceof ReadableStream) {\n await streamHTML(data.value, controller);\n return startHTMLStream();\n } else if (data.value instanceof Request) {\n let response:Response = await fetch(data.value),\n stream = response.body;\n if (stream) {\n await streamHTML(stream.pipeThrough(new TextDecoderStream()), controller);\n }\n return startHTMLStream();\n }\n } catch (error) {\n controller.enqueue(error as string);\n return startHTMLStream();\n }\n controller.close();\n }\n },\n });\n}\n/**\n * renders an HTML template generator and returns a promise that resolves to the resulting HTML as a string.\n *\n * @async\n * @param {Generator} generator\n * @returns {Promise<string>} A promise that resolves to the resulting HTML as a string.\n */\nasync function renderAsString(generator: Generator): Promise<string> {\n try {\n let readable = renderStream(generator).getReader(),\n html = \"\";\n while (true) {\n let data = await readable.read();\n if (data.done) {\n readable.releaseLock();\n break;\n }\n html += data.value;\n }\n return html;\n } catch (error) {\n throw error;\n }\n}\nexport { renderStream, renderAsString };\n","import { cachableHTML } from \"./html/cachehtml\";\nimport { liveHTML } from \"./html/livehtml\";\nimport { UnSafeHTML } from \"./utils/UnSafeHTML\";\nimport { renderStream, renderAsString } from \"./html/html\";\nimport { escapeHTML } from \"./utils/escapehtml\";\n\n/**\n * Renders an HTML template and sends it as a response\n *\n * @param {HTMLTemplate} template - HTML template to render\n * @param {{}} [headers={}] - Headers to send with the response\n * @param {number} [status=200] - HTTP status code\n * @param {string} [statusText='OK'] - HTTP status text\n * @returns {Response} - The rendered HTML response\n */\nfunction render(\n template: Generator,\n headers = {},\n status = 200,\n statusText = \"OK\",\n): Response {\n let responseHeaders = Object.assign(\n { \"Content-Type\": \"text/html; charset=utf-8\" },\n headers,\n );\n return new Response(\n renderStream(template).pipeThrough(new TextEncoderStream()),\n { headers: responseHeaders, status, statusText },\n );\n}\nexport {\n render,\n renderAsString,\n renderStream,\n liveHTML,\n cachableHTML as html,\n UnSafeHTML,\n escapeHTML,\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../src/utils/escapehtml.ts","../../src/utils/sanitizeArray.ts","../../src/utils/UnSafeHTML.ts","../../src/html/cachehtml.ts","../../src/html/livehtml.ts","../../src/utils/promisedValue.ts","../../src/utils/streamHTML.ts","../../src/html/html.ts","../../src/index.browser.ts"],"sourcesContent":["/**\n * Escapes HTML special characters in a string to prevent XSS attacks and ensure proper rendering in HTML.\n *\n * @param {string} str - The string to escape\n *\n * @returns {string} - The escaped string\n */\nexport function escapeHTML(str: string): string {\n return String(str).replace(/[&<>\"']/g, (char: string) => {\n switch (char) {\n case \"&\":\n return \"&amp;\";\n case \"<\":\n return \"&lt;\";\n case \">\":\n return \"&gt;\";\n case '\"':\n return \"&quot;\";\n case \"'\":\n return \"&#39;\";\n default:\n return char;\n }\n });\n}\n","import { escapeHTML } from \"./escapehtml\";\n\nexport function sanitizeArray(values: any[]): any[] {\n let index = values.length;\n while (index--) {\n let value = values[index];\n if (typeof value == \"string\") {\n values[index] = escapeHTML(value);\n }\n }\n return values;\n}\n","export class UnSafeHTML {\n public html: string;\n /**\n * Creates unsafe html that will not be escaped\n *\n * @param {string} html - string containing unsafe html\n */\n constructor(html: string) {\n this.html = html;\n }\n}\n","import { escapeHTML } from \"../utils/escapehtml\";\nimport { sanitizeArray } from \"../utils/sanitizeArray\";\nimport { UnSafeHTML } from \"../utils/UnSafeHTML\";\n\ntype GeneratorFunctionConstructor = new (\n ...args: string[]\n) => (...args: any[]) => Generator<any, any, any>;\nconst TemplateConstructor = function* () {}\n .constructor as GeneratorFunctionConstructor,\n templateCache = new WeakMap();\n\n/**\n * A function that generates the source code for a compiled HTML template function.\n *\n * @param {String[]} templates\n * @param {Array} values\n * @returns {string} source code of the compiled template function that can be called with the appropriate arguments to produce the final HTML output based on the provided templates and values.\n */\nfunction generateTemplateSourceCode(\n templates: TemplateStringsArray,\n values: TemplateValues[],\n): string {\n let sourceCode = `yield \\`${templates[0]}\\``,\n length = values.length;\n for (let index = 0; index < length; index++) {\n let value = values[index];\n if (typeof value == \"string\") {\n sourceCode += `+escapeHTML(args[${index}])+\\`${templates[index + 1]}\\``;\n } else if (value instanceof UnSafeHTML) {\n sourceCode += `+args[${index}].html+\\`${templates[index + 1]}\\``;\n } else if (value instanceof Error || typeof value == \"number\") {\n sourceCode += `+args[${index}]+\\`${templates[index + 1]}\\``;\n } else if (Array.isArray(value)) {\n sourceCode += `; yield * sanitizeArray(args[${index}]); yield \\`${templates[index + 1]}\\``;\n } else if ((value as any)?.[Symbol.iterator]) {\n sourceCode += `; yield * args[${index}]; yield \\`${templates[index + 1]}\\``;\n } else {\n sourceCode += `; yield args[${index}]; yield \\`${templates[index + 1]}\\``;\n }\n }\n return sourceCode;\n}\n/**\n * compiles an HTML template into a function that can be cached and reused with different values. It generates source code for the template by processing the provided templates and values, handling various types of values such as strings, UnSafeHTML instances, errors, numbers, arrays, and iterables. The generated source code is then used to create a new function using the TemplateConstructor, which can be called with the appropriate arguments to produce the final HTML output. This approach allows for efficient rendering of HTML templates while ensuring that string values are properly escaped to prevent XSS vulnerabilities.\n *\n * @param {String[]} templates\n * @param {Array} values\n * @returns {GeneratorFunction} A generator function that can be called with the appropriate arguments to produce the final HTML output based on the provided templates and values.\n */\nfunction compileTemplate(\n templates: TemplateStringsArray,\n values: TemplateValues[],\n) {\n let sourceCode = generateTemplateSourceCode(templates, values);\n return new TemplateConstructor(\n \"escapeHTML\",\n \"sanitizeArray\",\n \"args\",\n sourceCode,\n );\n}\n/**\n * A function that renders an HTML template with caching capabilities. It checks if a compiled template function already exists in the cache for the given templates. If it does, it calls the cached function with the provided values and returns the result. If not, it compiles a new template function using the compileTemplate function, stores it in the cache, and then calls it with the provided values. This allows for efficient rendering of HTML templates while ensuring that string values are properly escaped to prevent XSS vulnerabilities.\n *\n * @param {String[]} templates\n * @param {...(String|UnSafeHTML|Error|number|Array|Iterable)} values\n * @returns {GeneratorFunction} A generator function that can be called with the appropriate arguments to produce the final HTML output based on the provided templates and values.\n */\nfunction cachableHTML(\n templates: TemplateStringsArray,\n ...values: TemplateValues[]\n) {\n let template = templateCache.get(templates);\n if (template) {\n return template(escapeHTML, sanitizeArray, values);\n }\n template = compileTemplate(templates, values);\n templateCache.set(templates, template);\n return template(escapeHTML, sanitizeArray, values);\n}\n\nexport { cachableHTML };\n","import { UnSafeHTML } from \"../utils/UnSafeHTML\";\nimport { escapeHTML } from \"../utils/escapehtml\";\nimport { sanitizeArray } from \"../utils/sanitizeArray\";\n\n/**\n * A generator function that processes an HTML template without caching. It handles various types of values, including strings, UnSafeHTML instances, errors, numbers, promises, arrays, and iterables. The function ensures that string values are properly escaped to prevent XSS vulnerabilities, while allowing UnSafeHTML instances to be included as-is. It also supports asynchronous values by yielding promises and waiting for their resolution before processing them further.\n *\n * @export\n * @param {String[]} templates\n * @param {...TemplateValues} values\n * @returns {Generator} A generator that yields processed HTML content as a stream.\n */\nexport function* liveHTML(\n templates: TemplateStringsArray,\n ...values: TemplateValues[]\n) {\n let cache = templates[0],\n length = values.length;\n for (let index = 0; index < length; index++) {\n let value = values[index];\n if (typeof value == \"string\") {\n cache += escapeHTML(value);\n } else if (value instanceof UnSafeHTML) {\n cache += value.html;\n } else if (value instanceof Error || typeof value == \"number\") {\n cache += value;\n } else if (Array.isArray(value)) {\n if (cache) {\n yield cache;\n cache = \"\";\n }\n yield* sanitizeArray(value);\n } else if ((value as any)?.[Symbol.iterator]) {\n if (cache) {\n yield cache;\n cache = \"\";\n }\n yield* value as Generator;\n } else {\n yield value;\n }\n cache += templates[index + 1];\n }\n if (cache) {\n yield cache;\n cache = \"\";\n }\n}\n","export async function promisedValue(value: Promise<any>): Promise<any> {\n try {\n return await value;\n } catch (error) {\n if (error instanceof Promise) {\n return promisedValue(error);\n } else {\n return error;\n }\n }\n}\n","export async function streamHTML(\n readable: ReadableStream<string>,\n controller: ReadableStreamDefaultController,\n) {\n const stream: ReadableStreamDefaultReader = readable.getReader();\n try {\n while (true) {\n let data = await stream.read();\n if (data.done) {\n return;\n }\n controller.enqueue(data.value);\n }\n } catch (error) {\n controller.enqueue(error);\n } finally {\n stream.releaseLock();\n }\n}\n","import { UnSafeHTML } from \"../utils/UnSafeHTML\";\nimport { escapeHTML } from \"../utils/escapehtml\";\nimport { sanitizeArray } from \"../utils/sanitizeArray\";\nimport { promisedValue } from \"../utils/promisedValue\";\nimport { streamHTML } from \"../utils/streamHTML\";\n\n/**\n * A generator function that processes an HTML template with embedded values and yields the resulting HTML as a stream. It handles various types of values, including strings, UnSafeHTML instances, errors, numbers, promises, arrays, and iterables. The function ensures that string values are properly escaped to prevent XSS vulnerabilities, while allowing UnSafeHTML instances to be included as-is. It also supports asynchronous values by yielding promises and waiting for their resolution before processing them further.\n *\n * @param {Generator} templateGenerator\n * @param {ReadableStreamDefaultController} controller\n * @returns {IterableIterator<string>} An iterator that yields the resulting HTML as a stream.\n */\nfunction* processHTML(\n templateGenerator: Generator | Array<TemplateValues>,\n controller: ReadableStreamDefaultController<string>,\n): any {\n let cache: string = \"\";\n for (const value of templateGenerator) {\n if (typeof value == \"string\") {\n cache += value;\n } else if (value instanceof UnSafeHTML) {\n cache += value.html;\n } else if (value instanceof Error || typeof value == \"number\") {\n cache += value;\n } else if (value instanceof Promise) {\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n let resolvedValue = yield value;\n if (typeof resolvedValue == \"string\") {\n cache += escapeHTML(resolvedValue);\n } else if (resolvedValue instanceof UnSafeHTML) {\n cache += resolvedValue.html;\n } else if (\n resolvedValue instanceof Error ||\n typeof resolvedValue == \"number\"\n ) {\n cache += resolvedValue;\n } else if (Array.isArray(resolvedValue)) {\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n yield* processHTML(sanitizeArray(resolvedValue), controller);\n } else if (resolvedValue?.[Symbol.iterator]) {\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n yield* processHTML(resolvedValue, controller);\n } else if (resolvedValue == undefined) {\n continue;\n } else {\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n let resolvedValues = yield resolvedValue;\n void resolvedValues\n }\n } else if (Array.isArray(value)) {\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n yield* processHTML(sanitizeArray(value), controller);\n } else if (value?.[Symbol.iterator]) {\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n yield* processHTML(value, controller);\n } else if (value == undefined) {\n continue;\n } else {\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n let resolvedValue = yield value;\n void resolvedValue\n }\n }\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n}\n\n/**\n * A function that renders an HTML template generator and returns a ReadableStream that yields the resulting HTML as a stream. It uses the processHTML generator function to process the template and handle various types of values, including promises and streams, while ensuring that string values are properly escaped to prevent XSS vulnerabilities.\n *\n * @param {Generator} generator - The HTML template generator to render.\n * @returns {ReadableStream} A ReadableStream that yields the resulting HTML as a stream.\n */\nfunction renderStream(generator: Generator) {\n return new ReadableStream<string>({\n start(controller) {\n let templateGenerator = processHTML(generator, controller);\n return startHTMLStream(templateGenerator);\n async function startHTMLStream(\n value:\n | undefined\n | Promise<any>\n | Request\n | ReadableStream\n | Response = undefined,\n ) {\n let data = templateGenerator.next(value);\n try {\n if (data.value instanceof Promise) {\n let resolvedValue = await promisedValue(data.value);\n return startHTMLStream(resolvedValue);\n } else if (data.value instanceof Response) {\n await streamHTML(data.value.body.pipeThrough(new TextDecoderStream()), controller);\n return startHTMLStream();\n } else if (data.value instanceof ReadableStream) {\n await streamHTML(data.value, controller);\n return startHTMLStream();\n } else if (data.value instanceof Request) {\n let response:Response = await fetch(data.value),\n stream = response.body;\n if (stream) {\n await streamHTML(stream.pipeThrough(new TextDecoderStream()), controller);\n }\n return startHTMLStream();\n }\n } catch (error) {\n controller.enqueue(error as string);\n return startHTMLStream();\n }\n controller.close();\n }\n },\n });\n}\n/**\n * renders an HTML template generator and returns a promise that resolves to the resulting HTML as a string.\n *\n * @async\n * @param {Generator} generator\n * @returns {Promise<string>} A promise that resolves to the resulting HTML as a string.\n */\nasync function renderAsString(generator: Generator): Promise<string> {\n try {\n let readable = renderStream(generator).getReader(),\n html = \"\";\n while (true) {\n let data = await readable.read();\n if (data.done) {\n readable.releaseLock();\n break;\n }\n html += data.value;\n }\n return html;\n } catch (error) {\n throw error;\n }\n}\nexport { renderStream, renderAsString };\n","import { cachableHTML } from \"./html/cachehtml\";\nimport { liveHTML } from \"./html/livehtml\";\nimport { UnSafeHTML } from \"./utils/UnSafeHTML\";\nimport { renderStream, renderAsString } from \"./html/html\";\nimport { escapeHTML } from \"./utils/escapehtml\";\n\n/**\n * Renders an HTML template and sends it as a response\n *\n * @param {HTMLTemplate} template - HTML template to render\n * @param {{}} [headers={}] - Headers to send with the response\n * @param {number} [status=200] - HTTP status code\n * @param {string} [statusText='OK'] - HTTP status text\n * @returns {Response} - The rendered HTML response\n */\nfunction render(\n template: Generator,\n headers = {},\n status = 200,\n statusText = \"OK\",\n): Response {\n let responseHeaders = Object.assign(\n { \"Content-Type\": \"text/html; charset=utf-8\",\"X-Accel-Buffering\": \"no\" },\n headers,\n );\n return new Response(\n renderStream(template).pipeThrough(new TextEncoderStream()),\n { headers: responseHeaders, status, statusText },\n );\n}\nexport {\n render,\n renderAsString,\n renderStream,\n liveHTML,\n cachableHTML as html,\n UnSafeHTML,\n escapeHTML,\n};\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("node:stream");function t(e){return String(e).replace(/[&<>"']/g,e=>{switch(e){case`&`:return`&amp;`;case`<`:return`&lt;`;case`>`:return`&gt;`;case`"`:return`&quot;`;case`'`:return`&#39;`;default:return e}})}function n(e){let n=e.length;for(;n--;){let r=e[n];typeof r==`string`&&(e[n]=t(r))}return e}var r=class{html;constructor(e){this.html=e}};const i=function*(){}.constructor,a=new WeakMap;function o(e,t){let n=`yield \`${e[0]}\``,i=t.length;for(let a=0;a<i;a++){let i=t[a];typeof i==`string`?n+=`+escapeHTML(args[${a}])+\`${e[a+1]}\``:i instanceof r?n+=`+args[${a}].html+\`${e[a+1]}\``:i instanceof Error||typeof i==`number`?n+=`+args[${a}]+\`${e[a+1]}\``:Array.isArray(i)?n+=`; yield * sanitizeArray(args[${a}]); yield \`${e[a+1]}\``:i?.[Symbol.iterator]?n+=`; yield * args[${a}]; yield \`${e[a+1]}\``:n+=`; yield args[${a}]; yield \`${e[a+1]}\``}return n}function s(e,t){let n=o(e,t);return new i(`escapeHTML`,`sanitizeArray`,`args`,n)}function c(e,...r){let i=a.get(e);return i?i(t,n,r):(i=s(e,r),a.set(e,i),i(t,n,r))}function*l(e,...i){let a=e[0],o=i.length;for(let s=0;s<o;s++){let o=i[s];typeof o==`string`?a+=t(o):o instanceof r?a+=o.html:o instanceof Error||typeof o==`number`?a+=o:Array.isArray(o)?(a&&=(yield a,``),yield*n(o)):o?.[Symbol.iterator]?(a&&=(yield a,``),yield*o):yield o,a+=e[s+1]}a&&=(yield a,``)}async function u(e){try{return await e}catch(e){return e instanceof Promise?u(e):e}}async function d(e,t){let n=e.getReader();try{for(;;){let e=await n.read();if(e.done)return;t.enqueue(e.value)}}catch(e){t.enqueue(e)}finally{n.releaseLock()}}function*f(e,i){let a=``;for(let o of e)if(typeof o==`string`)a+=o;else if(o instanceof r)a+=o.html;else if(o instanceof Error||typeof o==`number`)a+=o;else if(o instanceof Promise){a&&=(i.enqueue(a),``);let e=yield o;if(typeof e==`string`)a+=t(e);else if(e instanceof r)a+=e.html;else if(e instanceof Error||typeof e==`number`)a+=e;else if(Array.isArray(e))a&&=(i.enqueue(a),``),yield*f(n(e),i);else if(e?.[Symbol.iterator])a&&=(i.enqueue(a),``),yield*f(e,i);else if(e==null)continue;else a&&=(i.enqueue(a),``),yield e}else if(Array.isArray(o))a&&=(i.enqueue(a),``),yield*f(n(o),i);else if(o?.[Symbol.iterator])a&&=(i.enqueue(a),``),yield*f(o,i);else if(o==null)continue;else a&&=(i.enqueue(a),``),yield o;a&&=(i.enqueue(a),``)}function p(e){return new ReadableStream({start(t){let n=f(e,t);return r(n);async function r(e=void 0){let i=n.next(e);try{if(i.value instanceof Promise)return r(await u(i.value));if(i.value instanceof Response)return await d(i.value.body.pipeThrough(new TextDecoderStream),t),r();if(i.value instanceof ReadableStream)return await d(i.value,t),r();if(i.value instanceof Request){let e=(await fetch(i.value)).body;return e&&await d(e.pipeThrough(new TextDecoderStream),t),r()}}catch(e){return t.enqueue(e),r()}t.close()}}})}async function m(e){try{let t=p(e).getReader(),n=``;for(;;){let e=await t.read();if(e.done){t.releaseLock();break}n+=e.value}return n}catch(e){throw e}}function h(t,n,r={},i=200,a=`OK`){let o=e.Readable.fromWeb(p(n));t.writeHead(i,a,Object.assign({"Content-Type":`text/html; charset=utf-8`},r)),o.pipe(t)}exports.UnSafeHTML=r,exports.escapeHTML=t,exports.html=c,exports.liveHTML=l,exports.render=h,exports.renderAsString=m,exports.renderStream=p;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("node:stream");function t(e){return String(e).replace(/[&<>"']/g,e=>{switch(e){case`&`:return`&amp;`;case`<`:return`&lt;`;case`>`:return`&gt;`;case`"`:return`&quot;`;case`'`:return`&#39;`;default:return e}})}function n(e){let n=e.length;for(;n--;){let r=e[n];typeof r==`string`&&(e[n]=t(r))}return e}var r=class{html;constructor(e){this.html=e}};const i=function*(){}.constructor,a=new WeakMap;function o(e,t){let n=`yield \`${e[0]}\``,i=t.length;for(let a=0;a<i;a++){let i=t[a];typeof i==`string`?n+=`+escapeHTML(args[${a}])+\`${e[a+1]}\``:i instanceof r?n+=`+args[${a}].html+\`${e[a+1]}\``:i instanceof Error||typeof i==`number`?n+=`+args[${a}]+\`${e[a+1]}\``:Array.isArray(i)?n+=`; yield * sanitizeArray(args[${a}]); yield \`${e[a+1]}\``:i?.[Symbol.iterator]?n+=`; yield * args[${a}]; yield \`${e[a+1]}\``:n+=`; yield args[${a}]; yield \`${e[a+1]}\``}return n}function s(e,t){let n=o(e,t);return new i(`escapeHTML`,`sanitizeArray`,`args`,n)}function c(e,...r){let i=a.get(e);return i?i(t,n,r):(i=s(e,r),a.set(e,i),i(t,n,r))}function*l(e,...i){let a=e[0],o=i.length;for(let s=0;s<o;s++){let o=i[s];typeof o==`string`?a+=t(o):o instanceof r?a+=o.html:o instanceof Error||typeof o==`number`?a+=o:Array.isArray(o)?(a&&=(yield a,``),yield*n(o)):o?.[Symbol.iterator]?(a&&=(yield a,``),yield*o):yield o,a+=e[s+1]}a&&=(yield a,``)}async function u(e){try{return await e}catch(e){return e instanceof Promise?u(e):e}}async function d(e,t){let n=e.getReader();try{for(;;){let e=await n.read();if(e.done)return;t.enqueue(e.value)}}catch(e){t.enqueue(e)}finally{n.releaseLock()}}function*f(e,i){let a=``;for(let o of e)if(typeof o==`string`)a+=o;else if(o instanceof r)a+=o.html;else if(o instanceof Error||typeof o==`number`)a+=o;else if(o instanceof Promise){a&&=(i.enqueue(a),``);let e=yield o;if(typeof e==`string`)a+=t(e);else if(e instanceof r)a+=e.html;else if(e instanceof Error||typeof e==`number`)a+=e;else if(Array.isArray(e))a&&=(i.enqueue(a),``),yield*f(n(e),i);else if(e?.[Symbol.iterator])a&&=(i.enqueue(a),``),yield*f(e,i);else if(e==null)continue;else a&&=(i.enqueue(a),``),yield e}else if(Array.isArray(o))a&&=(i.enqueue(a),``),yield*f(n(o),i);else if(o?.[Symbol.iterator])a&&=(i.enqueue(a),``),yield*f(o,i);else if(o==null)continue;else a&&=(i.enqueue(a),``),yield o;a&&=(i.enqueue(a),``)}function p(e){return new ReadableStream({start(t){let n=f(e,t);return r(n);async function r(e=void 0){let i=n.next(e);try{if(i.value instanceof Promise)return r(await u(i.value));if(i.value instanceof Response)return await d(i.value.body.pipeThrough(new TextDecoderStream),t),r();if(i.value instanceof ReadableStream)return await d(i.value,t),r();if(i.value instanceof Request){let e=(await fetch(i.value)).body;return e&&await d(e.pipeThrough(new TextDecoderStream),t),r()}}catch(e){return t.enqueue(e),r()}t.close()}}})}async function m(e){try{let t=p(e).getReader(),n=``;for(;;){let e=await t.read();if(e.done){t.releaseLock();break}n+=e.value}return n}catch(e){throw e}}function h(t,n,r={},i=200,a=`OK`){let o=e.Readable.fromWeb(p(n));t.writeHead(i,a,Object.assign({"Content-Type":`text/html; charset=utf-8`,"X-Accel-Buffering":`no`},r)),o.pipe(t)}exports.UnSafeHTML=r,exports.escapeHTML=t,exports.html=c,exports.liveHTML=l,exports.render=h,exports.renderAsString=m,exports.renderStream=p;
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["Readable"],"sources":["../../src/utils/escapehtml.ts","../../src/utils/sanitizeArray.ts","../../src/utils/UnSafeHTML.ts","../../src/html/cachehtml.ts","../../src/html/livehtml.ts","../../src/utils/promisedValue.ts","../../src/utils/streamHTML.ts","../../src/html/html.ts","../../src/index.node.ts"],"sourcesContent":["/**\n * Escapes HTML special characters in a string to prevent XSS attacks and ensure proper rendering in HTML.\n *\n * @param {string} str - The string to escape\n *\n * @returns {string} - The escaped string\n */\nexport function escapeHTML(str: string): string {\n return String(str).replace(/[&<>\"']/g, (char: string) => {\n switch (char) {\n case \"&\":\n return \"&amp;\";\n case \"<\":\n return \"&lt;\";\n case \">\":\n return \"&gt;\";\n case '\"':\n return \"&quot;\";\n case \"'\":\n return \"&#39;\";\n default:\n return char;\n }\n });\n}\n","import { escapeHTML } from \"./escapehtml\";\n\nexport function sanitizeArray(values: any[]): any[] {\n let index = values.length;\n while (index--) {\n let value = values[index];\n if (typeof value == \"string\") {\n values[index] = escapeHTML(value);\n }\n }\n return values;\n}\n","export class UnSafeHTML {\n public html: string;\n /**\n * Creates unsafe html that will not be escaped\n *\n * @param {string} html - string containing unsafe html\n */\n constructor(html: string) {\n this.html = html;\n }\n}\n","import { escapeHTML } from \"../utils/escapehtml\";\nimport { sanitizeArray } from \"../utils/sanitizeArray\";\nimport { UnSafeHTML } from \"../utils/UnSafeHTML\";\n\ntype GeneratorFunctionConstructor = new (\n ...args: string[]\n) => (...args: any[]) => Generator<any, any, any>;\nconst TemplateConstructor = function* () {}\n .constructor as GeneratorFunctionConstructor,\n templateCache = new WeakMap();\n\n/**\n * A function that generates the source code for a compiled HTML template function.\n *\n * @param {String[]} templates\n * @param {Array} values\n * @returns {string} source code of the compiled template function that can be called with the appropriate arguments to produce the final HTML output based on the provided templates and values.\n */\nfunction generateTemplateSourceCode(\n templates: TemplateStringsArray,\n values: TemplateValues[],\n): string {\n let sourceCode = `yield \\`${templates[0]}\\``,\n length = values.length;\n for (let index = 0; index < length; index++) {\n let value = values[index];\n if (typeof value == \"string\") {\n sourceCode += `+escapeHTML(args[${index}])+\\`${templates[index + 1]}\\``;\n } else if (value instanceof UnSafeHTML) {\n sourceCode += `+args[${index}].html+\\`${templates[index + 1]}\\``;\n } else if (value instanceof Error || typeof value == \"number\") {\n sourceCode += `+args[${index}]+\\`${templates[index + 1]}\\``;\n } else if (Array.isArray(value)) {\n sourceCode += `; yield * sanitizeArray(args[${index}]); yield \\`${templates[index + 1]}\\``;\n } else if ((value as any)?.[Symbol.iterator]) {\n sourceCode += `; yield * args[${index}]; yield \\`${templates[index + 1]}\\``;\n } else {\n sourceCode += `; yield args[${index}]; yield \\`${templates[index + 1]}\\``;\n }\n }\n return sourceCode;\n}\n/**\n * compiles an HTML template into a function that can be cached and reused with different values. It generates source code for the template by processing the provided templates and values, handling various types of values such as strings, UnSafeHTML instances, errors, numbers, arrays, and iterables. The generated source code is then used to create a new function using the TemplateConstructor, which can be called with the appropriate arguments to produce the final HTML output. This approach allows for efficient rendering of HTML templates while ensuring that string values are properly escaped to prevent XSS vulnerabilities.\n *\n * @param {String[]} templates\n * @param {Array} values\n * @returns {GeneratorFunction} A generator function that can be called with the appropriate arguments to produce the final HTML output based on the provided templates and values.\n */\nfunction compileTemplate(\n templates: TemplateStringsArray,\n values: TemplateValues[],\n) {\n let sourceCode = generateTemplateSourceCode(templates, values);\n return new TemplateConstructor(\n \"escapeHTML\",\n \"sanitizeArray\",\n \"args\",\n sourceCode,\n );\n}\n/**\n * A function that renders an HTML template with caching capabilities. It checks if a compiled template function already exists in the cache for the given templates. If it does, it calls the cached function with the provided values and returns the result. If not, it compiles a new template function using the compileTemplate function, stores it in the cache, and then calls it with the provided values. This allows for efficient rendering of HTML templates while ensuring that string values are properly escaped to prevent XSS vulnerabilities.\n *\n * @param {String[]} templates\n * @param {...(String|UnSafeHTML|Error|number|Array|Iterable)} values\n * @returns {GeneratorFunction} A generator function that can be called with the appropriate arguments to produce the final HTML output based on the provided templates and values.\n */\nfunction cachableHTML(\n templates: TemplateStringsArray,\n ...values: TemplateValues[]\n) {\n let template = templateCache.get(templates);\n if (template) {\n return template(escapeHTML, sanitizeArray, values);\n }\n template = compileTemplate(templates, values);\n templateCache.set(templates, template);\n return template(escapeHTML, sanitizeArray, values);\n}\n\nexport { cachableHTML };\n","import { UnSafeHTML } from \"../utils/UnSafeHTML\";\nimport { escapeHTML } from \"../utils/escapehtml\";\nimport { sanitizeArray } from \"../utils/sanitizeArray\";\n\n/**\n * A generator function that processes an HTML template without caching. It handles various types of values, including strings, UnSafeHTML instances, errors, numbers, promises, arrays, and iterables. The function ensures that string values are properly escaped to prevent XSS vulnerabilities, while allowing UnSafeHTML instances to be included as-is. It also supports asynchronous values by yielding promises and waiting for their resolution before processing them further.\n *\n * @export\n * @param {String[]} templates\n * @param {...TemplateValues} values\n * @returns {Generator} A generator that yields processed HTML content as a stream.\n */\nexport function* liveHTML(\n templates: TemplateStringsArray,\n ...values: TemplateValues[]\n) {\n let cache = templates[0],\n length = values.length;\n for (let index = 0; index < length; index++) {\n let value = values[index];\n if (typeof value == \"string\") {\n cache += escapeHTML(value);\n } else if (value instanceof UnSafeHTML) {\n cache += value.html;\n } else if (value instanceof Error || typeof value == \"number\") {\n cache += value;\n } else if (Array.isArray(value)) {\n if (cache) {\n yield cache;\n cache = \"\";\n }\n yield* sanitizeArray(value);\n } else if ((value as any)?.[Symbol.iterator]) {\n if (cache) {\n yield cache;\n cache = \"\";\n }\n yield* value as Generator;\n } else {\n yield value;\n }\n cache += templates[index + 1];\n }\n if (cache) {\n yield cache;\n cache = \"\";\n }\n}\n","export async function promisedValue(value: Promise<any>): Promise<any> {\n try {\n return await value;\n } catch (error) {\n if (error instanceof Promise) {\n return promisedValue(error);\n } else {\n return error;\n }\n }\n}\n","export async function streamHTML(\n readable: ReadableStream<string>,\n controller: ReadableStreamDefaultController,\n) {\n const stream: ReadableStreamDefaultReader = readable.getReader();\n try {\n while (true) {\n let data = await stream.read();\n if (data.done) {\n return;\n }\n controller.enqueue(data.value);\n }\n } catch (error) {\n controller.enqueue(error);\n } finally {\n stream.releaseLock();\n }\n}\n","import { UnSafeHTML } from \"../utils/UnSafeHTML\";\nimport { escapeHTML } from \"../utils/escapehtml\";\nimport { sanitizeArray } from \"../utils/sanitizeArray\";\nimport { promisedValue } from \"../utils/promisedValue\";\nimport { streamHTML } from \"../utils/streamHTML\";\n\n/**\n * A generator function that processes an HTML template with embedded values and yields the resulting HTML as a stream. It handles various types of values, including strings, UnSafeHTML instances, errors, numbers, promises, arrays, and iterables. The function ensures that string values are properly escaped to prevent XSS vulnerabilities, while allowing UnSafeHTML instances to be included as-is. It also supports asynchronous values by yielding promises and waiting for their resolution before processing them further.\n *\n * @param {Generator} templateGenerator\n * @param {ReadableStreamDefaultController} controller\n * @returns {IterableIterator<string>} An iterator that yields the resulting HTML as a stream.\n */\nfunction* processHTML(\n templateGenerator: Generator | Array<TemplateValues>,\n controller: ReadableStreamDefaultController<string>,\n): any {\n let cache: string = \"\";\n for (const value of templateGenerator) {\n if (typeof value == \"string\") {\n cache += value;\n } else if (value instanceof UnSafeHTML) {\n cache += value.html;\n } else if (value instanceof Error || typeof value == \"number\") {\n cache += value;\n } else if (value instanceof Promise) {\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n let resolvedValue = yield value;\n if (typeof resolvedValue == \"string\") {\n cache += escapeHTML(resolvedValue);\n } else if (resolvedValue instanceof UnSafeHTML) {\n cache += resolvedValue.html;\n } else if (\n resolvedValue instanceof Error ||\n typeof resolvedValue == \"number\"\n ) {\n cache += resolvedValue;\n } else if (Array.isArray(resolvedValue)) {\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n yield* processHTML(sanitizeArray(resolvedValue), controller);\n } else if (resolvedValue?.[Symbol.iterator]) {\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n yield* processHTML(resolvedValue, controller);\n } else if (resolvedValue == undefined) {\n continue;\n } else {\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n let resolvedValues = yield resolvedValue;\n void resolvedValues\n }\n } else if (Array.isArray(value)) {\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n yield* processHTML(sanitizeArray(value), controller);\n } else if (value?.[Symbol.iterator]) {\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n yield* processHTML(value, controller);\n } else if (value == undefined) {\n continue;\n } else {\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n let resolvedValue = yield value;\n void resolvedValue\n }\n }\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n}\n\n/**\n * A function that renders an HTML template generator and returns a ReadableStream that yields the resulting HTML as a stream. It uses the processHTML generator function to process the template and handle various types of values, including promises and streams, while ensuring that string values are properly escaped to prevent XSS vulnerabilities.\n *\n * @param {Generator} generator - The HTML template generator to render.\n * @returns {ReadableStream} A ReadableStream that yields the resulting HTML as a stream.\n */\nfunction renderStream(generator: Generator) {\n return new ReadableStream<string>({\n start(controller) {\n let templateGenerator = processHTML(generator, controller);\n return startHTMLStream(templateGenerator);\n async function startHTMLStream(\n value:\n | undefined\n | Promise<any>\n | Request\n | ReadableStream\n | Response = undefined,\n ) {\n let data = templateGenerator.next(value);\n try {\n if (data.value instanceof Promise) {\n let resolvedValue = await promisedValue(data.value);\n return startHTMLStream(resolvedValue);\n } else if (data.value instanceof Response) {\n await streamHTML(data.value.body.pipeThrough(new TextDecoderStream()), controller);\n return startHTMLStream();\n } else if (data.value instanceof ReadableStream) {\n await streamHTML(data.value, controller);\n return startHTMLStream();\n } else if (data.value instanceof Request) {\n let response:Response = await fetch(data.value),\n stream = response.body;\n if (stream) {\n await streamHTML(stream.pipeThrough(new TextDecoderStream()), controller);\n }\n return startHTMLStream();\n }\n } catch (error) {\n controller.enqueue(error as string);\n return startHTMLStream();\n }\n controller.close();\n }\n },\n });\n}\n/**\n * renders an HTML template generator and returns a promise that resolves to the resulting HTML as a string.\n *\n * @async\n * @param {Generator} generator\n * @returns {Promise<string>} A promise that resolves to the resulting HTML as a string.\n */\nasync function renderAsString(generator: Generator): Promise<string> {\n try {\n let readable = renderStream(generator).getReader(),\n html = \"\";\n while (true) {\n let data = await readable.read();\n if (data.done) {\n readable.releaseLock();\n break;\n }\n html += data.value;\n }\n return html;\n } catch (error) {\n throw error;\n }\n}\nexport { renderStream, renderAsString };\n","import { cachableHTML } from \"./html/cachehtml\";\nimport { liveHTML } from \"./html/livehtml\";\nimport { UnSafeHTML } from \"./utils/UnSafeHTML\";\nimport { renderStream, renderAsString } from \"./html/html\";\nimport { escapeHTML } from \"./utils/escapehtml\";\nimport { Readable } from \"node:stream\";\n\n/**\n * Renders an HTML template and sends it as a response\n *\n * @param {response} response - Node response object\n * @param {HTMLTemplate} template - HTML template to render\n * @param {{}} [headers={}] - Headers to send with the response\n * @param {number} [status=200] - HTTP status code\n * @param {string} [statusText='OK'] - HTTP status text\n * @returns {void}\n */\nfunction render(\n response: any,\n template: Generator,\n headers = {},\n status = 200,\n statusText = \"OK\",\n) {\n const readable = Readable.fromWeb(renderStream(template));\n response.writeHead(\n status,\n statusText,\n Object.assign({ \"Content-Type\": \"text/html; charset=utf-8\" }, headers),\n );\n readable.pipe(response);\n}\nexport {\n render,\n renderAsString,\n renderStream,\n liveHTML,\n cachableHTML as html,\n UnSafeHTML,\n escapeHTML,\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":["Readable"],"sources":["../../src/utils/escapehtml.ts","../../src/utils/sanitizeArray.ts","../../src/utils/UnSafeHTML.ts","../../src/html/cachehtml.ts","../../src/html/livehtml.ts","../../src/utils/promisedValue.ts","../../src/utils/streamHTML.ts","../../src/html/html.ts","../../src/index.node.ts"],"sourcesContent":["/**\n * Escapes HTML special characters in a string to prevent XSS attacks and ensure proper rendering in HTML.\n *\n * @param {string} str - The string to escape\n *\n * @returns {string} - The escaped string\n */\nexport function escapeHTML(str: string): string {\n return String(str).replace(/[&<>\"']/g, (char: string) => {\n switch (char) {\n case \"&\":\n return \"&amp;\";\n case \"<\":\n return \"&lt;\";\n case \">\":\n return \"&gt;\";\n case '\"':\n return \"&quot;\";\n case \"'\":\n return \"&#39;\";\n default:\n return char;\n }\n });\n}\n","import { escapeHTML } from \"./escapehtml\";\n\nexport function sanitizeArray(values: any[]): any[] {\n let index = values.length;\n while (index--) {\n let value = values[index];\n if (typeof value == \"string\") {\n values[index] = escapeHTML(value);\n }\n }\n return values;\n}\n","export class UnSafeHTML {\n public html: string;\n /**\n * Creates unsafe html that will not be escaped\n *\n * @param {string} html - string containing unsafe html\n */\n constructor(html: string) {\n this.html = html;\n }\n}\n","import { escapeHTML } from \"../utils/escapehtml\";\nimport { sanitizeArray } from \"../utils/sanitizeArray\";\nimport { UnSafeHTML } from \"../utils/UnSafeHTML\";\n\ntype GeneratorFunctionConstructor = new (\n ...args: string[]\n) => (...args: any[]) => Generator<any, any, any>;\nconst TemplateConstructor = function* () {}\n .constructor as GeneratorFunctionConstructor,\n templateCache = new WeakMap();\n\n/**\n * A function that generates the source code for a compiled HTML template function.\n *\n * @param {String[]} templates\n * @param {Array} values\n * @returns {string} source code of the compiled template function that can be called with the appropriate arguments to produce the final HTML output based on the provided templates and values.\n */\nfunction generateTemplateSourceCode(\n templates: TemplateStringsArray,\n values: TemplateValues[],\n): string {\n let sourceCode = `yield \\`${templates[0]}\\``,\n length = values.length;\n for (let index = 0; index < length; index++) {\n let value = values[index];\n if (typeof value == \"string\") {\n sourceCode += `+escapeHTML(args[${index}])+\\`${templates[index + 1]}\\``;\n } else if (value instanceof UnSafeHTML) {\n sourceCode += `+args[${index}].html+\\`${templates[index + 1]}\\``;\n } else if (value instanceof Error || typeof value == \"number\") {\n sourceCode += `+args[${index}]+\\`${templates[index + 1]}\\``;\n } else if (Array.isArray(value)) {\n sourceCode += `; yield * sanitizeArray(args[${index}]); yield \\`${templates[index + 1]}\\``;\n } else if ((value as any)?.[Symbol.iterator]) {\n sourceCode += `; yield * args[${index}]; yield \\`${templates[index + 1]}\\``;\n } else {\n sourceCode += `; yield args[${index}]; yield \\`${templates[index + 1]}\\``;\n }\n }\n return sourceCode;\n}\n/**\n * compiles an HTML template into a function that can be cached and reused with different values. It generates source code for the template by processing the provided templates and values, handling various types of values such as strings, UnSafeHTML instances, errors, numbers, arrays, and iterables. The generated source code is then used to create a new function using the TemplateConstructor, which can be called with the appropriate arguments to produce the final HTML output. This approach allows for efficient rendering of HTML templates while ensuring that string values are properly escaped to prevent XSS vulnerabilities.\n *\n * @param {String[]} templates\n * @param {Array} values\n * @returns {GeneratorFunction} A generator function that can be called with the appropriate arguments to produce the final HTML output based on the provided templates and values.\n */\nfunction compileTemplate(\n templates: TemplateStringsArray,\n values: TemplateValues[],\n) {\n let sourceCode = generateTemplateSourceCode(templates, values);\n return new TemplateConstructor(\n \"escapeHTML\",\n \"sanitizeArray\",\n \"args\",\n sourceCode,\n );\n}\n/**\n * A function that renders an HTML template with caching capabilities. It checks if a compiled template function already exists in the cache for the given templates. If it does, it calls the cached function with the provided values and returns the result. If not, it compiles a new template function using the compileTemplate function, stores it in the cache, and then calls it with the provided values. This allows for efficient rendering of HTML templates while ensuring that string values are properly escaped to prevent XSS vulnerabilities.\n *\n * @param {String[]} templates\n * @param {...(String|UnSafeHTML|Error|number|Array|Iterable)} values\n * @returns {GeneratorFunction} A generator function that can be called with the appropriate arguments to produce the final HTML output based on the provided templates and values.\n */\nfunction cachableHTML(\n templates: TemplateStringsArray,\n ...values: TemplateValues[]\n) {\n let template = templateCache.get(templates);\n if (template) {\n return template(escapeHTML, sanitizeArray, values);\n }\n template = compileTemplate(templates, values);\n templateCache.set(templates, template);\n return template(escapeHTML, sanitizeArray, values);\n}\n\nexport { cachableHTML };\n","import { UnSafeHTML } from \"../utils/UnSafeHTML\";\nimport { escapeHTML } from \"../utils/escapehtml\";\nimport { sanitizeArray } from \"../utils/sanitizeArray\";\n\n/**\n * A generator function that processes an HTML template without caching. It handles various types of values, including strings, UnSafeHTML instances, errors, numbers, promises, arrays, and iterables. The function ensures that string values are properly escaped to prevent XSS vulnerabilities, while allowing UnSafeHTML instances to be included as-is. It also supports asynchronous values by yielding promises and waiting for their resolution before processing them further.\n *\n * @export\n * @param {String[]} templates\n * @param {...TemplateValues} values\n * @returns {Generator} A generator that yields processed HTML content as a stream.\n */\nexport function* liveHTML(\n templates: TemplateStringsArray,\n ...values: TemplateValues[]\n) {\n let cache = templates[0],\n length = values.length;\n for (let index = 0; index < length; index++) {\n let value = values[index];\n if (typeof value == \"string\") {\n cache += escapeHTML(value);\n } else if (value instanceof UnSafeHTML) {\n cache += value.html;\n } else if (value instanceof Error || typeof value == \"number\") {\n cache += value;\n } else if (Array.isArray(value)) {\n if (cache) {\n yield cache;\n cache = \"\";\n }\n yield* sanitizeArray(value);\n } else if ((value as any)?.[Symbol.iterator]) {\n if (cache) {\n yield cache;\n cache = \"\";\n }\n yield* value as Generator;\n } else {\n yield value;\n }\n cache += templates[index + 1];\n }\n if (cache) {\n yield cache;\n cache = \"\";\n }\n}\n","export async function promisedValue(value: Promise<any>): Promise<any> {\n try {\n return await value;\n } catch (error) {\n if (error instanceof Promise) {\n return promisedValue(error);\n } else {\n return error;\n }\n }\n}\n","export async function streamHTML(\n readable: ReadableStream<string>,\n controller: ReadableStreamDefaultController,\n) {\n const stream: ReadableStreamDefaultReader = readable.getReader();\n try {\n while (true) {\n let data = await stream.read();\n if (data.done) {\n return;\n }\n controller.enqueue(data.value);\n }\n } catch (error) {\n controller.enqueue(error);\n } finally {\n stream.releaseLock();\n }\n}\n","import { UnSafeHTML } from \"../utils/UnSafeHTML\";\nimport { escapeHTML } from \"../utils/escapehtml\";\nimport { sanitizeArray } from \"../utils/sanitizeArray\";\nimport { promisedValue } from \"../utils/promisedValue\";\nimport { streamHTML } from \"../utils/streamHTML\";\n\n/**\n * A generator function that processes an HTML template with embedded values and yields the resulting HTML as a stream. It handles various types of values, including strings, UnSafeHTML instances, errors, numbers, promises, arrays, and iterables. The function ensures that string values are properly escaped to prevent XSS vulnerabilities, while allowing UnSafeHTML instances to be included as-is. It also supports asynchronous values by yielding promises and waiting for their resolution before processing them further.\n *\n * @param {Generator} templateGenerator\n * @param {ReadableStreamDefaultController} controller\n * @returns {IterableIterator<string>} An iterator that yields the resulting HTML as a stream.\n */\nfunction* processHTML(\n templateGenerator: Generator | Array<TemplateValues>,\n controller: ReadableStreamDefaultController<string>,\n): any {\n let cache: string = \"\";\n for (const value of templateGenerator) {\n if (typeof value == \"string\") {\n cache += value;\n } else if (value instanceof UnSafeHTML) {\n cache += value.html;\n } else if (value instanceof Error || typeof value == \"number\") {\n cache += value;\n } else if (value instanceof Promise) {\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n let resolvedValue = yield value;\n if (typeof resolvedValue == \"string\") {\n cache += escapeHTML(resolvedValue);\n } else if (resolvedValue instanceof UnSafeHTML) {\n cache += resolvedValue.html;\n } else if (\n resolvedValue instanceof Error ||\n typeof resolvedValue == \"number\"\n ) {\n cache += resolvedValue;\n } else if (Array.isArray(resolvedValue)) {\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n yield* processHTML(sanitizeArray(resolvedValue), controller);\n } else if (resolvedValue?.[Symbol.iterator]) {\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n yield* processHTML(resolvedValue, controller);\n } else if (resolvedValue == undefined) {\n continue;\n } else {\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n let resolvedValues = yield resolvedValue;\n void resolvedValues\n }\n } else if (Array.isArray(value)) {\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n yield* processHTML(sanitizeArray(value), controller);\n } else if (value?.[Symbol.iterator]) {\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n yield* processHTML(value, controller);\n } else if (value == undefined) {\n continue;\n } else {\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n let resolvedValue = yield value;\n void resolvedValue\n }\n }\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n}\n\n/**\n * A function that renders an HTML template generator and returns a ReadableStream that yields the resulting HTML as a stream. It uses the processHTML generator function to process the template and handle various types of values, including promises and streams, while ensuring that string values are properly escaped to prevent XSS vulnerabilities.\n *\n * @param {Generator} generator - The HTML template generator to render.\n * @returns {ReadableStream} A ReadableStream that yields the resulting HTML as a stream.\n */\nfunction renderStream(generator: Generator) {\n return new ReadableStream<string>({\n start(controller) {\n let templateGenerator = processHTML(generator, controller);\n return startHTMLStream(templateGenerator);\n async function startHTMLStream(\n value:\n | undefined\n | Promise<any>\n | Request\n | ReadableStream\n | Response = undefined,\n ) {\n let data = templateGenerator.next(value);\n try {\n if (data.value instanceof Promise) {\n let resolvedValue = await promisedValue(data.value);\n return startHTMLStream(resolvedValue);\n } else if (data.value instanceof Response) {\n await streamHTML(data.value.body.pipeThrough(new TextDecoderStream()), controller);\n return startHTMLStream();\n } else if (data.value instanceof ReadableStream) {\n await streamHTML(data.value, controller);\n return startHTMLStream();\n } else if (data.value instanceof Request) {\n let response:Response = await fetch(data.value),\n stream = response.body;\n if (stream) {\n await streamHTML(stream.pipeThrough(new TextDecoderStream()), controller);\n }\n return startHTMLStream();\n }\n } catch (error) {\n controller.enqueue(error as string);\n return startHTMLStream();\n }\n controller.close();\n }\n },\n });\n}\n/**\n * renders an HTML template generator and returns a promise that resolves to the resulting HTML as a string.\n *\n * @async\n * @param {Generator} generator\n * @returns {Promise<string>} A promise that resolves to the resulting HTML as a string.\n */\nasync function renderAsString(generator: Generator): Promise<string> {\n try {\n let readable = renderStream(generator).getReader(),\n html = \"\";\n while (true) {\n let data = await readable.read();\n if (data.done) {\n readable.releaseLock();\n break;\n }\n html += data.value;\n }\n return html;\n } catch (error) {\n throw error;\n }\n}\nexport { renderStream, renderAsString };\n","import { cachableHTML } from \"./html/cachehtml\";\nimport { liveHTML } from \"./html/livehtml\";\nimport { UnSafeHTML } from \"./utils/UnSafeHTML\";\nimport { renderStream, renderAsString } from \"./html/html\";\nimport { escapeHTML } from \"./utils/escapehtml\";\nimport { Readable } from \"node:stream\";\n\n/**\n * Renders an HTML template and sends it as a response\n *\n * @param {response} response - Node response object\n * @param {HTMLTemplate} template - HTML template to render\n * @param {{}} [headers={}] - Headers to send with the response\n * @param {number} [status=200] - HTTP status code\n * @param {string} [statusText='OK'] - HTTP status text\n * @returns {void}\n */\nfunction render(\n response: any,\n template: Generator,\n headers = {},\n status = 200,\n statusText = \"OK\",\n) {\n const readable = Readable.fromWeb(renderStream(template));\n response.writeHead(\n status,\n statusText,\n Object.assign({ \"Content-Type\": \"text/html; charset=utf-8\",\"X-Accel-Buffering\": \"no\" }, headers),\n );\n readable.pipe(response);\n}\nexport {\n render,\n renderAsString,\n renderStream,\n liveHTML,\n cachableHTML as html,\n UnSafeHTML,\n escapeHTML,\n};\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{Readable as e}from"node:stream";function t(e){return String(e).replace(/[&<>"']/g,e=>{switch(e){case`&`:return`&amp;`;case`<`:return`&lt;`;case`>`:return`&gt;`;case`"`:return`&quot;`;case`'`:return`&#39;`;default:return e}})}function n(e){let n=e.length;for(;n--;){let r=e[n];typeof r==`string`&&(e[n]=t(r))}return e}var r=class{html;constructor(e){this.html=e}};const i=function*(){}.constructor,a=new WeakMap;function o(e,t){let n=`yield \`${e[0]}\``,i=t.length;for(let a=0;a<i;a++){let i=t[a];typeof i==`string`?n+=`+escapeHTML(args[${a}])+\`${e[a+1]}\``:i instanceof r?n+=`+args[${a}].html+\`${e[a+1]}\``:i instanceof Error||typeof i==`number`?n+=`+args[${a}]+\`${e[a+1]}\``:Array.isArray(i)?n+=`; yield * sanitizeArray(args[${a}]); yield \`${e[a+1]}\``:i?.[Symbol.iterator]?n+=`; yield * args[${a}]; yield \`${e[a+1]}\``:n+=`; yield args[${a}]; yield \`${e[a+1]}\``}return n}function s(e,t){let n=o(e,t);return new i(`escapeHTML`,`sanitizeArray`,`args`,n)}function c(e,...r){let i=a.get(e);return i?i(t,n,r):(i=s(e,r),a.set(e,i),i(t,n,r))}function*l(e,...i){let a=e[0],o=i.length;for(let s=0;s<o;s++){let o=i[s];typeof o==`string`?a+=t(o):o instanceof r?a+=o.html:o instanceof Error||typeof o==`number`?a+=o:Array.isArray(o)?(a&&=(yield a,``),yield*n(o)):o?.[Symbol.iterator]?(a&&=(yield a,``),yield*o):yield o,a+=e[s+1]}a&&=(yield a,``)}async function u(e){try{return await e}catch(e){return e instanceof Promise?u(e):e}}async function d(e,t){let n=e.getReader();try{for(;;){let e=await n.read();if(e.done)return;t.enqueue(e.value)}}catch(e){t.enqueue(e)}finally{n.releaseLock()}}function*f(e,i){let a=``;for(let o of e)if(typeof o==`string`)a+=o;else if(o instanceof r)a+=o.html;else if(o instanceof Error||typeof o==`number`)a+=o;else if(o instanceof Promise){a&&=(i.enqueue(a),``);let e=yield o;if(typeof e==`string`)a+=t(e);else if(e instanceof r)a+=e.html;else if(e instanceof Error||typeof e==`number`)a+=e;else if(Array.isArray(e))a&&=(i.enqueue(a),``),yield*f(n(e),i);else if(e?.[Symbol.iterator])a&&=(i.enqueue(a),``),yield*f(e,i);else if(e==null)continue;else a&&=(i.enqueue(a),``),yield e}else if(Array.isArray(o))a&&=(i.enqueue(a),``),yield*f(n(o),i);else if(o?.[Symbol.iterator])a&&=(i.enqueue(a),``),yield*f(o,i);else if(o==null)continue;else a&&=(i.enqueue(a),``),yield o;a&&=(i.enqueue(a),``)}function p(e){return new ReadableStream({start(t){let n=f(e,t);return r(n);async function r(e=void 0){let i=n.next(e);try{if(i.value instanceof Promise)return r(await u(i.value));if(i.value instanceof Response)return await d(i.value.body.pipeThrough(new TextDecoderStream),t),r();if(i.value instanceof ReadableStream)return await d(i.value,t),r();if(i.value instanceof Request){let e=(await fetch(i.value)).body;return e&&await d(e.pipeThrough(new TextDecoderStream),t),r()}}catch(e){return t.enqueue(e),r()}t.close()}}})}async function m(e){try{let t=p(e).getReader(),n=``;for(;;){let e=await t.read();if(e.done){t.releaseLock();break}n+=e.value}return n}catch(e){throw e}}function h(t,n,r={},i=200,a=`OK`){let o=e.fromWeb(p(n));t.writeHead(i,a,Object.assign({"Content-Type":`text/html; charset=utf-8`},r)),o.pipe(t)}export{r as UnSafeHTML,t as escapeHTML,c as html,l as liveHTML,h as render,m as renderAsString,p as renderStream};
1
+ import{Readable as e}from"node:stream";function t(e){return String(e).replace(/[&<>"']/g,e=>{switch(e){case`&`:return`&amp;`;case`<`:return`&lt;`;case`>`:return`&gt;`;case`"`:return`&quot;`;case`'`:return`&#39;`;default:return e}})}function n(e){let n=e.length;for(;n--;){let r=e[n];typeof r==`string`&&(e[n]=t(r))}return e}var r=class{html;constructor(e){this.html=e}};const i=function*(){}.constructor,a=new WeakMap;function o(e,t){let n=`yield \`${e[0]}\``,i=t.length;for(let a=0;a<i;a++){let i=t[a];typeof i==`string`?n+=`+escapeHTML(args[${a}])+\`${e[a+1]}\``:i instanceof r?n+=`+args[${a}].html+\`${e[a+1]}\``:i instanceof Error||typeof i==`number`?n+=`+args[${a}]+\`${e[a+1]}\``:Array.isArray(i)?n+=`; yield * sanitizeArray(args[${a}]); yield \`${e[a+1]}\``:i?.[Symbol.iterator]?n+=`; yield * args[${a}]; yield \`${e[a+1]}\``:n+=`; yield args[${a}]; yield \`${e[a+1]}\``}return n}function s(e,t){let n=o(e,t);return new i(`escapeHTML`,`sanitizeArray`,`args`,n)}function c(e,...r){let i=a.get(e);return i?i(t,n,r):(i=s(e,r),a.set(e,i),i(t,n,r))}function*l(e,...i){let a=e[0],o=i.length;for(let s=0;s<o;s++){let o=i[s];typeof o==`string`?a+=t(o):o instanceof r?a+=o.html:o instanceof Error||typeof o==`number`?a+=o:Array.isArray(o)?(a&&=(yield a,``),yield*n(o)):o?.[Symbol.iterator]?(a&&=(yield a,``),yield*o):yield o,a+=e[s+1]}a&&=(yield a,``)}async function u(e){try{return await e}catch(e){return e instanceof Promise?u(e):e}}async function d(e,t){let n=e.getReader();try{for(;;){let e=await n.read();if(e.done)return;t.enqueue(e.value)}}catch(e){t.enqueue(e)}finally{n.releaseLock()}}function*f(e,i){let a=``;for(let o of e)if(typeof o==`string`)a+=o;else if(o instanceof r)a+=o.html;else if(o instanceof Error||typeof o==`number`)a+=o;else if(o instanceof Promise){a&&=(i.enqueue(a),``);let e=yield o;if(typeof e==`string`)a+=t(e);else if(e instanceof r)a+=e.html;else if(e instanceof Error||typeof e==`number`)a+=e;else if(Array.isArray(e))a&&=(i.enqueue(a),``),yield*f(n(e),i);else if(e?.[Symbol.iterator])a&&=(i.enqueue(a),``),yield*f(e,i);else if(e==null)continue;else a&&=(i.enqueue(a),``),yield e}else if(Array.isArray(o))a&&=(i.enqueue(a),``),yield*f(n(o),i);else if(o?.[Symbol.iterator])a&&=(i.enqueue(a),``),yield*f(o,i);else if(o==null)continue;else a&&=(i.enqueue(a),``),yield o;a&&=(i.enqueue(a),``)}function p(e){return new ReadableStream({start(t){let n=f(e,t);return r(n);async function r(e=void 0){let i=n.next(e);try{if(i.value instanceof Promise)return r(await u(i.value));if(i.value instanceof Response)return await d(i.value.body.pipeThrough(new TextDecoderStream),t),r();if(i.value instanceof ReadableStream)return await d(i.value,t),r();if(i.value instanceof Request){let e=(await fetch(i.value)).body;return e&&await d(e.pipeThrough(new TextDecoderStream),t),r()}}catch(e){return t.enqueue(e),r()}t.close()}}})}async function m(e){try{let t=p(e).getReader(),n=``;for(;;){let e=await t.read();if(e.done){t.releaseLock();break}n+=e.value}return n}catch(e){throw e}}function h(t,n,r={},i=200,a=`OK`){let o=e.fromWeb(p(n));t.writeHead(i,a,Object.assign({"Content-Type":`text/html; charset=utf-8`,"X-Accel-Buffering":`no`},r)),o.pipe(t)}export{r as UnSafeHTML,t as escapeHTML,c as html,l as liveHTML,h as render,m as renderAsString,p as renderStream};
2
2
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../src/utils/escapehtml.ts","../../src/utils/sanitizeArray.ts","../../src/utils/UnSafeHTML.ts","../../src/html/cachehtml.ts","../../src/html/livehtml.ts","../../src/utils/promisedValue.ts","../../src/utils/streamHTML.ts","../../src/html/html.ts","../../src/index.node.ts"],"sourcesContent":["/**\n * Escapes HTML special characters in a string to prevent XSS attacks and ensure proper rendering in HTML.\n *\n * @param {string} str - The string to escape\n *\n * @returns {string} - The escaped string\n */\nexport function escapeHTML(str: string): string {\n return String(str).replace(/[&<>\"']/g, (char: string) => {\n switch (char) {\n case \"&\":\n return \"&amp;\";\n case \"<\":\n return \"&lt;\";\n case \">\":\n return \"&gt;\";\n case '\"':\n return \"&quot;\";\n case \"'\":\n return \"&#39;\";\n default:\n return char;\n }\n });\n}\n","import { escapeHTML } from \"./escapehtml\";\n\nexport function sanitizeArray(values: any[]): any[] {\n let index = values.length;\n while (index--) {\n let value = values[index];\n if (typeof value == \"string\") {\n values[index] = escapeHTML(value);\n }\n }\n return values;\n}\n","export class UnSafeHTML {\n public html: string;\n /**\n * Creates unsafe html that will not be escaped\n *\n * @param {string} html - string containing unsafe html\n */\n constructor(html: string) {\n this.html = html;\n }\n}\n","import { escapeHTML } from \"../utils/escapehtml\";\nimport { sanitizeArray } from \"../utils/sanitizeArray\";\nimport { UnSafeHTML } from \"../utils/UnSafeHTML\";\n\ntype GeneratorFunctionConstructor = new (\n ...args: string[]\n) => (...args: any[]) => Generator<any, any, any>;\nconst TemplateConstructor = function* () {}\n .constructor as GeneratorFunctionConstructor,\n templateCache = new WeakMap();\n\n/**\n * A function that generates the source code for a compiled HTML template function.\n *\n * @param {String[]} templates\n * @param {Array} values\n * @returns {string} source code of the compiled template function that can be called with the appropriate arguments to produce the final HTML output based on the provided templates and values.\n */\nfunction generateTemplateSourceCode(\n templates: TemplateStringsArray,\n values: TemplateValues[],\n): string {\n let sourceCode = `yield \\`${templates[0]}\\``,\n length = values.length;\n for (let index = 0; index < length; index++) {\n let value = values[index];\n if (typeof value == \"string\") {\n sourceCode += `+escapeHTML(args[${index}])+\\`${templates[index + 1]}\\``;\n } else if (value instanceof UnSafeHTML) {\n sourceCode += `+args[${index}].html+\\`${templates[index + 1]}\\``;\n } else if (value instanceof Error || typeof value == \"number\") {\n sourceCode += `+args[${index}]+\\`${templates[index + 1]}\\``;\n } else if (Array.isArray(value)) {\n sourceCode += `; yield * sanitizeArray(args[${index}]); yield \\`${templates[index + 1]}\\``;\n } else if ((value as any)?.[Symbol.iterator]) {\n sourceCode += `; yield * args[${index}]; yield \\`${templates[index + 1]}\\``;\n } else {\n sourceCode += `; yield args[${index}]; yield \\`${templates[index + 1]}\\``;\n }\n }\n return sourceCode;\n}\n/**\n * compiles an HTML template into a function that can be cached and reused with different values. It generates source code for the template by processing the provided templates and values, handling various types of values such as strings, UnSafeHTML instances, errors, numbers, arrays, and iterables. The generated source code is then used to create a new function using the TemplateConstructor, which can be called with the appropriate arguments to produce the final HTML output. This approach allows for efficient rendering of HTML templates while ensuring that string values are properly escaped to prevent XSS vulnerabilities.\n *\n * @param {String[]} templates\n * @param {Array} values\n * @returns {GeneratorFunction} A generator function that can be called with the appropriate arguments to produce the final HTML output based on the provided templates and values.\n */\nfunction compileTemplate(\n templates: TemplateStringsArray,\n values: TemplateValues[],\n) {\n let sourceCode = generateTemplateSourceCode(templates, values);\n return new TemplateConstructor(\n \"escapeHTML\",\n \"sanitizeArray\",\n \"args\",\n sourceCode,\n );\n}\n/**\n * A function that renders an HTML template with caching capabilities. It checks if a compiled template function already exists in the cache for the given templates. If it does, it calls the cached function with the provided values and returns the result. If not, it compiles a new template function using the compileTemplate function, stores it in the cache, and then calls it with the provided values. This allows for efficient rendering of HTML templates while ensuring that string values are properly escaped to prevent XSS vulnerabilities.\n *\n * @param {String[]} templates\n * @param {...(String|UnSafeHTML|Error|number|Array|Iterable)} values\n * @returns {GeneratorFunction} A generator function that can be called with the appropriate arguments to produce the final HTML output based on the provided templates and values.\n */\nfunction cachableHTML(\n templates: TemplateStringsArray,\n ...values: TemplateValues[]\n) {\n let template = templateCache.get(templates);\n if (template) {\n return template(escapeHTML, sanitizeArray, values);\n }\n template = compileTemplate(templates, values);\n templateCache.set(templates, template);\n return template(escapeHTML, sanitizeArray, values);\n}\n\nexport { cachableHTML };\n","import { UnSafeHTML } from \"../utils/UnSafeHTML\";\nimport { escapeHTML } from \"../utils/escapehtml\";\nimport { sanitizeArray } from \"../utils/sanitizeArray\";\n\n/**\n * A generator function that processes an HTML template without caching. It handles various types of values, including strings, UnSafeHTML instances, errors, numbers, promises, arrays, and iterables. The function ensures that string values are properly escaped to prevent XSS vulnerabilities, while allowing UnSafeHTML instances to be included as-is. It also supports asynchronous values by yielding promises and waiting for their resolution before processing them further.\n *\n * @export\n * @param {String[]} templates\n * @param {...TemplateValues} values\n * @returns {Generator} A generator that yields processed HTML content as a stream.\n */\nexport function* liveHTML(\n templates: TemplateStringsArray,\n ...values: TemplateValues[]\n) {\n let cache = templates[0],\n length = values.length;\n for (let index = 0; index < length; index++) {\n let value = values[index];\n if (typeof value == \"string\") {\n cache += escapeHTML(value);\n } else if (value instanceof UnSafeHTML) {\n cache += value.html;\n } else if (value instanceof Error || typeof value == \"number\") {\n cache += value;\n } else if (Array.isArray(value)) {\n if (cache) {\n yield cache;\n cache = \"\";\n }\n yield* sanitizeArray(value);\n } else if ((value as any)?.[Symbol.iterator]) {\n if (cache) {\n yield cache;\n cache = \"\";\n }\n yield* value as Generator;\n } else {\n yield value;\n }\n cache += templates[index + 1];\n }\n if (cache) {\n yield cache;\n cache = \"\";\n }\n}\n","export async function promisedValue(value: Promise<any>): Promise<any> {\n try {\n return await value;\n } catch (error) {\n if (error instanceof Promise) {\n return promisedValue(error);\n } else {\n return error;\n }\n }\n}\n","export async function streamHTML(\n readable: ReadableStream<string>,\n controller: ReadableStreamDefaultController,\n) {\n const stream: ReadableStreamDefaultReader = readable.getReader();\n try {\n while (true) {\n let data = await stream.read();\n if (data.done) {\n return;\n }\n controller.enqueue(data.value);\n }\n } catch (error) {\n controller.enqueue(error);\n } finally {\n stream.releaseLock();\n }\n}\n","import { UnSafeHTML } from \"../utils/UnSafeHTML\";\nimport { escapeHTML } from \"../utils/escapehtml\";\nimport { sanitizeArray } from \"../utils/sanitizeArray\";\nimport { promisedValue } from \"../utils/promisedValue\";\nimport { streamHTML } from \"../utils/streamHTML\";\n\n/**\n * A generator function that processes an HTML template with embedded values and yields the resulting HTML as a stream. It handles various types of values, including strings, UnSafeHTML instances, errors, numbers, promises, arrays, and iterables. The function ensures that string values are properly escaped to prevent XSS vulnerabilities, while allowing UnSafeHTML instances to be included as-is. It also supports asynchronous values by yielding promises and waiting for their resolution before processing them further.\n *\n * @param {Generator} templateGenerator\n * @param {ReadableStreamDefaultController} controller\n * @returns {IterableIterator<string>} An iterator that yields the resulting HTML as a stream.\n */\nfunction* processHTML(\n templateGenerator: Generator | Array<TemplateValues>,\n controller: ReadableStreamDefaultController<string>,\n): any {\n let cache: string = \"\";\n for (const value of templateGenerator) {\n if (typeof value == \"string\") {\n cache += value;\n } else if (value instanceof UnSafeHTML) {\n cache += value.html;\n } else if (value instanceof Error || typeof value == \"number\") {\n cache += value;\n } else if (value instanceof Promise) {\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n let resolvedValue = yield value;\n if (typeof resolvedValue == \"string\") {\n cache += escapeHTML(resolvedValue);\n } else if (resolvedValue instanceof UnSafeHTML) {\n cache += resolvedValue.html;\n } else if (\n resolvedValue instanceof Error ||\n typeof resolvedValue == \"number\"\n ) {\n cache += resolvedValue;\n } else if (Array.isArray(resolvedValue)) {\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n yield* processHTML(sanitizeArray(resolvedValue), controller);\n } else if (resolvedValue?.[Symbol.iterator]) {\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n yield* processHTML(resolvedValue, controller);\n } else if (resolvedValue == undefined) {\n continue;\n } else {\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n let resolvedValues = yield resolvedValue;\n void resolvedValues\n }\n } else if (Array.isArray(value)) {\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n yield* processHTML(sanitizeArray(value), controller);\n } else if (value?.[Symbol.iterator]) {\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n yield* processHTML(value, controller);\n } else if (value == undefined) {\n continue;\n } else {\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n let resolvedValue = yield value;\n void resolvedValue\n }\n }\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n}\n\n/**\n * A function that renders an HTML template generator and returns a ReadableStream that yields the resulting HTML as a stream. It uses the processHTML generator function to process the template and handle various types of values, including promises and streams, while ensuring that string values are properly escaped to prevent XSS vulnerabilities.\n *\n * @param {Generator} generator - The HTML template generator to render.\n * @returns {ReadableStream} A ReadableStream that yields the resulting HTML as a stream.\n */\nfunction renderStream(generator: Generator) {\n return new ReadableStream<string>({\n start(controller) {\n let templateGenerator = processHTML(generator, controller);\n return startHTMLStream(templateGenerator);\n async function startHTMLStream(\n value:\n | undefined\n | Promise<any>\n | Request\n | ReadableStream\n | Response = undefined,\n ) {\n let data = templateGenerator.next(value);\n try {\n if (data.value instanceof Promise) {\n let resolvedValue = await promisedValue(data.value);\n return startHTMLStream(resolvedValue);\n } else if (data.value instanceof Response) {\n await streamHTML(data.value.body.pipeThrough(new TextDecoderStream()), controller);\n return startHTMLStream();\n } else if (data.value instanceof ReadableStream) {\n await streamHTML(data.value, controller);\n return startHTMLStream();\n } else if (data.value instanceof Request) {\n let response:Response = await fetch(data.value),\n stream = response.body;\n if (stream) {\n await streamHTML(stream.pipeThrough(new TextDecoderStream()), controller);\n }\n return startHTMLStream();\n }\n } catch (error) {\n controller.enqueue(error as string);\n return startHTMLStream();\n }\n controller.close();\n }\n },\n });\n}\n/**\n * renders an HTML template generator and returns a promise that resolves to the resulting HTML as a string.\n *\n * @async\n * @param {Generator} generator\n * @returns {Promise<string>} A promise that resolves to the resulting HTML as a string.\n */\nasync function renderAsString(generator: Generator): Promise<string> {\n try {\n let readable = renderStream(generator).getReader(),\n html = \"\";\n while (true) {\n let data = await readable.read();\n if (data.done) {\n readable.releaseLock();\n break;\n }\n html += data.value;\n }\n return html;\n } catch (error) {\n throw error;\n }\n}\nexport { renderStream, renderAsString };\n","import { cachableHTML } from \"./html/cachehtml\";\nimport { liveHTML } from \"./html/livehtml\";\nimport { UnSafeHTML } from \"./utils/UnSafeHTML\";\nimport { renderStream, renderAsString } from \"./html/html\";\nimport { escapeHTML } from \"./utils/escapehtml\";\nimport { Readable } from \"node:stream\";\n\n/**\n * Renders an HTML template and sends it as a response\n *\n * @param {response} response - Node response object\n * @param {HTMLTemplate} template - HTML template to render\n * @param {{}} [headers={}] - Headers to send with the response\n * @param {number} [status=200] - HTTP status code\n * @param {string} [statusText='OK'] - HTTP status text\n * @returns {void}\n */\nfunction render(\n response: any,\n template: Generator,\n headers = {},\n status = 200,\n statusText = \"OK\",\n) {\n const readable = Readable.fromWeb(renderStream(template));\n response.writeHead(\n status,\n statusText,\n Object.assign({ \"Content-Type\": \"text/html; charset=utf-8\" }, headers),\n );\n readable.pipe(response);\n}\nexport {\n render,\n renderAsString,\n renderStream,\n liveHTML,\n cachableHTML as html,\n UnSafeHTML,\n escapeHTML,\n};\n"],"mappings":"uCAOA,SAAgB,EAAW,EAAqB,CAC9C,OAAO,OAAO,CAAG,CAAC,CAAC,QAAQ,WAAa,GAAiB,CACvD,OAAQ,EAAR,CACE,IAAK,IACH,MAAO,QACT,IAAK,IACH,MAAO,OACT,IAAK,IACH,MAAO,OACT,IAAK,IACH,MAAO,SACT,IAAK,IACH,MAAO,QACT,QACE,OAAO,CACX,CACF,CAAC,CACH,CCtBA,SAAgB,EAAc,EAAsB,CAClD,IAAI,EAAQ,EAAO,OACnB,KAAO,KAAS,CACd,IAAI,EAAQ,EAAO,GACf,OAAO,GAAS,WAClB,EAAO,GAAS,EAAW,CAAK,EAEpC,CACA,OAAO,CACT,CCXA,IAAa,EAAb,KAAwB,CACtB,KAMA,YAAY,EAAc,CACxB,KAAK,KAAO,CACd,CACF,ECHA,MAAM,EAAsB,WAAa,CAAC,EACrC,YACH,EAAgB,IAAI,QAStB,SAAS,EACP,EACA,EACQ,CACR,IAAI,EAAa,WAAW,EAAU,GAAG,IACvC,EAAS,EAAO,OAClB,IAAK,IAAI,EAAQ,EAAG,EAAQ,EAAQ,IAAS,CAC3C,IAAI,EAAQ,EAAO,GACf,OAAO,GAAS,SAClB,GAAc,oBAAoB,EAAM,OAAO,EAAU,EAAQ,GAAG,IAC3D,aAAiB,EAC1B,GAAc,SAAS,EAAM,WAAW,EAAU,EAAQ,GAAG,IACpD,aAAiB,OAAS,OAAO,GAAS,SACnD,GAAc,SAAS,EAAM,MAAM,EAAU,EAAQ,GAAG,IAC/C,MAAM,QAAQ,CAAK,EAC5B,GAAc,gCAAgC,EAAM,cAAc,EAAU,EAAQ,GAAG,IAC7E,IAAgB,OAAO,UACjC,GAAc,kBAAkB,EAAM,aAAa,EAAU,EAAQ,GAAG,IAExE,GAAc,gBAAgB,EAAM,aAAa,EAAU,EAAQ,GAAG,GAE1E,CACA,OAAO,CACT,CAQA,SAAS,EACP,EACA,EACA,CACA,IAAI,EAAa,EAA2B,EAAW,CAAM,EAC7D,OAAO,IAAI,EACT,aACA,gBACA,OACA,CACF,CACF,CAQA,SAAS,EACP,EACA,GAAG,EACH,CACA,IAAI,EAAW,EAAc,IAAI,CAAS,EAM1C,OALI,EACK,EAAS,EAAY,EAAe,CAAM,GAEnD,EAAW,EAAgB,EAAW,CAAM,EAC5C,EAAc,IAAI,EAAW,CAAQ,EAC9B,EAAS,EAAY,EAAe,CAAM,EACnD,CCnEA,SAAiB,EACf,EACA,GAAG,EACH,CACA,IAAI,EAAQ,EAAU,GACpB,EAAS,EAAO,OAClB,IAAK,IAAI,EAAQ,EAAG,EAAQ,EAAQ,IAAS,CAC3C,IAAI,EAAQ,EAAO,GACf,OAAO,GAAS,SAClB,GAAS,EAAW,CAAK,EAChB,aAAiB,EAC1B,GAAS,EAAM,KACN,aAAiB,OAAS,OAAO,GAAS,SACnD,GAAS,EACA,MAAM,QAAQ,CAAK,GAC5B,AAEE,KADA,MAAM,EACE,IAEV,MAAO,EAAc,CAAK,GAChB,IAAgB,OAAO,WACjC,AAEE,KADA,MAAM,EACE,IAEV,MAAO,GAEP,MAAM,EAER,GAAS,EAAU,EAAQ,EAC7B,CACA,AAEE,KADA,MAAM,EACE,GAEZ,CC/CA,eAAsB,EAAc,EAAmC,CACrE,GAAI,CACF,OAAO,MAAM,CACf,OAAS,EAAO,CAIZ,OAHE,aAAiB,QACZ,EAAc,CAAK,EAEnB,CAEX,CACF,CCVA,eAAsB,EACpB,EACA,EACA,CACA,IAAM,EAAsC,EAAS,UAAU,EAC/D,GAAI,CACF,OAAa,CACX,IAAI,EAAO,MAAM,EAAO,KAAK,EAC7B,GAAI,EAAK,KACP,OAEF,EAAW,QAAQ,EAAK,KAAK,CAC/B,CACF,OAAS,EAAO,CACd,EAAW,QAAQ,CAAK,CAC1B,QAAU,CACR,EAAO,YAAY,CACrB,CACF,CCLA,SAAU,EACR,EACA,EACK,CACL,IAAI,EAAgB,GACpB,IAAK,IAAM,KAAS,EAClB,GAAI,OAAO,GAAS,SAClB,GAAS,OACJ,GAAI,aAAiB,EAC1B,GAAS,EAAM,UACV,GAAI,aAAiB,OAAS,OAAO,GAAS,SACnD,GAAS,OACJ,GAAI,aAAiB,QAAS,CACnC,AAEE,KADA,EAAW,QAAQ,CAAK,EAChB,IAEV,IAAI,EAAgB,MAAM,EAC1B,GAAI,OAAO,GAAiB,SAC1B,GAAS,EAAW,CAAa,OAC5B,GAAI,aAAyB,EAClC,GAAS,EAAc,UAClB,GACL,aAAyB,OACzB,OAAO,GAAiB,SAExB,GAAS,OACJ,GAAI,MAAM,QAAQ,CAAa,EACpC,AAEE,KADA,EAAW,QAAQ,CAAK,EAChB,IAEV,MAAO,EAAY,EAAc,CAAa,EAAG,CAAU,OACtD,GAAI,IAAgB,OAAO,UAChC,AAEE,KADA,EAAW,QAAQ,CAAK,EAChB,IAEV,MAAO,EAAY,EAAe,CAAU,OACvC,GAAI,GAAiB,KAC1B,aAEA,CAEE,KADA,EAAW,QAAQ,CAAK,EAChB,IAEW,MAAM,CAG/B,MAAO,GAAI,MAAM,QAAQ,CAAK,EAC5B,AAEE,KADA,EAAW,QAAQ,CAAK,EAChB,IAEV,MAAO,EAAY,EAAc,CAAK,EAAG,CAAU,OAC9C,GAAI,IAAQ,OAAO,UACxB,AAEE,KADA,EAAW,QAAQ,CAAK,EAChB,IAEV,MAAO,EAAY,EAAO,CAAU,OAC/B,GAAI,GAAS,KAClB,aAEA,CAEE,KADA,EAAW,QAAQ,CAAK,EAChB,IAEU,MAAM,EAI9B,AAEE,KADA,EAAW,QAAQ,CAAK,EAChB,GAEZ,CAQA,SAAS,EAAa,EAAsB,CAC1C,OAAO,IAAI,eAAuB,CAChC,MAAM,EAAY,CAChB,IAAI,EAAoB,EAAY,EAAW,CAAU,EACzD,OAAO,EAAgB,CAAiB,EACxC,eAAe,EACb,EAKe,IAAA,GACf,CACA,IAAI,EAAO,EAAkB,KAAK,CAAK,EACvC,GAAI,CACF,GAAI,EAAK,iBAAiB,QAExB,OAAO,EAAgB,MADG,EAAc,EAAK,KAAK,CACd,EAC/B,GAAI,EAAK,iBAAiB,SAE/B,OADA,MAAM,EAAW,EAAK,MAAM,KAAK,YAAY,IAAI,iBAAmB,EAAG,CAAU,EAC1E,EAAgB,EAClB,GAAI,EAAK,iBAAiB,eAE/B,OADA,MAAM,EAAW,EAAK,MAAO,CAAU,EAChC,EAAgB,EAClB,GAAI,EAAK,iBAAiB,QAAS,CACxC,IACE,GAAS,MADmB,MAAM,EAAK,KAAK,EAAA,CAC1B,KAIpB,OAHI,GACF,MAAM,EAAW,EAAO,YAAY,IAAI,iBAAmB,EAAG,CAAU,EAEnE,EAAgB,CACzB,CACF,OAAS,EAAO,CAEd,OADA,EAAW,QAAQ,CAAe,EAC3B,EAAgB,CACzB,CACA,EAAW,MAAM,CACnB,CACF,CACF,CAAC,CACH,CAQA,eAAe,EAAe,EAAuC,CACnE,GAAI,CACF,IAAI,EAAW,EAAa,CAAS,CAAC,CAAC,UAAU,EAC/C,EAAO,GACT,OAAa,CACX,IAAI,EAAO,MAAM,EAAS,KAAK,EAC/B,GAAI,EAAK,KAAM,CACb,EAAS,YAAY,EACrB,KACF,CACA,GAAQ,EAAK,KACf,CACA,OAAO,CACT,OAAS,EAAO,CACd,MAAM,CACR,CACF,CChJA,SAAS,EACP,EACA,EACA,EAAU,CAAC,EACX,EAAS,IACT,EAAa,KACb,CACA,IAAM,EAAW,EAAS,QAAQ,EAAa,CAAQ,CAAC,EACxD,EAAS,UACP,EACA,EACA,OAAO,OAAO,CAAE,eAAgB,0BAA2B,EAAG,CAAO,CACvE,EACA,EAAS,KAAK,CAAQ,CACxB"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../src/utils/escapehtml.ts","../../src/utils/sanitizeArray.ts","../../src/utils/UnSafeHTML.ts","../../src/html/cachehtml.ts","../../src/html/livehtml.ts","../../src/utils/promisedValue.ts","../../src/utils/streamHTML.ts","../../src/html/html.ts","../../src/index.node.ts"],"sourcesContent":["/**\n * Escapes HTML special characters in a string to prevent XSS attacks and ensure proper rendering in HTML.\n *\n * @param {string} str - The string to escape\n *\n * @returns {string} - The escaped string\n */\nexport function escapeHTML(str: string): string {\n return String(str).replace(/[&<>\"']/g, (char: string) => {\n switch (char) {\n case \"&\":\n return \"&amp;\";\n case \"<\":\n return \"&lt;\";\n case \">\":\n return \"&gt;\";\n case '\"':\n return \"&quot;\";\n case \"'\":\n return \"&#39;\";\n default:\n return char;\n }\n });\n}\n","import { escapeHTML } from \"./escapehtml\";\n\nexport function sanitizeArray(values: any[]): any[] {\n let index = values.length;\n while (index--) {\n let value = values[index];\n if (typeof value == \"string\") {\n values[index] = escapeHTML(value);\n }\n }\n return values;\n}\n","export class UnSafeHTML {\n public html: string;\n /**\n * Creates unsafe html that will not be escaped\n *\n * @param {string} html - string containing unsafe html\n */\n constructor(html: string) {\n this.html = html;\n }\n}\n","import { escapeHTML } from \"../utils/escapehtml\";\nimport { sanitizeArray } from \"../utils/sanitizeArray\";\nimport { UnSafeHTML } from \"../utils/UnSafeHTML\";\n\ntype GeneratorFunctionConstructor = new (\n ...args: string[]\n) => (...args: any[]) => Generator<any, any, any>;\nconst TemplateConstructor = function* () {}\n .constructor as GeneratorFunctionConstructor,\n templateCache = new WeakMap();\n\n/**\n * A function that generates the source code for a compiled HTML template function.\n *\n * @param {String[]} templates\n * @param {Array} values\n * @returns {string} source code of the compiled template function that can be called with the appropriate arguments to produce the final HTML output based on the provided templates and values.\n */\nfunction generateTemplateSourceCode(\n templates: TemplateStringsArray,\n values: TemplateValues[],\n): string {\n let sourceCode = `yield \\`${templates[0]}\\``,\n length = values.length;\n for (let index = 0; index < length; index++) {\n let value = values[index];\n if (typeof value == \"string\") {\n sourceCode += `+escapeHTML(args[${index}])+\\`${templates[index + 1]}\\``;\n } else if (value instanceof UnSafeHTML) {\n sourceCode += `+args[${index}].html+\\`${templates[index + 1]}\\``;\n } else if (value instanceof Error || typeof value == \"number\") {\n sourceCode += `+args[${index}]+\\`${templates[index + 1]}\\``;\n } else if (Array.isArray(value)) {\n sourceCode += `; yield * sanitizeArray(args[${index}]); yield \\`${templates[index + 1]}\\``;\n } else if ((value as any)?.[Symbol.iterator]) {\n sourceCode += `; yield * args[${index}]; yield \\`${templates[index + 1]}\\``;\n } else {\n sourceCode += `; yield args[${index}]; yield \\`${templates[index + 1]}\\``;\n }\n }\n return sourceCode;\n}\n/**\n * compiles an HTML template into a function that can be cached and reused with different values. It generates source code for the template by processing the provided templates and values, handling various types of values such as strings, UnSafeHTML instances, errors, numbers, arrays, and iterables. The generated source code is then used to create a new function using the TemplateConstructor, which can be called with the appropriate arguments to produce the final HTML output. This approach allows for efficient rendering of HTML templates while ensuring that string values are properly escaped to prevent XSS vulnerabilities.\n *\n * @param {String[]} templates\n * @param {Array} values\n * @returns {GeneratorFunction} A generator function that can be called with the appropriate arguments to produce the final HTML output based on the provided templates and values.\n */\nfunction compileTemplate(\n templates: TemplateStringsArray,\n values: TemplateValues[],\n) {\n let sourceCode = generateTemplateSourceCode(templates, values);\n return new TemplateConstructor(\n \"escapeHTML\",\n \"sanitizeArray\",\n \"args\",\n sourceCode,\n );\n}\n/**\n * A function that renders an HTML template with caching capabilities. It checks if a compiled template function already exists in the cache for the given templates. If it does, it calls the cached function with the provided values and returns the result. If not, it compiles a new template function using the compileTemplate function, stores it in the cache, and then calls it with the provided values. This allows for efficient rendering of HTML templates while ensuring that string values are properly escaped to prevent XSS vulnerabilities.\n *\n * @param {String[]} templates\n * @param {...(String|UnSafeHTML|Error|number|Array|Iterable)} values\n * @returns {GeneratorFunction} A generator function that can be called with the appropriate arguments to produce the final HTML output based on the provided templates and values.\n */\nfunction cachableHTML(\n templates: TemplateStringsArray,\n ...values: TemplateValues[]\n) {\n let template = templateCache.get(templates);\n if (template) {\n return template(escapeHTML, sanitizeArray, values);\n }\n template = compileTemplate(templates, values);\n templateCache.set(templates, template);\n return template(escapeHTML, sanitizeArray, values);\n}\n\nexport { cachableHTML };\n","import { UnSafeHTML } from \"../utils/UnSafeHTML\";\nimport { escapeHTML } from \"../utils/escapehtml\";\nimport { sanitizeArray } from \"../utils/sanitizeArray\";\n\n/**\n * A generator function that processes an HTML template without caching. It handles various types of values, including strings, UnSafeHTML instances, errors, numbers, promises, arrays, and iterables. The function ensures that string values are properly escaped to prevent XSS vulnerabilities, while allowing UnSafeHTML instances to be included as-is. It also supports asynchronous values by yielding promises and waiting for their resolution before processing them further.\n *\n * @export\n * @param {String[]} templates\n * @param {...TemplateValues} values\n * @returns {Generator} A generator that yields processed HTML content as a stream.\n */\nexport function* liveHTML(\n templates: TemplateStringsArray,\n ...values: TemplateValues[]\n) {\n let cache = templates[0],\n length = values.length;\n for (let index = 0; index < length; index++) {\n let value = values[index];\n if (typeof value == \"string\") {\n cache += escapeHTML(value);\n } else if (value instanceof UnSafeHTML) {\n cache += value.html;\n } else if (value instanceof Error || typeof value == \"number\") {\n cache += value;\n } else if (Array.isArray(value)) {\n if (cache) {\n yield cache;\n cache = \"\";\n }\n yield* sanitizeArray(value);\n } else if ((value as any)?.[Symbol.iterator]) {\n if (cache) {\n yield cache;\n cache = \"\";\n }\n yield* value as Generator;\n } else {\n yield value;\n }\n cache += templates[index + 1];\n }\n if (cache) {\n yield cache;\n cache = \"\";\n }\n}\n","export async function promisedValue(value: Promise<any>): Promise<any> {\n try {\n return await value;\n } catch (error) {\n if (error instanceof Promise) {\n return promisedValue(error);\n } else {\n return error;\n }\n }\n}\n","export async function streamHTML(\n readable: ReadableStream<string>,\n controller: ReadableStreamDefaultController,\n) {\n const stream: ReadableStreamDefaultReader = readable.getReader();\n try {\n while (true) {\n let data = await stream.read();\n if (data.done) {\n return;\n }\n controller.enqueue(data.value);\n }\n } catch (error) {\n controller.enqueue(error);\n } finally {\n stream.releaseLock();\n }\n}\n","import { UnSafeHTML } from \"../utils/UnSafeHTML\";\nimport { escapeHTML } from \"../utils/escapehtml\";\nimport { sanitizeArray } from \"../utils/sanitizeArray\";\nimport { promisedValue } from \"../utils/promisedValue\";\nimport { streamHTML } from \"../utils/streamHTML\";\n\n/**\n * A generator function that processes an HTML template with embedded values and yields the resulting HTML as a stream. It handles various types of values, including strings, UnSafeHTML instances, errors, numbers, promises, arrays, and iterables. The function ensures that string values are properly escaped to prevent XSS vulnerabilities, while allowing UnSafeHTML instances to be included as-is. It also supports asynchronous values by yielding promises and waiting for their resolution before processing them further.\n *\n * @param {Generator} templateGenerator\n * @param {ReadableStreamDefaultController} controller\n * @returns {IterableIterator<string>} An iterator that yields the resulting HTML as a stream.\n */\nfunction* processHTML(\n templateGenerator: Generator | Array<TemplateValues>,\n controller: ReadableStreamDefaultController<string>,\n): any {\n let cache: string = \"\";\n for (const value of templateGenerator) {\n if (typeof value == \"string\") {\n cache += value;\n } else if (value instanceof UnSafeHTML) {\n cache += value.html;\n } else if (value instanceof Error || typeof value == \"number\") {\n cache += value;\n } else if (value instanceof Promise) {\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n let resolvedValue = yield value;\n if (typeof resolvedValue == \"string\") {\n cache += escapeHTML(resolvedValue);\n } else if (resolvedValue instanceof UnSafeHTML) {\n cache += resolvedValue.html;\n } else if (\n resolvedValue instanceof Error ||\n typeof resolvedValue == \"number\"\n ) {\n cache += resolvedValue;\n } else if (Array.isArray(resolvedValue)) {\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n yield* processHTML(sanitizeArray(resolvedValue), controller);\n } else if (resolvedValue?.[Symbol.iterator]) {\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n yield* processHTML(resolvedValue, controller);\n } else if (resolvedValue == undefined) {\n continue;\n } else {\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n let resolvedValues = yield resolvedValue;\n void resolvedValues\n }\n } else if (Array.isArray(value)) {\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n yield* processHTML(sanitizeArray(value), controller);\n } else if (value?.[Symbol.iterator]) {\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n yield* processHTML(value, controller);\n } else if (value == undefined) {\n continue;\n } else {\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n let resolvedValue = yield value;\n void resolvedValue\n }\n }\n if (cache) {\n controller.enqueue(cache);\n cache = \"\";\n }\n}\n\n/**\n * A function that renders an HTML template generator and returns a ReadableStream that yields the resulting HTML as a stream. It uses the processHTML generator function to process the template and handle various types of values, including promises and streams, while ensuring that string values are properly escaped to prevent XSS vulnerabilities.\n *\n * @param {Generator} generator - The HTML template generator to render.\n * @returns {ReadableStream} A ReadableStream that yields the resulting HTML as a stream.\n */\nfunction renderStream(generator: Generator) {\n return new ReadableStream<string>({\n start(controller) {\n let templateGenerator = processHTML(generator, controller);\n return startHTMLStream(templateGenerator);\n async function startHTMLStream(\n value:\n | undefined\n | Promise<any>\n | Request\n | ReadableStream\n | Response = undefined,\n ) {\n let data = templateGenerator.next(value);\n try {\n if (data.value instanceof Promise) {\n let resolvedValue = await promisedValue(data.value);\n return startHTMLStream(resolvedValue);\n } else if (data.value instanceof Response) {\n await streamHTML(data.value.body.pipeThrough(new TextDecoderStream()), controller);\n return startHTMLStream();\n } else if (data.value instanceof ReadableStream) {\n await streamHTML(data.value, controller);\n return startHTMLStream();\n } else if (data.value instanceof Request) {\n let response:Response = await fetch(data.value),\n stream = response.body;\n if (stream) {\n await streamHTML(stream.pipeThrough(new TextDecoderStream()), controller);\n }\n return startHTMLStream();\n }\n } catch (error) {\n controller.enqueue(error as string);\n return startHTMLStream();\n }\n controller.close();\n }\n },\n });\n}\n/**\n * renders an HTML template generator and returns a promise that resolves to the resulting HTML as a string.\n *\n * @async\n * @param {Generator} generator\n * @returns {Promise<string>} A promise that resolves to the resulting HTML as a string.\n */\nasync function renderAsString(generator: Generator): Promise<string> {\n try {\n let readable = renderStream(generator).getReader(),\n html = \"\";\n while (true) {\n let data = await readable.read();\n if (data.done) {\n readable.releaseLock();\n break;\n }\n html += data.value;\n }\n return html;\n } catch (error) {\n throw error;\n }\n}\nexport { renderStream, renderAsString };\n","import { cachableHTML } from \"./html/cachehtml\";\nimport { liveHTML } from \"./html/livehtml\";\nimport { UnSafeHTML } from \"./utils/UnSafeHTML\";\nimport { renderStream, renderAsString } from \"./html/html\";\nimport { escapeHTML } from \"./utils/escapehtml\";\nimport { Readable } from \"node:stream\";\n\n/**\n * Renders an HTML template and sends it as a response\n *\n * @param {response} response - Node response object\n * @param {HTMLTemplate} template - HTML template to render\n * @param {{}} [headers={}] - Headers to send with the response\n * @param {number} [status=200] - HTTP status code\n * @param {string} [statusText='OK'] - HTTP status text\n * @returns {void}\n */\nfunction render(\n response: any,\n template: Generator,\n headers = {},\n status = 200,\n statusText = \"OK\",\n) {\n const readable = Readable.fromWeb(renderStream(template));\n response.writeHead(\n status,\n statusText,\n Object.assign({ \"Content-Type\": \"text/html; charset=utf-8\",\"X-Accel-Buffering\": \"no\" }, headers),\n );\n readable.pipe(response);\n}\nexport {\n render,\n renderAsString,\n renderStream,\n liveHTML,\n cachableHTML as html,\n UnSafeHTML,\n escapeHTML,\n};\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "achi-html-stream",
3
3
  "type": "module",
4
- "version": "1.0.2",
4
+ "version": "1.0.3",
5
5
  "description": "An HTML streaming library for multi-page progressive web apps that renders HTML in service workers and also works with Node.js and other JavaScript runtimes",
6
6
  "author": {
7
7
  "name": "Kimbugwe Mark",