Bringing JSX to Template Literals

basic JSX transpilation example

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

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Andrea Giammarchi

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