ulit
Tagged Template Literal html template library. Inspired by lit-html/hyperHTML.
Why another tagged template literal library?
"I cannot understand what I cannot build." - Feynman
Started this from a desire to see how hard it would be to improve upon the implementations of lit-html and hyperHTML, focusing on feature density and utilizing the platform, but abandoning support for legacy browsers to use the latest features without transpiling to es5 (instead targeting Chrome, Firefox, Safari, Edge latest versions).
What was the result?
Rough parity with lit-html + lit-extended on features and general api setup.
Pros:
- Transparent svg support - (no need for special svg tagged template function)
- Simple depth first search walkDOM(fn) avoids using slow TreeWalker and allows for simple tracking of path during recursive dfs.
- SSR support via serializable part paths. This uses followPath(Array<Number|String>), which handles most of the setup work, and it can be pre-rendered down to static html that can be delivered to the client and hydrated, bypassing the more expensive process required if a serialized template is not present in the dom.
- By using "{{}}" for attributes and <!--{{}}--> for part placeholders, this library doesn't need to use regex, doesn't force quotes on attributes in templates and can be generally simpler.
Cons:
- No plan to support partial parts. i.e.// DO NOT DO THIShtml`boom`you should instead always write your templates to replace the whole property/attribute as a single variable i.e.// DO NOT DO THIShtml``// DO THIS INSTEADhtml``
- Style tags within html tagged template literals are not supported initially, will need to add a style tagged template literal helper for this purpose, can be made outside of core.
// basic idea if someone feels like implementing somethinghtml``; // template out -> <style>...</style><div></div>
How can I use it?
If your build system/browser supports es2015 modules you can install and use it as normal.
Install
npm install --save ulit
API Dump
// repeat is used for rendering keyed lists of dom nodes// until allows you to conditionally load a template that is replaced upon promise completion (code-splitting, fetch, etc...); const target = document; // "components" are just template functionsconst hello = html`hello `;;targetinnerHTML === "<h1>hello world</h1>"; // true // calling render multiple times on the same container will update the current template in place if possible or replace it.;targetinnerHTML === "<h1>hello internet</h1>"; // true // Build your own directive to extend ulit...// the example below passthroughDirective is a dummy directive example that is equivalent to just passing the value to the part// in the template expressions.const passthroughDirective = ; ;targetinnerHTML === "<h1>pass through example...</h1>"; // true // Example Part API brain dumpconst partApiDirective = ; // Arrays/iterables are valid PartValue and render templates, this uses repeat() internallyconst nums = 0 1 2 3 4 5 6 7 8 9 10;;targetinnerHTML === "<h1>hello 0</h1><h1>hello 1</h1>..."; //true;targetinnerHTML === "<h1>hello 012345678910</h1>"; // true NOTE: each number would be it's own textNode in this case... // Promises are valid PartValues, by default they will leave the previous part value in place initially, and update to what is resolved...;// initiallytargetinnerHTML === "<h1>hello 012345678910</h1>"; // true; // true // until gives better support by allowing you to specify a default template while the promise resolves instead of a comment node;targetinnerHTML === "<h1>hello loading...</h1>"; //true; // true // eventsconst eventTemplate = html` console.log(e)}>click me`;;targetinnerHTML === "<button>click me</button>"; // true // nested templatesconst nested = ;;targetinnerHTML === "<h1>hello <h1>hello nested</h1></h1>"; // true
License
ulit is MIT licensed. See LICENSE.