Bringing JSX to Template Literals

Update

// this
const jsx = (
<div id="test">
<Component key={"value"} />
</div>
);
// becomes this
const jsx = callback(
// tag name or component
"div",
// all properties (attributes)
{id: "test"},
// zero, one, or more children
callback(Component, {
key: "value"
})
);
/** @jsx myCreateElement */
/** @jsxFrag myFragment */

About Template Literals

const tpl = html`
<div id="test">
<Component key=${value} />
</div>
`;
const html = (template, ...values) => { /*JIT*/ };

Tagged Literals Pros

Tagged Literals Cons

import {HTML, render, html} from 'ube';
export default class Div extends HTML.Div {
upgradedCallback() {
const {hello: name} = this.dataset;
render(this, html`Hello <strong>${name}</strong>`);
}
}


// ... rendering file ...
import {render, html} from 'ube';
import Div from './div-component.js';

render(document.body, html`<${Div} data-hello="µbe" />`);

… alternatives …

Creating Tagged Literals’ Arguments

/** @jsx callback *//** @jsxFrag callback */const callback = (tagName, props, ...children) => {
const template = [`<${tagName}`];
const values = [];
let i = 0;
// create attributes as interpolations
for (const [key, value] of Object.entries(props)) {
template[i] += ` ${key}="`;
values.push(value);
i = template.push('"') - 1;
}
// close the tag from last chunk
template[i] += '>';
// inner content
values.push(children);
// closing tag
template.push(`</${tagName}>`);
return [template].concat(values);
};
// test arguments
console.log(<div id="test">Hello!</div>);
const cache = new Map;
if (!cache.has(template.join('<☠>')))
cache.set(template.join('<☠>'), template);
// now we can use that
cache.get(template.join('<☠>'));
// so that its identity will be always the same

Understanding Components

const callback = (tagName, props, ...children) => {
if (typeof tagName === 'function')
return tagName({...props, children});
// ... rest of previous code
};
const callback = (tagName, props, ...children) => {
// we called jsxFrag callback so ...
if (tagName === callback)
return children;
// uland via JSX ... goodbye kaboobie
/** @jsx h *//** @jsxFrag h */
import {createPragma} from '//unpkg.com/jsx2tag?module';
import {Component, render, html, useState} from '//unpkg.com/uland?module';
const h = createPragma(html);const Button = Component(({count}) => {
const [current, update] = useState(count);
return html`
<button onClick=${() => update(current + 1)}>
Clicked ${current} times
</button>
`;
});
render(document.body, <Button count={0} />);

Last Thoughts on JSX2TAG

Web, Mobile, IoT, and all JS things since 00's. Formerly JS engineer at @nokia, @facebook, @twitter.