@werker/html
Version:
HTML templating and streaming response library for worker environments such as Cloudflare Workers
83 lines • 2.48 kB
JavaScript
import { filterXSS } from 'xss';
async function* unpackContent(content) {
const x = await content;
if (Array.isArray(x))
for (const xi of x)
yield* unpackContent(xi);
else if (x instanceof Unpackable)
yield* x;
else
yield filterXSS(x); // relying on string coercion for primitives within the xss module here
}
async function* unpack(content) {
try {
yield* unpackContent(typeof content === 'function' ? content() : content);
}
catch (err) {
if (err instanceof HTML)
yield* err;
else
throw err;
}
}
class Unpackable {
}
export class HTML extends Unpackable {
constructor(strings, args) {
super();
this.strings = strings;
this.args = args;
}
async *[Symbol.asyncIterator]() {
const stringsIt = this.strings[Symbol.iterator]();
const argsIt = this.args[Symbol.iterator]();
while (true) {
const { done: stringDone, value: string } = stringsIt.next();
if (stringDone)
break;
else
yield string;
const { done: argDone, value: arg } = argsIt.next();
if (argDone)
break;
else
yield* unpack(arg);
}
}
}
export class UnsafeHTML extends Unpackable {
constructor(value) { super(); this.value = value; }
async *[Symbol.asyncIterator]() { yield this.value; }
toString() { return this.value; }
toJSON() { return this.value; }
}
export class Fallback extends Unpackable {
constructor(content, fallback) {
super();
this.content = content;
this.fallback = fallback;
}
async *[Symbol.asyncIterator]() {
try {
yield* unpack(this.content);
}
catch (e) {
yield* typeof this.fallback === 'function'
? this.fallback(e)
: this.fallback;
}
}
}
export function html(strings, ...args) {
return new HTML(strings, args);
}
// For the purpose of generating strings, there is no difference between html and css
// so we can export this alias here to help with syntax highlighting and avoid confusion.
export { html as css, html as js };
export function fallback(content, fallback) {
return new Fallback(content, fallback);
}
export function unsafeHTML(content) {
return new UnsafeHTML(content);
}
//# sourceMappingURL=html.js.map