Files
open-wc/packages/testing-helpers/lit-html.js
2019-03-23 23:17:23 +01:00

67 lines
2.2 KiB
JavaScript

import { html as litHtml } from 'lit-html/lit-html.js';
export { render } from 'lit-html/lit-html.js';
/**
* This is a wrapper around lit-html that supports dynamic strings to be added as a preprocessing
* step, before a template is passed to lit's html function.
* A dynamic string will be evaluated one time (on init) and passed to lit-html as being
* part of the static string.
*
* WARNING: do not use in production!!! has a huge performance penalty as every string is
* different from lit-htmls perspective so a new tag is created every time.
*
* A valid use case for this would be to create dynamic tag names.
*
* @example:
* const tag = unsafeStatic('my-tag');
* html`<${tag} prop="${prop}"></${tag>`
* // will in turn calls lit-html html function as:
* html`<my-tag prop="${prop}"></my-tag>`
*
* @param {TemplateStringsArray} strings Static Parts
* @param {Array[any]} values Dynamic Parts
* @returns {import('lit-html').TemplateResult}
*/
export function html(strings, ...values) {
const newVal = []; // result values to be passed on to lit-html
const newStr = []; // result strings to be passed on to lit-html
if (values.length === 0) {
return litHtml(strings, ...values);
}
const isDynamicProp = p => p && p.d && typeof p.d === 'string' && Object.keys(p).length === 1;
const addToCurrentString = add => {
newStr[newStr.length - 1] = newStr[newStr.length - 1] + add;
};
// Create the result arrays
values.forEach((string, index) => {
if (index === 0) {
newStr.push(strings[0]); // this is either ''(if tagged starts with value) or string
}
// Situation 1 : dynamic string
const p = values[index]; // potential dynamic string
if (isDynamicProp(p)) {
addToCurrentString(p.d);
addToCurrentString(strings[index + 1]);
} else {
// Situation 2: no dynamic string, just push string and value
newVal.push(p); // a 'real' value
newStr.push(strings[index + 1]);
}
});
// Return lit template
// TODO: this is the reason it's not performant TemplateStringsArray needs to be always exactly
// the same => e.g. would require specific caching
// @ts-ignore
return litHtml(newStr, ...newVal);
}
export function unsafeStatic(options) {
return {
d: options,
};
}