diff --git a/CHANGELOG.md b/CHANGELOG.md index f479d768..60ac2164 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # hyper(html) Changelog +### v.2.23 + * monkey patched rollup generated code to export once the same module shared within sub-modules + +### v2.22 + * using latest domtagger + +### v2.21 + * refactored out all dependencies + ### v2.20 * re-tested every single supported browser nd fixed few outstanding issues with the 2.19 release diff --git a/HELPERS.md b/HELPERS.md new file mode 100644 index 00000000..d0f8aefb --- /dev/null +++ b/HELPERS.md @@ -0,0 +1,57 @@ +## [babel-plugin-remove-ungap] + +Remove the [@ungap ponyfill modules] from your bundle. This will decrease the size of +your bundle if you are targeting modern browsers only or if your build already includes +other polyfills. This has been tested with [hyperHTML] and [lighterhtml] bundles. + + +## [babel-plugin-template-html-minifier] + +Run [html-minifier] on hyperHTML templates. + + +## [babel-plugin-bare-import-rewrite] + +This can be used as an alternative to [rollup-plugin-node-resolve], or can be used with certain node.js +web servers to allow browsing live from source. + +Known web server integrations: +* [fastify-babel] plugin for [fastify] enables running any babel plugins, generally expects `payload.filename` as set by [fastify-static] +* [express-transform-bare-module-specifiers] for [express] servers + + +## [vinyl-rollup] + +This module copies the output of rollup builds to a stream of vinyl-fs objects for [gulp]. +In addition it optionally adds files from modules that were bundled into the stream. This +makes it easy to ensure that LICENSE and package.json files associated with bundled modules +are published on the web server without publishing node.js server-side dependencies to the web. +This can also be used to copy complete modules if required for licensing or if bundled code +requires additional assets that are not part of the bundled JS (images for example). + + +## [babel-plugin-bundled-import-meta] + +If `node_modules/some-web-component/index.js` uses `import.meta.url` to calculate the actual +path to `node_modules/some-web-components/image.png`, rollup does not compensate. This babel +plugin rewrites references to `import.meta.url` so it points to the original location where +it is expected that the additional assets (images and such) can be found. This plugin works +well with `vinyl-rollup` with `copyModules: true`. + + +[babel-plugin-remove-ungap]: https://github.com/cfware/babel-plugin-remove-ungap#readme +[@ungap ponyfill modules]: https://github.com/ungap/ungap.github.io#readme +[hyperHTML]: https://github.com/WebReflection/hyperHTML#readme +[lighterhtml]: https://github.com/WebReflection/lighterhtml#readme +[babel-plugin-template-html-minifier]: https://github.com/cfware/babel-plugin-template-html-minifier#readme +[html-minifier]: https://github.com/kangax/html-minifier#readme +[babel-plugin-bare-import-rewrite]: https://github.com/cfware/babel-plugin-bare-import-rewrite#readme +[rollup-plugin-node-resolve]: https://github.com/rollup/rollup-plugin-node-resolve#readme +[fastify]: https://github.com/fastify/fastify#readme +[fastify-babel]: https://github.com/cfware/fastify-babel#readme +[fastify-static]: https://github.com/fastify/fastify-static#readme +[express-transform-bare-module-specifiers]: https://github.com/nodecg/express-transform-bare-module-specifiers#readme +[express]: https://github.com/expressjs/express#readme +[vinyl-rollup]: https://github.com/cfware/vinyl-rollup#readme +[gulp]: https://github.com/gulpjs/gulp#readme +[babel-plugin-bundled-import-meta]: https://github.com/cfware/babel-plugin-bundled-import-meta#readme diff --git a/README.md b/README.md index 6a7b5a6a..087b89ee 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,13 @@ A **Fast & Light Virtual DOM Alternative** available for [Node.js](https://viper - - - +## lighterhtml 💡 + +This little brother is "_showing off_" these days, claiming better performance and unprecedented ease of use. + +[GitHub Repository](https://github.com/WebReflection/lighterhtml) + + ## Neverland 🌈🦄 If you like React hooks concept, don't miss this little wrap that adds 0._something_ overhead to the already lightweight hyperHTML, bringing in very similar concepts. @@ -34,6 +41,8 @@ You can require or import _hyperHTML_ with any bundler and in different ways. If requiring or importing from `"hyperhtml"` doesn't work, try requiring from `"hyperhtml/cjs"` for CommonJS friendly bundlers (WebPack), or `"hyperhtml/esm"` for ESM compatible bundlers (Rollup). +See [HELPERS.md](./HELPERS.md) for a list of additional tools which can be helpful for building hyperHTML based web applications. + - - - ## Sponsors @@ -121,6 +130,12 @@ You can verify directly through the following links: * [100% code coverage](https://webreflection.github.io/hyperHTML/test/) for browsers natively compatible with string literals * [100% code coverage](https://webreflection.github.io/hyperHTML/test/ie/) for IE9+ and browsers that need transpiled code + +#### Weakmap error on ie < 11 + +'@ungap/weakmap': object is not extensible + +Babel freezes the template literals by spec but that causes problems with the weakmap polyfill. To fix this error add the fix explained on [ungap/weakmap](https://github.com/ungap/weakmap#transpiled-code-and-frozen-objects-in-legacy-browsers) ## HTML Syntax Highlight @@ -138,7 +153,7 @@ Please ask anything you'd like to know in [StackOverflow](https://stackoverflow. #### hyper or lit ? -You can read more on this [hyperHTML vs lit-html](https://gist.github.com/WebReflection/fadcc419f5ccaae92bc167d8ff5c611b) comparison. +You can read more on this [hyperHTML vs lit-html](https://medium.com/@WebReflection/lit-html-vs-hyperhtml-vs-lighterhtml-c084abfe1285) comparison. #### installation? diff --git a/cjs/classes/Component.js b/cjs/classes/Component.js index ebe3ffa4..632986bf 100644 --- a/cjs/classes/Component.js +++ b/cjs/classes/Component.js @@ -107,7 +107,7 @@ function setup(content) { event.component = this; return (_wire$.dispatchEvent ? _wire$ : - _wire$.childNodes[0] + _wire$.firstChild ).dispatchEvent(event); } return false; @@ -155,3 +155,12 @@ const setValue = (self, secret, value) => value })[secret] ; + +Object.defineProperties( + Component.prototype, + { + // used to distinguish better than instanceof + ELEMENT_NODE: {value: 1}, + nodeType: {value: -1} + } +); diff --git a/cjs/classes/Wire.js b/cjs/classes/Wire.js deleted file mode 100644 index 2d1983ee..00000000 --- a/cjs/classes/Wire.js +++ /dev/null @@ -1,38 +0,0 @@ -'use strict'; -const { append, doc, fragment } = require('../shared/utils.js'); - -function Wire(childNodes) { - this.childNodes = childNodes; - this.length = childNodes.length; - this.first = childNodes[0]; - this.last = childNodes[this.length - 1]; - this._ = null; -} -Object.defineProperty(exports, '__esModule', {value: true}).default = Wire - -// when a wire is inserted, all its nodes will follow -Wire.prototype.valueOf = function valueOf(different) { - const noFragment = this._ == null; - if (noFragment) - this._ = fragment(this.first); - /* istanbul ignore else */ - if (noFragment || different) - append(this._, this.childNodes); - return this._; -}; - -// when a wire is removed, all its nodes must be removed as well -Wire.prototype.remove = function remove() { - this._ = null; - const first = this.first; - const last = this.last; - if (this.length === 2) { - last.parentNode.removeChild(last); - } else { - const range = doc(first).createRange(); - range.setStartBefore(this.childNodes[1]); - range.setEndAfter(last); - range.deleteContents(); - } - return first; -}; diff --git a/cjs/hyper/render.js b/cjs/hyper/render.js index cbb929ba..a401a66b 100644 --- a/cjs/hyper/render.js +++ b/cjs/hyper/render.js @@ -1,9 +1,9 @@ 'use strict'; const WeakMap = (m => m.__esModule ? /* istanbul ignore next */ m.default : /* istanbul ignore next */ m)(require('@ungap/weakmap')); +const tta = (m => m.__esModule ? /* istanbul ignore next */ m.default : /* istanbul ignore next */ m)(require('@ungap/template-tag-arguments')); const {OWNER_SVG_ELEMENT} = require('../shared/constants.js'); const {Tagger} = require('../objects/Updates.js'); -const {reArguments} = require('../shared/utils.js'); // a weak collection of contexts that // are already known to hyperHTML @@ -15,7 +15,7 @@ const bewitched = new WeakMap; // The `this` context is either a regular DOM node or a fragment. function render() { const wicked = bewitched.get(this); - const args = reArguments.apply(null, arguments); + const args = tta.apply(null, arguments); if (wicked && wicked.template === args[0]) { wicked.tagger.apply(null, args); } else { @@ -28,13 +28,12 @@ function render() { // parse it once, if unknown, to map all interpolations // as single DOM callbacks, relate such template // to the current context, and render it after cleaning the context up -function upgrade() { - const args = reArguments.apply(null, arguments); +function upgrade(template) { const type = OWNER_SVG_ELEMENT in this ? 'svg' : 'html'; const tagger = new Tagger(type); - bewitched.set(this, {tagger, template: args[0]}); + bewitched.set(this, {tagger, template: template}); this.textContent = ''; - this.appendChild(tagger.apply(null, args)); + this.appendChild(tagger.apply(null, arguments)); } Object.defineProperty(exports, '__esModule', {value: true}).default = render; diff --git a/cjs/hyper/wire.js b/cjs/hyper/wire.js index 5965186c..139eaaba 100644 --- a/cjs/hyper/wire.js +++ b/cjs/hyper/wire.js @@ -1,12 +1,10 @@ 'use strict'; const WeakMap = (m => m.__esModule ? /* istanbul ignore next */ m.default : /* istanbul ignore next */ m)(require('@ungap/weakmap')); -const trim = (m => m.__esModule ? /* istanbul ignore next */ m.default : /* istanbul ignore next */ m)(require('@ungap/trim')); +const tta = (m => m.__esModule ? /* istanbul ignore next */ m.default : /* istanbul ignore next */ m)(require('@ungap/template-tag-arguments')); -const {ELEMENT_NODE} = require('../shared/constants.js'); -const Wire = (m => m.__esModule ? /* istanbul ignore next */ m.default : /* istanbul ignore next */ m)(require('../classes/Wire.js')); +const Wire = (m => m.__esModule ? /* istanbul ignore next */ m.default : /* istanbul ignore next */ m)(require('hyperhtml-wire')); const {Tagger} = require('../objects/Updates.js'); -const {reArguments} = require('../shared/utils.js'); // all wires used per each context const wires = new WeakMap; @@ -33,7 +31,7 @@ const wire = (obj, type) => obj == null ? const content = type => { let wire, tagger, template; return function () { - const args = reArguments.apply(null, arguments); + const args = tta.apply(null, arguments); if (template !== args[0]) { template = args[0]; tagger = new Tagger(type); @@ -69,24 +67,16 @@ const weakly = (obj, type) => { // stay associated with the original interpolation. // To prevent hyperHTML from forgetting about a fragment's sub-nodes, // fragments are instead returned as an Array of nodes or, if there's only one entry, -// as a single referenced node which, unlike framents, will indeed persist +// as a single referenced node which, unlike fragments, will indeed persist // wire content throughout multiple renderings. // The initial fragment, at this point, would be used as unique reference to this // array of nodes or to this single referenced node. const wireContent = node => { const childNodes = node.childNodes; - const length = childNodes.length; - const wireNodes = []; - for (let i = 0; i < length; i++) { - let child = childNodes[i]; - if ( - child.nodeType === ELEMENT_NODE || - trim.call(child.textContent).length !== 0 - ) { - wireNodes.push(child); - } - } - return wireNodes.length === 1 ? wireNodes[0] : new Wire(wireNodes); + const {length} = childNodes; + return length === 1 ? + childNodes[0] : + (length ? new Wire(childNodes) : node); }; exports.content = content; diff --git a/cjs/index.js b/cjs/index.js index 96a17441..04ed734a 100644 --- a/cjs/index.js +++ b/cjs/index.js @@ -11,7 +11,6 @@ const {observe, Tagger} = require('./objects/Updates.js'); const wire = (m => m.__esModule ? /* istanbul ignore next */ m.default : /* istanbul ignore next */ m)(require('./hyper/wire.js')); const {content, weakly} = require('./hyper/wire.js'); const render = (m => m.__esModule ? /* istanbul ignore next */ m.default : /* istanbul ignore next */ m)(require('./hyper/render.js')); -const { G } = require('./shared/constants.js'); // all functions are self bound to the right context // you can do the following @@ -35,7 +34,6 @@ hyper.wire = wire; // that don't necessarily need upfront polyfills // i.e. those still targeting IE hyper._ = { - global: G, WeakMap, WeakSet }; diff --git a/cjs/objects/Basic.js b/cjs/objects/Basic.js deleted file mode 100644 index ad9a93a7..00000000 --- a/cjs/objects/Basic.js +++ /dev/null @@ -1 +0,0 @@ -'use strict'; diff --git a/cjs/objects/Engine.js b/cjs/objects/Engine.js deleted file mode 100644 index b5195357..00000000 --- a/cjs/objects/Engine.js +++ /dev/null @@ -1,46 +0,0 @@ -'use strict'; -Object.defineProperty(exports, '__esModule', {value: true}).default = { - update: ( - utils, - liveNodes, liveStart, liveEnd, liveLength, - virtualNodes, virtualStart, virtualEnd /*, virtualLength */ - ) => { - const { splicer } = utils; - while (liveStart < liveEnd && virtualStart < virtualEnd) { - const liveValue = liveNodes[liveStart]; - const virtualValue = virtualNodes[virtualStart]; - const status = liveValue === virtualValue ? - 0 : (liveNodes.indexOf(virtualValue) < 0 ? 1 : -1); - // nodes can be either removed ... - if (status < 0) { - splicer.splice(liveStart, 1); - liveEnd--; - liveLength--; - } - // ... appended ... - else if (0 < status) { - splicer.splice(liveStart, 0, virtualValue); - liveStart++; - liveEnd++; - liveLength++; - virtualStart++; - } - // ... or ignored, since it's the same ... - else { - liveStart++; - virtualStart++; - } - } - if (liveStart < liveEnd) { - splicer.splice(liveStart, liveEnd - liveStart); - } - if (virtualStart < virtualEnd) { - splicer.splice.apply( - splicer, - [liveEnd, 0].concat( - virtualNodes.slice(virtualStart, virtualEnd) - ) - ); - } - } -}; \ No newline at end of file diff --git a/cjs/objects/Path.js b/cjs/objects/Path.js deleted file mode 100644 index aef883cf..00000000 --- a/cjs/objects/Path.js +++ /dev/null @@ -1,58 +0,0 @@ -'use strict'; -const { - COMMENT_NODE, - DOCUMENT_FRAGMENT_NODE, - ELEMENT_NODE -} = require('../shared/constants.js'); - -// every template literal interpolation indicates -// a precise target in the DOM the template is representing. -// `

some ${'content'}

` -// hyperHTML finds only once per template literal, -// hence once per entire application life-cycle, -// all nodes that are related to interpolations. -// These nodes are stored as indexes used to retrieve, -// once per upgrade, nodes that will change on each future update. -// A path example is [2, 0, 1] representing the operation: -// node.childNodes[2].childNodes[0].childNodes[1] -// Attributes are addressed via their owner node and their name. -const createPath = node => { - const path = []; - let parentNode; - switch (node.nodeType) { - case ELEMENT_NODE: - case DOCUMENT_FRAGMENT_NODE: - parentNode = node; - break; - case COMMENT_NODE: - parentNode = node.parentNode; - prepend(path, parentNode, node); - break; - default: - parentNode = node.ownerElement; - break; - } - for ( - node = parentNode; - (parentNode = parentNode.parentNode); - node = parentNode - ) { - prepend(path, parentNode, node); - } - return path; -}; - -const prepend = (path, parent, node) => { - path.unshift(path.indexOf.call(parent.childNodes, node)); -}; - -Object.defineProperty(exports, '__esModule', {value: true}).default = { - create: (type, node, name) => ({type, name, node, path: createPath(node)}), - find: (node, path) => { - const length = path.length; - for (let i = 0; i < length; i++) { - node = node.childNodes[path[i]]; - } - return node; - } -} diff --git a/cjs/objects/Style.js b/cjs/objects/Style.js deleted file mode 100644 index 9b177723..00000000 --- a/cjs/objects/Style.js +++ /dev/null @@ -1,82 +0,0 @@ -'use strict'; -// from https://github.com/developit/preact/blob/33fc697ac11762a1cb6e71e9847670d047af7ce5/src/constants.js -const IS_NON_DIMENSIONAL = /acit|ex(?:s|g|n|p|$)|rph|ows|mnc|ntw|ine[ch]|zoo|^ord/i; - -// style is handled as both string and object -// even if the target is an SVG element (consistency) -Object.defineProperty(exports, '__esModule', {value: true}).default = (node, original, isSVG) => { - if (isSVG) { - const style = original.cloneNode(true); - style.value = ''; - node.setAttributeNode(style); - return update(style, isSVG); - } - return update(node.style, isSVG); -}; - -// the update takes care or changing/replacing -// only properties that are different or -// in case of string, the whole node -const update = (style, isSVG) => { - let oldType, oldValue; - return newValue => { - switch (typeof newValue) { - case 'object': - if (newValue) { - if (oldType === 'object') { - if (!isSVG) { - if (oldValue !== newValue) { - for (const key in oldValue) { - if (!(key in newValue)) { - style[key] = ''; - } - } - } - } - } else { - if (isSVG) - style.value = ''; - else - style.cssText = ''; - } - const info = isSVG ? {} : style; - for (const key in newValue) { - const value = newValue[key]; - const styleValue = typeof value === 'number' && - !IS_NON_DIMENSIONAL.test(key) ? - (value + 'px') : value; - if (!isSVG && /^--/.test(key)) - info.setProperty(key, styleValue); - else - info[key] = styleValue; - } - oldType = 'object'; - if (isSVG) - style.value = toStyle((oldValue = info)); - else - oldValue = newValue; - break; - } - default: - if (oldValue != newValue) { - oldType = 'string'; - oldValue = newValue; - if (isSVG) - style.value = newValue || ''; - else - style.cssText = newValue || ''; - } - break; - } - }; -}; - -const hyphen = /([^A-Z])([A-Z]+)/g; -const ized = ($0, $1, $2) => $1 + '-' + $2.toLowerCase(); -const toStyle = object => { - const css = []; - for (const key in object) { - css.push(key.replace(hyphen, ized), ':', object[key], ';'); - } - return css.join(''); -}; diff --git a/cjs/objects/Updates.js b/cjs/objects/Updates.js index bd45002a..081e1c6f 100644 --- a/cjs/objects/Updates.js +++ b/cjs/objects/Updates.js @@ -2,21 +2,23 @@ const CustomEvent = (m => m.__esModule ? /* istanbul ignore next */ m.default : /* istanbul ignore next */ m)(require('@ungap/custom-event')); const WeakSet = (m => m.__esModule ? /* istanbul ignore next */ m.default : /* istanbul ignore next */ m)(require('@ungap/essential-weakset')); const isArray = (m => m.__esModule ? /* istanbul ignore next */ m.default : /* istanbul ignore next */ m)(require('@ungap/is-array')); - const createContent = (m => m.__esModule ? /* istanbul ignore next */ m.default : /* istanbul ignore next */ m)(require('@ungap/create-content')); + const disconnected = (m => m.__esModule ? /* istanbul ignore next */ m.default : /* istanbul ignore next */ m)(require('disconnected')); const domdiff = (m => m.__esModule ? /* istanbul ignore next */ m.default : /* istanbul ignore next */ m)(require('domdiff')); const domtagger = (m => m.__esModule ? /* istanbul ignore next */ m.default : /* istanbul ignore next */ m)(require('domtagger')); const hyperStyle = (m => m.__esModule ? /* istanbul ignore next */ m.default : /* istanbul ignore next */ m)(require('hyperhtml-style')); +const Wire = (m => m.__esModule ? /* istanbul ignore next */ m.default : /* istanbul ignore next */ m)(require('hyperhtml-wire')); const { CONNECTED, DISCONNECTED, DOCUMENT_FRAGMENT_NODE, OWNER_SVG_ELEMENT } = require('../shared/constants.js'); const Component = (m => m.__esModule ? /* istanbul ignore next */ m.default : /* istanbul ignore next */ m)(require('../classes/Component.js')); -const Wire = (m => m.__esModule ? /* istanbul ignore next */ m.default : /* istanbul ignore next */ m)(require('../classes/Wire.js')); const Intent = (m => m.__esModule ? /* istanbul ignore next */ m.default : /* istanbul ignore next */ m)(require('./Intent.js')); -const { slice, text } = require('../shared/utils.js'); + +const componentType = Component.prototype.nodeType; +const wireType = Wire.prototype.nodeType; const observe = disconnected({Event: CustomEvent, WeakSet}); @@ -28,24 +30,24 @@ const asHTML = html => ({html}); // returns nodes from wires and components const asNode = (item, i) => { - return 'ELEMENT_NODE' in item ? - item : - (item.constructor === Wire ? + switch (item.nodeType) { + case wireType: // in the Wire case, the content can be // removed, post-pended, inserted, or pre-pended and // all these cases are handled by domdiff already /* istanbul ignore next */ - ((1 / i) < 0 ? - (i ? item.remove() : item.last) : - (i ? item.valueOf(true) : item.first)) : - asNode(item.render(), i)); + return (1 / i) < 0 ? + (i ? item.remove(true) : item.lastChild) : + (i ? item.valueOf(true) : item.firstChild); + case componentType: + return asNode(item.render(), i); + default: + return item; + } } // returns true if domdiff can handle the value -const canDiff = value => - 'ELEMENT_NODE' in value || - value instanceof Wire || - value instanceof Component; +const canDiff = value => 'ELEMENT_NODE' in value; // when a Promise is used as interpolation value // its result must be parsed once resolved. @@ -70,6 +72,12 @@ const isPromise_ish = value => value != null && 'then' in value; // list of attributes that should not be directly assigned const readOnly = /^(?:form|list)$/i; +// reused every slice time +const slice = [].slice; + +// simplifies text node creation +const text = (node, text) => node.ownerDocument.createTextNode(text); + function Tagger(type) { this.type = type; return domtagger(this); @@ -132,9 +140,16 @@ Tagger.prototype = { }; } else if (name in Intent.attributes) { + oldValue; return any => { - oldValue = Intent.attributes[name](node, any); - node.setAttribute(name, oldValue == null ? '' : oldValue); + const newValue = Intent.attributes[name](node, any); + if (oldValue !== newValue) { + oldValue = newValue; + if (newValue == null) + node.removeAttribute(name); + else + node.setAttribute(name, newValue); + } }; } // in every other case, use the attribute node as it is diff --git a/cjs/objects/hyperstyle.js b/cjs/objects/hyperstyle.js deleted file mode 100644 index 20caaea8..00000000 --- a/cjs/objects/hyperstyle.js +++ /dev/null @@ -1,79 +0,0 @@ -'use strict'; -var hyperStyle = (function (){'use strict'; - // from https://github.com/developit/preact/blob/33fc697ac11762a1cb6e71e9847670d047af7ce5/src/varants.js - var IS_NON_DIMENSIONAL = /acit|ex(?:s|g|n|p|$)|rph|ows|mnc|ntw|ine[ch]|zoo|^ord/i; - var hyphen = /([^A-Z])([A-Z]+)/g; - return function hyperStyle(node) { - return 'ownerSVGElement' in node ? svg(node) : update(node.style, false); - }; - function ized($0, $1, $2) { - return $1 + '-' + $2.toLowerCase(); - } - function svg(node) { - node.setAttribute('style', ''); - return update(node.getAttributeNode('style'), true); - } - function toStyle(object) { - var key, css = []; - for (key in object) { - css.push(key.replace(hyphen, ized), ':', object[key], ';'); - } - return css.join(''); - } - function update(style, isSVG) { - var oldType, oldValue; - return function (newValue) { - var info, key, styleValue, value; - switch (typeof newValue) { - case 'object': - if (newValue) { - if (oldType === 'object') { - if (!isSVG) { - if (oldValue !== newValue) { - for (key in oldValue) { - if (!(key in newValue)) { - style[key] = ''; - } - } - } - } - } else { - if (isSVG) - style.value = ''; - else - style.cssText = ''; - } - info = isSVG ? {} : style; - for (key in newValue) { - value = newValue[key]; - styleValue = typeof value === 'number' && - !IS_NON_DIMENSIONAL.test(key) ? - (value + 'px') : value; - if (!isSVG && /^--/.test(key)) - info.setProperty(key, styleValue); - else - info[key] = styleValue; - } - oldType = 'object'; - if (isSVG) - style.value = toStyle((oldValue = info)); - else - oldValue = newValue; - break; - } - default: - if (oldValue != newValue) { - oldType = 'string'; - oldValue = newValue; - if (isSVG) - style.value = newValue || ''; - else - style.cssText = newValue || ''; - } - break; - } - }; - } -}()); - -Object.defineProperty(exports, '__esModule', {value: true}).default = hyperStyle; diff --git a/cjs/shared/constants.js b/cjs/shared/constants.js index 9aafa3be..ebe14667 100644 --- a/cjs/shared/constants.js +++ b/cjs/shared/constants.js @@ -1,7 +1,4 @@ 'use strict'; -const G = document.defaultView; -exports.G = G; - // Node.CONSTANTS // 'cause some engine has no global Node defined // (i.e. Node, NativeScript, basicHTML ... ) diff --git a/cjs/shared/easy-dom.js b/cjs/shared/easy-dom.js deleted file mode 100644 index e5fd2186..00000000 --- a/cjs/shared/easy-dom.js +++ /dev/null @@ -1,8 +0,0 @@ -'use strict'; -// these are tiny helpers to simplify most common operations needed here -const doc = node => node.ownerDocument || node; -exports.doc = doc; -const fragment = node => doc(node).createDocumentFragment(); -exports.fragment = fragment; -const text = (node, text) => doc(node).createTextNode(text); -exports.text = text; diff --git a/cjs/shared/features-detection.js b/cjs/shared/features-detection.js deleted file mode 100644 index f5980ac4..00000000 --- a/cjs/shared/features-detection.js +++ /dev/null @@ -1,6 +0,0 @@ -'use strict'; -const {fragment} = require('./easy-dom.js'); - -// DOM4 node.append(...many) -const hasAppend = 'append' in fragment(document); -exports.hasAppend = hasAppend; diff --git a/cjs/shared/re.js b/cjs/shared/re.js deleted file mode 100644 index 07897d90..00000000 --- a/cjs/shared/re.js +++ /dev/null @@ -1,23 +0,0 @@ -'use strict'; -// TODO: I'd love to code-cover RegExp too here -// these are fundamental for this library - -const spaces = ' \\f\\n\\r\\t'; -const almostEverything = '[^ ' + spaces + '\\/>"\'=]+'; -const attrName = '[ ' + spaces + ']+' + almostEverything; -const tagName = '<([A-Za-z]+[A-Za-z0-9:_-]*)((?:'; -const attrPartials = '(?:=(?:\'[^\']*?\'|"[^"]*?"|<[^>]*?>|' + almostEverything + '))?)'; - -const attrSeeker = new RegExp( - tagName + attrName + attrPartials + '+)([ ' + spaces + ']*/?>)', - 'g' -); - -const selfClosing = new RegExp( - tagName + attrName + attrPartials + '*)([ ' + spaces + ']*/>)', - 'g' -); - -exports.attrName = attrName; -exports.attrSeeker = attrSeeker; -exports.selfClosing = selfClosing; diff --git a/cjs/shared/utils.js b/cjs/shared/utils.js index d5ae3d15..ad9a93a7 100644 --- a/cjs/shared/utils.js +++ b/cjs/shared/utils.js @@ -1,41 +1 @@ 'use strict'; -const unique = (m => m.__esModule ? /* istanbul ignore next */ m.default : /* istanbul ignore next */ m)(require('@ungap/template-literal')); - -// these are tiny helpers to simplify most common operations needed here -const doc = node => node.ownerDocument || node; -exports.doc = doc; -const fragment = node => doc(node).createDocumentFragment(); -exports.fragment = fragment; -const text = (node, text) => doc(node).createTextNode(text); -exports.text = text; - -// appends an array of nodes -// to a generic node/fragment -// When available, uses append passing all arguments at once -// hoping that's somehow faster, even if append has more checks on type -// istanbul ignore next -const append = 'append' in fragment(document) ? - (node, childNodes) => { - node.append.apply(node, childNodes); - } : - (node, childNodes) => { - const length = childNodes.length; - for (let i = 0; i < length; i++) { - node.appendChild(childNodes[i]); - } - }; -exports.append = append; - -// normalizes the template once for all arguments cases -const reArguments = function (template) { - const args = [unique(template)]; - for (let i = 1, length = arguments.length; i < length; i++) - args[i] = arguments[i]; - return args; -} -exports.reArguments = reArguments - -// just recycling a one-off array to use slice -// in every needed place -const slice = [].slice; -exports.slice = slice; diff --git a/esm.js b/esm.js index 5bd3e3f9..1502fe4f 100644 --- a/esm.js +++ b/esm.js @@ -1,5 +1,6 @@ -/*! (c) Andrea Giammarchi (ISC) */var hyperHTML=function(e){"use strict";function t(){return this}function n(e){return e.join(ne).replace(ve,o).replace(he,r)}function r(e,t,n,r){return"<"+t+n.replace(pe,i)+r}function i(e,t,n){return t+(n||'"')+te+(n||'"')}function o(e,t,n){return ce.test(t)?e:"<"+t+n+">"}function a(e,t,n){return{type:e,name:n,node:t,path:u(t)}}function u(e){var t,n=[];switch(e.nodeType){case oe:case ie:t=e;break;case re:t=e.parentNode,f(n,t,e);break;default:t=e.ownerElement}for(;t=(e=t).parentNode;)f(n,t,e);return n}function c(e,t){for(var n=t.length,r=0;r=u;){for(var c=t,l=i;ca;)--c;l=u+r-c;var m=Array(l),b=s[c];for(--n;b;){for(var w=b,y=w.newi,N=w.oldi;n>y;)m[--l]=1,--n;for(;a>N;)m[--l]=-1,--a;m[--l]=0,--n,--a,b=b.prev}for(;n>=t;)m[--l]=1,--n;for(;a>=o;)m[--l]=-1,--a;return m},W=function(e,t,n,r,i,o,a){var u=n+o,c=[],l=void 0,s=void 0,f=void 0,d=void 0,h=void 0,v=void 0,p=void 0;e:for(l=0;l<=u;l++){if(l>50)return null;for(p=l-1,h=l?c[l-1]:[0,0],v=c[l]=[],s=-l;s<=l;s+=2){for(d=s===-l||s!==l&&h[p+s-1]=0;l--){for(;d>0&&f>0&&a(r[i+d-1],e[t+f-1]);)g[m--]=0,d--,f--;if(!l)break;p=l-1,h=l?c[l-1]:[0,0],s=d-f,s===-l||s!==l&&h[p+s-1]>>0;n",t(r,o.firstChild.childNodes),r}var i="fragment",o="content"in n("template"),a=o?function(e){var t=n("template");return t.innerHTML=e,t.content}:function(e){var r=n(i),o=n("template"),a=null;if(/^[^\S]*?<(col(?:group)?|t(?:head|body|foot|r|d|h))/i.test(e)){var u=RegExp.$1;o.innerHTML=""+e+"
",a=o.querySelectorAll(u)}else o.innerHTML=e,a=o.childNodes;return t(r,a),r};return function(e,t){return("svg"===t?r:a)(e)}}(e),X=function(e){function t(e,t){for(var n=t.length;n--;)e.appendChild(t[0])}function n(t){return t===i?e.createDocumentFragment():e.createElementNS("http://www.w3.org/1999/xhtml",t)}function r(e){var r=n(i),o=n("div");return o.innerHTML=''+e+"",t(r,o.firstChild.childNodes),r}var i="fragment",o="content"in n("template"),a=o?function(e){var t=n("template");return t.innerHTML=e,t.content}:function(e){var r=n(i),o=n("template"),a=null;if(/^[^\S]*?<(col(?:group)?|t(?:head|body|foot|r|d|h))/i.test(e)){var u=RegExp.$1;o.innerHTML=""+e+"
",a=o.querySelectorAll(u)}else o.innerHTML=e,a=o.childNodes;return t(r,a),r};return function(e,t){return("svg"===t?r:a)(e)}}(e),Y=function(e,t,n,r,i){var o="importNode"in e,a=e.createDocumentFragment();return a.appendChild(e.createTextNode("g")),a.appendChild(e.createTextNode("")),(o?e.importNode(a,!0):a.cloneNode(!0)).childNodes.length<2?function u(e,t){for(var n=e.cloneNode(),r=e.childNodes||[],i=r.length,o=0;t&&o

',e.content.childNodes[0].getAttribute("tabindex")==te)})(e.createElement("template"))||(te="_dt: "+te.slice(1,-1)+";");var ne="\x3c!--"+te+"--\x3e",re=8,ie=11,oe=1,ae=3,ue=/^(?:style|textarea)$/i,ce=/^(?:area|base|br|col|embed|hr|img|input|keygen|link|menuitem|meta|param|source|track|wbr)$/i,le=" \\f\\n\\r\\t",se="[ "+le+"]+[^ \\f\\n\\r\\t\\/>\"'=]+",fe="<([A-Za-z]+[A-Za-z0-9:_-]*)((?:",de="(?:\\s*=\\s*(?:'[^']*?'|\"[^\"]*?\"|<[^>]*?>|[^ \\f\\n\\r\\t\\/>\"'=]+))?)",he=new RegExp(fe+se+de+"+)([ "+le+"]*/?>)","g"),ve=new RegExp(fe+se+de+"*)([ "+le+"]*/>)","g"),pe=new RegExp("("+se+"\\s*=\\s*)(['\"]?)"+ne+"\\2","gi"),ge=new x,me=new x,be=function(){function e(e,t,n){return t+"-"+n.toLowerCase()}function t(e,t){var n;return t?n=t.cloneNode(!0):(e.setAttribute("style","--hyper:style;"),n=e.getAttributeNode("style")),n.value="",e.setAttributeNode(n),r(n,!0)}function n(t){var n,r=[];for(n in t)r.push(n.replace(o,e),":",t[n],";");return r.join("")}function r(e,t){var r,o;return function(a){var u,c,l,s;switch(typeof a){case"object":if(a){if("object"===r){if(!t&&o!==a)for(c in o)c in a||(e[c]="")}else t?e.value="":e.cssText="";u=t?{}:e;for(c in a)s=a[c],l="number"!=typeof s||i.test(c)?s:s+"px",!t&&/^--/.test(c)?u.setProperty(c,l):u[c]=l;r="object",t?e.value=n(o=u):o=a;break}default:o!=a&&(r="string",o=a,t?e.value=a||"":e.cssText=a||"")}}}var i=/acit|ex(?:s|g|n|p|$)|rph|ows|mnc|ntw|ine[ch]|zoo|^ord/i,o=/([^A-Z])([A-Z]+)/g;return function(e,n){return"ownerSVGElement"in e?t(e,n):r(e.style,!1)}}(),we=e.defaultView,ye="ownerSVGElement",Ne=function(){var t=!1,n=function(r){if(!("raw"in r)||r.propertyIsEnumerable("raw")||!Object.isFrozen(r.raw)||/Firefox\/(\d+)/.test((e.defaultView.navigator||{}).userAgent)&&parseFloat(RegExp.$1)<55){var i={};return(n=function(e){var t="raw"+e.join("raw");return i[t]||(i[t]=e)})(r)}return t=!0,r};return function(e){return t?e:n(e)}}(),xe=function(e){return e.ownerDocument||e},Ee=function(e){return xe(e).createDocumentFragment()},ke=function(e,t){return xe(e).createTextNode(t)},Ce="append"in Ee(e)?function(e,t){e.append.apply(e,t)}:function(e,t){for(var n=t.length,r=0;r"}function a(e,t,n,r){return{name:r,node:t,path:n,type:e}}function u(e,t){for(var n=t.length,r=0;r=u;){for(var c=t,l=i;ca;)--c;l=u+r-c;var g=Array(l),b=s[c];for(--n;b;){for(var y=b,w=y.newi,N=y.oldi;n>w;)g[--l]=1,--n;for(;a>N;)g[--l]=-1,--a;g[--l]=0,--n,--a,b=b.prev}for(;n>=t;)g[--l]=1,--n;for(;a>=o;)g[--l]=-1,--a;return g},L=function(e,t,n,r,i,o,a){var u,c,l,s,f,h,d,p=n+o,v=[];e:for(u=0;u<=p;u++){if(u>50)return null;for(d=u-1,f=u?v[u-1]:[0,0],h=v[u]=[],c=-u;c<=u;c+=2){for(s=c===-u||c!==u&&f[d+c-1]=0;u--){for(;s>0&&l>0&&a(r[i+s-1],e[t+l-1]);)m[g--]=0,s--,l--;if(!u)break;d=u-1,f=u?v[u-1]:[0,0],c=s-l,c===-u||c!==u&&f[d+c-1]>>0;n",t(r,o.firstChild.childNodes),r}var i="fragment",o="content"in n("template"),a=o?function(e){var t=n("template");return t.innerHTML=e,t.content}:function(e){var r=n(i),o=n("template"),a=null;if(/^[^\S]*?<(col(?:group)?|t(?:head|body|foot|r|d|h))/i.test(e)){var u=RegExp.$1;o.innerHTML=""+e+"
",a=o.querySelectorAll(u)}else o.innerHTML=e,a=o.childNodes;return t(r,a),r};return function(e,t){return("svg"===t?r:a)(e)}}(e),Q=function(e,t,n,r,i){var o="importNode"in e,a=e.createDocumentFragment();return a.appendChild(e.createTextNode("g")),a.appendChild(e.createTextNode("")),(o?e.importNode(a,!0):a.cloneNode(!0)).childNodes.length<2?function u(e,t){for(var n=e.cloneNode(),r=e.childNodes||[],i=r.length,o=0;t&&o

',e.content.childNodes[0].getAttribute("tabindex")==X)})(e.createElement("template"))||(X="_dt: "+X.slice(1,-1)+";");var Y="\x3c!--"+X+"--\x3e",ee=8,te=1,ne=3,re=/^(?:style|textarea)$/i,ie=/^(?:area|base|br|col|embed|hr|img|input|keygen|link|menuitem|meta|param|source|track|wbr)$/i,oe=" \\f\\n\\r\\t",ae="[ "+oe+"]+[^ \\f\\n\\r\\t\\/>\"'=]+",ue="<([A-Za-z]+[A-Za-z0-9:_-]*)((?:",ce="(?:\\s*=\\s*(?:'[^']*?'|\"[^\"]*?\"|<[^>]*?>|[^ \\f\\n\\r\\t\\/>\"'=]+))?)",le=new RegExp(ue+ae+ce+"+)([ "+oe+"]*/?>)","g"),se=new RegExp(ue+ae+ce+"*)([ "+oe+"]*/>)","g"),fe=new RegExp("("+ae+"\\s*=\\s*)(['\"]?)"+Y+"\\2","gi"),he=new w,de=new w,pe=function(){function e(e,t,n){return t+"-"+n.toLowerCase()}function t(e,t){var n;return t?n=t.cloneNode(!0):(e.setAttribute("style","--hyper:style;"),n=e.getAttributeNode("style")),n.value="",e.setAttributeNode(n),r(n,!0)}function n(t){var n,r=[];for(n in t)r.push(n.replace(o,e),":",t[n],";");return r.join("")}function r(e,t){var r,o;return function(a){var u,c,l,s;switch(typeof a){case"object":if(a){if("object"===r){if(!t&&o!==a)for(c in o)c in a||(e[c]="")}else t?e.value="":e.cssText="";u=t?{}:e;for(c in a)s=a[c],l="number"!=typeof s||i.test(c)?s:s+"px",!t&&/^--/.test(c)?u.setProperty(c,l):u[c]=l;r="object",t?e.value=n(o=u):o=a;break}default:o!=a&&(r="string",o=a,t?e.value=a||"":e.cssText=a||"")}}}var i=/acit|ex(?:s|g|n|p|$)|rph|ows|mnc|ntw|ine[ch]|zoo|^ord/i,o=/([^A-Z])([A-Z]+)/g;return function(e,n){return"ownerSVGElement"in e?t(e,n):r(e.style,!1)}}(),ve=function(e,t){function n(t){var n=this.childNodes=e.call(t,0);this.firstChild=n[0],this.lastChild=n[n.length-1],this.ownerDocument=n[0].ownerDocument,this._=null}return t=n.prototype,t.ELEMENT_NODE=1,t.nodeType=111,t.remove=function(e){var t=this.childNodes,n=this.firstChild,r=this.lastChild;if(this._=null,e&&2===t.length)r.parentNode.removeChild(r);else{var i=this.ownerDocument.createRange();i.setStartBefore(e?t[1]:n),i.setEndAfter(r),i.deleteContents()}return n},t.valueOf=function(e){var t=this._,n=null==t;if(n&&(t=this._=this.ownerDocument.createDocumentFragment()),n||e)for(var r=this.childNodes,i=0,o=r.length;i value })[secret] ; + +Object.defineProperties( + Component.prototype, + { + // used to distinguish better than instanceof + ELEMENT_NODE: {value: 1}, + nodeType: {value: -1} + } +); diff --git a/esm/classes/Wire.js b/esm/classes/Wire.js deleted file mode 100644 index 42c3dfc1..00000000 --- a/esm/classes/Wire.js +++ /dev/null @@ -1,36 +0,0 @@ -import { append, doc, fragment } from '../shared/utils.js'; - -export default function Wire(childNodes) { - this.childNodes = childNodes; - this.length = childNodes.length; - this.first = childNodes[0]; - this.last = childNodes[this.length - 1]; - this._ = null; -} - -// when a wire is inserted, all its nodes will follow -Wire.prototype.valueOf = function valueOf(different) { - const noFragment = this._ == null; - if (noFragment) - this._ = fragment(this.first); - /* istanbul ignore else */ - if (noFragment || different) - append(this._, this.childNodes); - return this._; -}; - -// when a wire is removed, all its nodes must be removed as well -Wire.prototype.remove = function remove() { - this._ = null; - const first = this.first; - const last = this.last; - if (this.length === 2) { - last.parentNode.removeChild(last); - } else { - const range = doc(first).createRange(); - range.setStartBefore(this.childNodes[1]); - range.setEndAfter(last); - range.deleteContents(); - } - return first; -}; diff --git a/esm/hyper/render.js b/esm/hyper/render.js index 803818c7..b3c4c863 100644 --- a/esm/hyper/render.js +++ b/esm/hyper/render.js @@ -1,8 +1,8 @@ import WeakMap from '@ungap/weakmap'; +import tta from '@ungap/template-tag-arguments'; import {OWNER_SVG_ELEMENT} from '../shared/constants.js'; import {Tagger} from '../objects/Updates.js'; -import {reArguments} from '../shared/utils.js'; // a weak collection of contexts that // are already known to hyperHTML @@ -14,7 +14,7 @@ const bewitched = new WeakMap; // The `this` context is either a regular DOM node or a fragment. function render() { const wicked = bewitched.get(this); - const args = reArguments.apply(null, arguments); + const args = tta.apply(null, arguments); if (wicked && wicked.template === args[0]) { wicked.tagger.apply(null, args); } else { @@ -27,13 +27,12 @@ function render() { // parse it once, if unknown, to map all interpolations // as single DOM callbacks, relate such template // to the current context, and render it after cleaning the context up -function upgrade() { - const args = reArguments.apply(null, arguments); +function upgrade(template) { const type = OWNER_SVG_ELEMENT in this ? 'svg' : 'html'; const tagger = new Tagger(type); - bewitched.set(this, {tagger, template: args[0]}); + bewitched.set(this, {tagger, template: template}); this.textContent = ''; - this.appendChild(tagger.apply(null, args)); + this.appendChild(tagger.apply(null, arguments)); } export default render; diff --git a/esm/hyper/wire.js b/esm/hyper/wire.js index 3bebef2e..3911fbc7 100644 --- a/esm/hyper/wire.js +++ b/esm/hyper/wire.js @@ -1,11 +1,9 @@ import WeakMap from '@ungap/weakmap'; -import trim from '@ungap/trim'; +import tta from '@ungap/template-tag-arguments'; -import {ELEMENT_NODE} from '../shared/constants.js'; -import Wire from '../classes/Wire.js'; +import Wire from 'hyperhtml-wire'; import {Tagger} from '../objects/Updates.js'; -import {reArguments} from '../shared/utils.js'; // all wires used per each context const wires = new WeakMap; @@ -32,7 +30,7 @@ const wire = (obj, type) => obj == null ? const content = type => { let wire, tagger, template; return function () { - const args = reArguments.apply(null, arguments); + const args = tta.apply(null, arguments); if (template !== args[0]) { template = args[0]; tagger = new Tagger(type); @@ -68,24 +66,16 @@ const weakly = (obj, type) => { // stay associated with the original interpolation. // To prevent hyperHTML from forgetting about a fragment's sub-nodes, // fragments are instead returned as an Array of nodes or, if there's only one entry, -// as a single referenced node which, unlike framents, will indeed persist +// as a single referenced node which, unlike fragments, will indeed persist // wire content throughout multiple renderings. // The initial fragment, at this point, would be used as unique reference to this // array of nodes or to this single referenced node. const wireContent = node => { const childNodes = node.childNodes; - const length = childNodes.length; - const wireNodes = []; - for (let i = 0; i < length; i++) { - let child = childNodes[i]; - if ( - child.nodeType === ELEMENT_NODE || - trim.call(child.textContent).length !== 0 - ) { - wireNodes.push(child); - } - } - return wireNodes.length === 1 ? wireNodes[0] : new Wire(wireNodes); + const {length} = childNodes; + return length === 1 ? + childNodes[0] : + (length ? new Wire(childNodes) : node); }; export { content, weakly }; diff --git a/esm/index.js b/esm/index.js index aead3a0f..254708a6 100644 --- a/esm/index.js +++ b/esm/index.js @@ -8,7 +8,6 @@ import Intent from './objects/Intent.js'; import {observe, Tagger} from './objects/Updates.js'; import wire, {content, weakly} from './hyper/wire.js'; import render from './hyper/render.js'; -import { G } from './shared/constants.js'; // all functions are self bound to the right context // you can do the following @@ -32,7 +31,6 @@ hyper.wire = wire; // that don't necessarily need upfront polyfills // i.e. those still targeting IE hyper._ = { - global: G, WeakMap, WeakSet }; diff --git a/esm/objects/Basic.js b/esm/objects/Basic.js deleted file mode 100644 index e69de29b..00000000 diff --git a/esm/objects/Updates.js b/esm/objects/Updates.js index 8283e753..7def5d54 100644 --- a/esm/objects/Updates.js +++ b/esm/objects/Updates.js @@ -1,12 +1,13 @@ import CustomEvent from '@ungap/custom-event'; import WeakSet from '@ungap/essential-weakset'; import isArray from '@ungap/is-array'; - import createContent from '@ungap/create-content'; + import disconnected from 'disconnected'; import domdiff from 'domdiff'; import domtagger from 'domtagger'; import hyperStyle from 'hyperhtml-style'; +import Wire from 'hyperhtml-wire'; import { CONNECTED, DISCONNECTED, @@ -15,9 +16,10 @@ import { } from '../shared/constants.js'; import Component from '../classes/Component.js'; -import Wire from '../classes/Wire.js'; import Intent from './Intent.js'; -import { slice, text } from '../shared/utils.js'; + +const componentType = Component.prototype.nodeType; +const wireType = Wire.prototype.nodeType; const observe = disconnected({Event: CustomEvent, WeakSet}); @@ -28,24 +30,24 @@ const asHTML = html => ({html}); // returns nodes from wires and components const asNode = (item, i) => { - return 'ELEMENT_NODE' in item ? - item : - (item.constructor === Wire ? + switch (item.nodeType) { + case wireType: // in the Wire case, the content can be // removed, post-pended, inserted, or pre-pended and // all these cases are handled by domdiff already /* istanbul ignore next */ - ((1 / i) < 0 ? - (i ? item.remove() : item.last) : - (i ? item.valueOf(true) : item.first)) : - asNode(item.render(), i)); + return (1 / i) < 0 ? + (i ? item.remove(true) : item.lastChild) : + (i ? item.valueOf(true) : item.firstChild); + case componentType: + return asNode(item.render(), i); + default: + return item; + } } // returns true if domdiff can handle the value -const canDiff = value => - 'ELEMENT_NODE' in value || - value instanceof Wire || - value instanceof Component; +const canDiff = value => 'ELEMENT_NODE' in value; // when a Promise is used as interpolation value // its result must be parsed once resolved. @@ -70,6 +72,12 @@ const isPromise_ish = value => value != null && 'then' in value; // list of attributes that should not be directly assigned const readOnly = /^(?:form|list)$/i; +// reused every slice time +const slice = [].slice; + +// simplifies text node creation +const text = (node, text) => node.ownerDocument.createTextNode(text); + function Tagger(type) { this.type = type; return domtagger(this); @@ -132,9 +140,16 @@ Tagger.prototype = { }; } else if (name in Intent.attributes) { + oldValue; return any => { - oldValue = Intent.attributes[name](node, any); - node.setAttribute(name, oldValue == null ? '' : oldValue); + const newValue = Intent.attributes[name](node, any); + if (oldValue !== newValue) { + oldValue = newValue; + if (newValue == null) + node.removeAttribute(name); + else + node.setAttribute(name, newValue); + } }; } // in every other case, use the attribute node as it is diff --git a/esm/shared/constants.js b/esm/shared/constants.js index f6cd3c51..667b8e9d 100644 --- a/esm/shared/constants.js +++ b/esm/shared/constants.js @@ -1,5 +1,3 @@ -export const G = document.defaultView; - // Node.CONSTANTS // 'cause some engine has no global Node defined // (i.e. Node, NativeScript, basicHTML ... ) diff --git a/esm/shared/utils.js b/esm/shared/utils.js deleted file mode 100644 index 42391f27..00000000 --- a/esm/shared/utils.js +++ /dev/null @@ -1,34 +0,0 @@ -import unique from '@ungap/template-literal'; - -// these are tiny helpers to simplify most common operations needed here -export const doc = node => node.ownerDocument || node; -export const fragment = node => doc(node).createDocumentFragment(); -export const text = (node, text) => doc(node).createTextNode(text); - -// appends an array of nodes -// to a generic node/fragment -// When available, uses append passing all arguments at once -// hoping that's somehow faster, even if append has more checks on type -// istanbul ignore next -export const append = 'append' in fragment(document) ? - (node, childNodes) => { - node.append.apply(node, childNodes); - } : - (node, childNodes) => { - const length = childNodes.length; - for (let i = 0; i < length; i++) { - node.appendChild(childNodes[i]); - } - }; - -// normalizes the template once for all arguments cases -export const reArguments = function (template) { - const args = [unique(template)]; - for (let i = 1, length = arguments.length; i < length; i++) - args[i] = arguments[i]; - return args; -} - -// just recycling a one-off array to use slice -// in every needed place -export const slice = [].slice; diff --git a/index.js b/index.js index 7f6c61a2..bc83dde1 100644 --- a/index.js +++ b/index.js @@ -2,7 +2,10 @@ var hyperHTML = (function (document) { 'use strict'; /*! (c) Andrea Giammarchi - ISC */ - var self = null || /* istanbul ignore next */{}; + var self = null || + /* istanbul ignore next */ + {}; + try { self.WeakMap = WeakMap; } catch (WeakMap) { @@ -13,59 +16,89 @@ var hyperHTML = (function (document) { var dP = Object.defineProperty; var hOP = Object.hasOwnProperty; var proto = WeakMap.prototype; + proto.delete = function (key) { return this.has(key) && delete key[this._]; }; + proto.get = function (key) { return this.has(key) ? key[this._] : void 0; }; + proto.has = function (key) { return hOP.call(key, this._); }; + proto.set = function (key, value) { - dP(key, this._, { configurable: true, value: value }); + dP(key, this._, { + configurable: true, + value: value + }); return this; }; + return WeakMap; + function WeakMap(iterable) { - dP(this, '_', { value: '_@ungap/weakmap' + id++ }); + dP(this, '_', { + value: '_@ungap/weakmap' + id++ + }); if (iterable) iterable.forEach(add, this); } + function add(pair) { this.set(pair[0], pair[1]); } }(Math.random(), Object); } + var WeakMap$1 = self.WeakMap; /*! (c) Andrea Giammarchi - ISC */ - var self$1 = null || /* istanbul ignore next */{}; + var self$1 = null || + /* istanbul ignore next */ + {}; + try { self$1.WeakSet = WeakSet; } catch (WeakSet) { (function (id, dP) { var proto = WeakSet.prototype; + proto.add = function (object) { - if (!this.has(object)) dP(object, this._, { value: true, configurable: true }); + if (!this.has(object)) dP(object, this._, { + value: true, + configurable: true + }); return this; }; + proto.has = function (object) { return this.hasOwnProperty.call(object, this._); }; + proto.delete = function (object) { return this.has(object) && delete object[this._]; }; + self$1.WeakSet = WeakSet; + function WeakSet() { - dP(this, '_', { value: '_@ungap/weakmap' + id++ }); + dP(this, '_', { + value: '_@ungap/weakmap' + id++ + }); } })(Math.random(), Object.defineProperty); } + var WeakSet$1 = self$1.WeakSet; /*! (c) Andrea Giammarchi - ISC */ - var self$2 = null || /* istanbul ignore next */{}; + var self$2 = null || + /* istanbul ignore next */ + {}; + try { self$2.Map = Map; } catch (Map) { @@ -76,10 +109,12 @@ var hyperHTML = (function (document) { return { delete: function _delete(key) { var had = contains(key); + if (had) { k.splice(i, 1); v.splice(i, 1); } + return had; }, get: function get(key) { @@ -93,59 +128,64 @@ var hyperHTML = (function (document) { return this; } }; + function contains(v) { i = k.indexOf(v); return -1 < i; } }; } + var Map$1 = self$2.Map; var append = function append(get, parent, children, start, end, before) { if (end - start < 2) parent.insertBefore(get(children[start], 1), before);else { var fragment = parent.ownerDocument.createDocumentFragment(); + while (start < end) { fragment.appendChild(get(children[start++], 1)); - }parent.insertBefore(fragment, before); + } + + parent.insertBefore(fragment, before); } }; - var eqeq = function eqeq(a, b) { return a == b; }; - var identity = function identity(O) { return O; }; - var indexOf = function indexOf(moreNodes, moreStart, moreEnd, lessNodes, lessStart, lessEnd, compare) { var length = lessEnd - lessStart; /* istanbul ignore if */ + if (length < 1) return -1; + while (moreEnd - moreStart >= length) { var m = moreStart; var l = lessStart; + while (m < moreEnd && l < lessEnd && compare(moreNodes[m], lessNodes[l])) { m++; l++; } + if (l === lessEnd) return moreStart; moreStart = m + 1; } + return -1; }; - var isReversed = function isReversed(futureNodes, futureEnd, currentNodes, currentStart, currentEnd, compare) { while (currentStart < currentEnd && compare(currentNodes[currentStart], futureNodes[futureEnd - 1])) { currentStart++; futureEnd--; - } return futureEnd === 0; + } + return futureEnd === 0; }; - var next = function next(get, list, i, length, before) { return i < length ? get(list[i], 0) : 0 < i ? get(list[i - 1], -0).nextSibling : before; }; - var remove = function remove(get, parent, children, start, end) { if (end - start < 2) parent.removeChild(get(children[start], -1));else { var range = parent.ownerDocument.createRange(); @@ -153,9 +193,7 @@ var hyperHTML = (function (document) { range.setEndAfter(get(children[end - 1], -1)); range.deleteContents(); } - }; - - // - - - - - - - - - - - - - - - - - - - + }; // - - - - - - - - - - - - - - - - - - - // diff related constants and utilities // - - - - - - - - - - - - - - - - - - - @@ -165,9 +203,9 @@ var hyperHTML = (function (document) { var SKIP_OND = 50; var HS = function HS(futureNodes, futureStart, futureEnd, futureChanges, currentNodes, currentStart, currentEnd, currentChanges) { - var k = 0; /* istanbul ignore next */ + var minLen = futureChanges < currentChanges ? futureChanges : currentChanges; var link = Array(minLen++); var tresh = Array(minLen); @@ -175,14 +213,21 @@ var hyperHTML = (function (document) { for (var i = 1; i < minLen; i++) { tresh[i] = currentEnd; - }var keymap = new Map$1(); + } + + var keymap = new Map$1(); + for (var _i = currentStart; _i < currentEnd; _i++) { keymap.set(currentNodes[_i], _i); - }for (var _i2 = futureStart; _i2 < futureEnd; _i2++) { + } + + for (var _i2 = futureStart; _i2 < futureEnd; _i2++) { var idxInOld = keymap.get(futureNodes[_i2]); + if (idxInOld != null) { k = findK(tresh, minLen, idxInOld); /* istanbul ignore else */ + if (-1 < k) { tresh[k] = idxInOld; link[k] = { @@ -196,12 +241,16 @@ var hyperHTML = (function (document) { k = --minLen; --currentEnd; + while (tresh[k] > currentEnd) { --k; - }minLen = currentChanges + futureChanges - k; + } + + minLen = currentChanges + futureChanges - k; var diff = Array(minLen); var ptr = link[k]; --futureEnd; + while (ptr) { var _ptr = ptr, newi = _ptr.newi, @@ -211,65 +260,72 @@ var hyperHTML = (function (document) { diff[--minLen] = INSERTION; --futureEnd; } + while (currentEnd > oldi) { diff[--minLen] = DELETION; --currentEnd; } + diff[--minLen] = SKIP; --futureEnd; --currentEnd; ptr = ptr.prev; } + while (futureEnd >= futureStart) { diff[--minLen] = INSERTION; --futureEnd; } + while (currentEnd >= currentStart) { diff[--minLen] = DELETION; --currentEnd; } - return diff; - }; - // this is pretty much the same petit-dom code without the delete map part + return diff; + }; // this is pretty much the same petit-dom code without the delete map part // https://github.com/yelouafi/petit-dom/blob/bd6f5c919b5ae5297be01612c524c40be45f14a7/src/vdom.js#L556-L561 + + var OND = function OND(futureNodes, futureStart, rows, currentNodes, currentStart, cols, compare) { var length = rows + cols; var v = []; - var d = void 0, - k = void 0, - r = void 0, - c = void 0, - pv = void 0, - cv = void 0, - pd = void 0; + var d, k, r, c, pv, cv, pd; + outer: for (d = 0; d <= length; d++) { /* istanbul ignore if */ if (d > SKIP_OND) return null; pd = d - 1; /* istanbul ignore next */ + pv = d ? v[d - 1] : [0, 0]; cv = v[d] = []; + for (k = -d; k <= d; k += 2) { if (k === -d || k !== d && pv[pd + k - 1] < pv[pd + k + 1]) { c = pv[pd + k + 1]; } else { c = pv[pd + k - 1] + 1; } + r = c - k; + while (c < cols && r < rows && compare(currentNodes[currentStart + c], futureNodes[futureStart + r])) { c++; r++; } + if (c === cols && r === rows) { break outer; } + cv[d + k] = c; } } var diff = Array(d / 2 + length / 2); var diffIdx = diff.length - 1; + for (d = v.length - 1; d >= 0; d--) { while (c > 0 && r > 0 && compare(currentNodes[currentStart + c - 1], futureNodes[futureStart + r - 1])) { // diagonal edge = equality @@ -277,11 +333,14 @@ var hyperHTML = (function (document) { c--; r--; } + if (!d) break; pd = d - 1; /* istanbul ignore next */ + pv = d ? v[d - 1] : [0, 0]; k = c - r; + if (k === -d || k !== d && pv[pd + k - 1] < pv[pd + k + 1]) { // vertical edge = insertion r--; @@ -292,6 +351,7 @@ var hyperHTML = (function (document) { diff[diffIdx--] = DELETION; } } + return diff; }; @@ -300,28 +360,34 @@ var hyperHTML = (function (document) { var length = diff.length; var currentIndex = currentStart; var i = 0; + while (i < length) { switch (diff[i++]) { case SKIP: futureStart++; currentIndex++; break; + case INSERTION: // TODO: bulk appends for sequential nodes live.set(futureNodes[futureStart], 1); - append(get, parentNode, futureNodes, futureStart++, futureStart, currentIndex < currentLength ? get(currentNodes[currentIndex], 1) : before); + append(get, parentNode, futureNodes, futureStart++, futureStart, currentIndex < currentLength ? get(currentNodes[currentIndex], 0) : before); break; + case DELETION: currentIndex++; break; } } + i = 0; + while (i < length) { switch (diff[i++]) { case SKIP: currentStart++; break; + case DELETION: // TODO: bulk removes for sequential nodes if (live.has(currentNodes[currentStart])) currentStart++;else remove(get, parentNode, currentNodes, currentStart++, currentStart); @@ -333,10 +399,12 @@ var hyperHTML = (function (document) { var findK = function findK(ktr, length, j) { var lo = 1; var hi = length; + while (lo < hi) { var mid = (lo + hi) / 2 >>> 0; if (j < ktr[mid]) hi = mid;else lo = mid + 1; } + return lo; }; @@ -355,43 +423,37 @@ var hyperHTML = (function (document) { // node(generic) => Node ) { if (!options) options = {}; - var compare = options.compare || eqeq; var get = options.node || identity; var before = options.before == null ? null : get(options.before, 0); - var currentLength = currentNodes.length; var currentEnd = currentLength; var currentStart = 0; - var futureEnd = futureNodes.length; - var futureStart = 0; + var futureStart = 0; // common prefix - // common prefix while (currentStart < currentEnd && futureStart < futureEnd && compare(currentNodes[currentStart], futureNodes[futureStart])) { currentStart++; futureStart++; - } + } // common suffix + - // common suffix while (currentStart < currentEnd && futureStart < futureEnd && compare(currentNodes[currentEnd - 1], futureNodes[futureEnd - 1])) { currentEnd--; futureEnd--; } var currentSame = currentStart === currentEnd; - var futureSame = futureStart === futureEnd; + var futureSame = futureStart === futureEnd; // same list - // same list - if (currentSame && futureSame) return futureNodes; + if (currentSame && futureSame) return futureNodes; // only stuff to add - // only stuff to add if (currentSame && futureStart < futureEnd) { append(get, parentNode, futureNodes, futureStart, futureEnd, next(get, currentNodes, currentStart, currentLength, before)); return futureNodes; - } + } // only stuff to remove + - // only stuff to remove if (futureSame && currentStart < currentEnd) { remove(get, parentNode, currentNodes, currentStart, currentEnd); return futureNodes; @@ -399,12 +461,11 @@ var hyperHTML = (function (document) { var currentChanges = currentEnd - currentStart; var futureChanges = futureEnd - futureStart; - var i = -1; + var i = -1; // 2 simple indels: the shortest sequence is a subsequence of the longest - // 2 simple indels: the shortest sequence is a subsequence of the longest if (currentChanges < futureChanges) { - i = indexOf(futureNodes, futureStart, futureEnd, currentNodes, currentStart, currentEnd, compare); - // inner diff + i = indexOf(futureNodes, futureStart, futureEnd, currentNodes, currentStart, currentEnd, compare); // inner diff + if (-1 < i) { append(get, parentNode, futureNodes, futureStart, i, get(currentNodes[currentStart], 0)); append(get, parentNode, futureNodes, i + currentChanges, futureEnd, next(get, currentNodes, currentEnd, currentLength, before)); @@ -413,48 +474,52 @@ var hyperHTML = (function (document) { } /* istanbul ignore else */ else if (futureChanges < currentChanges) { - i = indexOf(currentNodes, currentStart, currentEnd, futureNodes, futureStart, futureEnd, compare); - // outer diff + i = indexOf(currentNodes, currentStart, currentEnd, futureNodes, futureStart, futureEnd, compare); // outer diff + if (-1 < i) { remove(get, parentNode, currentNodes, currentStart, i); remove(get, parentNode, currentNodes, i + futureChanges, currentEnd); return futureNodes; } - } - - // common case with one replacement for many nodes + } // common case with one replacement for many nodes // or many nodes replaced for a single one + /* istanbul ignore else */ + + if (currentChanges < 2 || futureChanges < 2) { append(get, parentNode, futureNodes, futureStart, futureEnd, get(currentNodes[currentStart], 0)); remove(get, parentNode, currentNodes, currentStart, currentEnd); return futureNodes; - } - - // the half match diff part has been skipped in petit-dom + } // the half match diff part has been skipped in petit-dom // https://github.com/yelouafi/petit-dom/blob/bd6f5c919b5ae5297be01612c524c40be45f14a7/src/vdom.js#L391-L397 // accordingly, I think it's safe to skip in here too // if one day it'll come out like the speediest thing ever to do // then I might add it in here too - // Extra: before going too fancy, what about reversed lists ? // This should bail out pretty quickly if that's not the case. + + if (currentChanges === futureChanges && isReversed(futureNodes, futureEnd, currentNodes, currentStart, currentEnd, compare)) { append(get, parentNode, futureNodes, futureStart, futureEnd, next(get, currentNodes, currentEnd, currentLength, before)); return futureNodes; - } + } // last resort through a smart diff - // last resort through a smart diff - smartDiff(get, parentNode, futureNodes, futureStart, futureEnd, futureChanges, currentNodes, currentStart, currentEnd, currentChanges, currentLength, compare, before); + smartDiff(get, parentNode, futureNodes, futureStart, futureEnd, futureChanges, currentNodes, currentStart, currentEnd, currentChanges, currentLength, compare, before); return futureNodes; }; + + /*! (c) Andrea Giammarchi - ISC */ - var self$3 = null || /* istanbul ignore next */{}; + var self$3 = null || + /* istanbul ignore next */ + {}; self$3.CustomEvent = typeof CustomEvent === 'function' ? CustomEvent : function (__p__) { CustomEvent[__p__] = new CustomEvent('').constructor[__p__]; return CustomEvent; + function CustomEvent(type, init) { if (!init) init = {}; var e = document.createEvent('CustomEvent'); @@ -464,7 +529,6 @@ var hyperHTML = (function (document) { }('prototype'); var CustomEvent$1 = self$3.CustomEvent; - // hyperHTML.Component is a very basic class // able to create Custom Elements like components // including the ability to listen to connect/disconnect // events via onconnect/ondisconnect attributes @@ -472,44 +536,54 @@ var hyperHTML = (function (document) { // The main difference is that declared components // will not automatically render on setState(...) // to simplify state handling on render. + function Component() { return this; // this is needed in Edge !!! - } - - // Component is lazily setup because it needs + } // Component is lazily setup because it needs // wire mechanism as lazy content + function setup(content) { // there are various weakly referenced variables in here // and mostly are to use Component.for(...) static method. var children = new WeakMap$1(); var create = Object.create; + var createEntry = function createEntry(wm, id, component) { wm.set(id, component); return component; }; + var get = function get(Class, info, context, id) { var relation = info.get(Class) || relate(Class, info); - switch (typeof id) { + + switch (typeof(id)) { case 'object': case 'function': var wm = relation.w || (relation.w = new WeakMap$1()); return wm.get(id) || createEntry(wm, id, new Class(context)); + default: var sm = relation.p || (relation.p = create(null)); return sm[id] || (sm[id] = new Class(context)); } }; + var relate = function relate(Class, info) { - var relation = { w: null, p: null }; + var relation = { + w: null, + p: null + }; info.set(Class, relation); return relation; }; + var set = function set(context) { var info = new Map$1(); children.set(context, info); return info; - }; - // The Component Class + }; // The Component Class + + Object.defineProperties(Component, { // Component.for(context[, id]) is a convenient way // to automatically relate data/context to children components @@ -561,8 +635,9 @@ var hyperHTML = (function (document) { detail: detail }); event.component = this; - return (_wire$.dispatchEvent ? _wire$ : _wire$.childNodes[0]).dispatchEvent(event); + return (_wire$.dispatchEvent ? _wire$ : _wire$.firstChild).dispatchEvent(event); } + return false; } }, @@ -573,19 +648,21 @@ var hyperHTML = (function (document) { value: function value(state, render) { var target = this.state; var source = typeof state === 'function' ? state.call(this, target) : state; + for (var key in source) { target[key] = source[key]; - }if (render !== false) this.render(); + } + + if (render !== false) this.render(); return this; } } }); - } - - // instead of a secret key I could've used a WeakMap + } // instead of a secret key I could've used a WeakMap // However, attaching a property directly will result // into better performance with thousands of components // hanging around, and less memory pressure caused by the WeakMap + var lazyGetter = function lazyGetter(type, fn) { var secret = '_' + type + '$'; return { @@ -596,9 +673,9 @@ var hyperHTML = (function (document) { setValue(this, secret, value); } }; - }; + }; // shortcut to set value on get or set(value) + - // shortcut to set value on get or set(value) var setValue = function setValue(self, secret, value) { return Object.defineProperty(self, secret, { configurable: true, @@ -608,18 +685,24 @@ var hyperHTML = (function (document) { })[secret]; }; + Object.defineProperties(Component.prototype, { + // used to distinguish better than instanceof + ELEMENT_NODE: { + value: 1 + }, + nodeType: { + value: -1 + } + }); + var attributes = {}; var intents = {}; var keys = []; var hasOwnProperty = intents.hasOwnProperty; - var length = 0; - var Intent = { - // used to invoke right away hyper:attributes attributes: attributes, - // hyperHTML.define('intent', (object, update) => {...}) // can be used to define a third parts update mechanism // when every other known mechanism failed. @@ -630,17 +713,18 @@ var hyperHTML = (function (document) { if (!(intent in intents)) { length = keys.push(intent); } + intents[intent] = callback; } else { attributes[intent] = callback; } }, - // this method is used internally as last resort // to retrieve a value out of an object invoke: function invoke(object, callback) { for (var i = 0; i < length; i++) { var key = keys[i]; + if (hasOwnProperty.call(object, key)) { return intents[key](object[key], callback); } @@ -661,7 +745,6 @@ var hyperHTML = (function (document) { var FRAGMENT = 'fragment'; var TEMPLATE = 'template'; var HAS_CONTENT = 'content' in create(TEMPLATE); - var createHTML = HAS_CONTENT ? function (html) { var template = create(TEMPLATE); template.innerHTML = html; @@ -670,6 +753,7 @@ var hyperHTML = (function (document) { var content = create(FRAGMENT); var template = create(TEMPLATE); var childNodes = null; + if (/^[^\S]*?<(col(?:group)?|t(?:head|body|foot|r|d|h))/i.test(html)) { var selector = RegExp.$1; template.innerHTML = '' + html + '
'; @@ -678,28 +762,29 @@ var hyperHTML = (function (document) { template.innerHTML = html; childNodes = template.childNodes; } + append(content, childNodes); return content; }; - return function createContent(markup, type) { return (type === 'svg' ? createSVG : createHTML)(markup); }; function append(root, childNodes) { var length = childNodes.length; + while (length--) { root.appendChild(childNodes[0]); } } function create(element) { - return element === FRAGMENT ? document.createDocumentFragment() : document.createElement(element); - } - - // it could use createElementNS when hasNode is there + return element === FRAGMENT ? document.createDocumentFragment() : document.createElementNS('http://www.w3.org/1999/xhtml', element); + } // it could use createElementNS when hasNode is there // but this fallback is equally fast and easier to maintain // it is also battle tested already in all IE + + function createSVG(svg) { var content = create(FRAGMENT); var template = create('div'); @@ -723,16 +808,23 @@ var hyperHTML = (function (document) { notObserving = !notObserving; startObserving(node.ownerDocument); } + observer.add(node); return node; }; + function startObserving(document) { var dispatched = null; + try { - new MutationObserver(changes).observe(document, { subtree: true, childList: true }); + new MutationObserver(changes).observe(document, { + subtree: true, + childList: true + }); } catch (o_O) { var timer = 0; var records = []; + var reschedule = function reschedule(record) { records.push(record); clearTimeout(timer); @@ -740,25 +832,38 @@ var hyperHTML = (function (document) { changes(records.splice(timer = 0, records.length)); }, 0); }; + document.addEventListener('DOMNodeRemoved', function (event) { - reschedule({ addedNodes: [], removedNodes: [event.target] }); + reschedule({ + addedNodes: [], + removedNodes: [event.target] + }); }, true); document.addEventListener('DOMNodeInserted', function (event) { - reschedule({ addedNodes: [event.target], removedNodes: [] }); + reschedule({ + addedNodes: [event.target], + removedNodes: [] + }); }, true); } + function changes(records) { dispatched = new Tracker(); + for (var record, length = records.length, i = 0; i < length; i++) { record = records[i]; dispatchAll(record.removedNodes, DISCONNECTED, CONNECTED); dispatchAll(record.addedNodes, CONNECTED, DISCONNECTED); } + dispatched = null; } + function dispatchAll(nodes, type, counter) { - for (var node, event = new Event(type), length = nodes.length, i = 0; i < length; (node = nodes[i++]).nodeType === 1 && dispatchTarget(node, event, type, counter)) {} + for (var node, event = new Event(type), length = nodes.length, i = 0; i < length; (node = nodes[i++]).nodeType === 1 && dispatchTarget(node, event, type, counter)) { + } } + function dispatchTarget(node, event, type, counter) { if (observer.has(node) && !dispatched[type].has(node)) { dispatched[counter].delete(node); @@ -778,11 +883,13 @@ var hyperHTML = (function (document) { } */ } - for (var - // apparently is node.children || IE11 ... ^_^;; + + for (var // apparently is node.children || IE11 ... ^_^;; // https://github.com/WebReflection/disconnected/issues/1 - children = node.children || [], length = children.length, i = 0; i < length; dispatchTarget(children[i++], event, type, counter)) {} + children = node.children || [], length = children.length, i = 0; i < length; dispatchTarget(children[i++], event, type, counter)) { + } } + function Tracker() { this[CONNECTED] = new WeakSet(); this[DISCONNECTED] = new WeakSet(); @@ -790,74 +897,22 @@ var hyperHTML = (function (document) { } } - /*! (c) Andrea Giammarchi - ISC */ - var createContent$1 = function (document) { - - var FRAGMENT = 'fragment'; - var TEMPLATE = 'template'; - var HAS_CONTENT = 'content' in create(TEMPLATE); - - var createHTML = HAS_CONTENT ? function (html) { - var template = create(TEMPLATE); - template.innerHTML = html; - return template.content; - } : function (html) { - var content = create(FRAGMENT); - var template = create(TEMPLATE); - var childNodes = null; - if (/^[^\S]*?<(col(?:group)?|t(?:head|body|foot|r|d|h))/i.test(html)) { - var selector = RegExp.$1; - template.innerHTML = '' + html + '
'; - childNodes = template.querySelectorAll(selector); - } else { - template.innerHTML = html; - childNodes = template.childNodes; - } - append(content, childNodes); - return content; - }; - - return function createContent(markup, type) { - return (type === 'svg' ? createSVG : createHTML)(markup); - }; - - function append(root, childNodes) { - var length = childNodes.length; - while (length--) { - root.appendChild(childNodes[0]); - } - } - - function create(element) { - return element === FRAGMENT ? document.createDocumentFragment() : document.createElementNS('http://www.w3.org/1999/xhtml', element); - } - - // it could use createElementNS when hasNode is there - // but this fallback is equally fast and easier to maintain - // it is also battle tested already in all IE - function createSVG(svg) { - var content = create(FRAGMENT); - var template = create('div'); - template.innerHTML = '' + svg + ''; - append(content, template.firstChild.childNodes); - return content; - } - }(document); - /*! (c) Andrea Giammarchi - ISC */ var importNode = function (document, appendChild, cloneNode, createTextNode, importNode) { - var native = importNode in document; - // IE 11 has problems with cloning templates: + var native = importNode in document; // IE 11 has problems with cloning templates: // it "forgets" empty childNodes. This feature-detects that. + var fragment = document.createDocumentFragment(); fragment[appendChild](document[createTextNode]('g')); fragment[appendChild](document[createTextNode]('')); var content = native ? document[importNode](fragment, true) : fragment[cloneNode](true); return content.childNodes.length < 2 ? function importNode(node, deep) { var clone = node[cloneNode](); + for (var childNodes = node.childNodes || [], length = childNodes.length, i = 0; deep && i < length; i++) { clone[appendChild](importNode(childNodes[i], deep)); } + return clone; } : native ? document[importNode] : function (node, deep) { return node[cloneNode](!!deep); @@ -869,34 +924,30 @@ var hyperHTML = (function (document) { }; // Custom - var UID = '-' + Math.random().toFixed(6) + '%'; - // Edge issue! + var UID = '-' + Math.random().toFixed(6) + '%'; // Edge issue! + if (!function (template, content, tabindex) { return content in template && (template.innerHTML = '

', template[content].childNodes[0].getAttribute(tabindex) == UID); }(document.createElement('template'), 'content', 'tabindex')) { UID = '_dt: ' + UID.slice(1, -1) + ';'; } - var UIDC = ''; - // DOM + var UIDC = ''; // DOM + var COMMENT_NODE = 8; - var DOCUMENT_FRAGMENT_NODE = 11; var ELEMENT_NODE = 1; var TEXT_NODE = 3; - var SHOULD_USE_TEXT_CONTENT = /^(?:style|textarea)$/i; var VOID_ELEMENTS = /^(?:area|base|br|col|embed|hr|img|input|keygen|link|menuitem|meta|param|source|track|wbr)$/i; function sanitize (template) { return template.join(UIDC).replace(selfClosing, fullClosing).replace(attrSeeker, attrReplacer); } - var spaces = ' \\f\\n\\r\\t'; var almostEverything = '[^ ' + spaces + '\\/>"\'=]+'; var attrName = '[ ' + spaces + ']+' + almostEverything; var tagName = '<([A-Za-z]+[A-Za-z0-9:_-]*)((?:'; var attrPartials = '(?:\\s*=\\s*(?:\'[^\']*?\'|"[^"]*?"|<[^>]*?>|' + almostEverything + '))?)'; - var attrSeeker = new RegExp(tagName + attrName + attrPartials + '+)([ ' + spaces + ']*/?>)', 'g'); var selfClosing = new RegExp(tagName + attrName + attrPartials + '*)([ ' + spaces + ']*/>)', 'g'); var findAttributes = new RegExp('(' + attrName + '\\s*=\\s*)([\'"]?)' + UIDC + '\\2', 'gi'); @@ -913,119 +964,121 @@ var hyperHTML = (function (document) { return VOID_ELEMENTS.test($1) ? $0 : '<' + $1 + $2 + '>'; } - function create(type, node, name) { - return { type: type, name: name, node: node, path: createPath(node) }; - } - - function createPath(node) { - var parentNode; - var path = []; - switch (node.nodeType) { - case ELEMENT_NODE: - case DOCUMENT_FRAGMENT_NODE: - parentNode = node; - break; - case COMMENT_NODE: - parentNode = node.parentNode; - prepend(path, parentNode, node); - break; - default: - parentNode = node.ownerElement; - break; - } - while (parentNode = (node = parentNode).parentNode) { - prepend(path, parentNode, node); - }return path; + function create(type, node, path, name) { + return { + name: name, + node: node, + path: path, + type: type + }; } function find(node, path) { var length = path.length; var i = 0; + while (i < length) { node = node.childNodes[path[i++]]; - }return node; + } + + return node; } - function parse(node, paths, parts) { + function parse(node, holes, parts, path) { var childNodes = node.childNodes; var length = childNodes.length; var i = 0; + while (i < length) { - var child = childNodes[i++]; + var child = childNodes[i]; + switch (child.nodeType) { case ELEMENT_NODE: - parseAttributes(child, paths, parts); - parse(child, paths, parts); + var childPath = path.concat(i); + parseAttributes(child, holes, parts, childPath); + parse(child, holes, parts, childPath); break; + case COMMENT_NODE: if (child.textContent === UID) { parts.shift(); - paths.push( - // basicHTML or other non standard engines + holes.push( // basicHTML or other non standard engines // might end up having comments in nodes // where they shouldn't, hence this check. - SHOULD_USE_TEXT_CONTENT.test(node.nodeName) ? create('text', node) : create('any', child)); + SHOULD_USE_TEXT_CONTENT.test(node.nodeName) ? create('text', node, path) : create('any', child, path.concat(i))); } + break; + case TEXT_NODE: // the following ignore is actually covered by browsers // only basicHTML ends up on previous COMMENT_NODE case // instead of TEXT_NODE because it knows nothing about // special style or textarea behavior + /* istanbul ignore if */ if (SHOULD_USE_TEXT_CONTENT.test(node.nodeName) && trim.call(child.textContent) === UIDC) { parts.shift(); - paths.push(create('text', node)); + holes.push(create('text', node, path)); } + break; } + + i++; } } - function parseAttributes(node, paths, parts) { + function parseAttributes(node, holes, parts, path) { var cache = new Map$1(); var attributes = node.attributes; var remove = []; var array = remove.slice.call(attributes, 0); var length = array.length; var i = 0; + while (i < length) { var attribute = array[i++]; + if (attribute.value === UID) { - var name = attribute.name; - // the following ignore is covered by IE + var name = attribute.name; // the following ignore is covered by IE // and the IE9 double viewBox test + /* istanbul ignore else */ + if (!cache.has(name)) { var realName = parts.shift().replace(/^(?:|[\S\s]*?\s)(\S+?)\s*=\s*['"]?$/, '$1'); - var value = attributes[realName] || - // the following ignore is covered by browsers + var value = attributes[realName] || // the following ignore is covered by browsers // while basicHTML is already case-sensitive + /* istanbul ignore next */ attributes[realName.toLowerCase()]; cache.set(name, value); - paths.push(create('attr', value, realName)); + holes.push(create('attr', value, path, realName)); } + remove.push(attribute); } } + length = remove.length; i = 0; + while (i < length) { // Edge HTML bug #16878726 var attr = remove[i++]; - if (/^id$/i.test(attr.name)) node.removeAttribute(attr.name); - // standard browsers would work just fine here + if (/^id$/i.test(attr.name)) node.removeAttribute(attr.name); // standard browsers would work just fine here else node.removeAttributeNode(attr); - } - - // This is a very specific Firefox/Safari issue + } // This is a very specific Firefox/Safari issue // but since it should be a not so common pattern, // it's probably worth patching regardless. // Basically, scripts created through strings are death. // You need to create fresh new scripts instead. // TODO: is there any other node that needs such nonsense? + + var nodeName = node.nodeName; + if (/^script$/i.test(nodeName)) { // this used to be like that // var script = createElement(node, nodeName); @@ -1035,19 +1088,17 @@ var hyperHTML = (function (document) { var script = document.createElement(nodeName); length = attributes.length; i = 0; + while (i < length) { script.setAttributeNode(attributes[i++].cloneNode(true)); - }script.textContent = node.textContent; + } + + script.textContent = node.textContent; node.parentNode.replaceChild(script, node); } } - function prepend(path, parent, node) { - path.unshift(path.indexOf.call(parent.childNodes, node)); - } - // globals - var parsed = new WeakMap$1(); var referenced = new WeakMap$1(); @@ -1055,42 +1106,51 @@ var hyperHTML = (function (document) { var markup = sanitize(template); var transform = options.transform; if (transform) markup = transform(markup); - var content = createContent$1(markup, options.type); + var content = createContent(markup, options.type); cleanContent(content); var holes = []; - parse(content, holes, template.slice(0)); + parse(content, holes, template.slice(0), []); var info = { content: content, updates: function updates(content) { var callbacks = []; var len = holes.length; var i = 0; + while (i < len) { var info = holes[i++]; var node = find(content, info.path); + switch (info.type) { case 'any': callbacks.push(options.any(node, [])); break; + case 'attr': callbacks.push(options.attribute(node, info.name, info.node)); break; + case 'text': callbacks.push(options.text(node)); node.textContent = ''; break; } } + return function () { var length = arguments.length; var values = length - 1; var i = 1; + if (len !== values) { throw new Error(values + ' values instead of ' + len + '\n' + template.join(', ')); } + while (i < length) { callbacks[i - 1](arguments[i++]); - }return content; + } + + return content; }; } }; @@ -1122,8 +1182,10 @@ var hyperHTML = (function (document) { function cleanContent(fragment) { var childNodes = fragment.childNodes; var i = childNodes.length; + while (i--) { var child = childNodes[i]; + if (child.nodeType !== 1 && trim.call(child.textContent).length === 0) { fragment.removeChild(child); } @@ -1132,16 +1194,17 @@ var hyperHTML = (function (document) { /*! (c) Andrea Giammarchi - ISC */ var hyperStyle = function () { - // from https://github.com/developit/preact/blob/33fc697ac11762a1cb6e71e9847670d047af7ce5/src/varants.js var IS_NON_DIMENSIONAL = /acit|ex(?:s|g|n|p|$)|rph|ows|mnc|ntw|ine[ch]|zoo|^ord/i; var hyphen = /([^A-Z])([A-Z]+)/g; return function hyperStyle(node, original) { return 'ownerSVGElement' in node ? svg(node, original) : update(node.style, false); }; + function ized($0, $1, $2) { return $1 + '-' + $2.toLowerCase(); } + function svg(node, original) { var style; if (original) style = original.cloneNode(true);else { @@ -1152,18 +1215,24 @@ var hyperHTML = (function (document) { node.setAttributeNode(style); return update(style, true); } + function toStyle(object) { var key, css = []; + for (key in object) { css.push(key.replace(hyphen, ized), ':', object[key], ';'); - }return css.join(''); + } + + return css.join(''); } + function update(style, isSVG) { var oldType, oldValue; return function (newValue) { var info, key, styleValue, value; - switch (typeof newValue) { + + switch (typeof(newValue)) { case 'object': if (newValue) { if (oldType === 'object') { @@ -1179,171 +1248,134 @@ var hyperHTML = (function (document) { } else { if (isSVG) style.value = '';else style.cssText = ''; } + info = isSVG ? {} : style; + for (key in newValue) { value = newValue[key]; styleValue = typeof value === 'number' && !IS_NON_DIMENSIONAL.test(key) ? value + 'px' : value; if (!isSVG && /^--/.test(key)) info.setProperty(key, styleValue);else info[key] = styleValue; } + oldType = 'object'; if (isSVG) style.value = toStyle(oldValue = info);else oldValue = newValue; break; } + default: if (oldValue != newValue) { oldType = 'string'; oldValue = newValue; if (isSVG) style.value = newValue || '';else style.cssText = newValue || ''; } + break; } }; } }(); - var G = document.defaultView; - - // Node.CONSTANTS - // 'cause some engine has no global Node defined - // (i.e. Node, NativeScript, basicHTML ... ) - var ELEMENT_NODE$1 = 1; - var DOCUMENT_FRAGMENT_NODE$1 = 11; - - // SVG related constants - var OWNER_SVG_ELEMENT = 'ownerSVGElement'; + /*! (c) Andrea Giammarchi - ISC */ + var Wire = function (slice, proto) { + proto = Wire.prototype; + proto.ELEMENT_NODE = 1; + proto.nodeType = 111; + + proto.remove = function (keepFirst) { + var childNodes = this.childNodes; + var first = this.firstChild; + var last = this.lastChild; + this._ = null; + + if (keepFirst && childNodes.length === 2) { + last.parentNode.removeChild(last); + } else { + var range = this.ownerDocument.createRange(); + range.setStartBefore(keepFirst ? childNodes[1] : first); + range.setEndAfter(last); + range.deleteContents(); + } - // Custom Elements / MutationObserver constants - var CONNECTED = 'connected'; - var DISCONNECTED = 'dis' + CONNECTED; + return first; + }; - var templateLiteral = function () { + proto.valueOf = function (forceAppend) { + var fragment = this._; + var noFragment = fragment == null; + if (noFragment) fragment = this._ = this.ownerDocument.createDocumentFragment(); - var RAW = 'raw'; - var isNoOp = false; - var _templateLiteral = function templateLiteral(tl) { - if ( - // for badly transpiled literals - !(RAW in tl) || - // for some version of TypeScript - tl.propertyIsEnumerable(RAW) || - // and some other version of TypeScript - !Object.isFrozen(tl.raw) || - // or for Firefox < 55 - /Firefox\/(\d+)/.test((document.defaultView.navigator || {}).userAgent) && parseFloat(RegExp.$1) < 55) { - var forever = {}; - _templateLiteral = function templateLiteral(tl) { - var key = RAW + tl.join(RAW); - return forever[key] || (forever[key] = tl); - }; - return _templateLiteral(tl); - } else { - isNoOp = true; - return tl; + if (noFragment || forceAppend) { + for (var n = this.childNodes, i = 0, l = n.length; i < l; i++) { + fragment.appendChild(n[i]); + } } + + return fragment; }; - return function (tl) { - return isNoOp ? tl : _templateLiteral(tl); - }; - }(); - // these are tiny helpers to simplify most common operations needed here - var doc = function doc(node) { - return node.ownerDocument || node; - }; - var fragment = function fragment(node) { - return doc(node).createDocumentFragment(); - }; - var text = function text(node, _text) { - return doc(node).createTextNode(_text); - }; + return Wire; - // appends an array of nodes - // to a generic node/fragment - // When available, uses append passing all arguments at once - // hoping that's somehow faster, even if append has more checks on type - // istanbul ignore next - var append$1 = 'append' in fragment(document) ? function (node, childNodes) { - node.append.apply(node, childNodes); - } : function (node, childNodes) { - var length = childNodes.length; - for (var i = 0; i < length; i++) { - node.appendChild(childNodes[i]); + function Wire(childNodes) { + var nodes = this.childNodes = slice.call(childNodes, 0); + this.firstChild = nodes[0]; + this.lastChild = nodes[nodes.length - 1]; + this.ownerDocument = nodes[0].ownerDocument; + this._ = null; } - }; + }([].slice); - // normalizes the template once for all arguments cases - var reArguments = function reArguments(template) { - var args = [templateLiteral(template)]; - for (var i = 1, length = arguments.length; i < length; i++) { - args[i] = arguments[i]; - }return args; - }; - - // just recycling a one-off array to use slice - // in every needed place - var slice = [].slice; + // Node.CONSTANTS + var DOCUMENT_FRAGMENT_NODE$1 = 11; // SVG related constants - function Wire(childNodes) { - this.childNodes = childNodes; - this.length = childNodes.length; - this.first = childNodes[0]; - this.last = childNodes[this.length - 1]; - this._ = null; - } + var OWNER_SVG_ELEMENT = 'ownerSVGElement'; // Custom Elements / MutationObserver constants - // when a wire is inserted, all its nodes will follow - Wire.prototype.valueOf = function valueOf(different) { - var noFragment = this._ == null; - if (noFragment) this._ = fragment(this.first); - /* istanbul ignore else */ - if (noFragment || different) append$1(this._, this.childNodes); - return this._; - }; - - // when a wire is removed, all its nodes must be removed as well - Wire.prototype.remove = function remove() { - this._ = null; - var first = this.first; - var last = this.last; - if (this.length === 2) { - last.parentNode.removeChild(last); - } else { - var range = doc(first).createRange(); - range.setStartBefore(this.childNodes[1]); - range.setEndAfter(last); - range.deleteContents(); - } - return first; - }; + var CONNECTED = 'connected'; + var DISCONNECTED = 'dis' + CONNECTED; - var observe = disconnected({ Event: CustomEvent$1, WeakSet: WeakSet$1 }); + var componentType = Component.prototype.nodeType; + var wireType = Wire.prototype.nodeType; + var observe = disconnected({ + Event: CustomEvent$1, + WeakSet: WeakSet$1 + }); - // returns an intent to explicitly inject content as html var asHTML = function asHTML(html) { - return { html: html }; - }; + return { + html: html + }; + }; // returns nodes from wires and components + - // returns nodes from wires and components var asNode = function asNode(item, i) { - return 'ELEMENT_NODE' in item ? item : item.constructor === Wire ? - // in the Wire case, the content can be - // removed, post-pended, inserted, or pre-pended and - // all these cases are handled by domdiff already - /* istanbul ignore next */ - 1 / i < 0 ? i ? item.remove() : item.last : i ? item.valueOf(true) : item.first : asNode(item.render(), i); - }; + switch (item.nodeType) { + case wireType: + // in the Wire case, the content can be + // removed, post-pended, inserted, or pre-pended and + // all these cases are handled by domdiff already - // returns true if domdiff can handle the value - var canDiff = function canDiff(value) { - return 'ELEMENT_NODE' in value || value instanceof Wire || value instanceof Component; - }; + /* istanbul ignore next */ + return 1 / i < 0 ? i ? item.remove(true) : item.lastChild : i ? item.valueOf(true) : item.firstChild; - // when a Promise is used as interpolation value + case componentType: + return asNode(item.render(), i); + + default: + return item; + } + }; // returns true if domdiff can handle the value + + + var canDiff = function canDiff(value) { + return 'ELEMENT_NODE' in value; + }; // when a Promise is used as interpolation value // its result must be parsed once resolved. // This callback is in charge of understanding what to do // with a returned value once the promise is resolved. + + var invokeAtDistance = function invokeAtDistance(value, callback) { callback(value.placeholder); + if ('text' in value) { Promise.resolve(value.text).then(String).then(callback); } else if ('any' in value) { @@ -1353,15 +1385,21 @@ var hyperHTML = (function (document) { } else { Promise.resolve(Intent.invoke(value, callback)).then(callback); } - }; + }; // quick and dirty way to check for Promise/ish values + - // quick and dirty way to check for Promise/ish values var isPromise_ish = function isPromise_ish(value) { return value != null && 'then' in value; - }; + }; // list of attributes that should not be directly assigned + - // list of attributes that should not be directly assigned - var readOnly = /^(?:form|list)$/i; + var readOnly = /^(?:form|list)$/i; // reused every slice time + + var slice = [].slice; // simplifies text node creation + + var text = function text(node, _text) { + return node.ownerDocument.createTextNode(_text); + }; function Tagger(type) { this.type = type; @@ -1369,7 +1407,6 @@ var hyperHTML = (function (document) { } Tagger.prototype = { - // there are four kind of attributes, and related behavior: // * events, with a name starting with `on`, to add/remove event listeners // * special, with a name present in their inherited prototype, accessed directly @@ -1379,19 +1416,20 @@ var hyperHTML = (function (document) { // fully inspired by Preact library and its simplicity. attribute: function attribute(node, name, original) { var isSVG = OWNER_SVG_ELEMENT in node; - var oldValue = void 0; - // if the attribute is the style one + var oldValue; // if the attribute is the style one // handle it differently from others - if (name === 'style') return hyperStyle(node, original, isSVG); - // the name is an event one, + + if (name === 'style') return hyperStyle(node, original, isSVG); // the name is an event one, // add/remove event listeners accordingly else if (/^on/.test(name)) { var type = name.slice(2); + if (type === CONNECTED || type === DISCONNECTED) { observe(node); } else if (name.toLowerCase() in node) { type = type.toLowerCase(); } + return function (newValue) { if (oldValue !== newValue) { if (oldValue) node.removeEventListener(type, oldValue, false); @@ -1399,16 +1437,17 @@ var hyperHTML = (function (document) { if (newValue) node.addEventListener(type, newValue, false); } }; - } - // the attribute is special ('value' in input) + } // the attribute is special ('value' in input) // and it's not SVG *or* the name is exactly data, // in this case assign the value directly else if (name === 'data' || !isSVG && name in node && !readOnly.test(name)) { return function (newValue) { if (oldValue !== newValue) { oldValue = newValue; + if (node[name] !== newValue) { node[name] = newValue; + if (newValue == null) { node.removeAttribute(name); } @@ -1417,11 +1456,14 @@ var hyperHTML = (function (document) { }; } else if (name in Intent.attributes) { return function (any) { - oldValue = Intent.attributes[name](node, any); - node.setAttribute(name, oldValue == null ? '' : oldValue); + var newValue = Intent.attributes[name](node, any); + + if (oldValue !== newValue) { + oldValue = newValue; + if (newValue == null) node.removeAttribute(name);else node.setAttribute(name, newValue); + } }; - } - // in every other case, use the attribute node as it is + } // in every other case, use the attribute node as it is // update only the value, set it as node only when/if needed else { var owner = false; @@ -1429,15 +1471,18 @@ var hyperHTML = (function (document) { return function (newValue) { if (oldValue !== newValue) { oldValue = newValue; + if (attribute.value !== newValue) { if (newValue == null) { if (owner) { owner = false; node.removeAttributeNode(attribute); } + attribute.value = newValue; } else { attribute.value = newValue; + if (!owner) { owner = true; node.setAttributeNode(attribute); @@ -1448,8 +1493,6 @@ var hyperHTML = (function (document) { }; } }, - - // in a hyper(node)`
${content}
` case // everything could happen: // * it's a JS primitive, stored as text @@ -1460,12 +1503,18 @@ var hyperHTML = (function (document) { // * it's an Array, resolve all values if Promises and/or // update the node with the resulting list of content any: function any(node, childNodes) { - var diffOptions = { node: asNode, before: node }; - var nodeType = OWNER_SVG_ELEMENT in node ? /* istanbul ignore next */'svg' : 'html'; + var diffOptions = { + node: asNode, + before: node + }; + var nodeType = OWNER_SVG_ELEMENT in node ? + /* istanbul ignore next */ + 'svg' : 'html'; var fastPath = false; - var oldValue = void 0; + var oldValue; + var anyContent = function anyContent(value) { - switch (typeof value) { + switch (typeof(value)) { case 'string': case 'number': case 'boolean': @@ -1479,10 +1528,13 @@ var hyperHTML = (function (document) { oldValue = value; childNodes = domdiff(node.parentNode, childNodes, [text(node, value)], diffOptions); } + break; + case 'function': anyContent(value(node)); break; + case 'object': case 'undefined': if (value == null) { @@ -1490,29 +1542,36 @@ var hyperHTML = (function (document) { childNodes = domdiff(node.parentNode, childNodes, [], diffOptions); break; } + default: fastPath = false; oldValue = value; + if (isArray(value)) { if (value.length === 0) { if (childNodes.length) { childNodes = domdiff(node.parentNode, childNodes, [], diffOptions); } } else { - switch (typeof value[0]) { + switch (typeof(value[0])) { case 'string': case 'number': case 'boolean': - anyContent({ html: value }); + anyContent({ + html: value + }); break; + case 'object': if (isArray(value[0])) { value = value.concat.apply([], value); } + if (isPromise_ish(value[0])) { Promise.all(value).then(anyContent); break; } + default: childNodes = domdiff(node.parentNode, childNodes, value, diffOptions); break; @@ -1535,23 +1594,26 @@ var hyperHTML = (function (document) { } else { anyContent(Intent.invoke(value, anyContent)); } + break; } }; + return anyContent; }, - - // style or textareas don't accept HTML as content // it's pointless to transform or analyze anything // different from text there but it's worth checking // for possible defined intents. - text: function text$$1(node) { - var oldValue = void 0; + text: function text(node) { + var oldValue; + var textContent = function textContent(value) { if (oldValue !== value) { oldValue = value; - var type = typeof value; + + var type = typeof(value); + if (type === 'object' && value) { if (isPromise_ish(value)) { value.then(textContent); @@ -1575,14 +1637,59 @@ var hyperHTML = (function (document) { } } }; + return textContent; } }; - // all wires used per each context - var wires = new WeakMap$1(); + /*! (c) Andrea Giammarchi - ISC */ + var templateLiteral = function () { + + var RAW = 'raw'; + var isNoOp = false; + + var _templateLiteral = function templateLiteral(tl) { + if ( // for badly transpiled literals + !(RAW in tl) || // for some version of TypeScript + tl.propertyIsEnumerable(RAW) || // and some other version of TypeScript + !Object.isFrozen(tl[RAW]) || // or for Firefox < 55 + /Firefox\/(\d+)/.test((document.defaultView.navigator || {}).userAgent) && parseFloat(RegExp.$1) < 55) { + var forever = {}; + + _templateLiteral = function templateLiteral(tl) { + for (var key = '.', i = 0; i < tl.length; i++) { + key += tl[i].length + '.' + tl[i]; + } - // A wire is a callback used as tag function + return forever[key] || (forever[key] = tl); + }; + } else { + isNoOp = true; + } + + return TL(tl); + }; + + return TL; + + function TL(tl) { + return isNoOp ? tl : _templateLiteral(tl); + } + }(); + + function tta (template) { + var length = arguments.length; + var args = [templateLiteral(template)]; + var i = 1; + + while (i < length) { + args.push(arguments[i++]); + } + + return args; + } + + var wires = new WeakMap$1(); // A wire is a callback used as tag function // to lazily relate a generic object to a template literal. // hyper.wire(user)`
${user.name}
`; => the div#user // This provides the ability to have a unique DOM structure @@ -1591,22 +1698,22 @@ var hyperHTML = (function (document) { // via html:id or :id convention. Such :id allows same JS objects // to be associated to different DOM structures accordingly with // the used template literal without losing previously rendered parts. + var wire = function wire(obj, type) { return obj == null ? content(type || 'html') : weakly(obj, type || 'html'); - }; - - // A wire content is a virtual reference to one or more nodes. + }; // A wire content is a virtual reference to one or more nodes. // It's represented by either a DOM node, or an Array. // In both cases, the wire content role is to simply update // all nodes through the list of related callbacks. // In few words, a wire content is like an invisible parent node // in charge of updating its content like a bound element would do. + + var content = function content(type) { - var wire = void 0, - tagger = void 0, - template = void 0; + var wire, tagger, template; return function () { - var args = reArguments.apply(null, arguments); + var args = tta.apply(null, arguments); + if (template !== args[0]) { template = args[0]; tagger = new Tagger(type); @@ -1614,26 +1721,27 @@ var hyperHTML = (function (document) { } else { tagger.apply(tagger, args); } + return wire; }; - }; - - // wires are weakly created through objects. + }; // wires are weakly created through objects. // Each object can have multiple wires associated // and this is thanks to the type + :id feature. + + var weakly = function weakly(obj, type) { var i = type.indexOf(':'); var wire = wires.get(obj); var id = type; + if (-1 < i) { id = type.slice(i + 1); type = type.slice(0, i) || 'html'; } + if (!wire) wires.set(obj, wire = {}); return wire[id] || (wire[id] = content(type)); - }; - - // A document fragment loses its nodes + }; // A document fragment loses its nodes // as soon as it is appended into another node. // This has the undesired effect of losing wired content // on a second render call, because (by then) the fragment would be empty: @@ -1641,67 +1749,64 @@ var hyperHTML = (function (document) { // stay associated with the original interpolation. // To prevent hyperHTML from forgetting about a fragment's sub-nodes, // fragments are instead returned as an Array of nodes or, if there's only one entry, - // as a single referenced node which, unlike framents, will indeed persist + // as a single referenced node which, unlike fragments, will indeed persist // wire content throughout multiple renderings. // The initial fragment, at this point, would be used as unique reference to this // array of nodes or to this single referenced node. + + var wireContent = function wireContent(node) { var childNodes = node.childNodes; var length = childNodes.length; - var wireNodes = []; - for (var i = 0; i < length; i++) { - var child = childNodes[i]; - if (child.nodeType === ELEMENT_NODE$1 || trim.call(child.textContent).length !== 0) { - wireNodes.push(child); - } - } - return wireNodes.length === 1 ? wireNodes[0] : new Wire(wireNodes); + return length === 1 ? childNodes[0] : length ? new Wire(childNodes) : node; }; - // a weak collection of contexts that // are already known to hyperHTML - var bewitched = new WeakMap$1(); - // better known as hyper.bind(node), the render is + var bewitched = new WeakMap$1(); // better known as hyper.bind(node), the render is // the main tag function in charge of fully upgrading // or simply updating, contexts used as hyperHTML targets. // The `this` context is either a regular DOM node or a fragment. + function render() { var wicked = bewitched.get(this); - var args = reArguments.apply(null, arguments); + var args = tta.apply(null, arguments); + if (wicked && wicked.template === args[0]) { wicked.tagger.apply(null, args); } else { upgrade.apply(this, args); } - return this; - } - // an upgrade is in charge of collecting template info, + return this; + } // an upgrade is in charge of collecting template info, // parse it once, if unknown, to map all interpolations // as single DOM callbacks, relate such template // to the current context, and render it after cleaning the context up - function upgrade() { - var args = reArguments.apply(null, arguments); + + + function upgrade(template) { var type = OWNER_SVG_ELEMENT in this ? 'svg' : 'html'; var tagger = new Tagger(type); - bewitched.set(this, { tagger: tagger, template: args[0] }); + bewitched.set(this, { + tagger: tagger, + template: template + }); this.textContent = ''; - this.appendChild(tagger.apply(null, args)); + this.appendChild(tagger.apply(null, arguments)); } /*! (c) Andrea Giammarchi (ISC) */ - - // all functions are self bound to the right context // you can do the following // const {bind, wire} = hyperHTML; // and use them right away: bind(node)`hello!`; + var bind = function bind(context) { return render.bind(context); }; + var define = Intent.define; var tagger = Tagger.prototype; - hyper.Component = Component; hyper.bind = bind; hyper.define = define; @@ -1709,25 +1814,21 @@ var hyperHTML = (function (document) { hyper.hyper = hyper; hyper.observe = observe; hyper.tagger = tagger; - hyper.wire = wire; - - // exported as shared utils + hyper.wire = wire; // exported as shared utils // for projects based on hyperHTML // that don't necessarily need upfront polyfills // i.e. those still targeting IE + hyper._ = { - global: G, WeakMap: WeakMap$1, WeakSet: WeakSet$1 - }; - - // the wire content is the lazy defined + }; // the wire content is the lazy defined // html or svg property of each hyper.Component - setup(content); - // by default, hyperHTML is a smart function + setup(content); // everything is exported directly or through the // that "magically" understands what's the best // thing to do with passed arguments + function hyper(HTML) { return arguments.length < 2 ? HTML == null ? content('html') : typeof HTML === 'string' ? hyper.wire(null, HTML) : 'raw' in HTML ? content('html')(HTML) : 'nodeType' in HTML ? hyper.bind(HTML) : weakly(HTML, 'html') : ('raw' in HTML ? content('html') : hyper.wire).apply(null, arguments); } diff --git a/min.js b/min.js index 619490dd..213b6d0c 100644 --- a/min.js +++ b/min.js @@ -1,3 +1,4 @@ -/*! (c) Andrea Giammarchi (ISC) */var hyperHTML=function(e){"use strict";function t(){return this}function n(e){return e.join(ne).replace(ve,o).replace(he,r)}function r(e,t,n,r){return"<"+t+n.replace(pe,i)+r}function i(e,t,n){return t+(n||'"')+te+(n||'"')}function o(e,t,n){return ce.test(t)?e:"<"+t+n+">"}function a(e,t,n){return{type:e,name:n,node:t,path:u(t)}}function u(e){var t,n=[];switch(e.nodeType){case oe:case ie:t=e;break;case re:t=e.parentNode,f(n,t,e);break;default:t=e.ownerElement}for(;t=(e=t).parentNode;)f(n,t,e);return n}function c(e,t){for(var n=t.length,r=0;r=u;){for(var c=t,l=i;ca;)--c;l=u+r-c;var m=Array(l),b=s[c];for(--n;b;){for(var w=b,y=w.newi,N=w.oldi;n>y;)m[--l]=1,--n;for(;a>N;)m[--l]=-1,--a;m[--l]=0,--n,--a,b=b.prev}for(;n>=t;)m[--l]=1,--n;for(;a>=o;)m[--l]=-1,--a;return m},W=function(e,t,n,r,i,o,a){var u=n+o,c=[],l=void 0,s=void 0,f=void 0,d=void 0,h=void 0,v=void 0,p=void 0;e:for(l=0;l<=u;l++){if(l>50)return null;for(p=l-1,h=l?c[l-1]:[0,0],v=c[l]=[],s=-l;s<=l;s+=2){for(d=s===-l||s!==l&&h[p+s-1]=0;l--){for(;d>0&&f>0&&a(r[i+d-1],e[t+f-1]);)g[m--]=0,d--,f--;if(!l)break;p=l-1,h=l?c[l-1]:[0,0],s=d-f,s===-l||s!==l&&h[p+s-1]>>0;n",t(r,o.firstChild.childNodes),r}var i="fragment",o="content"in n("template"),a=o?function(e){var t=n("template");return t.innerHTML=e,t.content}:function(e){var r=n(i),o=n("template"),a=null;if(/^[^\S]*?<(col(?:group)?|t(?:head|body|foot|r|d|h))/i.test(e)){var u=RegExp.$1;o.innerHTML=""+e+"
",a=o.querySelectorAll(u)}else o.innerHTML=e,a=o.childNodes;return t(r,a),r};return function(e,t){return("svg"===t?r:a)(e)}}(e),X=function(e){function t(e,t){for(var n=t.length;n--;)e.appendChild(t[0])}function n(t){return t===i?e.createDocumentFragment():e.createElementNS("http://www.w3.org/1999/xhtml",t)}function r(e){var r=n(i),o=n("div");return o.innerHTML=''+e+"",t(r,o.firstChild.childNodes),r}var i="fragment",o="content"in n("template"),a=o?function(e){var t=n("template");return t.innerHTML=e,t.content}:function(e){var r=n(i),o=n("template"),a=null;if(/^[^\S]*?<(col(?:group)?|t(?:head|body|foot|r|d|h))/i.test(e)){var u=RegExp.$1;o.innerHTML=""+e+"
",a=o.querySelectorAll(u)}else o.innerHTML=e,a=o.childNodes;return t(r,a),r};return function(e,t){return("svg"===t?r:a)(e)}}(e),Y=function(e,t,n,r,i){var o="importNode"in e,a=e.createDocumentFragment();return a.appendChild(e.createTextNode("g")),a.appendChild(e.createTextNode("")),(o?e.importNode(a,!0):a.cloneNode(!0)).childNodes.length<2?function u(e,t){for(var n=e.cloneNode(),r=e.childNodes||[],i=r.length,o=0;t&&o

',e.content.childNodes[0].getAttribute("tabindex")==te)})(e.createElement("template"))||(te="_dt: "+te.slice(1,-1)+";");var ne="\x3c!--"+te+"--\x3e",re=8,ie=11,oe=1,ae=3,ue=/^(?:style|textarea)$/i,ce=/^(?:area|base|br|col|embed|hr|img|input|keygen|link|menuitem|meta|param|source|track|wbr)$/i,le=" \\f\\n\\r\\t",se="[ "+le+"]+[^ \\f\\n\\r\\t\\/>\"'=]+",fe="<([A-Za-z]+[A-Za-z0-9:_-]*)((?:",de="(?:\\s*=\\s*(?:'[^']*?'|\"[^\"]*?\"|<[^>]*?>|[^ \\f\\n\\r\\t\\/>\"'=]+))?)",he=new RegExp(fe+se+de+"+)([ "+le+"]*/?>)","g"),ve=new RegExp(fe+se+de+"*)([ "+le+"]*/>)","g"),pe=new RegExp("("+se+"\\s*=\\s*)(['\"]?)"+ne+"\\2","gi"),ge=new x,me=new x,be=function(){function e(e,t,n){return t+"-"+n.toLowerCase()}function t(e,t){var n;return t?n=t.cloneNode(!0):(e.setAttribute("style","--hyper:style;"),n=e.getAttributeNode("style")),n.value="",e.setAttributeNode(n),r(n,!0)}function n(t){var n,r=[];for(n in t)r.push(n.replace(o,e),":",t[n],";");return r.join("")}function r(e,t){var r,o;return function(a){var u,c,l,s;switch(typeof a){case"object":if(a){if("object"===r){if(!t&&o!==a)for(c in o)c in a||(e[c]="")}else t?e.value="":e.cssText="";u=t?{}:e;for(c in a)s=a[c],l="number"!=typeof s||i.test(c)?s:s+"px",!t&&/^--/.test(c)?u.setProperty(c,l):u[c]=l;r="object",t?e.value=n(o=u):o=a;break}default:o!=a&&(r="string",o=a,t?e.value=a||"":e.cssText=a||"")}}}var i=/acit|ex(?:s|g|n|p|$)|rph|ows|mnc|ntw|ine[ch]|zoo|^ord/i,o=/([^A-Z])([A-Z]+)/g;return function(e,n){return"ownerSVGElement"in e?t(e,n):r(e.style,!1)}}(),we=e.defaultView,ye="ownerSVGElement",Ne=function(){var t=!1,n=function(r){if(!("raw"in r)||r.propertyIsEnumerable("raw")||!Object.isFrozen(r.raw)||/Firefox\/(\d+)/.test((e.defaultView.navigator||{}).userAgent)&&parseFloat(RegExp.$1)<55){var i={};return(n=function(e){var t="raw"+e.join("raw");return i[t]||(i[t]=e)})(r)}return t=!0,r};return function(e){return t?e:n(e)}}(),xe=function(e){return e.ownerDocument||e},Ee=function(e){return xe(e).createDocumentFragment()},ke=function(e,t){return xe(e).createTextNode(t)},Ce="append"in Ee(e)?function(e,t){e.append.apply(e,t)}:function(e,t){for(var n=t.length,r=0;r"}function a(e,t,n,r){return{name:r,node:t,path:n,type:e}}function u(e,t){for(var n=t.length,r=0;r=u;){for(var c=t,l=i;ca;)--c;l=u+r-c;var g=Array(l),b=s[c];for(--n;b;){for(var y=b,w=y.newi,N=y.oldi;n>w;)g[--l]=1,--n;for(;a>N;)g[--l]=-1,--a;g[--l]=0,--n,--a,b=b.prev}for(;n>=t;)g[--l]=1,--n;for(;a>=o;)g[--l]=-1,--a;return g},L=function(e,t,n,r,i,o,a){var u,c,l,s,f,h,d,p=n+o,v=[];e:for(u=0;u<=p;u++){if(u>50)return null;for(d=u-1,f=u?v[u-1]:[0,0],h=v[u]=[],c=-u;c<=u;c+=2){for(s=c===-u||c!==u&&f[d+c-1]=0;u--){for(;s>0&&l>0&&a(r[i+s-1],e[t+l-1]);)m[g--]=0,s--,l--;if(!u)break;d=u-1,f=u?v[u-1]:[0,0],c=s-l,c===-u||c!==u&&f[d+c-1]>>0;n",t(r,o.firstChild.childNodes),r}var i="fragment",o="content"in n("template"),a=o?function(e){var t=n("template");return t.innerHTML=e,t.content}:function(e){var r=n(i),o=n("template"),a=null;if(/^[^\S]*?<(col(?:group)?|t(?:head|body|foot|r|d|h))/i.test(e)){var u=RegExp.$1;o.innerHTML=""+e+"
",a=o.querySelectorAll(u)}else o.innerHTML=e,a=o.childNodes;return t(r,a),r};return function(e,t){return("svg"===t?r:a)(e)}}(e),Q=function(e,t,n,r,i){var o="importNode"in e,a=e.createDocumentFragment();return a.appendChild(e.createTextNode("g")),a.appendChild(e.createTextNode("")),(o?e.importNode(a,!0):a.cloneNode(!0)).childNodes.length<2?function u(e,t){for(var n=e.cloneNode(),r=e.childNodes||[],i=r.length,o=0;t&&o

',e.content.childNodes[0].getAttribute("tabindex")==X)})(e.createElement("template"))||(X="_dt: "+X.slice(1,-1)+";");var Y="\x3c!--"+X+"--\x3e",ee=8,te=1,ne=3,re=/^(?:style|textarea)$/i,ie=/^(?:area|base|br|col|embed|hr|img|input|keygen|link|menuitem|meta|param|source|track|wbr)$/i,oe=" \\f\\n\\r\\t",ae="[ "+oe+"]+[^ \\f\\n\\r\\t\\/>\"'=]+",ue="<([A-Za-z]+[A-Za-z0-9:_-]*)((?:",ce="(?:\\s*=\\s*(?:'[^']*?'|\"[^\"]*?\"|<[^>]*?>|[^ \\f\\n\\r\\t\\/>\"'=]+))?)",le=new RegExp(ue+ae+ce+"+)([ "+oe+"]*/?>)","g"),se=new RegExp(ue+ae+ce+"*)([ "+oe+"]*/>)","g"),fe=new RegExp("("+ae+"\\s*=\\s*)(['\"]?)"+Y+"\\2","gi"),he=new w,de=new w,pe=function(){function e(e,t,n){return t+"-"+n.toLowerCase()}function t(e,t){var n;return t?n=t.cloneNode(!0):(e.setAttribute("style","--hyper:style;"),n=e.getAttributeNode("style")),n.value="",e.setAttributeNode(n),r(n,!0)}function n(t){var n,r=[];for(n in t)r.push(n.replace(o,e),":",t[n],";");return r.join("")}function r(e,t){var r,o;return function(a){var u,c,l,s;switch(typeof a){case"object":if(a){if("object"===r){if(!t&&o!==a)for(c in o)c in a||(e[c]="")}else t?e.value="":e.cssText="";u=t?{}:e;for(c in a)s=a[c],l="number"!=typeof s||i.test(c)?s:s+"px",!t&&/^--/.test(c)?u.setProperty(c,l):u[c]=l;r="object",t?e.value=n(o=u):o=a;break}default:o!=a&&(r="string",o=a,t?e.value=a||"":e.cssText=a||"")}}}var i=/acit|ex(?:s|g|n|p|$)|rph|ows|mnc|ntw|ine[ch]|zoo|^ord/i,o=/([^A-Z])([A-Z]+)/g;return function(e,n){return"ownerSVGElement"in e?t(e,n):r(e.style,!1)}}(),ve=function(e,t){function n(t){var n=this.childNodes=e.call(t,0);this.firstChild=n[0],this.lastChild=n[n.length-1],this.ownerDocument=n[0].ownerDocument,this._=null}return t=n.prototype,t.ELEMENT_NODE=1,t.nodeType=111,t.remove=function(e){var t=this.childNodes,n=this.firstChild,r=this.lastChild;if(this._=null,e&&2===t.length)r.parentNode.removeChild(r);else{var i=this.ownerDocument.createRange();i.setStartBefore(e?t[1]:n),i.setEndAfter(r),i.deleteContents()}return n},t.valueOf=function(e){var t=this._,n=null==t;if(n&&(t=this._=this.ownerDocument.createDocumentFragment()),n||e)for(var r=this.childNodes,i=0,o=r.length;i index.clean" + "sed '/var createContent$1 =/,/(document);/d' |", + "sed 's/createContent$1/createContent/' |", + "sed 's/({})/(document)/' |", + "sed -e 's/var isNoOp =.*/var isNoOp = false;/' > index.clean" ], "mv index.clean index.js" ] @@ -119,27 +121,16 @@ "url": "https://github.com/WebReflection/hyperhtml/issues" }, "devDependencies": { - "ascjs": "^2.4.0", - "babel-cli": "^6.26.0", - "babel-plugin-check-es2015-constants": "^6.22.0", - "babel-plugin-transform-es2015-arrow-functions": "^6.22.0", - "babel-plugin-transform-es2015-block-scoped-functions": "^6.22.0", - "babel-plugin-transform-es2015-block-scoping": "^6.26.0", - "babel-plugin-transform-es2015-classes": "^6.24.1", - "babel-plugin-transform-es2015-computed-properties": "^6.24.1", - "babel-plugin-transform-es2015-destructuring": "^6.23.0", - "babel-plugin-transform-es2015-duplicate-keys": "^6.24.1", - "babel-plugin-transform-es2015-function-name": "^6.24.1", - "babel-plugin-transform-es2015-literals": "^6.22.0", - "babel-plugin-transform-es2015-shorthand-properties": "^6.24.1", - "babel-plugin-transform-es2015-spread": "^6.22.0", - "babel-plugin-transform-es2015-template-literals": "^6.22.0", - "basichtml": "^0.20.2", + "@babel/core": "^7.2.2", + "@babel/preset-env": "^7.2.0", + "ascjs": "^3.0.0", + "basichtml": "^0.21.0", "coveralls": "^3.0.2", + "drop-babel-typeof": "^1.0.1", "istanbul": "^0.4.5", "npm-dollar": "^2.1.3", "rollup": "^0.68.0", - "rollup-plugin-babel": "^3.0.7", + "rollup-plugin-babel": "^4.1.0", "rollup-plugin-node-resolve": "^4.0.0", "tressa": "^0.3.1", "uglify-js": "^2.8.29" @@ -151,19 +142,19 @@ ] }, "dependencies": { - "@ungap/create-content": "^0.1.1", + "@ungap/create-content": "^0.1.4", "@ungap/custom-event": "^0.2.0", "@ungap/essential-map": "^0.1.7", "@ungap/essential-weakset": "^0.1.2", "@ungap/is-array": "^0.1.1", - "@ungap/template-literal": "^0.1.0", - "@ungap/trim": "^0.1.1", + "@ungap/template-tag-arguments": "^0.1.1", "@ungap/weakmap": "^0.1.4", "disconnected": "^0.1.6", - "domdiff": "^2.0.2", - "domtagger": "^0.1.6", + "domdiff": "^2.0.3", + "domtagger": "^0.2.3", "hyperhtml-style": "^0.1.2", - "lightercollective": "^0.1.0" + "hyperhtml-wire": "^2.1.0", + "lightercollective": "^0.2.0" }, "collective": { "type": "opencollective", diff --git a/rollup.config.js b/rollup.config.js index f38cce83..65f24dc2 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -1,15 +1,11 @@ -import babel from 'rollup-plugin-babel'; import resolve from 'rollup-plugin-node-resolve'; +import babel from 'rollup-plugin-babel'; export default { input: 'esm/index.js', plugins: [ - resolve({ - module: true - }), - babel({ - plugins: require('./babel-plugins.json') - }) + resolve({module: true}), + babel({presets: ["@babel/preset-env"]}) ], context: 'null', moduleContext: 'null', diff --git a/rollup.ie.js b/rollup.ie.js new file mode 100644 index 00000000..3f1c1a3f --- /dev/null +++ b/rollup.ie.js @@ -0,0 +1,16 @@ +import resolve from 'rollup-plugin-node-resolve'; +import babel from 'rollup-plugin-babel'; + +export default { + input: 'test/test.js', + plugins: [ + resolve({module: true}), + babel({presets: ["@babel/preset-env"]}) + ], + context: 'null', + moduleContext: 'null', + output: { + file: 'test/ie/test/test.js', + format: 'iife' + } +}; diff --git a/test/ie/index.html b/test/ie/index.html index de4c8248..ee2f0823 100644 --- a/test/ie/index.html +++ b/test/ie/index.html @@ -9,7 +9,9 @@ h1 { font-size: 1.2em; } - + - +

results in console

diff --git a/test/ie/test/test.js b/test/ie/test/test.js index a65db291..82691c58 100644 --- a/test/ie/test/test.js +++ b/test/ie/test/test.js @@ -1,1482 +1,3019 @@ -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -var _templateObject = _taggedTemplateLiteral(['\n

\n Time: ', '\n

\n '], ['\n

\n Time: ', '\n

\n ']), - _templateObject2 = _taggedTemplateLiteral(['

', ' world

'], ['

', ' world

']), - _templateObject3 = _taggedTemplateLiteral(['

', '

'], ['

', '

']), - _templateObject4 = _taggedTemplateLiteral(['click'], ['click']), - _templateObject5 = _taggedTemplateLiteral(['how cool'], ['how cool']), - _templateObject6 = _taggedTemplateLiteral(['\n

1

\n

2

\n '], ['\n

1

\n

2

\n ']), - _templateObject7 = _taggedTemplateLiteral(['\n

1

\n

2

\n

3

\n '], ['\n

1

\n

2

\n

3

\n ']), - _templateObject8 = _taggedTemplateLiteral(['

OK

'], ['

OK

']), - _templateObject9 = _taggedTemplateLiteral(['\n

1

\n '], ['\n

1

\n ']), - _templateObject10 = _taggedTemplateLiteral(['\n 0\n

1

\n '], ['\n 0\n

1

\n ']), - _templateObject11 = _taggedTemplateLiteral(['', ''], ['', '']), - _templateObject12 = _taggedTemplateLiteral(['a'], ['a']), - _templateObject13 = _taggedTemplateLiteral(['\n O'], ['\n O']), - _templateObject14 = _taggedTemplateLiteral(['\n
\n
    ', '
\n
'], ['\n
\n
    ', '
\n
']), - _templateObject15 = _taggedTemplateLiteral(['\n
  • ', '
  • \n '], ['\n
  • ', '
  • \n ']), - _templateObject16 = _taggedTemplateLiteral(['
    ', '
    '], ['
    ', '
    ']), - _templateObject17 = _taggedTemplateLiteral([''], ['']), - _templateObject18 = _taggedTemplateLiteral(['

    '], ['

    ']), - _templateObject19 = _taggedTemplateLiteral(['

    ', '

    ', '
    ', '
    ', ''], ['

    ', '

    ', '
    ', '
    ', '']), - _templateObject20 = _taggedTemplateLiteral([''], ['']), - _templateObject21 = _taggedTemplateLiteral(['
    ', ''], ['
    ', '']), - _templateObject22 = _taggedTemplateLiteral(['', '
    '], ['', '
    ']), - _templateObject23 = _taggedTemplateLiteral([''], ['']), - _templateObject24 = _taggedTemplateLiteral(['a=', ''], ['a=', '']), - _templateObject25 = _taggedTemplateLiteral(['[', ']'], ['[', ']']), - _templateObject26 = _taggedTemplateLiteral(['

    '], ['

    ']), - _templateObject27 = _taggedTemplateLiteral(['
    ', '
    '], ['
    ', '
    ']), - _templateObject28 = _taggedTemplateLiteral([''], ['']), - _templateObject29 = _taggedTemplateLiteral([''], ['']), - _templateObject30 = _taggedTemplateLiteral([''], ['']), - _templateObject31 = _taggedTemplateLiteral(['ok'], ['ok']), - _templateObject32 = _taggedTemplateLiteral(['
    ', '
    '], ['
    ', '
    ']), - _templateObject33 = _taggedTemplateLiteral([''], ['']), - _templateObject34 = _taggedTemplateLiteral(['

    '], ['

    ']), - _templateObject35 = _taggedTemplateLiteral(['

    ', '

    '], ['

    ', '

    ']), - _templateObject36 = _taggedTemplateLiteral([''], ['']), - _templateObject37 = _taggedTemplateLiteral(['

    '], ['

    ']), - _templateObject38 = _taggedTemplateLiteral([''], ['']), - _templateObject39 = _taggedTemplateLiteral([''], ['']), - _templateObject40 = _taggedTemplateLiteral(['\n '], ['\n ']), - _templateObject41 = _taggedTemplateLiteral(['\n
    First name: ', '
    \n

    '], ['\n
    First name: ', '
    \n

    ']), - _templateObject42 = _taggedTemplateLiteral(['\n

    ', ''], ['\n

    ', '']), - _templateObject43 = _taggedTemplateLiteral(['\n

    ', ''], ['\n

    ', '']), - _templateObject44 = _taggedTemplateLiteral([''], ['']), - _templateObject45 = _taggedTemplateLiteral(['

    '], ['

    ']), - _templateObject46 = _taggedTemplateLiteral(['

    '], ['

    ']), - _templateObject47 = _taggedTemplateLiteral(['a ', ''], ['a ', '']), - _templateObject48 = _taggedTemplateLiteral(['

    any content

    '], ['

    any content

    ']), - _templateObject49 = _taggedTemplateLiteral([''], ['']), - _templateObject50 = _taggedTemplateLiteral(['abc'], ['abc']), - _templateObject51 = _taggedTemplateLiteral(['

    a', 'c

    '], ['

    a', 'c

    ']), - _templateObject52 = _taggedTemplateLiteral(['a', 'c'], ['a', 'c']), - _templateObject53 = _taggedTemplateLiteral([''], ['']), - _templateObject54 = _taggedTemplateLiteral(['
    abc
    '], ['
    abc
    ']), - _templateObject55 = _taggedTemplateLiteral(['\n '], ['\n ']), - _templateObject56 = _taggedTemplateLiteral(['\n '], ['\n ']), - _templateObject57 = _taggedTemplateLiteral(['\n

    hello

    '], ['\n

    hello

    ']), - _templateObject58 = _taggedTemplateLiteral(['\n

    hello

    '], ['\n

    hello

    ']), - _templateObject59 = _taggedTemplateLiteral(['
    \n \n
    '], ['
    \n \n
    ']), - _templateObject60 = _taggedTemplateLiteral(['
      \n ', '\n
    '], ['
      \n ', '\n
    ']), - _templateObject61 = _taggedTemplateLiteral(['
  • ', '
  • '], ['
  • ', '
  • ']), - _templateObject62 = _taggedTemplateLiteral(['\n

    hello

    '], ['\n

    hello

    ']), - _templateObject63 = _taggedTemplateLiteral(['

    '], ['

    ']), - _templateObject64 = _taggedTemplateLiteral(['
    '], ['
    ']), - _templateObject65 = _taggedTemplateLiteral(['
    \n \n
    '], ['
    \n \n
    ']), - _templateObject66 = _taggedTemplateLiteral(['\n
    \n \n \n \n \n
    \n '], ['\n
    \n \n \n \n \n
    \n ']), - _templateObject67 = _taggedTemplateLiteral(['\n
    \n