UNPKG

heresy

Version:

lighterhtml based custom elements builtins

1,643 lines (1,362 loc) 70.5 kB
var heresy = (function (document,exports) { 'use strict'; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 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 _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } } 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 _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; } function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); } function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); } function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); } function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter); } function _iterableToArrayLimit(arr, i) { if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return; var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } /*! (c) Andrea Giammarchi - ISC */ var self = {}; try { self.WeakMap = WeakMap; } catch (WeakMap) { // this could be better but 90% of the time // it's everything developers need as fallback self.WeakMap = function (id, Object) { 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 }); return this; }; return WeakMap; function WeakMap(iterable) { 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; var uhyphen = (function (camel) { return camel.replace(/(([A-Z0-9])([A-Z0-9][a-z]))|(([a-z])([A-Z]))/g, '$2$5-$3$6').toLowerCase(); }); /*! (c) Andrea Giammarchi - ISC */ var self$1 = {}; try { self$1.Event = new Event('.').constructor; } catch (Event) { try { self$1.Event = new CustomEvent('.').constructor; } catch (Event) { self$1.Event = function Event(type, init) { if (!init) init = {}; var e = document.createEvent('Event'); var bubbles = !!init.bubbles; var cancelable = !!init.cancelable; e.initEvent(type, bubbles, cancelable); try { e.bubbles = bubbles; e.cancelable = cancelable; } catch (e) {} return e; }; } } var Event$1 = self$1.Event; /*! (c) Andrea Giammarchi - ISC */ var self$2 = {}; try { self$2.WeakSet = WeakSet; } catch (WeakSet) { // requires a global WeakMap (IE11+) (function (WeakMap) { var all = new WeakMap(); var proto = WeakSet.prototype; proto.add = function (value) { return all.get(this).set(value, 1), this; }; proto["delete"] = function (value) { return all.get(this)["delete"](value); }; proto.has = function (value) { return all.get(this).has(value); }; self$2.WeakSet = WeakSet; function WeakSet(iterable) { all.set(this, new WeakMap()); if (iterable) iterable.forEach(this.add, this); } })(WeakMap); } var WeakSet$1 = self$2.WeakSet; /*! (c) Andrea Giammarchi - ISC */ // Custom var UID = '-' + Math.random().toFixed(6) + '%'; // Edge issue! var UID_IE = false; try { if (!function (template, content, tabindex) { return content in template && (template.innerHTML = '<p ' + tabindex + '="' + UID + '"></p>', template[content].childNodes[0].getAttribute(tabindex) == UID); }(document.createElement('template'), 'content', 'tabindex')) { UID = '_dt: ' + UID.slice(1, -1) + ';'; UID_IE = true; } } catch (meh) {} var UIDC = '<!--' + UID + '-->'; // DOM var COMMENT_NODE = 8; var ELEMENT_NODE = 1; var TEXT_NODE = 3; var SHOULD_USE_TEXT_CONTENT = /^(?:plaintext|script|style|textarea|title|xmp)$/i; var VOID_ELEMENTS = /^(?:area|base|br|col|embed|hr|img|input|keygen|link|menuitem|meta|param|source|track|wbr)$/i; /*! (c) Andrea Giammarchi - ISC */ function domsanitizer (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.replace('\\/', '') + '))?)'; 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'); function attrReplacer($0, $1, $2, $3) { return '<' + $1 + $2.replace(findAttributes, replaceAttributes) + $3; } function replaceAttributes($0, $1, $2) { return $1 + ($2 || '"') + UID + ($2 || '"'); } function fullClosing($0, $1, $2) { return VOID_ELEMENTS.test($1) ? $0 : '<' + $1 + $2 + '></' + $1 + '>'; } var isArray = Array.isArray; var _ref = [], slice = _ref.slice; var umap = (function (_) { return { // About: get: _.get.bind(_) // It looks like WebKit/Safari didn't optimize bind at all, // so that using bind slows it down by 60%. // Firefox and Chrome are just fine in both cases, // so let's use the approach that works fast everywhere 👍 get: function get(key) { return _.get(key); }, set: function set(key, value) { return _.set(key, value), value; } }; }); var ELEMENT_NODE$1 = 1; var nodeType = 111; var remove = function remove(_ref) { var firstChild = _ref.firstChild, lastChild = _ref.lastChild; var range = document.createRange(); range.setStartAfter(firstChild); range.setEndAfter(lastChild); range.deleteContents(); return firstChild; }; var diffable = function diffable(node, operation) { return node.nodeType === nodeType ? 1 / operation < 0 ? operation ? remove(node) : node.lastChild : operation ? node.valueOf() : node.firstChild : node; }; var persistent = function persistent(fragment) { var childNodes = fragment.childNodes; var length = childNodes.length; if (length < 2) return length ? childNodes[0] : fragment; var nodes = slice.call(childNodes, 0); var firstChild = nodes[0]; var lastChild = nodes[length - 1]; return { ELEMENT_NODE: ELEMENT_NODE$1, nodeType: nodeType, firstChild: firstChild, lastChild: lastChild, valueOf: function valueOf() { if (childNodes.length !== length) { var i = 0; while (i < length) { fragment.appendChild(nodes[i++]); } } return fragment; } }; }; /*! (c) Andrea Giammarchi - ISC */ var createContent = 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 = '<table>' + html + '</table>'; 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 xmlns="http://www.w3.org/2000/svg">' + svg + '</svg>'; append(content, template.firstChild.childNodes); return content; } }(document); /** * ISC License * * Copyright (c) 2020, Andrea Giammarchi, @WebReflection * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ /** * @param {Node} parentNode The container where children live * @param {Node[]} a The list of current/live children * @param {Node[]} b The list of future children * @param {(entry: Node, action: number) => Node} get * The callback invoked per each entry related DOM operation. * @param {Node} [before] The optional node used as anchor to insert before. * @returns {Node[]} The same list of future children. */ var udomdiff = (function (parentNode, a, b, get, before) { var bLength = b.length; var aEnd = a.length; var bEnd = bLength; var aStart = 0; var bStart = 0; var map = null; while (aStart < aEnd || bStart < bEnd) { // append head, tail, or nodes in between: fast path if (aEnd === aStart) { // we could be in a situation where the rest of nodes that // need to be added are not at the end, and in such case // the node to `insertBefore`, if the index is more than 0 // must be retrieved, otherwise it's gonna be the first item. var node = bEnd < bLength ? bStart ? get(b[bStart - 1], -0).nextSibling : get(b[bEnd - bStart], 0) : before; while (bStart < bEnd) { parentNode.insertBefore(get(b[bStart++], 1), node); } } // remove head or tail: fast path else if (bEnd === bStart) { while (aStart < aEnd) { // remove the node only if it's unknown or not live if (!map || !map.has(a[aStart])) parentNode.removeChild(get(a[aStart], -1)); aStart++; } } // same node: fast path else if (a[aStart] === b[bStart]) { aStart++; bStart++; } // same tail: fast path else if (a[aEnd - 1] === b[bEnd - 1]) { aEnd--; bEnd--; } // The once here single last swap "fast path" has been removed in v1.1.0 // https://github.com/WebReflection/udomdiff/blob/single-final-swap/esm/index.js#L69-L85 // reverse swap: also fast path else if (a[aStart] === b[bEnd - 1] && b[bStart] === a[aEnd - 1]) { // this is a "shrink" operation that could happen in these cases: // [1, 2, 3, 4, 5] // [1, 4, 3, 2, 5] // or asymmetric too // [1, 2, 3, 4, 5] // [1, 2, 3, 5, 6, 4] var _node = get(a[--aEnd], -1).nextSibling; parentNode.insertBefore(get(b[bStart++], 1), get(a[aStart++], -1).nextSibling); parentNode.insertBefore(get(b[--bEnd], 1), _node); // mark the future index as identical (yeah, it's dirty, but cheap 👍) // The main reason to do this, is that when a[aEnd] will be reached, // the loop will likely be on the fast path, as identical to b[bEnd]. // In the best case scenario, the next loop will skip the tail, // but in the worst one, this node will be considered as already // processed, bailing out pretty quickly from the map index check a[aEnd] = b[bEnd]; } // map based fallback, "slow" path else { // the map requires an O(bEnd - bStart) operation once // to store all future nodes indexes for later purposes. // In the worst case scenario, this is a full O(N) cost, // and such scenario happens at least when all nodes are different, // but also if both first and last items of the lists are different if (!map) { map = new Map(); var i = bStart; while (i < bEnd) { map.set(b[i], i++); } } // if it's a future node, hence it needs some handling if (map.has(a[aStart])) { // grab the index of such node, 'cause it might have been processed var index = map.get(a[aStart]); // if it's not already processed, look on demand for the next LCS if (bStart < index && index < bEnd) { var _i = aStart; // counts the amount of nodes that are the same in the future var sequence = 1; while (++_i < aEnd && _i < bEnd && map.get(a[_i]) === index + sequence) { sequence++; } // effort decision here: if the sequence is longer than replaces // needed to reach such sequence, which would brings again this loop // to the fast path, prepend the difference before a sequence, // and move only the future list index forward, so that aStart // and bStart will be aligned again, hence on the fast path. // An example considering aStart and bStart are both 0: // a: [1, 2, 3, 4] // b: [7, 1, 2, 3, 6] // this would place 7 before 1 and, from that time on, 1, 2, and 3 // will be processed at zero cost if (sequence > index - bStart) { var _node2 = get(a[aStart], 0); while (bStart < index) { parentNode.insertBefore(get(b[bStart++], 1), _node2); } } // if the effort wasn't good enough, fallback to a replace, // moving both source and target indexes forward, hoping that some // similar node will be found later on, to go back to the fast path else { parentNode.replaceChild(get(b[bStart++], 1), get(a[aStart++], -1)); } } // otherwise move the source forward, 'cause there's nothing to do else aStart++; } // this node has no meaning in the future list, so it's more than safe // to remove it, and check the next live node out instead, meaning // that only the live list index should be forwarded else parentNode.removeChild(get(a[aStart++], -1)); } } return b; }); /*! (c) Andrea Giammarchi - ISC */ var importNode = function (document, appendChild, cloneNode, createTextNode, importNode) { 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]('')); /* istanbul ignore next */ 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 /* istanbul ignore next */ childNodes = node.childNodes || [], length = childNodes.length, i = 0; deep && i < length; i++) { clone[appendChild](importNode(childNodes[i], deep)); } return clone; } : /* istanbul ignore next */ _native ? document[importNode] : function (node, deep) { return node[cloneNode](!!deep); }; }(document, 'appendChild', 'cloneNode', 'createTextNode', 'importNode'); var trim = ''.trim || /* istanbul ignore next */ function () { return String(this).replace(/^\s+|\s+/g, ''); }; /* istanbul ignore next */ var normalizeAttributes = UID_IE ? function (attributes, parts) { var html = parts.join(' '); return parts.slice.call(attributes, 0).sort(function (left, right) { return html.indexOf(left.name) <= html.indexOf(right.name) ? -1 : 1; }); } : function (attributes, parts) { return parts.slice.call(attributes, 0); }; function find(node, path) { var length = path.length; var i = 0; while (i < length) { node = node.childNodes[path[i++]]; } return node; } function parse(node, holes, parts, path) { var childNodes = node.childNodes; var length = childNodes.length; var i = 0; while (i < length) { var child = childNodes[i]; switch (child.nodeType) { case ELEMENT_NODE: var childPath = path.concat(i); parseAttributes(child, holes, parts, childPath); parse(child, holes, parts, childPath); break; case COMMENT_NODE: var textContent = child.textContent; if (textContent === UID) { parts.shift(); 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) ? Text(node, path) : Any(child, path.concat(i))); } else { switch (textContent.slice(0, 2)) { case '/*': if (textContent.slice(-2) !== '*/') break; case "\uD83D\uDC7B": // ghost node.removeChild(child); i--; length--; } } 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(); holes.push(Text(node, path)); } break; } i++; } } function parseAttributes(node, holes, parts, path) { var attributes = node.attributes; var cache = []; var remove = []; var array = normalizeAttributes(attributes, parts); var length = array.length; var i = 0; while (i < length) { var attribute = array[i++]; var direct = attribute.value === UID; var sparse; if (direct || 1 < (sparse = attribute.value.split(UIDC)).length) { var name = attribute.name; // the following ignore is covered by IE // and the IE9 double viewBox test /* istanbul ignore else */ if (cache.indexOf(name) < 0) { cache.push(name); var realName = parts.shift().replace(direct ? /^(?:|[\S\s]*?\s)(\S+?)\s*=\s*('|")?$/ : new RegExp('^(?:|[\\S\\s]*?\\s)(' + name + ')\\s*=\\s*(\'|")[\\S\\s]*', 'i'), '$1'); var value = attributes[realName] || // the following ignore is covered by browsers // while basicHTML is already case-sensitive /* istanbul ignore next */ attributes[realName.toLowerCase()]; if (direct) holes.push(Attr(value, path, realName, null));else { var skip = sparse.length - 2; while (skip--) { parts.shift(); } holes.push(Attr(value, path, realName, sparse)); } } remove.push(attribute); } } length = remove.length; i = 0; /* istanbul ignore next */ var cleanValue = 0 < length && UID_IE && !('ownerSVGElement' in node); while (i < length) { // Edge HTML bug #16878726 var attr = remove[i++]; // IE/Edge bug lighterhtml#63 - clean the value or it'll persist /* istanbul ignore next */ if (cleanValue) attr.value = ''; // IE/Edge bug lighterhtml#64 - don't use removeAttributeNode node.removeAttribute(attr.name); } // 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); // then Edge arrived and decided that scripts created // through template documents aren't worth executing // so it became this ... hopefully it won't hurt in the wild var script = document.createElement(nodeName); length = attributes.length; i = 0; while (i < length) { script.setAttributeNode(attributes[i++].cloneNode(true)); } script.textContent = node.textContent; node.parentNode.replaceChild(script, node); } } function Any(node, path) { return { type: 'any', node: node, path: path }; } function Attr(node, path, name, sparse) { return { type: 'attr', node: node, path: path, name: name, sparse: sparse }; } function Text(node, path) { return { type: 'text', node: node, path: path }; } // globals var parsed = umap(new WeakMap$1()); function createInfo(options, template) { var markup = (options.convert || domsanitizer)(template); var transform = options.transform; if (transform) markup = transform(markup); var content = createContent(markup, options.type); cleanContent(content); var holes = []; parse(content, holes, template.slice(0), []); return { content: content, updates: function updates(content) { var updates = []; var len = holes.length; var i = 0; var off = 0; while (i < len) { var info = holes[i++]; var node = find(content, info.path); switch (info.type) { case 'any': updates.push({ fn: options.any(node, []), sparse: false }); break; case 'attr': var sparse = info.sparse; var fn = options.attribute(node, info.name, info.node); if (sparse === null) updates.push({ fn: fn, sparse: false });else { off += sparse.length - 2; updates.push({ fn: fn, sparse: true, values: sparse }); } break; case 'text': updates.push({ fn: options.text(node), sparse: false }); node.textContent = ''; break; } } len += off; return function () { var length = arguments.length; if (len !== length - 1) { throw new Error(length - 1 + ' values instead of ' + len + '\n' + template.join('${value}')); } var i = 1; var off = 1; while (i < length) { var update = updates[i - off]; if (update.sparse) { var values = update.values; var value = values[0]; var j = 1; var l = values.length; off += l - 2; while (j < l) { value += arguments[i++] + values[j++]; } update.fn(value); } else update.fn(arguments[i++]); } return content; }; } }; } function createDetails(options, template) { var info = parsed.get(template) || parsed.set(template, createInfo(options, template)); return info.updates(importNode.call(document, info.content, true)); } var empty = []; function domtagger(options) { var previous = empty; var updates = cleanContent; return function (template) { if (previous !== template) updates = createDetails(options, previous = template); return updates.apply(null, arguments); }; } 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); } } } /*! (c) Andrea Giammarchi - ISC */ var hyperStyle = function () { 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 { node.setAttribute('style', '--hyper:style;'); style = node.getAttributeNode('style'); } style.value = ''; 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(''); } 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; } }; } }(); var aria = function aria(node) { return function (values) { for (var key in values) { var name = key === 'role' ? key : "aria-".concat(key); var value = values[key]; if (value == null) node.removeAttribute(name);else node.setAttribute(name, value); } }; }; var attribute = function attribute(node, name) { var oldValue, orphan = true; var attributeNode = document.createAttributeNS(null, name); return function (newValue) { if (oldValue !== newValue) { oldValue = newValue; if (oldValue == null) { if (!orphan) { node.removeAttributeNode(attributeNode); orphan = true; } } else { attributeNode.value = newValue; if (orphan) { node.setAttributeNodeNS(attributeNode); orphan = false; } } } }; }; var data = function data(_ref) { var dataset = _ref.dataset; return function (values) { for (var key in values) { var value = values[key]; if (value == null) delete dataset[key];else dataset[key] = value; } }; }; var event = function event(node, name) { var oldValue, type = name.slice(2); if (!(name in node) && name.toLowerCase() in node) type = type.toLowerCase(); return function (newValue) { var info = isArray(newValue) ? newValue : [newValue, false]; if (oldValue !== info[0]) { if (oldValue) node.removeEventListener(type, oldValue, info[1]); if (oldValue = info[0]) node.addEventListener(type, oldValue, info[1]); } }; }; var ref = function ref(node) { return function (value) { if (typeof value === 'function') value(node);else value.current = node; }; }; var setter = function setter(node, key) { return function (value) { node[key] = value; }; }; var hyperProperty = function hyperProperty(node, name) { var oldValue; return function (newValue) { if (oldValue !== newValue) { oldValue = newValue; if (node[name] !== newValue) { if (newValue == null) { // cleanup before dropping the attribute to fix IE/Edge gotcha node[name] = ''; node.removeAttribute(name); } else node[name] = newValue; } } }; }; // list of attributes that should not be directly assigned var readOnly = /^(?:form|list)$/i; // simplifies text node creation var text = function text(node, _text) { return node.ownerDocument.createTextNode(_text); }; function Tagger(type) { this.type = type; return domtagger(this); } 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 // * regular, accessed through get/setAttribute standard DOM methods // * style, the only regular attribute that also accepts an object as value // so that you can style=${{width: 120}}. In this case, the behavior has been // fully inspired by Preact library and its simplicity. attribute: function attribute$1(node, name, original) { var isSVG = this.type === 'svg'; switch (name) { case 'class': if (isSVG) return attribute(node, name); name = 'className'; case 'props': return setter(node, name); case 'aria': return aria(node); case 'style': return hyperStyle(node, original, isSVG); case 'ref': return ref(node); case '.dataset': return data(node); default: if (name.slice(0, 1) === '.') return setter(node, name.slice(1)); if (name.slice(0, 2) === 'on') return event(node, name); if (name in node && !(isSVG || readOnly.test(name))) return hyperProperty(node, name); return attribute(node, name); } }, // in a hyper(node)`<div>${content}</div>` case // everything could happen: // * it's a JS primitive, stored as text // * it's null or undefined, the node should be cleaned // * it's a promise, update the content once resolved // * it's an explicit intent, perform the desired operation // * 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 type = this.type; var fastPath = false; var oldValue; var anyContent = function anyContent(value) { switch (typeof(value)) { case 'string': case 'number': case 'boolean': if (fastPath) { if (oldValue !== value) { oldValue = value; childNodes[0].textContent = value; } } else { fastPath = true; oldValue = value; childNodes = udomdiff(node.parentNode, childNodes, [text(node, value)], diffable, node); } break; case 'function': anyContent(value(node)); break; case 'object': case 'undefined': if (value == null) { fastPath = false; childNodes = udomdiff(node.parentNode, childNodes, [], diffable, node); break; } default: fastPath = false; oldValue = value; if (isArray(value)) { if (value.length === 0) { if (childNodes.length) { childNodes = udomdiff(node.parentNode, childNodes, [], diffable, node); } } else { switch (typeof(value[0])) { case 'string': case 'number': case 'boolean': anyContent(String(value)); break; case 'function': anyContent(value.map(invoke, node)); break; case 'object': if (isArray(value[0])) { value = value.concat.apply([], value); } default: childNodes = udomdiff(node.parentNode, childNodes, value, diffable, node); break; } } } else if ('ELEMENT_NODE' in value) { childNodes = udomdiff(node.parentNode, childNodes, value.nodeType === 11 ? slice.call(value.childNodes) : [value], diffable, node); } else if ('text' in value) { anyContent(String(value.text)); } else if ('any' in value) { anyContent(value.any); } else if ('html' in value) { childNodes = udomdiff(node.parentNode, childNodes, slice.call(createContent([].concat(value.html).join(''), type).childNodes), diffable, node); } else if ('length' in value) { anyContent(slice.call(value)); } 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(node) { var oldValue; var textContent = function textContent(value) { if (oldValue !== value) { oldValue = value; var type = typeof(value); if (type === 'object' && value) { if ('text' in value) { textContent(String(value.text)); } else if ('any' in value) { textContent(value.any); } else if ('html' in value) { textContent([].concat(value.html).join('')); } else if ('length' in value) { textContent(slice.call(value).join('')); } } else if (type === 'function') { textContent(value(node)); } else { node.textContent = value == null ? '' : value; } } }; return textContent; } }; function invoke(callback) { return callback(this); } var create = Object.create, freeze = Object.freeze, keys = Object.keys; var tProto = Tagger.prototype; var cache = umap(new WeakMap$1()); var createRender = function createRender(Tagger) { return { html: outer('html', Tagger), svg: outer('svg', Tagger), render: function render(where, what) { var hole = typeof what === 'function' ? what() : what; var info = cache.get(where) || cache.set(where, createCache()); var wire = hole instanceof LighterHole ? unroll(Tagger, info, hole) : hole; if (wire !== info.wire) { info.wire = wire; where.textContent = ''; where.appendChild(wire.valueOf()); } return where; } }; }; var createCache = function createCache() { return { stack: [], entry: null, wire: null }; }; var outer = function outer(type, Tagger) { var cache = umap(new WeakMap$1()); var fixed = function fixed(info) { return function () { return unroll(Tagger, info, hole.apply(null, arguments)); }; }; hole["for"] = function (ref, id) { var memo = cache.get(ref) || cache.set(ref, create(null)); return memo[id] || (memo[id] = fixed(createCache())); }; hole.node = function () { return unroll(Tagger, createCache(), hole.apply(null, arguments)).valueOf(); }; return hole; function hole() { return new LighterHole(type, tta.apply(null, arguments)); } }; var unroll = function unroll(Tagger, info, _ref) { var _entry; var type = _ref.type, template = _ref.template, values = _ref.values; var length = values.length; unrollValues(Tagger, info, values, length); var entry = info.entry; if (!entry || entry.template !== template || entry.type !== type) { var tag = new Tagger(type); info.entry = entry = { type: type, template: template, tag: tag, wire: persistent(tag.apply(void 0, [template].concat(_toConsumableArray(values)))) }; } else (_entry = entry).tag.apply(_entry, [template].concat(_toConsumableArray(values))); return entry.wire; }; var unrollValues = function unrollValues(Tagger, _ref2, values, length) { var stack = _ref2.stack; for (var i = 0; i < length; i++) { var hole = values[i]; if (hole instanceof Hole) values[i] = unroll(Tagger, stack[i] || (stack[i] = createCache()), hole);else if (isArray(hole)) unrollValues(Tagger, stack[i] || (stack[i] = createCache()), hole, hole.length);else stack[i] = null; } if (length < stack.length) stack.splice(length); }; freeze(LighterHole); function LighterHole(type, args) { this.type = type; this.template = args.shift(); this.values = args; } var Hole = LighterHole; var custom = function custom(overrides) { var prototype = create(tProto); keys(overrides).forEach(function (key) { prototype[key] = overrides[key](prototype[key] || (key === 'convert' ? domsanitizer : String)); }); CustomTagger.prototype = prototype; return createRender(CustomTagger); function CustomTagger() { return Tagger.apply(this, arguments); } }; var _createRender = createRender(Tagger); function tta() { var out = [], i = 0, length = arguments.length; while (i < length) { out.push(arguments[i++]); } return out; } var compat = typeof cancelAnimationFrame === 'function'; var cAF = compat ? cancelAnimationFrame : clearTimeout; var rAF = compat ? requestAnimationFrame : setTimeout; function reraf(limit) { var force, timer, callback, self, args; reset(); return function reschedule(_callback, _self, _args) { callback = _callback; self = _self; args = _args; if (!timer) timer = rAF(invoke); if (--force < 0) stop(true); return stop; }; function invoke() { reset(); callback.apply(self, args || []); } function reset() { force = limit || Infinity; timer = compat ? 0 : null; } function stop(flush) { var didStop = !!timer; if (didStop) { cAF(timer); if (flush) invoke(); } return didStop; } } /*! (c) Andrea Giammarchi - ISC */ var state = null; // main exports var augmentor = function augmentor(fn) { var stack = []; return function hook() { var prev = state; var after = []; state = { hook: hook, args: arguments, stack: stack, i: 0, length: stack.length, after: after }; try { return fn.apply(null, arguments); } finally { state = prev; for (var i = 0, length = after.length; i < length; i++) { after[i](); } } }; }; var contextual = function contextual(fn) { var check = true; var context = null; var augmented = augmentor(function () { return fn.apply(context, arguments); }); return function hook() { var result = augmented.apply(context = this, arguments); // perform hasEffect check only once if (check) { check = !check; // and copy same Array if any FX was used if (hasEffect(augmented)) effects.set(hook, effects.get(augmented)); } return result; }; }; // useReducer var updates = umap(new WeakMap()); var hookdate = function hookdate(hook, ctx, args) { hook.apply(ctx, args); }; var defaults = { async: false, always: false }; var getValue = function getValue(value, f) { return typeof f == 'function' ? f(value) : f; }; var useReducer = function useReducer(reducer, value, init, options) { var i = state.i++; var _state = state, hook = _state.hook, args = _state.args, stack = _state.stack, length = _state.length; if (i === length) state.length = stack.push({}); var ref = stack[i]; ref.args = args; if (i === length) { var fn = typeof init === 'function'; var _ref = (fn ? options : init) || options || defaults, asy = _ref.async, always = _ref.always; ref.$ = fn ? init(value) : getValue(void 0, value); ref._ = asy ? updates.get(hook) || updates.set(hook, reraf()) : hookdate; ref.f = function (value) { var $value = reducer(ref.$, value); if (always || ref.$ !== $value) { ref.$ = $value; ref._(hook, null, ref.args); } }; } return [ref.$, ref.f]; }; // useState var useState = function useState(value, options) { return useReducer(getValue, value, void 0, options); }; // useContext var hooks = new WeakMap(); var invoke$1 = function invoke(_ref2) { var hook = _ref2.hook, args = _ref2.args; hook.apply(null, args); }; var createContext = function createContext(value) { var context = { value: value, provide: provide }; hooks.set(context, []); return context; }; var useContext = function useContext(context) { var _state2 = state, hook = _state2.hook, args = _state2.args; var stack = hooks.get(context); var info = { hook: hook, args: args }; if (!stack.some(update, info)) stack.push(info); return context.value; }; function provide(value) { if (this.value !== value) { this.value = value; hooks.get(this).forEach(invoke$1); } } function update(_ref3) { var hook = _ref3.hook; return hook === this.hook; } // dropEffect, hasEffect, useEffect, useLayoutEffect var effects = new WeakMap(); var fx = umap(effects); var stop = function stop() {}; var createEffect = function createEffect(asy) { return function (effect, guards) { var i = state.i++; var _state3 = state, hook = _state3.hook, after = _state3.after, stack = _state3.stack, length = _state3.length; if (i < length) { var info = stack[i]; var _update = info.update, values = info.values, _stop = info.stop; if (!guards || guards.some(different, values)) { info.values = guards; if (asy) _stop(asy); var clean = info.clean; if (clean) { info.clean = null; clean(); } var _invoke = function _invoke() { info.clean = effect(); }; if (asy) _update(_invoke);else after.push(_invoke); } } else { var _update2 = asy ? reraf() : stop; var _info = { clean: null, update: _update2, values: guards, stop: stop }; state.length = stack.push(_info); (fx.get(hook) || fx.set(hook, [])).push(_info); var _invoke2 = function _invoke2() {