Reputation: 3648
In lit/lit-html/lit-element, a standard component is the TemplateResult (usually HTMLTemplateResult), created like:
function renderMe(msg) {
return html`<div>Hello ${msg}!</div>`;
}
and of course the power and efficiency of the library is that subsequent calls will reuse the same <div>
Element and only replace the changed fragments.
For testing the renderMe()
function above, however, it would be helpful to be able to see the return value as a standard string, like:
assert.equal(
RENDER_AS_STRING(renderMe('kimiko')),
'<div>Hello kimiko!</div>'
);
and fix any bugs in the function before testing how it renders into the browser itself.
Is there a function like RENDER_AS_STRING
either in lit itself or in a testing library? I have searched and not found one.
Upvotes: 6
Views: 5128
Reputation: 3648
updated/expanded for a broader mix of TemplateResults, arrays and primitives...
export function template_as_string(data) {
// template
const {strings = null, values = []} = data ?? {};
// if not a template
if(!strings) return data ?? '';
return strings.reduce((res, txt, i)=>{
const v = values[i] ?? '';
res.push(txt);
if(Array.isArray(v)){
res.push(...(v.map(template_as_string)))
}else{
res.push( template_as_string(v) );
}
return res;
}, []).join('');
}
export function test_template_as_string({html=()=>{}, src='./image.webp', make=template_as_string}, ...tests){
return [
html`<img src=${src} />`,
html`<b>${ [1,2,html`<b>bb${7}b</b>`] }</b>`,
...tests
].map( stuff=> make(stuff) )
}
/*
// str info at https://lit.dev/docs/localization/overview/#strings-with-expressions
console.log(test_template_as_string({html}, html`<b>${ str`${ 123 }` }</b>`));
console.log(test_template_as_string({html}));
*/
Upvotes: 2
Reputation: 4381
The result of execution contains html strings
and values
that alternate:
We can combine them in the same order:
function renderMe(msg) {
return html`<div>Hello ${msg}!</div>`;
}
const getRenderString = (data) => {
const {strings, values} = data;
const v = [...values, ''] // + last emtpty part
return strings.reduce((acc,s, i) => acc + s + v[i], '')
}
console.log(getRenderString(renderMe('SO')))
You can test it in the playground
And the recursive version
import {html, css, LitElement} from 'lit';
function renderMe(msg) {
return html`<p>Hello ${msg}!</p>`;
}
function renderBlock(msg) {
return html`<div>${renderMe(msg)}</div>`;
}
const getRenderString = (data) => {
const {strings, values} = data;
const v = [...values, ''].map(e => typeof e === 'object' ? getRenderString(e) : e )
return strings.reduce((acc,s, i) => acc + s + v[i], '')
}
document.getElementById('output').textContent = getRenderString(renderBlock('SO'))
Upvotes: 6