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+">"+t+">"}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\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(['\n1
\n2
\n '], ['\n1
\n2
\n ']), - _templateObject7 = _taggedTemplateLiteral(['\n1
\n2
\n3
\n '], ['\n1
\n2
\n3
\n ']), - _templateObject8 = _taggedTemplateLiteral(['OK
'], ['OK
']), - _templateObject9 = _taggedTemplateLiteral(['\n1
\n '], ['\n1
\n ']), - _templateObject10 = _taggedTemplateLiteral(['\n 0\n1
\n '], ['\n 0\n1
\n ']), - _templateObject11 = _taggedTemplateLiteral(['', ''], ['', '']), - _templateObject12 = _taggedTemplateLiteral(['a'], ['a']), - _templateObject13 = _taggedTemplateLiteral(['\n O'], ['\n O']), - _templateObject14 = _taggedTemplateLiteral(['\n', '
', '', '
', '', '
'], ['', '
']), - _templateObject36 = _taggedTemplateLiteral([''], ['']), - _templateObject37 = _taggedTemplateLiteral([''], ['']), - _templateObject38 = _taggedTemplateLiteral([''], ['']), - _templateObject39 = _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(['hello
'], ['\nhello
']), - _templateObject58 = _taggedTemplateLiteral(['\nhello
'], ['\nhello
']), - _templateObject59 = _taggedTemplateLiteral(['hello
'], ['\nhello
']), - _templateObject63 = _taggedTemplateLiteral([''], ['']), - _templateObject64 = _taggedTemplateLiteral(['I\'m grand child
'], ['\nI\'m grand child
']), - _templateObject72 = _taggedTemplateLiteral(['\na
b
'], ['a
b
']), - _templateObject77 = _taggedTemplateLiteral(['c
'], ['c
']), - _templateObject78 = _taggedTemplateLiteral(['', ' - ', ''], ['', ' - ', '']), - _templateObject79 = _taggedTemplateLiteral([''], ['']), - _templateObject80 = _taggedTemplateLiteral([''], ['']), - _templateObject81 = _taggedTemplateLiteral([''], ['']), - _templateObject82 = _taggedTemplateLiteral(['\s*Time: \d+\.\d+<[^>]+?>\s*<\/p>\s*$/i.test(html)
- );
- }
- var html = update(i++).innerHTML;
- var p = div.querySelector('p');
- var attr = p.attributes[0];
- tressa.assert(compare(html), 'correct HTML');
- tressa.assert(html === div.innerHTML, 'correctly returned');
- setTimeout(function () {
- tressa.log('## updating same nodes');
- var html = update(i++).innerHTML;
- tressa.assert(compare(html), 'correct HTML update');
- tressa.assert(html === div.innerHTML, 'update applied');
- tressa.assert(p === div.querySelector('p'), 'no node was changed');
- tressa.assert(attr === p.attributes[0], 'no attribute was changed');
- done();
- });
-}).then(function () {
- return tressa.async(function (done) {
- tressa.log('## perf: same virtual text twice');
- var div = document.body.appendChild(document.createElement('div'));
- var render = hyperHTML.bind(div);
- var html = (update('hello').innerHTML, update('hello').innerHTML);
- function update(text) {
- return render(_templateObject2, text);
+(function () {
+ 'use strict';
+
+ function _classCallCheck(instance, Constructor) {
+ if (!(instance instanceof Constructor)) {
+ throw new TypeError("Cannot call a class as a function");
}
- tressa.assert(update('hello').innerHTML === update('hello').innerHTML, 'same text');
- done(div);
- });
-}).then(function () {
- return tressa.async(function (done) {
- tressa.log('## injecting HTML');
+ }
+
+ 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);
+ }
+ }
+
+ function _createClass(Constructor, protoProps, staticProps) {
+ if (protoProps) _defineProperties(Constructor.prototype, protoProps);
+ if (staticProps) _defineProperties(Constructor, staticProps);
+ return Constructor;
+ }
+
+ function _inherits(subClass, superClass) {
+ if (typeof superClass !== "function" && superClass !== null) {
+ throw new TypeError("Super expression must either be null or a function");
+ }
+
+ subClass.prototype = Object.create(superClass && superClass.prototype, {
+ constructor: {
+ value: subClass,
+ writable: true,
+ configurable: true
+ }
+ });
+ if (superClass) _setPrototypeOf(subClass, superClass);
+ }
+
+ function _getPrototypeOf(o) {
+ _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
+ return o.__proto__ || Object.getPrototypeOf(o);
+ };
+ return _getPrototypeOf(o);
+ }
+
+ function _setPrototypeOf(o, p) {
+ _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
+ o.__proto__ = p;
+ return o;
+ };
+
+ return _setPrototypeOf(o, p);
+ }
+
+ function _assertThisInitialized(self) {
+ if (self === void 0) {
+ throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
+ }
+
+ return self;
+ }
+
+ function _possibleConstructorReturn(self, call) {
+ if (call && (typeof call === "object" || typeof call === "function")) {
+ return call;
+ }
+
+ return _assertThisInitialized(self);
+ }
+
+ function _taggedTemplateLiteral(strings, raw) {
+ if (!raw) {
+ raw = strings.slice(0);
+ }
+
+ return Object.freeze(Object.defineProperties(strings, {
+ raw: {
+ value: Object.freeze(raw)
+ }
+ }));
+ }
+
+ function _templateObject130() {
+ var data = _taggedTemplateLiteral(["
c
"]); + + _templateObject124 = function _templateObject124() { + return data; + }; + + return data; + } + + function _templateObject123() { + var data = _taggedTemplateLiteral(["a
b
"]); + + _templateObject123 = function _templateObject123() { + return data; + }; + + return data; + } + + function _templateObject122() { + var data = _taggedTemplateLiteral(["", ""]); + + _templateObject122 = function _templateObject122() { + return data; + }; + + return data; + } + + function _templateObject121() { + var data = _taggedTemplateLiteral(["", ""]); + + _templateObject121 = function _templateObject121() { + return data; + }; + + return data; + } + + function _templateObject120() { + var data = _taggedTemplateLiteral(["\nI'm grand child
"]); + + _templateObject115 = function _templateObject115() { + return data; + }; + + return data; + } + + function _templateObject114() { + var data = _taggedTemplateLiteral(["\n "]); + + _templateObject114 = function _templateObject114() { + return data; + }; + + return data; + } + + function _templateObject113() { + var data = _taggedTemplateLiteral(["\n "]); + + _templateObject113 = function _templateObject113() { + return data; + }; + + return data; + } + + function _templateObject112() { + var data = _taggedTemplateLiteral(["\n "]); + + _templateObject112 = function _templateObject112() { + return data; + }; + + return data; + } + + function _templateObject111() { + var data = _taggedTemplateLiteral(["\n "]); + + _templateObject111 = function _templateObject111() { + return data; + }; + + return data; + } + + function _templateObject110() { + var data = _taggedTemplateLiteral(["\nhello
"]); + + _templateObject106 = function _templateObject106() { + return data; + }; + + return data; + } + + function _templateObject105() { + var data = _taggedTemplateLiteral(["hello
"]); + + _templateObject102 = function _templateObject102() { + return data; + }; + + return data; + } + + function _templateObject101() { + var data = _taggedTemplateLiteral(["", ""]); + + _templateObject101 = function _templateObject101() { + return data; + }; + + return data; + } + + function _templateObject100() { + var data = _taggedTemplateLiteral(["", ""]); + + _templateObject100 = function _templateObject100() { + return data; + }; + + return data; + } + + function _templateObject99() { + var data = _taggedTemplateLiteral(["", ""]); + + _templateObject99 = function _templateObject99() { + return data; + }; + + return data; + } + + function _templateObject98() { + var data = _taggedTemplateLiteral(["\nhello
"]); + + _templateObject98 = function _templateObject98() { + return data; + }; + + return data; + } + + function _templateObject97() { + var data = _taggedTemplateLiteral(["\na", "c
"]); + + _templateObject93 = function _templateObject93() { + return data; + }; + + return data; + } + + function _templateObject92() { + var data = _taggedTemplateLiteral(["abc"]); + + _templateObject92 = function _templateObject92() { + return data; + }; + + return data; + } + + function _templateObject91() { + var data = _taggedTemplateLiteral(["a", "c
"]); + + _templateObject91 = function _templateObject91() { + return data; + }; + + return data; + } + + function _templateObject90() { + var data = _taggedTemplateLiteral(["abc"]); + + _templateObject90 = function _templateObject90() { + return data; + }; + + return data; + } + + function _templateObject89() { + var data = _taggedTemplateLiteral(["a", "c"]); + + _templateObject89 = function _templateObject89() { + return data; + }; + + return data; + } + + function _templateObject88() { + var data = _taggedTemplateLiteral(["abc"]); + + _templateObject88 = function _templateObject88() { + return data; + }; + + return data; + } + + function _templateObject87() { + var data = _taggedTemplateLiteral(["a", "c
"]); + + _templateObject87 = function _templateObject87() { + return data; + }; + + return data; + } + + function _templateObject86() { + var data = _taggedTemplateLiteral(["abc"]); + + _templateObject86 = function _templateObject86() { + return data; + }; + + return data; + } + + function _templateObject85() { + var data = _taggedTemplateLiteral(["", "
"]); + + _templateObject85 = function _templateObject85() { + return data; + }; + + return data; + } + + function _templateObject84() { + var data = _taggedTemplateLiteral(["", "
"]); + + _templateObject84 = function _templateObject84() { + return data; + }; + + return data; + } + + function _templateObject83() { + var data = _taggedTemplateLiteral(["", "
"]); + + _templateObject83 = function _templateObject83() { + return data; + }; + + return data; + } + + function _templateObject82() { + var data = _taggedTemplateLiteral(["a=", ""]); + + _templateObject82 = function _templateObject82() { + return data; + }; + + return data; + } + + function _templateObject81() { + var data = _taggedTemplateLiteral(["", "
"]); + + _templateObject81 = function _templateObject81() { + return data; + }; + + return data; + } + + function _templateObject80() { + var data = _taggedTemplateLiteral([""]); + + _templateObject80 = function _templateObject80() { + return data; + }; + + return data; + } + + function _templateObject79() { + var data = _taggedTemplateLiteral(["any content
"]); + + _templateObject79 = function _templateObject79() { + return data; + }; + + return data; + } + + function _templateObject78() { + var data = _taggedTemplateLiteral(["a=", ""]); + + _templateObject78 = function _templateObject78() { + return data; + }; + + return data; + } + + function _templateObject77() { + var data = _taggedTemplateLiteral(["", "
"]); + + _templateObject77 = function _templateObject77() { + return data; + }; + + return data; + } + + function _templateObject76() { + var data = _taggedTemplateLiteral(["a=", ""]); + + _templateObject76 = function _templateObject76() { + return data; + }; + + return data; + } + + function _templateObject75() { + var data = _taggedTemplateLiteral(["a ", ""]); + + _templateObject75 = function _templateObject75() { + return data; + }; + + return data; + } + + function _templateObject74() { + var data = _taggedTemplateLiteral(["a ", ""]); + + _templateObject74 = function _templateObject74() { + return data; + }; + + return data; + } + + function _templateObject73() { + var data = _taggedTemplateLiteral(["a ", ""]); + + _templateObject73 = function _templateObject73() { + return data; + }; + + return data; + } + + function _templateObject72() { + var data = _taggedTemplateLiteral(["a ", ""]); + + _templateObject72 = function _templateObject72() { + return data; + }; + + return data; + } + + function _templateObject71() { + var data = _taggedTemplateLiteral(["a ", ""]); + + _templateObject71 = function _templateObject71() { + return data; + }; + + return data; + } + + function _templateObject70() { + var data = _taggedTemplateLiteral(["", "
"]); + + _templateObject70 = function _templateObject70() { + return data; + }; + + return data; + } + + function _templateObject69() { + var data = _taggedTemplateLiteral(["", "
"]); + + _templateObject69 = function _templateObject69() { + return data; + }; + + return data; + } + + function _templateObject68() { + var data = _taggedTemplateLiteral(["", "
"]); + + _templateObject68 = function _templateObject68() { + return data; + }; + + return data; + } + + function _templateObject67() { + var data = _taggedTemplateLiteral([""]); + + _templateObject67 = function _templateObject67() { + return data; + }; + + return data; + } + + function _templateObject66() { + var data = _taggedTemplateLiteral([""]); + + _templateObject66 = function _templateObject66() { + return data; + }; + + return data; + } + + function _templateObject65() { + var data = _taggedTemplateLiteral([""]); + + _templateObject65 = function _templateObject65() { + return data; + }; + + return data; + } + + function _templateObject64() { + var data = _taggedTemplateLiteral(["\n ", ""]); + + _templateObject64 = function _templateObject64() { + return data; + }; + + return data; + } + + function _templateObject63() { + var data = _taggedTemplateLiteral(["\n ", ""]); + + _templateObject63 = function _templateObject63() { + return data; + }; + + return data; + } + + function _templateObject62() { + var data = _taggedTemplateLiteral(["", ""]); + + _templateObject62 = function _templateObject62() { + return data; + }; + + return data; + } + + function _templateObject61() { + var data = _taggedTemplateLiteral(["\n", "
"]); + + _templateObject45 = function _templateObject45() { + return data; + }; + + return data; + } + + function _templateObject44() { + var data = _taggedTemplateLiteral([""]); + + _templateObject44 = function _templateObject44() { + return data; + }; + + return data; + } + + function _templateObject43() { + var data = _taggedTemplateLiteral([""]); + + _templateObject43 = function _templateObject43() { + return data; + }; + + return data; + } + + function _templateObject42() { + var data = _taggedTemplateLiteral(["", "
", "1
\n "]); + + _templateObject11 = function _templateObject11() { + return data; + }; + + return data; + } + + function _templateObject10() { + var data = _taggedTemplateLiteral(["\n1
\n "]); + + _templateObject10 = function _templateObject10() { + return data; + }; + + return data; + } + + function _templateObject9() { + var data = _taggedTemplateLiteral(["OK
"]); + + _templateObject9 = function _templateObject9() { + return data; + }; + + return data; + } + + function _templateObject8() { + var data = _taggedTemplateLiteral(["\n1
\n2
\n3
\n "]); + + _templateObject8 = function _templateObject8() { + return data; + }; + + return data; + } + + function _templateObject7() { + var data = _taggedTemplateLiteral(["\n1
\n2
\n "]); + + _templateObject7 = function _templateObject7() { + return data; + }; + + return data; + } + + function _templateObject6() { + var data = _taggedTemplateLiteral(["how cool"]); + + _templateObject6 = function _templateObject6() { + return data; + }; + + return data; + } + + function _templateObject5() { + var data = _taggedTemplateLiteral(["", "
"]); + + _templateObject5 = function _templateObject5() { + return data; + }; + + return data; + } + + function _templateObject4() { + var data = _taggedTemplateLiteral(["click"]); + + _templateObject4 = function _templateObject4() { + return data; + }; + + return data; + } + + function _templateObject3() { + var data = _taggedTemplateLiteral(["", "
"]); + + _templateObject3 = function _templateObject3() { + return data; + }; + + return data; + } + + function _templateObject2() { + var data = _taggedTemplateLiteral(["", " world
"]); + + _templateObject2 = function _templateObject2() { + return data; + }; + + return data; + } + + function _templateObject() { + var data = _taggedTemplateLiteral(["\n\n Time: ", "\n
\n "]); + + _templateObject = function _templateObject() { + return data; + }; + + return data; + } + + tressa.title('HyperHTML'); + tressa.assert(typeof hyperHTML === 'function', 'hyperHTML is a function'); + + try { + tressa.log(''); + } catch (e) { + tressa.log = console.log.bind(console); + } + + tressa.async(function (done) { + tressa.log('## injecting text and attributes'); + var i = 0; var div = document.body.appendChild(document.createElement('div')); var render = hyperHTML.bind(div); - var html = update('hello').innerHTML; - function update(text) { - return render(_templateObject3, ['' + text + '']); + + function update(i) { + return render(_templateObject(), i, // IE Edge mobile did something funny here + // as template string returned xxx.xxxx + // but as innerHTML returned xxx.xx + (Math.random() * new Date()).toFixed(2)); } + function compare(html) { - return (/^\w+<\/strong><\/p>$/i.test(html)
- );
+ return /^\s* \s*Time: \d+\.\d+<[^>]+?>\s*<\/p>\s*$/i.test(html);
}
- tressa.assert(compare(html), 'HTML injected');
- tressa.assert(html === div.innerHTML, 'HTML returned');
- done(div);
- });
-}).then(function (div) {
- return tressa.async(function (done) {
- tressa.log('## function attributes');
- var render = hyperHTML.bind(div);
- var times = 0;
- update(function (e) {
- console.log(e.type);
- if (++times > 1) {
- return tressa.assert(false, 'events are broken');
+
+ var html = update(i++).innerHTML;
+ var p = div.querySelector('p');
+ var attr = p.attributes[0];
+ tressa.assert(compare(html), 'correct HTML');
+ tressa.assert(html === div.innerHTML, 'correctly returned');
+ setTimeout(function () {
+ tressa.log('## updating same nodes');
+ var html = update(i++).innerHTML;
+ tressa.assert(compare(html), 'correct HTML update');
+ tressa.assert(html === div.innerHTML, 'update applied');
+ tressa.assert(p === div.querySelector('p'), 'no node was changed');
+ tressa.assert(attr === p.attributes[0], 'no attribute was changed');
+ done();
+ });
+ }).then(function () {
+ return tressa.async(function (done) {
+ tressa.log('## perf: same virtual text twice');
+ var div = document.body.appendChild(document.createElement('div'));
+ var render = hyperHTML.bind(div);
+ var html = (update('hello').innerHTML, update('hello').innerHTML);
+
+ function update(text) {
+ return render(_templateObject2(), text);
+ }
+
+ tressa.assert(update('hello').innerHTML === update('hello').innerHTML, 'same text');
+ done(div);
+ });
+ }).then(function () {
+ return tressa.async(function (done) {
+ tressa.log('## injecting HTML');
+ var div = document.body.appendChild(document.createElement('div'));
+ var render = hyperHTML.bind(div);
+ var html = update('hello').innerHTML;
+
+ function update(text) {
+ return render(_templateObject3(), ['' + text + '']);
+ }
+
+ function compare(html) {
+ return /^ \w+<\/strong><\/p>$/i.test(html);
}
- if (e) {
- e.preventDefault();
- e.stopPropagation();
+
+ tressa.assert(compare(html), 'HTML injected');
+ tressa.assert(html === div.innerHTML, 'HTML returned');
+ done(div);
+ });
+ }).then(function (div) {
+ return tressa.async(function (done) {
+ tressa.log('## function attributes');
+ var render = hyperHTML.bind(div);
+ var times = 0;
+ update(function (e) {
+ console.log(e.type);
+
+ if (++times > 1) {
+ return tressa.assert(false, 'events are broken');
+ }
+
+ if (e) {
+ e.preventDefault();
+ e.stopPropagation();
+ }
+
+ tressa.assert(true, 'onclick invoked');
+ tressa.assert(!a.hasAttribute('onclick'), 'no attribute');
+ update(null);
+ e = document.createEvent('Event');
+ e.initEvent('click', false, false);
+ a.dispatchEvent(e);
+ done(div);
+ });
+
+ function update(click) {
+ // also test case-insensitive builtin events
+ return render(_templateObject4(), click);
}
- tressa.assert(true, 'onclick invoked');
- tressa.assert(!a.hasAttribute('onclick'), 'no attribute');
- update(null);
- e = document.createEvent('Event');
+
+ var a = div.querySelector('a');
+ var e = document.createEvent('Event');
e.initEvent('click', false, false);
a.dispatchEvent(e);
- done(div);
});
- function update(click) {
- // also test case-insensitive builtin events
- return render(_templateObject4, click);
- }
- var a = div.querySelector('a');
- var e = document.createEvent('Event');
- e.initEvent('click', false, false);
- a.dispatchEvent(e);
- });
-}).then(function (div) {
- return tressa.async(function (done) {
- tressa.log('## changing template');
- var render = hyperHTML.bind(div);
- var html = update('hello').innerHTML;
- function update(text) {
- return render(_templateObject3, { any: ['' + text + ''] });
- }
- function compare(html) {
- return (/^ \w+<\/em><\/p>$/i.test(html)
- );
- }
- tressa.assert(compare(html), 'new HTML injected');
- tressa.assert(html === div.innerHTML, 'new HTML returned');
- done(div);
- });
-}).then(function () {
- return tressa.async(function (done) {
- tressa.log('## custom events');
- var render = hyperHTML.bind(document.createElement('p'));
- var e = document.createEvent('Event');
- e.initEvent('Custom-EVENT', true, true);
- render(_templateObject5, function (e) {
- tressa.assert(e.type === 'Custom-EVENT', 'event triggered');
- done();
- }).firstElementChild.dispatchEvent(e);
- });
-}).then(function () {
- tressa.log('## multi wire removal');
- var render = hyperHTML.wire();
- var update = function update() {
- return render(_templateObject6);
- };
- update().remove();
- update = function update() {
- return render(_templateObject7);
- };
- update().remove();
- tressa.assert(true, 'OK');
-}).then(function () {
- tressa.log('## the attribute id');
- var div = document.createElement('div');
- hyperHTML.bind(div)(_templateObject8, 'id');
- tressa.assert(div.firstChild.id === 'id', 'the id is preserved');
- tressa.assert(div.firstChild.className === 'class', 'the class is preserved');
-}).then(function () {
- return tressa.async(function (done) {
- tressa.log('## hyperHTML.wire()');
+ }).then(function (div) {
+ return tressa.async(function (done) {
+ tressa.log('## changing template');
+ var render = hyperHTML.bind(div);
+ var html = update('hello').innerHTML;
+
+ function update(text) {
+ return render(_templateObject5(), {
+ any: ['' + text + '']
+ });
+ }
+
+ function compare(html) {
+ return /^ \w+<\/em><\/p>$/i.test(html);
+ }
+ tressa.assert(compare(html), 'new HTML injected');
+ tressa.assert(html === div.innerHTML, 'new HTML returned');
+ done(div);
+ });
+ }).then(function () {
+ return tressa.async(function (done) {
+ tressa.log('## custom events');
+ var render = hyperHTML.bind(document.createElement('p'));
+ var e = document.createEvent('Event');
+ e.initEvent('Custom-EVENT', true, true);
+ render(_templateObject6(), function (e) {
+ tressa.assert(e.type === 'Custom-EVENT', 'event triggered');
+ done();
+ }).firstElementChild.dispatchEvent(e);
+ });
+ }).then(function () {
+ tressa.log('## multi wire removal');
var render = hyperHTML.wire();
+
var update = function update() {
- return render(_templateObject9);
+ return render(_templateObject7());
};
- var node = update();
- tressa.assert(node.nodeName.toLowerCase() === 'p', 'correct node');
- var same = update();
- tressa.assert(node === same, 'same node returned');
- render = hyperHTML.wire(null);
+ update().remove();
+
update = function update() {
- return render(_templateObject10);
+ return render(_templateObject8());
};
- node = update().childNodes;
- tressa.assert(Array.isArray(node), 'list of nodes');
- same = update().childNodes;
- tressa.assert(node.length === same.length && node[0] && node.every(function (n, i) {
- return same[i] === n;
- }), 'same list returned');
+ update().remove();
+ tressa.assert(true, 'OK');
+ }).then(function () {
+ tressa.log('## the attribute id');
var div = document.createElement('div');
- render = hyperHTML.bind(div);
- render(_templateObject11, node);
- same = div.childNodes;
- tressa.assert(node[0] && node.every(function (n, i) {
- return same[i] === n;
- }), 'same list applied');
-
- function returnSame() {
- return render(_templateObject12);
- }
- render = hyperHTML.wire();
- tressa.assert(returnSame() === returnSame(), 'template sensible wire');
-
- done();
- });
-}).then(function () {
- return tressa.async(function (done) {
- tressa.log('## hyperHTML.wire(object)');
- var point = { x: 1, y: 2 };
- function update() {
- return hyperHTML.wire(point)(_templateObject13, '\n position: absolute;\n left: ' + point.x + 'px;\n top: ' + point.y + 'px;\n ');
- }
- try {
- update();
- } catch (e) {
- console.error(e);
- }
- tressa.assert(update() === update(), 'same output');
- tressa.assert(hyperHTML.wire(point) === hyperHTML.wire(point), 'same wire');
- done();
- });
-}).then(function () {
- if (typeof MutationObserver === 'undefined') return;
- return tressa.async(function (done) {
- tressa.log('## preserve first child where first child is the same as incoming');
- var div = document.body.appendChild(document.createElement('div'));
- var render = hyperHTML.bind(div);
- var observer = new MutationObserver(function (mutations) {
- for (var i = 0, len = mutations.length; i < len; i++) {
- trackMutations(mutations[i].addedNodes, 'added');
- trackMutations(mutations[i].removedNodes, 'removed');
+ hyperHTML.bind(div)(_templateObject9(), 'id');
+ tressa.assert(div.firstChild.id === 'id', 'the id is preserved');
+ tressa.assert(div.firstChild.className === 'class', 'the class is preserved');
+ }).then(function () {
+ return tressa.async(function (done) {
+ tressa.log('## hyperHTML.wire()');
+ var render = hyperHTML.wire();
+
+ var update = function update() {
+ return render(_templateObject10());
+ };
+
+ var node = update();
+ tressa.assert(node.nodeName.toLowerCase() === 'p', 'correct node');
+ var same = update();
+ tressa.assert(node === same, 'same node returned');
+ render = hyperHTML.wire(null);
+
+ update = function update() {
+ return render(_templateObject11());
+ };
+
+ node = update().childNodes;
+ tressa.assert(Array.isArray(node), 'list of nodes');
+ same = update().childNodes;
+ tressa.assert(node.length === same.length && node[0] && node.every(function (n, i) {
+ return same[i] === n;
+ }), 'same list returned');
+ var div = document.createElement('div');
+ render = hyperHTML.bind(div);
+ render(_templateObject12(), node);
+ same = div.childNodes;
+ tressa.assert(node[0] && node.every(function (n, i) {
+ return same[i] === n;
+ }), 'same list applied');
+
+ function returnSame() {
+ return render(_templateObject13());
}
- });
- observer.observe(div, {
- childList: true,
- subtree: true
+ render = hyperHTML.wire();
+ tressa.assert(returnSame() === returnSame(), 'template sensible wire');
+ done();
});
+ }).then(function () {
+ return tressa.async(function (done) {
+ tressa.log('## hyperHTML.wire(object)');
+ var point = {
+ x: 1,
+ y: 2
+ };
+
+ function update() {
+ return hyperHTML.wire(point)(_templateObject14(), "\n position: absolute;\n left: ".concat(point.x, "px;\n top: ").concat(point.y, "px;\n "));
+ }
- var counters = [];
+ try {
+ update();
+ } catch (e) {
+ console.error(e);
+ }
- function trackMutations(nodes, countKey) {
- for (var i = 0, len = nodes.length, counter, key; i < len; i++) {
- if (nodes[i] && nodes[i].getAttribute && nodes[i].getAttribute('data-test')) {
- key = nodes[i].getAttribute('data-test');
- counter = counters[key] || (counters[key] = { added: 0, removed: 0 });
- counter[countKey]++;
+ tressa.assert(update() === update(), 'same output');
+ tressa.assert(hyperHTML.wire(point) === hyperHTML.wire(point), 'same wire');
+ done();
+ });
+ }).then(function () {
+ if (typeof MutationObserver === 'undefined') return;
+ return tressa.async(function (done) {
+ tressa.log('## preserve first child where first child is the same as incoming');
+ var div = document.body.appendChild(document.createElement('div'));
+ var render = hyperHTML.bind(div);
+ var observer = new MutationObserver(function (mutations) {
+ for (var i = 0, len = mutations.length; i < len; i++) {
+ trackMutations(mutations[i].addedNodes, 'added');
+ trackMutations(mutations[i].removedNodes, 'removed');
}
- if (nodes[i].childNodes.length > 0) {
- trackMutations(nodes[i].childNodes, countKey);
+ });
+ observer.observe(div, {
+ childList: true,
+ subtree: true
+ });
+ var counters = [];
+
+ function trackMutations(nodes, countKey) {
+ for (var i = 0, len = nodes.length, counter, key; i < len; i++) {
+ if (nodes[i] && nodes[i].getAttribute && nodes[i].getAttribute('data-test')) {
+ key = nodes[i].getAttribute('data-test');
+ counter = counters[key] || (counters[key] = {
+ added: 0,
+ removed: 0
+ });
+ counter[countKey]++;
+ }
+
+ if (nodes[i].childNodes.length > 0) {
+ trackMutations(nodes[i].childNodes, countKey);
+ }
}
}
- }
- var listItems = [];
+ var listItems = [];
- function update(items) {
- render(_templateObject14, items.map(function (item, i) {
- return hyperHTML.wire(listItems[i] || (listItems[i] = {}))(_templateObject15, i, function () {
- return item.text;
- });
- }));
- }
+ function update(items) {
+ render(_templateObject15(), items.map(function (item, i) {
+ return hyperHTML.wire(listItems[i] || (listItems[i] = {}))(_templateObject16(), i, function () {
+ return item.text;
+ });
+ }));
+ }
- update([]);
+ update([]);
+ setTimeout(function () {
+ update([{
+ text: 'test1'
+ }]);
+ }, 10);
+ setTimeout(function () {
+ update([{
+ text: 'test1'
+ }, {
+ text: 'test2'
+ }]);
+ }, 20);
+ setTimeout(function () {
+ update([{
+ text: 'test1'
+ }]);
+ }, 30);
+ setTimeout(function () {
+ if (counters.length) {
+ tressa.assert(counters[0].added === 1, 'first item added only once');
+ tressa.assert(counters[0].removed === 0, 'first item never removed');
+ }
- setTimeout(function () {
- update([{ text: 'test1' }]);
- }, 10);
- setTimeout(function () {
- update([{ text: 'test1' }, { text: 'test2' }]);
- }, 20);
- setTimeout(function () {
- update([{ text: 'test1' }]);
- }, 30);
- setTimeout(function () {
- if (counters.length) {
- tressa.assert(counters[0].added === 1, 'first item added only once');
- tressa.assert(counters[0].removed === 0, 'first item never removed');
+ done();
+ }, 100);
+ });
+ }).then(function () {
+ tressa.log('## rendering one node');
+ var div = document.createElement('div');
+ var br = document.createElement('br');
+ var hr = document.createElement('hr');
+ hyperHTML.bind(div)(_templateObject17(), br);
+ tressa.assert(div.firstChild.firstChild === br, 'one child is added');
+ hyperHTML.bind(div)(_templateObject18(), hr);
+ tressa.assert(div.firstChild.firstChild === hr, 'one child is changed');
+ hyperHTML.bind(div)(_templateObject19(), [hr, br]);
+ tressa.assert(div.firstChild.childNodes[0] === hr && div.firstChild.childNodes[1] === br, 'more children are added');
+ hyperHTML.bind(div)(_templateObject20(), [br, hr]);
+ tressa.assert(div.firstChild.childNodes[0] === br && div.firstChild.childNodes[1] === hr, 'children can be swapped');
+ hyperHTML.bind(div)(_templateObject21(), br);
+ tressa.assert(div.firstChild.firstChild === br, 'one child is kept');
+ hyperHTML.bind(div)(_templateObject22(), []);
+ tressa.assert(/ is correct');
- tressa.assert(wires.a() === wires.a(), 'same wire for ');
- tressa.assert(wires.p() === wires.p(), 'same wire for ');
-}).then(function () {
- return tressa.async(function (done) {
- tressa.log('## Promises instead of nodes');
+ };
+ tressa.assert(wires.a().nodeName.toLowerCase() === 'a', ' is correct');
+ tressa.assert(wires.p().nodeName.toLowerCase() === 'p', '