From 69a7c72d727e5178ce2afe412b6ee75b3ec66e74 Mon Sep 17 00:00:00 2001 From: Evan You Date: Tue, 19 Apr 2016 11:50:40 -0400 Subject: [PATCH 01/32] Return early in module update functions --- modules/attributes.js | 22 +++++++++++++--------- modules/class.js | 9 +++++++-- modules/dataset.js | 8 ++++++-- modules/eventlisteners.js | 8 ++++++-- modules/props.js | 7 ++++++- modules/style.js | 11 ++++++++--- 6 files changed, 46 insertions(+), 19 deletions(-) diff --git a/modules/attributes.js b/modules/attributes.js index c92492e..d798a03 100644 --- a/modules/attributes.js +++ b/modules/attributes.js @@ -1,19 +1,23 @@ -var booleanAttrs = ["allowfullscreen", "async", "autofocus", "autoplay", "checked", "compact", "controls", "declare", - "default", "defaultchecked", "defaultmuted", "defaultselected", "defer", "disabled", "draggable", - "enabled", "formnovalidate", "hidden", "indeterminate", "inert", "ismap", "itemscope", "loop", "multiple", - "muted", "nohref", "noresize", "noshade", "novalidate", "nowrap", "open", "pauseonexit", "readonly", - "required", "reversed", "scoped", "seamless", "selected", "sortable", "spellcheck", "translate", +var booleanAttrs = ["allowfullscreen", "async", "autofocus", "autoplay", "checked", "compact", "controls", "declare", + "default", "defaultchecked", "defaultmuted", "defaultselected", "defer", "disabled", "draggable", + "enabled", "formnovalidate", "hidden", "indeterminate", "inert", "ismap", "itemscope", "loop", "multiple", + "muted", "nohref", "noresize", "noshade", "novalidate", "nowrap", "open", "pauseonexit", "readonly", + "required", "reversed", "scoped", "seamless", "selected", "sortable", "spellcheck", "translate", "truespeed", "typemustmatch", "visible"]; - + var booleanAttrsDict = {}; for(var i=0, len = booleanAttrs.length; i < len; i++) { booleanAttrsDict[booleanAttrs[i]] = true; } - + function updateAttrs(oldVnode, vnode) { var key, cur, old, elm = vnode.elm, - oldAttrs = oldVnode.data.attrs || {}, attrs = vnode.data.attrs || {}; - + oldAttrs = oldVnode.data.attrs, attrs = vnode.data.attrs; + + if (!oldAttrs && !attrs) return; + oldAttrs = oldAttrs || {}; + attrs = attrs || {}; + // update modified attributes, add new attributes for (key in attrs) { cur = attrs[key]; diff --git a/modules/class.js b/modules/class.js index 3805305..35e19de 100644 --- a/modules/class.js +++ b/modules/class.js @@ -1,7 +1,12 @@ function updateClass(oldVnode, vnode) { var cur, name, elm = vnode.elm, - oldClass = oldVnode.data.class || {}, - klass = vnode.data.class || {}; + oldClass = oldVnode.data.class, + klass = vnode.data.class; + + if (!oldClass && !klass) return; + oldClass = oldClass || {}; + klass = klass || {}; + for (name in oldClass) { if (!klass[name]) { elm.classList.remove(name); diff --git a/modules/dataset.js b/modules/dataset.js index ec38dc5..37e573b 100644 --- a/modules/dataset.js +++ b/modules/dataset.js @@ -1,9 +1,13 @@ function updateDataset(oldVnode, vnode) { var elm = vnode.elm, - oldDataset = oldVnode.data.dataset || {}, - dataset = vnode.data.dataset || {}, + oldDataset = oldVnode.data.dataset, + dataset = vnode.data.dataset, key + if (!oldDataset && !dataset) return; + oldDataset = oldDataset || {}; + dataset = dataset || {}; + for (key in oldDataset) { if (!dataset[key]) { delete elm.dataset[key]; diff --git a/modules/eventlisteners.js b/modules/eventlisteners.js index ecbe7b5..8dddfa4 100644 --- a/modules/eventlisteners.js +++ b/modules/eventlisteners.js @@ -13,8 +13,12 @@ function fnInvoker(o) { function updateEventListeners(oldVnode, vnode) { var name, cur, old, elm = vnode.elm, - oldOn = oldVnode.data.on || {}, on = vnode.data.on; - if (!on) return; + oldOn = oldVnode.data.on, on = vnode.data.on; + + if (!on && !oldOn) return; + on = on || {}; + oldOn = oldOn || {}; + for (name in on) { cur = on[name]; old = oldOn[name]; diff --git a/modules/props.js b/modules/props.js index 84ed631..843c8a8 100644 --- a/modules/props.js +++ b/modules/props.js @@ -1,6 +1,11 @@ function updateProps(oldVnode, vnode) { var key, cur, old, elm = vnode.elm, - oldProps = oldVnode.data.props || {}, props = vnode.data.props || {}; + oldProps = oldVnode.data.props, props = vnode.data.props; + + if (!oldProps && !props) return; + oldProps = oldProps || {}; + props = props || {}; + for (key in oldProps) { if (!props[key]) { delete elm[key]; diff --git a/modules/style.js b/modules/style.js index 8f525ff..e03b633 100644 --- a/modules/style.js +++ b/modules/style.js @@ -7,9 +7,14 @@ function setNextFrame(obj, prop, val) { function updateStyle(oldVnode, vnode) { var cur, name, elm = vnode.elm, - oldStyle = oldVnode.data.style || {}, - style = vnode.data.style || {}, - oldHasDel = 'delayed' in oldStyle; + oldStyle = oldVnode.data.style, + style = vnode.data.style; + + if (!oldStyle && !style) return; + oldStyle = oldStyle || {}; + style = style || {}; + var oldHasDel = 'delayed' in oldStyle; + for (name in oldStyle) { if (!style[name]) { elm.style[name] = ''; From 137ecacfb313df6898929c2efe9e2c61e9870e29 Mon Sep 17 00:00:00 2001 From: Veaceslav Grimalschi Date: Sun, 22 May 2016 20:14:15 +0300 Subject: [PATCH 02/32] Extra variable in think.js --- thunk.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/thunk.js b/thunk.js index 042923c..21bf7b1 100644 --- a/thunk.js +++ b/thunk.js @@ -11,7 +11,7 @@ function copyToThunk(vnode, thunk) { } function init(thunk) { - var i, cur = thunk.data; + var cur = thunk.data; var vnode = cur.fn.apply(undefined, cur.args); copyToThunk(vnode, thunk); } From 2bf8926564b4618de1c13ee2f164346ab4f196ff Mon Sep 17 00:00:00 2001 From: Tylor Steinberger Date: Sat, 28 May 2016 15:58:54 -0400 Subject: [PATCH 03/32] chore(TS): add typescript definitions --- package.json | 1 + type-definitions/snabbdom.d.ts | 148 +++++++++++++++++++++++++++++++++ 2 files changed, 149 insertions(+) create mode 100644 type-definitions/snabbdom.d.ts diff --git a/package.json b/package.json index add9997..c0a5eb2 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,7 @@ "version": "0.5.0", "description": "A virtual DOM library with focus on simplicity, modularity, powerful features and performance.", "main": "snabbdom.js", + "typgings": "type-definitions/snabbdom.d.ts", "directories": { "example": "examples", "test": "test" diff --git a/type-definitions/snabbdom.d.ts b/type-definitions/snabbdom.d.ts new file mode 100644 index 0000000..da51aa8 --- /dev/null +++ b/type-definitions/snabbdom.d.ts @@ -0,0 +1,148 @@ +export interface VNodeData { + // modules - use any because Object type is useless + props?: any; + attrs?: any; + class?: any; + style?: any; + dataset?: any; + on?: any; + hero?: any; + // end of modules + hook?: Hooks; + key?: string | number; + ns?: string; // for SVGs + fn?: () => VNode; // for thunks + args?: Array; // for thunks +} + +export interface VNode { + sel: string; + data?: VNodeData; + children?: Array; + elm?: Element | Text; + text?: string; + key?: string | number; +} + +export interface ThunkData extends VNodeData { + fn: () => VNode; + args: Array; +} + +export interface Thunk extends VNode { + data: ThunkData; +} + +export type PreHook = () => any; +export type InitHook = (vNode: VNode) => any; +export type CreateHook = (emptyVNode: VNode, vNode: VNode) => any; +export type InsertHook = (vNode: VNode) => any; +export type PrePatchHook = (oldVNode: VNode, vNode: VNode) => any; +export type UpdateHook = (oldVNode: VNode, vNode: VNode) => any; +export type PostPatchHook = (oldVNode: VNode, vNode: VNode) => any; +export type DestroyHook = (vNode: VNode) => any; +export type RemoveHook = (vNode: VNode, removeCallback: () => void) => any; +export type PostHook = () => any; + +export interface Hooks { + pre?: PreHook; + init?: InitHook; + create?: CreateHook; + insert?: InsertHook; + prepatch?: PrePatchHook; + update?: UpdateHook; + postpatch?: PostPatchHook; + destroy?: DestroyHook; + remove?: RemoveHook; + post?: PostHook; +} + +export interface Module { + pre?: PreHook; + create?: CreateHook; + update?: UpdateHook; + destroy?: DestroyHook; + remove?: RemoveHook; + post?: PostHook; +} + +export interface SnabbdomAPI { + createElement(tagName: string): T; + createElementNS(namespaceURI: string, qualifiedName: string): T; + createTextNode(text: string): T; + insertBefore(parentNode: T, newNode: T, referenceNode: T): void; + removeChild(node: T, child: T): void; + appendChild(node: T, child: T): void; + parentNode(node: T): T; + nextSibling(node: T): T; + tagName(node: T): string; + setTextContent(node: T, text: string): void; +} + +declare module "snabbdom" { + export interface PatchFunction { + (oldVNode: VNode, vnode: VNode): VNode; + } + + export function init(modules: Object, api?: SnabbdomAPI): PatchFunction; +} + +declare module "snabbdom/vnode" { + export default function vnode(sel: string, + data: VNodeData, + children: Array, + text: string, + elm: any): VNode; +} + +declare module "snabbdom/is" { + export function array(x: any): boolean; + export function primitive(x: any): boolean; +} + +declare module "snabbdom/thunk" { + export default function thunk(sel: string, + key: string, + render: (...state: Array) => VNode, + ...state: Array): Thunk; +} + +declare module "snabbdom/htmldomapi" { + let api: SnabbdomAPI; + export = api; +} + +declare module "snabbdom/modules/class" { + let ClassModule: Module; + export = ClassModule; +} + +declare module "snabbdom/modules/props" { + let PropsModule: Module; + export = PropsModule; +} + +declare module "snabbdom/modules/attributes" { + let AttrsModule: Module; + export = AttrsModule; +} + +declare module "snabbdom/modules/eventlisteners" { + let EventsModule: Module; + export = EventsModule; +} + +declare module "snabbdom/modules/hero" { + let HeroModule: Module; + export = HeroModule; +} + +declare module "snabbdom/modules/style" { + let StyleModule: Module; + export = StyleModule; +} + +declare module "snabbdom/modules/dataset" { + let DatasetModule: Module; + export = DatasetModule; +} From 3d48eb84c4b8db7aef293011d166afb67b8bebc1 Mon Sep 17 00:00:00 2001 From: Christian S Date: Mon, 4 Jul 2016 08:22:18 +0200 Subject: [PATCH 04/32] fix style example in README.md fixes #127 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 516c620..ae569f8 100644 --- a/README.md +++ b/README.md @@ -80,7 +80,7 @@ var container = document.getElementById('container'); // Patch into empty DOM element – this modifies the DOM as a side effect patch(container, vnode); var newVnode = h('div#container.two.classes', {on: {click: anotherEventHandler}}, [ - h('span', {style: {fontWeight: 'normal', fontStyle: 'italics'}}, 'This is now italics'), + h('span', {style: {fontWeight: 'normal', fontStyle: 'italic'}}, 'This is now italic type'), ' and this is still just normal text', h('a', {props: {href: '/bar'}}, 'I\'ll take you places!') ]); From fbfee2d620981061be584ce4db39e13b6c1217e3 Mon Sep 17 00:00:00 2001 From: Oliver Joseph Ash Date: Wed, 13 Jul 2016 16:34:17 +0100 Subject: [PATCH 05/32] Fix typo --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c0a5eb2..a10b586 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "version": "0.5.0", "description": "A virtual DOM library with focus on simplicity, modularity, powerful features and performance.", "main": "snabbdom.js", - "typgings": "type-definitions/snabbdom.d.ts", + "typings": "type-definitions/snabbdom.d.ts", "directories": { "example": "examples", "test": "test" From 258c8b91da8258755107aad0c51f194bec230e7b Mon Sep 17 00:00:00 2001 From: Harry Wincup Date: Mon, 18 Jul 2016 12:05:29 +0100 Subject: [PATCH 06/32] Dont add SVG namespace to children of SVG foreignObject --- h.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/h.js b/h.js index edc7ef6..ac07850 100644 --- a/h.js +++ b/h.js @@ -1,11 +1,12 @@ var VNode = require('./vnode'); var is = require('./is'); -function addNS(data, children) { +function addNS(data, children, sel) { data.ns = 'http://www.w3.org/2000/svg'; - if (children !== undefined) { + + if (sel !== 'foreignObject' && children !== undefined) { for (var i = 0; i < children.length; ++i) { - addNS(children[i].data, children[i].children); + addNS(children[i].data, children[i].children, children[i].sel); } } } @@ -27,7 +28,7 @@ module.exports = function h(sel, b, c) { } } if (sel[0] === 's' && sel[1] === 'v' && sel[2] === 'g') { - addNS(data, children); + addNS(data, children, sel); } return VNode(sel, data, children, text, undefined); }; From 68d878c274e9d76cb0bc9f3a0ffb503768c5d4f0 Mon Sep 17 00:00:00 2001 From: Harry Wincup Date: Mon, 18 Jul 2016 12:06:37 +0100 Subject: [PATCH 07/32] Additional namespace tests for SVG foreignObject case --- test/core.js | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/test/core.js b/test/core.js index b6b35b4..07e2e74 100644 --- a/test/core.js +++ b/test/core.js @@ -73,8 +73,21 @@ describe('snabbdom', function() { assert.equal(elm.firstChild.id, 'unique'); }); it('has correct namespace', function() { - elm = patch(vnode0, h('div', [h('div', {ns: 'http://www.w3.org/2000/svg'})])).elm; - assert.equal(elm.firstChild.namespaceURI, 'http://www.w3.org/2000/svg'); + var SVGNamespace = 'http://www.w3.org/2000/svg'; + var XHTMLNamespace = 'http://www.w3.org/1999/xhtml'; + + elm = patch(vnode0, h('div', [h('div', {ns: SVGNamespace})])).elm; + assert.equal(elm.firstChild.namespaceURI, SVGNamespace); + + elm = patch(vnode0, h('svg', [ + h('foreignObject', [ + h('div', ['I am HTML embedded in SVG']) + ]) + ])).elm; + + assert.equal(elm.namespaceURI, SVGNamespace); + assert.equal(elm.firstChild.namespaceURI, SVGNamespace); + assert.equal(elm.firstChild.firstChild.namespaceURI, XHTMLNamespace); }); it('is recieves classes in selector', function() { elm = patch(vnode0, h('div', [h('i.am.a.class')])).elm; From aa6aee5ddf23daa7c2b69f2b46f65e4e32f856bd Mon Sep 17 00:00:00 2001 From: Harry Wincup Date: Tue, 19 Jul 2016 21:26:56 +0100 Subject: [PATCH 08/32] Move browserified tests file outside of watcher dir to prevent reloading loop --- testem.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/testem.json b/testem.json index eb8bb06..1071056 100644 --- a/testem.json +++ b/testem.json @@ -5,9 +5,9 @@ "test/*.js" ], "serve_files": [ - "test/browserified.js" + "browserified.js" ], - "before_tests": "browserify -d test/index.js -o test/browserified.js", - "on_exit": "rm test/browserified.js", + "before_tests": "browserify -d test/index.js -o browserified.js", + "on_exit": "rm browserified.js", "launch_in_dev": [ "firefox", "chromium" ] } From 7a496fb61f93981cf6120c76bd6327cf8bf4030d Mon Sep 17 00:00:00 2001 From: Stu Cox Date: Wed, 20 Jul 2016 09:33:41 +0100 Subject: [PATCH 09/32] Correct formatting in README --- README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ae569f8..0514fc2 100644 --- a/README.md +++ b/README.md @@ -570,9 +570,11 @@ create a virtual node with as its `.children` property. -#### text : string The `.text` property is created when a virtual node -is created with only a single child that possesses text and only -requires `document.createTextNode()` to be used. +#### text : string + +The `.text` property is created when a virtual node is created with +only a single child that possesses text and only requires +`document.createTextNode()` to be used. For example: `h('h1', {}, 'Hello')` will create a virtual node with `Hello` as its `.text` property. From fd539435f65f7ea0cf747486eb32a4059ada9f07 Mon Sep 17 00:00:00 2001 From: paldepind Date: Thu, 21 Jul 2016 21:20:16 +0200 Subject: [PATCH 10/32] Version 0.5.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a10b586..bceae8a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "snabbdom", - "version": "0.5.0", + "version": "0.5.1", "description": "A virtual DOM library with focus on simplicity, modularity, powerful features and performance.", "main": "snabbdom.js", "typings": "type-definitions/snabbdom.d.ts", From 40c62fd2be75e3e371b916e70e34fb1ca9a09c51 Mon Sep 17 00:00:00 2001 From: sk1981 Date: Thu, 28 Jul 2016 13:02:06 +0530 Subject: [PATCH 11/32] Added details on using classes with SVG Using SVG elements with classes has two issues due to className being readonly for these elements and some browsers not accepting classlist on them. Added details and workaround. --- README.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/README.md b/README.md index 0514fc2..9cece7f 100644 --- a/README.md +++ b/README.md @@ -465,6 +465,24 @@ var vnode = h('div', [ See also the [SVG example](./examples/svg) and the [SVG Carousel example](./examples/carousel-svg/). +#### Using Classes +Due to a bug in certain browsers like IE 11 and below and UC Browser, SVG Objects in these browsers do not support classlist property. Hence, the classes module (which uses classlist property internally) will not work for these browsers. + +Also, using snabbdom/h to create an element by passing a className along with the element type will not work as className property is read-only for SVG elements. + +You can add classes to SVG elements for both of these cases by using the attributes module as shown below:- +```javascript +h('text', { + attrs: { + x: xPos, + y: yPos, + dy: "5", + class: 'text_class' + }}, + text +); +``` + ### Thunks The `thunk` function takes a selector, a key for identifying a thunk, From 8ca33c916b3b38991aba148ace735dcb825bd7e3 Mon Sep 17 00:00:00 2001 From: "K." Date: Fri, 29 Jul 2016 11:58:43 +0500 Subject: [PATCH 12/32] New implementation of eventlisteners module --- modules/eventlisteners.js | 115 ++++++++++++++++++++++---------------- test/eventlisteners.js | 59 ++++++++++++++++++- 2 files changed, 124 insertions(+), 50 deletions(-) diff --git a/modules/eventlisteners.js b/modules/eventlisteners.js index 4b03b28..203d846 100644 --- a/modules/eventlisteners.js +++ b/modules/eventlisteners.js @@ -1,62 +1,79 @@ -var is = require('../is'); - -function arrInvoker(arr) { - return function() { - if (!arr.length) return; - // Special case when length is two, for performance - arr.length === 2 ? arr[0](arr[1]) : arr[0].apply(undefined, arr.slice(1)); - }; +function invokeHandler(handler, vnode, event) { + if (typeof handler === "function") { + // call function handler + handler.call(vnode, event); + } else if (typeof handler === "object") { + // call handler with arguments + if (typeof handler[0] === "function") { + // special case for single argument for performance + handler.length === 2 ? + handler[0].call(vnode, handler[1], event) : + handler[0].apply(vnode, handler.slice(1).concat(event)); + } else { + // call multiple handlers + for (var i = 0; i < handler.length; i++) { + invokeHandler(handler[i]); + } + } + } +} + +function handleEvent(event, vnode) { + var name = event.type, + on = vnode.data.on; + + // call event handler(s) if exists + if (on && on[name]) { + invokeHandler(on[name], vnode, event); + } } -function fnInvoker(o) { - return function(ev) { - if (o.fn === null) return; - o.fn(ev); - }; +function createListener() { + return function handler(event) { + handleEvent(event, handler.vnode); + } } function updateEventListeners(oldVnode, vnode) { - var name, cur, old, elm = vnode.elm, - oldOn = oldVnode.data.on, on = vnode.data.on; - - if (!on && !oldOn) return; - on = on || {}; - oldOn = oldOn || {}; - - for (name in on) { - cur = on[name]; - old = oldOn[name]; - if (old === undefined) { - if (is.array(cur)) { - elm.addEventListener(name, arrInvoker(cur)); - } else { - cur = {fn: cur}; - on[name] = cur; - elm.addEventListener(name, fnInvoker(cur)); + var oldOn = oldVnode.data.on, + oldListener = oldVnode.listener, + oldElm = oldVnode.elm, + on = vnode && vnode.data.on, + elm = vnode && vnode.elm; + + // improvement for immutable handlers + if (oldElm === elm && oldOn === on) { + return; + } + + // remove existing listeners which no longer used + if (oldOn && oldListener) { + for (var _name in oldOn) { + // remove listener if element was changed or existing listener(s) removed + if (elm !== oldElm || !on || !on[_name]) { + oldElm.removeEventListener(_name, oldListener, false); } - } else if (is.array(old)) { - // Deliberately modify old array since it's captured in closure created with `arrInvoker` - old.length = cur.length; - for (var i = 0; i < old.length; ++i) old[i] = cur[i]; - on[name] = old; - } else { - old.fn = cur; - on[name] = old; } } - if (oldOn) { - for (name in oldOn) { - if (on[name] === undefined) { - var old = oldOn[name]; - if (is.array(old)) { - old.length = 0; - } - else { - old.fn = null; - } + + // add new listeners which has not already attached + if (on) { + // reuse existing listener or create new + var listener = vnode.listener = oldVnode.listener || createListener(); + // update vnode for listener + listener.vnode = vnode; + + for (var name in on) { + // add listener if element was changed or new listener(s) added + if (elm !== oldElm || !oldOn || !oldOn[name]) { + elm.addEventListener(name, listener, false); } } } } -module.exports = {create: updateEventListeners, update: updateEventListeners}; +module.exports = { + create: updateEventListeners, + update: updateEventListeners, + destroy: updateEventListeners +}; diff --git a/test/eventlisteners.js b/test/eventlisteners.js index 1e66b45..6ec2879 100644 --- a/test/eventlisteners.js +++ b/test/eventlisteners.js @@ -69,7 +69,7 @@ describe('event listeners', function() { }); it('handles changed several values in array', function() { var result = []; - function clicked() { result.push([].slice.call(arguments)); } + function clicked() { result.push([].slice.call(arguments, 0, arguments.length-1)); } var vnode1 = h('div', {on: {click: [clicked, 1, 2, 3]}}, [ h('a', 'Click my parent'), ]); @@ -87,4 +87,61 @@ describe('event listeners', function() { elm.click(); assert.deepEqual(result, [[1, 2, 3], [1, 2], [2, 3]]); }); + it('detach attached click event handler to element', function() { + var result = []; + function clicked(ev) { result.push(ev); } + var vnode1 = h('div', {on: {click: clicked}}, [ + h('a', 'Click my parent'), + ]); + elm = patch(vnode0, vnode1).elm; + elm.click(); + assert.equal(1, result.length); + var vnode2 = h('div', {on: {}}, [ + h('a', 'Click my parent'), + ]); + elm = patch(vnode1, vnode2).elm; + elm.click(); + assert.equal(1, result.length); + }); + it('multiple event handlers for same event on same element', function() { + var result = []; + function clicked(ev) { result.push(ev); } + var vnode1 = h('div', {on: {click: [[clicked], [clicked], [clicked]]}}, [ + h('a', 'Click my parent'), + ]); + elm = patch(vnode0, vnode1).elm; + elm.click(); + assert.equal(3, result.length); + var vnode2 = h('div', {on: {click: [[clicked], [clicked]]}}, [ + h('a', 'Click my parent'), + ]); + elm = patch(vnode1, vnode2).elm; + elm.click(); + assert.equal(5, result.length); + }); + it('access to virtual node in event handler', function() { + var result = []; + function clicked(ev) { result.push(this); } + var vnode1 = h('div', {on: {click: clicked }}, [ + h('a', 'Click my parent'), + ]); + elm = patch(vnode0, vnode1).elm; + elm.click(); + assert.equal(1, result.length); + assert.equal(vnode1, result[0]); + }); + it('shared handlers in parent and child nodes', function() { + var result = []; + var sharedHandlers = { + click: function(ev) { result.push(ev); } + }; + var vnode1 = h('div', {on: sharedHandlers}, [ + h('a', {on: sharedHandlers}, 'Click my parent'), + ]); + elm = patch(vnode0, vnode1).elm; + elm.click(); + assert.equal(1, result.length); + elm.firstChild.click(); + assert.equal(3, result.length); + }); }); From 831bd0e1eede28c8f19990b7c402e35fb546b727 Mon Sep 17 00:00:00 2001 From: Kayo Phoenix Date: Wed, 3 Aug 2016 02:05:48 +0500 Subject: [PATCH 13/32] Optimizations for eventlistener.js --- modules/eventlisteners.js | 40 ++++++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/modules/eventlisteners.js b/modules/eventlisteners.js index 203d846..5f79c0c 100644 --- a/modules/eventlisteners.js +++ b/modules/eventlisteners.js @@ -39,19 +39,29 @@ function updateEventListeners(oldVnode, vnode) { oldListener = oldVnode.listener, oldElm = oldVnode.elm, on = vnode && vnode.data.on, - elm = vnode && vnode.elm; + elm = vnode && vnode.elm, + elmChanged = oldElm !== elm, + name; - // improvement for immutable handlers - if (oldElm === elm && oldOn === on) { + // optimization for immutable handlers + if (!elmChanged && oldOn === on) { return; } // remove existing listeners which no longer used if (oldOn && oldListener) { - for (var _name in oldOn) { - // remove listener if element was changed or existing listener(s) removed - if (elm !== oldElm || !on || !on[_name]) { - oldElm.removeEventListener(_name, oldListener, false); + // if element changed or deleted we remove all existing listeners unconditionally + if (elmChanged || !on) { + for (name in oldOn) { + // remove listener if element was changed or existing listeners removed + oldElm.removeEventListener(name, oldListener, false); + } + } else { + for (name in oldOn) { + // remove listener if existing listener removed + if (!on[name]) { + oldElm.removeEventListener(name, oldListener, false); + } } } } @@ -62,12 +72,20 @@ function updateEventListeners(oldVnode, vnode) { var listener = vnode.listener = oldVnode.listener || createListener(); // update vnode for listener listener.vnode = vnode; - - for (var name in on) { - // add listener if element was changed or new listener(s) added - if (elm !== oldElm || !oldOn || !oldOn[name]) { + + // if element changed or added we add all needed listeners unconditionally + if (elmChanged || !oldOn) { + for (name in on) { + // add listener if element was changed or new listeners added elm.addEventListener(name, listener, false); } + } else { + for (name in on) { + // add listener if new listener added + if (!oldOn[name]) { + elm.addEventListener(name, listener, false); + } + } } } } From 174941c6a49fff91e4e3949fa39423c7cb28939c Mon Sep 17 00:00:00 2001 From: Kayo Phoenix Date: Wed, 3 Aug 2016 02:33:43 +0500 Subject: [PATCH 14/32] Added vnode as last argument to event handler --- modules/eventlisteners.js | 6 +++--- test/eventlisteners.js | 31 ++++++++++++++++++++++++++++--- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/modules/eventlisteners.js b/modules/eventlisteners.js index 5f79c0c..53ffffb 100644 --- a/modules/eventlisteners.js +++ b/modules/eventlisteners.js @@ -1,14 +1,14 @@ function invokeHandler(handler, vnode, event) { if (typeof handler === "function") { // call function handler - handler.call(vnode, event); + handler.call(vnode, event, vnode); } else if (typeof handler === "object") { // call handler with arguments if (typeof handler[0] === "function") { // special case for single argument for performance handler.length === 2 ? - handler[0].call(vnode, handler[1], event) : - handler[0].apply(vnode, handler.slice(1).concat(event)); + handler[0].call(vnode, handler[1], event, vnode) : + handler[0].apply(vnode, handler.slice(1).concat(event, vnode)); } else { // call multiple handlers for (var i = 0; i < handler.length; i++) { diff --git a/test/eventlisteners.js b/test/eventlisteners.js index 6ec2879..7bc5eeb 100644 --- a/test/eventlisteners.js +++ b/test/eventlisteners.js @@ -69,7 +69,7 @@ describe('event listeners', function() { }); it('handles changed several values in array', function() { var result = []; - function clicked() { result.push([].slice.call(arguments, 0, arguments.length-1)); } + function clicked() { result.push([].slice.call(arguments, 0, arguments.length-2)); } var vnode1 = h('div', {on: {click: [clicked, 1, 2, 3]}}, [ h('a', 'Click my parent'), ]); @@ -121,14 +121,39 @@ describe('event listeners', function() { }); it('access to virtual node in event handler', function() { var result = []; - function clicked(ev) { result.push(this); } + function clicked(ev, vnode) { result.push(this); result.push(vnode); } var vnode1 = h('div', {on: {click: clicked }}, [ h('a', 'Click my parent'), ]); elm = patch(vnode0, vnode1).elm; elm.click(); - assert.equal(1, result.length); + assert.equal(2, result.length); + assert.equal(vnode1, result[0]); + assert.equal(vnode1, result[1]); + }), + it('access to virtual node in event handler with argument', function() { + var result = []; + function clicked(arg, ev, vnode) { result.push(this); result.push(vnode); } + var vnode1 = h('div', {on: {click: [clicked, 1] }}, [ + h('a', 'Click my parent'), + ]); + elm = patch(vnode0, vnode1).elm; + elm.click(); + assert.equal(2, result.length); + assert.equal(vnode1, result[0]); + assert.equal(vnode1, result[1]); + }), + it('access to virtual node in event handler with arguments', function() { + var result = []; + function clicked(arg1, arg2, ev, vnode) { result.push(this); result.push(vnode); } + var vnode1 = h('div', {on: {click: [clicked, 1, "2"] }}, [ + h('a', 'Click my parent'), + ]); + elm = patch(vnode0, vnode1).elm; + elm.click(); + assert.equal(2, result.length); assert.equal(vnode1, result[0]); + assert.equal(vnode1, result[1]); }); it('shared handlers in parent and child nodes', function() { var result = []; From cf4793c10a15762196cccf87570ba44a185744a8 Mon Sep 17 00:00:00 2001 From: "K." Date: Thu, 25 Aug 2016 11:32:16 +0500 Subject: [PATCH 15/32] Removing 'elm changed' case. --- modules/eventlisteners.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/modules/eventlisteners.js b/modules/eventlisteners.js index 53ffffb..f086a43 100644 --- a/modules/eventlisteners.js +++ b/modules/eventlisteners.js @@ -40,18 +40,17 @@ function updateEventListeners(oldVnode, vnode) { oldElm = oldVnode.elm, on = vnode && vnode.data.on, elm = vnode && vnode.elm, - elmChanged = oldElm !== elm, name; - // optimization for immutable handlers - if (!elmChanged && oldOn === on) { + // optimization for reused immutable handlers + if (oldOn === on) { return; } // remove existing listeners which no longer used if (oldOn && oldListener) { // if element changed or deleted we remove all existing listeners unconditionally - if (elmChanged || !on) { + if (!on) { for (name in oldOn) { // remove listener if element was changed or existing listeners removed oldElm.removeEventListener(name, oldListener, false); @@ -74,7 +73,7 @@ function updateEventListeners(oldVnode, vnode) { listener.vnode = vnode; // if element changed or added we add all needed listeners unconditionally - if (elmChanged || !oldOn) { + if (!oldOn) { for (name in on) { // add listener if element was changed or new listeners added elm.addEventListener(name, listener, false); From 41394317942e5151a3218511b772cbc955cc02e9 Mon Sep 17 00:00:00 2001 From: "K." Date: Thu, 25 Aug 2016 11:34:11 +0500 Subject: [PATCH 16/32] Optimization invoking handler with multiple arguments. --- modules/eventlisteners.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/modules/eventlisteners.js b/modules/eventlisteners.js index f086a43..34ad98d 100644 --- a/modules/eventlisteners.js +++ b/modules/eventlisteners.js @@ -6,9 +6,14 @@ function invokeHandler(handler, vnode, event) { // call handler with arguments if (typeof handler[0] === "function") { // special case for single argument for performance - handler.length === 2 ? - handler[0].call(vnode, handler[1], event, vnode) : - handler[0].apply(vnode, handler.slice(1).concat(event, vnode)); + if (handler.length === 2) { + handler[0].call(vnode, handler[1], event, vnode); + } else { + var args = handler.slice(1); + args.push(event); + args.push(vnode); + handler[0].apply(vnode, args); + } } else { // call multiple handlers for (var i = 0; i < handler.length; i++) { From f178f91dfa0a7a62188efeabfbc40b9a80a0f869 Mon Sep 17 00:00:00 2001 From: paldepind Date: Sat, 3 Sep 2016 09:35:16 +0200 Subject: [PATCH 17/32] Version 0.5.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index bceae8a..0e54113 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "snabbdom", - "version": "0.5.1", + "version": "0.5.2", "description": "A virtual DOM library with focus on simplicity, modularity, powerful features and performance.", "main": "snabbdom.js", "typings": "type-definitions/snabbdom.d.ts", From c091c59c5946cb15f77d7ffca846f2cdae23b785 Mon Sep 17 00:00:00 2001 From: Andre Staltz Date: Sun, 4 Sep 2016 18:01:33 +0300 Subject: [PATCH 18/32] Fix patch() so that the root is patched instead of recreated Previously, patch(element, vnode) would create a new element every time for the top-level element, unless the top-level vnode had no id and className. This is because emptyNodeAt() would create a vnode with sel equal to the element's tagName, NOT including id and className. This seems to be just a small fix, however this fix was crucial to get Web Components (custom elements) working with Cycle.js, because the custom element's "create" callback was being called infinitely and recursively, because snabbdom was creating the top-level element every time, even if the sel of oldVNode and vnode were supposed to be the same. --- snabbdom.js | 4 +++- test/core.js | 23 +++++++++++++++++------ 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/snabbdom.js b/snabbdom.js index 476f7d2..1fcc2ed 100644 --- a/snabbdom.js +++ b/snabbdom.js @@ -39,7 +39,9 @@ function init(modules, api) { } function emptyNodeAt(elm) { - return VNode(api.tagName(elm).toLowerCase(), {}, [], undefined, elm); + var id = elm.id ? '#' + elm.id : ''; + var c = elm.className ? '.' + elm.className.split(' ').join('.') : ''; + return VNode(api.tagName(elm).toLowerCase() + id + c, {}, [], undefined, elm); } function createRmCb(childElm, listeners) { diff --git a/test/core.js b/test/core.js index 07e2e74..dd3bac6 100644 --- a/test/core.js +++ b/test/core.js @@ -136,6 +136,17 @@ describe('snabbdom', function() { done(); } }); + it('is a patch of the root element', function () { + var elmWithIdAndClass = document.createElement('div'); + elmWithIdAndClass.id = 'id'; + elmWithIdAndClass.className = 'class'; + var vnode1 = h('div#id.class', [h('span', 'Hi')]); + elm = patch(elmWithIdAndClass, vnode1).elm; + assert.strictEqual(elm, elmWithIdAndClass); + assert.equal(elm.tagName, 'DIV'); + assert.equal(elm.id, 'id'); + assert.equal(elm.className, 'class'); + }); }); describe('pathing an element', function() { it('changes the elements classes', function() { @@ -670,7 +681,7 @@ describe('snabbdom', function() { {remove: function(_, rm) { rm2 = rm; }}, ]); var vnode1 = h('div', [h('a', {hook: {remove: function(_, rm) { rm3 = rm; }}})]); - var vnode2 = h('div', []); + var vnode2 = h('div', []); elm = patch(vnode0, vnode1).elm; assert.equal(elm.children.length, 1); elm = patch(vnode1, vnode2).elm; @@ -686,7 +697,7 @@ describe('snabbdom', function() { var result = []; var parent = document.createElement('div'); var vnode0 = document.createElement('div'); - parent.appendChild(vnode0); + parent.appendChild(vnode0); function cb(vnode, rm) { result.push(vnode); rm(); @@ -725,7 +736,7 @@ describe('snabbdom', function() { h('span', 'Child 2'), ]), ]); - var vnode2 = h('div'); + var vnode2 = h('div'); patch(vnode0, vnode1); patch(vnode1, vnode2); assert.equal(result.length, 1); @@ -752,7 +763,7 @@ describe('snabbdom', function() { h('span', 'Child 2'), ]), ]); - var vnode2 = h('div'); + var vnode2 = h('div'); patch(vnode0, vnode1); patch(vnode1, vnode2); assert.equal(created, 4); @@ -770,7 +781,7 @@ describe('snabbdom', function() { '', h('span', 'Third child'), ]); - var vnode2 = h('div'); + var vnode2 = h('div'); patch(vnode0, vnode1); patch(vnode1, vnode2); assert.equal(created, 2); @@ -790,7 +801,7 @@ describe('snabbdom', function() { h('span', ['Text 1', 'Text 2']), ]), ]); - var vnode2 = h('div'); + var vnode2 = h('div'); patch(vnode0, vnode1); patch(vnode1, vnode2); assert.equal(created, 4); From e68fb5884cf0b565ee238a145a83eb83437adfe4 Mon Sep 17 00:00:00 2001 From: fix-fix Date: Wed, 7 Sep 2016 17:35:14 +0500 Subject: [PATCH 19/32] Add test bundle to gitignore --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 708cc1b..6c739de 100644 --- a/.gitignore +++ b/.gitignore @@ -29,4 +29,5 @@ node_modules # Vim *.swp -test/browserified.js \ No newline at end of file +test/browserified.js +browserified.js From 4fe2f5fedffa422957cb574029e050b2584ec82f Mon Sep 17 00:00:00 2001 From: fix-fix Date: Wed, 7 Sep 2016 17:37:06 +0500 Subject: [PATCH 20/32] Add tests for attributes module --- test/attributes.js | 59 ++++++++++++++++++++++++++++++++++++++++++++++ test/index.js | 1 + 2 files changed, 60 insertions(+) create mode 100644 test/attributes.js diff --git a/test/attributes.js b/test/attributes.js new file mode 100644 index 0000000..1ab372c --- /dev/null +++ b/test/attributes.js @@ -0,0 +1,59 @@ +var assert = require('assert'); + +var snabbdom = require('../snabbdom'); +var patch = snabbdom.init([ + require('../modules/attributes'), +]); +var h = require('../h'); + +describe('attributes', function() { + var elm, vnode0; + beforeEach(function() { + elm = document.createElement('div'); + vnode0 = elm; + }); + it('have their provided values', function() { + var vnode1 = h('div', {attrs: {href: '/foo', minlength: 1, value: true}}); + elm = patch(vnode0, vnode1).elm; + assert.strictEqual(elm.getAttribute('href'), '/foo'); + assert.strictEqual(elm.getAttribute('minlength'), '1'); + assert.strictEqual(elm.getAttribute('value'), 'true'); + }); + it('are not omitted when falsy values are provided', function() { + var vnode1 = h('div', {attrs: {href: null, minlength: 0, value: false}}); + elm = patch(vnode0, vnode1).elm; + assert.strictEqual(elm.getAttribute('href'), 'null'); + assert.strictEqual(elm.getAttribute('minlength'), '0'); + assert.strictEqual(elm.getAttribute('value'), 'false'); + }); + describe('boolean attribute', function() { + it('is present if the value is truthy', function() { + var vnode1 = h('div', {attrs: {required: true, readonly: 1, noresize: 'truthy'}}); + elm = patch(vnode0, vnode1).elm; + assert.strictEqual(elm.getAttribute('required'), 'true'); + assert.strictEqual(elm.getAttribute('readonly'), '1'); + assert.strictEqual(elm.getAttribute('noresize'), 'truthy'); + }); + it('is omitted if the value is falsy', function() { + var vnode1 = h('div', {attrs: {required: false, readonly: 0, noresize: null}}); + elm = patch(vnode0, vnode1).elm; + assert.strictEqual(elm.getAttribute('required'), null); + assert.strictEqual(elm.getAttribute('readonly'), null); + assert.strictEqual(elm.getAttribute('noresize'), null); + }); + }); + describe('Object.prototype property', function() { + it('is not considered as a boolean attribute and shouldn\'t be omitted', function() { + var vnode1 = h('div', {attrs: {valueOf: true, toString: 1, constructor: 'truthy'}}); + elm = patch(vnode0, vnode1).elm; + assert.strictEqual(elm.getAttribute('valueOf'), 'true'); + assert.strictEqual(elm.getAttribute('toString'), '1'); + assert.strictEqual(elm.getAttribute('constructor'), 'truthy'); + var vnode2 = h('div', {attrs: {valueOf: false, toString: 0, constructor: null}}); + elm = patch(vnode0, vnode2).elm; + assert.strictEqual(elm.getAttribute('valueOf'), 'false'); + assert.strictEqual(elm.getAttribute('toString'), '0'); + assert.strictEqual(elm.getAttribute('constructor'), 'null'); + }) + }); +}); diff --git a/test/index.js b/test/index.js index 365c422..97fe3aa 100644 --- a/test/index.js +++ b/test/index.js @@ -4,3 +4,4 @@ require('./dataset'); require('./eventlisteners'); require('./attachto'); require('./thunk'); +require('./attributes'); From 95913ee3cae618db88b7acca8398a47c64845017 Mon Sep 17 00:00:00 2001 From: fix-fix Date: Wed, 7 Sep 2016 18:07:49 +0500 Subject: [PATCH 21/32] Don't treat Object.prototype properties as boolean attributes Keep boolean properties in an object without prototype to prevent false positive checks against attributes with the same name as Object.prototype properties. --- modules/attributes.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/attributes.js b/modules/attributes.js index d798a03..9a50259 100644 --- a/modules/attributes.js +++ b/modules/attributes.js @@ -5,7 +5,7 @@ var booleanAttrs = ["allowfullscreen", "async", "autofocus", "autoplay", "checke "required", "reversed", "scoped", "seamless", "selected", "sortable", "spellcheck", "translate", "truespeed", "typemustmatch", "visible"]; -var booleanAttrsDict = {}; +var booleanAttrsDict = Object.create(null); for(var i=0, len = booleanAttrs.length; i < len; i++) { booleanAttrsDict[booleanAttrs[i]] = true; } From 3e3acfcc54853a69890ddd917196dabc5028c215 Mon Sep 17 00:00:00 2001 From: paldepind Date: Fri, 9 Sep 2016 13:47:24 +0200 Subject: [PATCH 22/32] Version 0.5.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0e54113..6db5ef7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "snabbdom", - "version": "0.5.2", + "version": "0.5.3", "description": "A virtual DOM library with focus on simplicity, modularity, powerful features and performance.", "main": "snabbdom.js", "typings": "type-definitions/snabbdom.d.ts", From 453d982180604dbd0ebaf4ebb084d596e6d94feb Mon Sep 17 00:00:00 2001 From: Vitaly Dub Date: Mon, 26 Sep 2016 12:05:34 +0300 Subject: [PATCH 23/32] fixed links in README (paldepind -> snabbdom) --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 9cece7f..81b52cf 100644 --- a/README.md +++ b/README.md @@ -90,9 +90,9 @@ patch(vnode, newVnode); // Snabbdom efficiently updates the old view to the new ## Examples -* [Animated reordering of elements](http://paldepind.github.io/snabbdom/examples/reorder-animation/) -* [Hero transitions](http://paldepind.github.io/snabbdom/examples/hero/) -* [SVG Carousel](http://paldepind.github.io/snabbdom/examples/carousel-svg/) +* [Animated reordering of elements](http://snabbdom.github.io/snabbdom/examples/reorder-animation/) +* [Hero transitions](http://snabbdom.github.io/snabbdom/examples/hero/) +* [SVG Carousel](http://snabbdom.github.io/snabbdom/examples/carousel-svg/) ## Core documentation From 1b48d39e5611ecd1c855aa583d1866b4d0bf336f Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Sun, 2 Oct 2016 07:21:39 +1100 Subject: [PATCH 24/32] Fixed typos --- README.md | 12 ++++++------ test/attachto.js | 2 +- test/core.js | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 81b52cf..ef1fb28 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ performance, small size and all the features listed below. to hook into any part of the diff and patch process. * Splendid performance. Snabbdom is among the fastest virtual DOM libraries in the [Virtual DOM Benchmark](http://vdom-benchmark.github.io/vdom-benchmark/). - * Patch function with a function signature equivelant to a reduce/scan + * Patch function with a function signature equivalent to a reduce/scan function. Allows for easier integration with a FRP library. * Features in modules * `h` function for easily creating virtual DOM nodes. @@ -64,7 +64,7 @@ performance, small size and all the features listed below. ```javascript var snabbdom = require('snabbdom'); -var patch = snabbdom.init([ // Init patch function with choosen modules +var patch = snabbdom.init([ // Init patch function with chosen modules require('snabbdom/modules/class'), // makes it easy to toggle classes require('snabbdom/modules/props'), // for setting properties on DOM elements require('snabbdom/modules/style'), // handles styling on elements with support for animations @@ -121,7 +121,7 @@ is a vnode representing the new, updated view. If a DOM element with a parent is passed, `newVnode` will be turned into a DOM node, and the passed element will be replaced by the -created DOM node. If an old vnode is passed, Snabbdom will effeciently +created DOM node. If an old vnode is passed, Snabbdom will efficiently modify it to match the description in the new vnode. Any old vnode passed must be the resulting vnode from a previous call @@ -259,7 +259,7 @@ var myModule = { }; ``` -With this mechanism you can easily augument the behaviour of Snabbdom. +With this mechanism you can easily augment the behaviour of Snabbdom. For demonstration, take a look at the implementations of the default modules. @@ -452,7 +452,7 @@ h('div', [ ### SVG SVG just works when using the `h` function for creating virtual -nodes. SVG elements are automatially created with the appropriate +nodes. SVG elements are automatically created with the appropriate namespaces. ```javascript @@ -487,7 +487,7 @@ h('text', { The `thunk` function takes a selector, a key for identifying a thunk, a function that returns a vnode and a variable amount of state -parameters. If invoked, the render function will recieve the state +parameters. If invoked, the render function will receive the state arguments. `thunk(selector, key, renderFn, [stateArguments])` diff --git a/test/attachto.js b/test/attachto.js index db87e88..9645d68 100644 --- a/test/attachto.js +++ b/test/attachto.js @@ -75,7 +75,7 @@ describe('attachTo', function() { elm = patch(vnode1, vnode2).elm; assert.equal(elm.children.length, 1); }); - it('remove hook recieves real element', function() { + it('remove hook receives real element', function() { function rm(vnode, cb) { assert.equal(vnode.elm.tagName, 'DIV'); assert.equal(vnode.elm.innerHTML, 'First text'); diff --git a/test/core.js b/test/core.js index dd3bac6..33d7539 100644 --- a/test/core.js +++ b/test/core.js @@ -89,13 +89,13 @@ describe('snabbdom', function() { assert.equal(elm.firstChild.namespaceURI, SVGNamespace); assert.equal(elm.firstChild.firstChild.namespaceURI, XHTMLNamespace); }); - it('is recieves classes in selector', function() { + it('is receives classes in selector', function() { elm = patch(vnode0, h('div', [h('i.am.a.class')])).elm; assert(elm.firstChild.classList.contains('am')); assert(elm.firstChild.classList.contains('a')); assert(elm.firstChild.classList.contains('class')); }); - it('is recieves classes in class property', function() { + it('is receives classes in class property', function() { elm = patch(vnode0, h('i', {class: {am: true, a: true, class: true, not: false}})).elm; assert(elm.classList.contains('am')); assert(elm.classList.contains('a')); From 463cf0304d925be375d854dfa97196335befb48d Mon Sep 17 00:00:00 2001 From: LukaJCB Date: Tue, 11 Oct 2016 16:21:10 +0200 Subject: [PATCH 25/32] Updates distribution --- dist/h.js | 11 +- dist/h.min.js | 3 +- dist/h.min.js.map | 2 +- dist/snabbdom.js | 6 +- dist/snabbdom.min.js | 3 +- dist/snabbdom.min.js.map | 2 +- dist/snabbdom_attributes.js | 24 +++-- dist/snabbdom_attributes.min.js | 3 +- dist/snabbdom_attributes.min.js.map | 2 +- dist/snabbdom_class.js | 11 +- dist/snabbdom_class.min.js | 3 +- dist/snabbdom_class.min.js.map | 2 +- dist/snabbdom_eventlisteners.js | 135 +++++++++++++++--------- dist/snabbdom_eventlisteners.min.js | 3 +- dist/snabbdom_eventlisteners.min.js.map | 2 +- dist/snabbdom_props.js | 9 +- dist/snabbdom_props.min.js | 3 +- dist/snabbdom_props.min.js.map | 2 +- dist/snabbdom_style.js | 13 ++- dist/snabbdom_style.min.js | 3 +- dist/snabbdom_style.min.js.map | 2 +- 21 files changed, 148 insertions(+), 96 deletions(-) diff --git a/dist/h.js b/dist/h.js index de54c4a..b6b5d86 100644 --- a/dist/h.js +++ b/dist/h.js @@ -2,11 +2,12 @@ var VNode = require('./vnode'); var is = require('./is'); -function addNS(data, children) { +function addNS(data, children, sel) { data.ns = 'http://www.w3.org/2000/svg'; - if (children !== undefined) { + + if (sel !== 'foreignObject' && children !== undefined) { for (var i = 0; i < children.length; ++i) { - addNS(children[i].data, children[i].children); + addNS(children[i].data, children[i].children, children[i].sel); } } } @@ -28,7 +29,7 @@ module.exports = function h(sel, b, c) { } } if (sel[0] === 's' && sel[1] === 'v' && sel[2] === 'g') { - addNS(data, children); + addNS(data, children, sel); } return VNode(sel, data, children, text, undefined); }; @@ -48,4 +49,4 @@ module.exports = function(sel, data, children, text, elm) { },{}]},{},[1])(1) }); -//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJoLmpzIiwiaXMuanMiLCJ2bm9kZS5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQ0FBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ0pBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsImZpbGUiOiJnZW5lcmF0ZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uIGUodCxuLHIpe2Z1bmN0aW9uIHMobyx1KXtpZighbltvXSl7aWYoIXRbb10pe3ZhciBhPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7aWYoIXUmJmEpcmV0dXJuIGEobywhMCk7aWYoaSlyZXR1cm4gaShvLCEwKTt2YXIgZj1uZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiK28rXCInXCIpO3Rocm93IGYuY29kZT1cIk1PRFVMRV9OT1RfRk9VTkRcIixmfXZhciBsPW5bb109e2V4cG9ydHM6e319O3Rbb11bMF0uY2FsbChsLmV4cG9ydHMsZnVuY3Rpb24oZSl7dmFyIG49dFtvXVsxXVtlXTtyZXR1cm4gcyhuP246ZSl9LGwsbC5leHBvcnRzLGUsdCxuLHIpfXJldHVybiBuW29dLmV4cG9ydHN9dmFyIGk9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtmb3IodmFyIG89MDtvPHIubGVuZ3RoO28rKylzKHJbb10pO3JldHVybiBzfSkiLCJ2YXIgVk5vZGUgPSByZXF1aXJlKCcuL3Zub2RlJyk7XG52YXIgaXMgPSByZXF1aXJlKCcuL2lzJyk7XG5cbmZ1bmN0aW9uIGFkZE5TKGRhdGEsIGNoaWxkcmVuKSB7XG4gIGRhdGEubnMgPSAnaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnO1xuICBpZiAoY2hpbGRyZW4gIT09IHVuZGVmaW5lZCkge1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY2hpbGRyZW4ubGVuZ3RoOyArK2kpIHtcbiAgICAgIGFkZE5TKGNoaWxkcmVuW2ldLmRhdGEsIGNoaWxkcmVuW2ldLmNoaWxkcmVuKTtcbiAgICB9XG4gIH1cbn1cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBoKHNlbCwgYiwgYykge1xuICB2YXIgZGF0YSA9IHt9LCBjaGlsZHJlbiwgdGV4dCwgaTtcbiAgaWYgKGMgIT09IHVuZGVmaW5lZCkge1xuICAgIGRhdGEgPSBiO1xuICAgIGlmIChpcy5hcnJheShjKSkgeyBjaGlsZHJlbiA9IGM7IH1cbiAgICBlbHNlIGlmIChpcy5wcmltaXRpdmUoYykpIHsgdGV4dCA9IGM7IH1cbiAgfSBlbHNlIGlmIChiICE9PSB1bmRlZmluZWQpIHtcbiAgICBpZiAoaXMuYXJyYXkoYikpIHsgY2hpbGRyZW4gPSBiOyB9XG4gICAgZWxzZSBpZiAoaXMucHJpbWl0aXZlKGIpKSB7IHRleHQgPSBiOyB9XG4gICAgZWxzZSB7IGRhdGEgPSBiOyB9XG4gIH1cbiAgaWYgKGlzLmFycmF5KGNoaWxkcmVuKSkge1xuICAgIGZvciAoaSA9IDA7IGkgPCBjaGlsZHJlbi5sZW5ndGg7ICsraSkge1xuICAgICAgaWYgKGlzLnByaW1pdGl2ZShjaGlsZHJlbltpXSkpIGNoaWxkcmVuW2ldID0gVk5vZGUodW5kZWZpbmVkLCB1bmRlZmluZWQsIHVuZGVmaW5lZCwgY2hpbGRyZW5baV0pO1xuICAgIH1cbiAgfVxuICBpZiAoc2VsWzBdID09PSAncycgJiYgc2VsWzFdID09PSAndicgJiYgc2VsWzJdID09PSAnZycpIHtcbiAgICBhZGROUyhkYXRhLCBjaGlsZHJlbik7XG4gIH1cbiAgcmV0dXJuIFZOb2RlKHNlbCwgZGF0YSwgY2hpbGRyZW4sIHRleHQsIHVuZGVmaW5lZCk7XG59O1xuIiwibW9kdWxlLmV4cG9ydHMgPSB7XG4gIGFycmF5OiBBcnJheS5pc0FycmF5LFxuICBwcmltaXRpdmU6IGZ1bmN0aW9uKHMpIHsgcmV0dXJuIHR5cGVvZiBzID09PSAnc3RyaW5nJyB8fCB0eXBlb2YgcyA9PT0gJ251bWJlcic7IH0sXG59O1xuIiwibW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihzZWwsIGRhdGEsIGNoaWxkcmVuLCB0ZXh0LCBlbG0pIHtcbiAgdmFyIGtleSA9IGRhdGEgPT09IHVuZGVmaW5lZCA/IHVuZGVmaW5lZCA6IGRhdGEua2V5O1xuICByZXR1cm4ge3NlbDogc2VsLCBkYXRhOiBkYXRhLCBjaGlsZHJlbjogY2hpbGRyZW4sXG4gICAgICAgICAgdGV4dDogdGV4dCwgZWxtOiBlbG0sIGtleToga2V5fTtcbn07XG4iXX0= +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJoLmpzIiwiaXMuanMiLCJ2bm9kZS5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQ0FBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDSkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwiZmlsZSI6ImdlbmVyYXRlZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzQ29udGVudCI6WyIoZnVuY3Rpb24gZSh0LG4scil7ZnVuY3Rpb24gcyhvLHUpe2lmKCFuW29dKXtpZighdFtvXSl7dmFyIGE9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtpZighdSYmYSlyZXR1cm4gYShvLCEwKTtpZihpKXJldHVybiBpKG8sITApO3ZhciBmPW5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIrbytcIidcIik7dGhyb3cgZi5jb2RlPVwiTU9EVUxFX05PVF9GT1VORFwiLGZ9dmFyIGw9bltvXT17ZXhwb3J0czp7fX07dFtvXVswXS5jYWxsKGwuZXhwb3J0cyxmdW5jdGlvbihlKXt2YXIgbj10W29dWzFdW2VdO3JldHVybiBzKG4/bjplKX0sbCxsLmV4cG9ydHMsZSx0LG4scil9cmV0dXJuIG5bb10uZXhwb3J0c312YXIgaT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2Zvcih2YXIgbz0wO288ci5sZW5ndGg7bysrKXMocltvXSk7cmV0dXJuIHN9KSIsInZhciBWTm9kZSA9IHJlcXVpcmUoJy4vdm5vZGUnKTtcbnZhciBpcyA9IHJlcXVpcmUoJy4vaXMnKTtcblxuZnVuY3Rpb24gYWRkTlMoZGF0YSwgY2hpbGRyZW4sIHNlbCkge1xuICBkYXRhLm5zID0gJ2h0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnJztcblxuICBpZiAoc2VsICE9PSAnZm9yZWlnbk9iamVjdCcgJiYgY2hpbGRyZW4gIT09IHVuZGVmaW5lZCkge1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY2hpbGRyZW4ubGVuZ3RoOyArK2kpIHtcbiAgICAgIGFkZE5TKGNoaWxkcmVuW2ldLmRhdGEsIGNoaWxkcmVuW2ldLmNoaWxkcmVuLCBjaGlsZHJlbltpXS5zZWwpO1xuICAgIH1cbiAgfVxufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGgoc2VsLCBiLCBjKSB7XG4gIHZhciBkYXRhID0ge30sIGNoaWxkcmVuLCB0ZXh0LCBpO1xuICBpZiAoYyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgZGF0YSA9IGI7XG4gICAgaWYgKGlzLmFycmF5KGMpKSB7IGNoaWxkcmVuID0gYzsgfVxuICAgIGVsc2UgaWYgKGlzLnByaW1pdGl2ZShjKSkgeyB0ZXh0ID0gYzsgfVxuICB9IGVsc2UgaWYgKGIgIT09IHVuZGVmaW5lZCkge1xuICAgIGlmIChpcy5hcnJheShiKSkgeyBjaGlsZHJlbiA9IGI7IH1cbiAgICBlbHNlIGlmIChpcy5wcmltaXRpdmUoYikpIHsgdGV4dCA9IGI7IH1cbiAgICBlbHNlIHsgZGF0YSA9IGI7IH1cbiAgfVxuICBpZiAoaXMuYXJyYXkoY2hpbGRyZW4pKSB7XG4gICAgZm9yIChpID0gMDsgaSA8IGNoaWxkcmVuLmxlbmd0aDsgKytpKSB7XG4gICAgICBpZiAoaXMucHJpbWl0aXZlKGNoaWxkcmVuW2ldKSkgY2hpbGRyZW5baV0gPSBWTm9kZSh1bmRlZmluZWQsIHVuZGVmaW5lZCwgdW5kZWZpbmVkLCBjaGlsZHJlbltpXSk7XG4gICAgfVxuICB9XG4gIGlmIChzZWxbMF0gPT09ICdzJyAmJiBzZWxbMV0gPT09ICd2JyAmJiBzZWxbMl0gPT09ICdnJykge1xuICAgIGFkZE5TKGRhdGEsIGNoaWxkcmVuLCBzZWwpO1xuICB9XG4gIHJldHVybiBWTm9kZShzZWwsIGRhdGEsIGNoaWxkcmVuLCB0ZXh0LCB1bmRlZmluZWQpO1xufTtcbiIsIm1vZHVsZS5leHBvcnRzID0ge1xuICBhcnJheTogQXJyYXkuaXNBcnJheSxcbiAgcHJpbWl0aXZlOiBmdW5jdGlvbihzKSB7IHJldHVybiB0eXBlb2YgcyA9PT0gJ3N0cmluZycgfHwgdHlwZW9mIHMgPT09ICdudW1iZXInOyB9LFxufTtcbiIsIm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oc2VsLCBkYXRhLCBjaGlsZHJlbiwgdGV4dCwgZWxtKSB7XG4gIHZhciBrZXkgPSBkYXRhID09PSB1bmRlZmluZWQgPyB1bmRlZmluZWQgOiBkYXRhLmtleTtcbiAgcmV0dXJuIHtzZWw6IHNlbCwgZGF0YTogZGF0YSwgY2hpbGRyZW46IGNoaWxkcmVuLFxuICAgICAgICAgIHRleHQ6IHRleHQsIGVsbTogZWxtLCBrZXk6IGtleX07XG59O1xuIl19 diff --git a/dist/h.min.js b/dist/h.min.js index 7280672..60393d2 100644 --- a/dist/h.min.js +++ b/dist/h.min.js @@ -1,2 +1 @@ -!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var r;r="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,r.h=e()}}(function(){return function e(r,n,i){function o(f,u){if(!n[f]){if(!r[f]){var d="function"==typeof require&&require;if(!u&&d)return d(f,!0);if(t)return t(f,!0);var a=new Error("Cannot find module '"+f+"'");throw a.code="MODULE_NOT_FOUND",a}var v=n[f]={exports:{}};r[f][0].call(v.exports,function(e){var n=r[f][1][e];return o(n?n:e)},v,v.exports,e,r,n,i)}return n[f].exports}for(var t="function"==typeof require&&require,f=0;f=r;++r)i=e[r].key,o(i)&&(f[i]=r);return f}function l(e,t){function n(e){return a(t.tagName(e).toLowerCase(),{},[],void 0,e)}function l(e,n){return function(){if(0===--n){var r=t.parentNode(e);t.removeChild(r,e)}}}function m(e,n){var r,i=e.data;o(i)&&o(r=i.hook)&&o(r=r.init)&&(r(e),i=e.data);var f,l=e.children,a=e.sel;if(o(a)){var d=a.indexOf("#"),s=a.indexOf(".",d),p=d>0?d:a.length,h=s>0?s:a.length,v=-1!==d||-1!==s?a.slice(0,Math.min(p,h)):a;if(f=e.elm=o(i)&&o(r=i.ns)?t.createElementNS(r,v):t.createElement(v),h>p&&(f.id=a.slice(p+1,h)),s>0&&(f.className=a.slice(h+1).replace(/\./g," ")),u.array(l))for(r=0;r=o;++o)t.insertBefore(e,m(r[o],f),n)}function h(e){var t,n,r=e.data;if(o(r)){for(o(t=r.hook)&&o(t=t.destroy)&&t(e),t=0;t=r;++r){var f,a,u,d=n[r];if(o(d))if(o(d.sel)){for(h(d),a=C.remove.length+1,u=l(d.elm,a),f=0;f=s&&C>=h;)r(y)?y=n[++s]:r(N)?N=n[--x]:i(y,k)?(g(y,k,l),y=n[++s],k=o[++h]):i(N,b)?(g(N,b,l),N=n[--x],b=o[--C]):i(y,b)?(g(y,b,l),t.insertBefore(e,y.elm,t.nextSibling(N.elm)),y=n[++s],b=o[--C]):i(N,k)?(g(N,k,l),t.insertBefore(e,N.elm,y.elm),N=n[--x],k=o[++h]):(r(a)&&(a=f(n,s,x)),u=a[k.key],r(u)?(t.insertBefore(e,m(k,l),y.elm),k=o[++h]):(d=n[u],g(d,k,l),n[u]=void 0,t.insertBefore(e,d.elm,y.elm),k=o[++h]));s>x?(c=r(o[C+1])?null:o[C+1].elm,p(e,c,o,h,C,l)):h>C&&v(e,n,s,x)}function g(e,n,f){var l,a;o(l=n.data)&&o(a=l.hook)&&o(l=a.prepatch)&&l(e,n);var u=n.elm=e.elm,d=e.children,c=n.children;if(e!==n){if(!i(e,n)){var s=t.parentNode(e.elm);return u=m(n,f),t.insertBefore(s,u,e.elm),void v(s,[e],0,0)}if(o(n.data)){for(l=0;l0?d:a.length,h=s>0?s:a.length,v=d!==-1||s!==-1?a.slice(0,Math.min(p,h)):a;if(l=e.elm=o(i)&&o(r=i.ns)?t.createElementNS(r,v):t.createElement(v),p0&&(l.className=a.slice(h+1).replace(/\./g," ")),u.array(f))for(r=0;rx?(c=r(o[C+1])?null:o[C+1].elm,p(e,c,o,h,C,f)):h>C&&v(e,n,s,x)}function g(e,n,l){var f,a;o(f=n.data)&&o(a=f.hook)&&o(f=a.prepatch)&&f(e,n);var u=n.elm=e.elm,d=e.children,c=n.children;if(e!==n){if(!i(e,n)){var s=t.parentNode(e.elm);return u=m(n,l),t.insertBefore(s,u,e.elm),void v(s,[e],0,0)}if(o(n.data)){for(f=0;f 0 ? hashIdx : sel.length;\n var dot = dotIdx > 0 ? dotIdx : sel.length;\n var tag = hashIdx !== -1 || dotIdx !== -1 ? sel.slice(0, Math.min(hash, dot)) : sel;\n elm = vnode.elm = isDef(data) && isDef(i = data.ns) ? api.createElementNS(i, tag)\n : api.createElement(tag);\n if (hash < dot) elm.id = sel.slice(hash + 1, dot);\n if (dotIdx > 0) elm.className = sel.slice(dot + 1).replace(/\\./g, ' ');\n if (is.array(children)) {\n for (i = 0; i < children.length; ++i) {\n api.appendChild(elm, createElm(children[i], insertedVnodeQueue));\n }\n } else if (is.primitive(vnode.text)) {\n api.appendChild(elm, api.createTextNode(vnode.text));\n }\n for (i = 0; i < cbs.create.length; ++i) cbs.create[i](emptyNode, vnode);\n i = vnode.data.hook; // Reuse variable\n if (isDef(i)) {\n if (i.create) i.create(emptyNode, vnode);\n if (i.insert) insertedVnodeQueue.push(vnode);\n }\n } else {\n elm = vnode.elm = api.createTextNode(vnode.text);\n }\n return vnode.elm;\n }\n\n function addVnodes(parentElm, before, vnodes, startIdx, endIdx, insertedVnodeQueue) {\n for (; startIdx <= endIdx; ++startIdx) {\n api.insertBefore(parentElm, createElm(vnodes[startIdx], insertedVnodeQueue), before);\n }\n }\n\n function invokeDestroyHook(vnode) {\n var i, j, data = vnode.data;\n if (isDef(data)) {\n if (isDef(i = data.hook) && isDef(i = i.destroy)) i(vnode);\n for (i = 0; i < cbs.destroy.length; ++i) cbs.destroy[i](vnode);\n if (isDef(i = vnode.children)) {\n for (j = 0; j < vnode.children.length; ++j) {\n invokeDestroyHook(vnode.children[j]);\n }\n }\n }\n }\n\n function removeVnodes(parentElm, vnodes, startIdx, endIdx) {\n for (; startIdx <= endIdx; ++startIdx) {\n var i, listeners, rm, ch = vnodes[startIdx];\n if (isDef(ch)) {\n if (isDef(ch.sel)) {\n invokeDestroyHook(ch);\n listeners = cbs.remove.length + 1;\n rm = createRmCb(ch.elm, listeners);\n for (i = 0; i < cbs.remove.length; ++i) cbs.remove[i](ch, rm);\n if (isDef(i = ch.data) && isDef(i = i.hook) && isDef(i = i.remove)) {\n i(ch, rm);\n } else {\n rm();\n }\n } else { // Text node\n api.removeChild(parentElm, ch.elm);\n }\n }\n }\n }\n\n function updateChildren(parentElm, oldCh, newCh, insertedVnodeQueue) {\n var oldStartIdx = 0, newStartIdx = 0;\n var oldEndIdx = oldCh.length - 1;\n var oldStartVnode = oldCh[0];\n var oldEndVnode = oldCh[oldEndIdx];\n var newEndIdx = newCh.length - 1;\n var newStartVnode = newCh[0];\n var newEndVnode = newCh[newEndIdx];\n var oldKeyToIdx, idxInOld, elmToMove, before;\n\n while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) {\n if (isUndef(oldStartVnode)) {\n oldStartVnode = oldCh[++oldStartIdx]; // Vnode has been moved left\n } else if (isUndef(oldEndVnode)) {\n oldEndVnode = oldCh[--oldEndIdx];\n } else if (sameVnode(oldStartVnode, newStartVnode)) {\n patchVnode(oldStartVnode, newStartVnode, insertedVnodeQueue);\n oldStartVnode = oldCh[++oldStartIdx];\n newStartVnode = newCh[++newStartIdx];\n } else if (sameVnode(oldEndVnode, newEndVnode)) {\n patchVnode(oldEndVnode, newEndVnode, insertedVnodeQueue);\n oldEndVnode = oldCh[--oldEndIdx];\n newEndVnode = newCh[--newEndIdx];\n } else if (sameVnode(oldStartVnode, newEndVnode)) { // Vnode moved right\n patchVnode(oldStartVnode, newEndVnode, insertedVnodeQueue);\n api.insertBefore(parentElm, oldStartVnode.elm, api.nextSibling(oldEndVnode.elm));\n oldStartVnode = oldCh[++oldStartIdx];\n newEndVnode = newCh[--newEndIdx];\n } else if (sameVnode(oldEndVnode, newStartVnode)) { // Vnode moved left\n patchVnode(oldEndVnode, newStartVnode, insertedVnodeQueue);\n api.insertBefore(parentElm, oldEndVnode.elm, oldStartVnode.elm);\n oldEndVnode = oldCh[--oldEndIdx];\n newStartVnode = newCh[++newStartIdx];\n } else {\n if (isUndef(oldKeyToIdx)) oldKeyToIdx = createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx);\n idxInOld = oldKeyToIdx[newStartVnode.key];\n if (isUndef(idxInOld)) { // New element\n api.insertBefore(parentElm, createElm(newStartVnode, insertedVnodeQueue), oldStartVnode.elm);\n newStartVnode = newCh[++newStartIdx];\n } else {\n elmToMove = oldCh[idxInOld];\n patchVnode(elmToMove, newStartVnode, insertedVnodeQueue);\n oldCh[idxInOld] = undefined;\n api.insertBefore(parentElm, elmToMove.elm, oldStartVnode.elm);\n newStartVnode = newCh[++newStartIdx];\n }\n }\n }\n if (oldStartIdx > oldEndIdx) {\n before = isUndef(newCh[newEndIdx+1]) ? null : newCh[newEndIdx+1].elm;\n addVnodes(parentElm, before, newCh, newStartIdx, newEndIdx, insertedVnodeQueue);\n } else if (newStartIdx > newEndIdx) {\n removeVnodes(parentElm, oldCh, oldStartIdx, oldEndIdx);\n }\n }\n\n function patchVnode(oldVnode, vnode, insertedVnodeQueue) {\n var i, hook;\n if (isDef(i = vnode.data) && isDef(hook = i.hook) && isDef(i = hook.prepatch)) {\n i(oldVnode, vnode);\n }\n var elm = vnode.elm = oldVnode.elm, oldCh = oldVnode.children, ch = vnode.children;\n if (oldVnode === vnode) return;\n if (!sameVnode(oldVnode, vnode)) {\n var parentElm = api.parentNode(oldVnode.elm);\n elm = createElm(vnode, insertedVnodeQueue);\n api.insertBefore(parentElm, elm, oldVnode.elm);\n removeVnodes(parentElm, [oldVnode], 0, 0);\n return;\n }\n if (isDef(vnode.data)) {\n for (i = 0; i < cbs.update.length; ++i) cbs.update[i](oldVnode, vnode);\n i = vnode.data.hook;\n if (isDef(i) && isDef(i = i.update)) i(oldVnode, vnode);\n }\n if (isUndef(vnode.text)) {\n if (isDef(oldCh) && isDef(ch)) {\n if (oldCh !== ch) updateChildren(elm, oldCh, ch, insertedVnodeQueue);\n } else if (isDef(ch)) {\n if (isDef(oldVnode.text)) api.setTextContent(elm, '');\n addVnodes(elm, null, ch, 0, ch.length - 1, insertedVnodeQueue);\n } else if (isDef(oldCh)) {\n removeVnodes(elm, oldCh, 0, oldCh.length - 1);\n } else if (isDef(oldVnode.text)) {\n api.setTextContent(elm, '');\n }\n } else if (oldVnode.text !== vnode.text) {\n api.setTextContent(elm, vnode.text);\n }\n if (isDef(hook) && isDef(i = hook.postpatch)) {\n i(oldVnode, vnode);\n }\n }\n\n return function(oldVnode, vnode) {\n var i, elm, parent;\n var insertedVnodeQueue = [];\n for (i = 0; i < cbs.pre.length; ++i) cbs.pre[i]();\n\n if (isUndef(oldVnode.sel)) {\n oldVnode = emptyNodeAt(oldVnode);\n }\n\n if (sameVnode(oldVnode, vnode)) {\n patchVnode(oldVnode, vnode, insertedVnodeQueue);\n } else {\n elm = oldVnode.elm;\n parent = api.parentNode(elm);\n\n createElm(vnode, insertedVnodeQueue);\n\n if (parent !== null) {\n api.insertBefore(parent, vnode.elm, api.nextSibling(elm));\n removeVnodes(parent, [oldVnode], 0, 0);\n }\n }\n\n for (i = 0; i < insertedVnodeQueue.length; ++i) {\n insertedVnodeQueue[i].data.hook.insert(insertedVnodeQueue[i]);\n }\n for (i = 0; i < cbs.post.length; ++i) cbs.post[i]();\n return vnode;\n };\n}\n\nmodule.exports = {init: init};\n\n},{\"./htmldomapi\":1,\"./is\":2,\"./vnode\":4}],4:[function(require,module,exports){\nmodule.exports = function(sel, data, children, text, elm) {\n var key = data === undefined ? undefined : data.key;\n return {sel: sel, data: data, children: children,\n text: text, elm: elm, key: key};\n};\n\n},{}]},{},[3])(3)\n});\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJodG1sZG9tYXBpLmpzIiwiaXMuanMiLCJzbmFiYmRvbS5qcyIsInZub2RlLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FDQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdERBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDSkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbFFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsImZpbGUiOiJnZW5lcmF0ZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uIGUodCxuLHIpe2Z1bmN0aW9uIHMobyx1KXtpZighbltvXSl7aWYoIXRbb10pe3ZhciBhPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7aWYoIXUmJmEpcmV0dXJuIGEobywhMCk7aWYoaSlyZXR1cm4gaShvLCEwKTt2YXIgZj1uZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiK28rXCInXCIpO3Rocm93IGYuY29kZT1cIk1PRFVMRV9OT1RfRk9VTkRcIixmfXZhciBsPW5bb109e2V4cG9ydHM6e319O3Rbb11bMF0uY2FsbChsLmV4cG9ydHMsZnVuY3Rpb24oZSl7dmFyIG49dFtvXVsxXVtlXTtyZXR1cm4gcyhuP246ZSl9LGwsbC5leHBvcnRzLGUsdCxuLHIpfXJldHVybiBuW29dLmV4cG9ydHN9dmFyIGk9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtmb3IodmFyIG89MDtvPHIubGVuZ3RoO28rKylzKHJbb10pO3JldHVybiBzfSkiLCJmdW5jdGlvbiBjcmVhdGVFbGVtZW50KHRhZ05hbWUpe1xuICByZXR1cm4gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCh0YWdOYW1lKTtcbn1cblxuZnVuY3Rpb24gY3JlYXRlRWxlbWVudE5TKG5hbWVzcGFjZVVSSSwgcXVhbGlmaWVkTmFtZSl7XG4gIHJldHVybiBkb2N1bWVudC5jcmVhdGVFbGVtZW50TlMobmFtZXNwYWNlVVJJLCBxdWFsaWZpZWROYW1lKTtcbn1cblxuZnVuY3Rpb24gY3JlYXRlVGV4dE5vZGUodGV4dCl7XG4gIHJldHVybiBkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZSh0ZXh0KTtcbn1cblxuXG5mdW5jdGlvbiBpbnNlcnRCZWZvcmUocGFyZW50Tm9kZSwgbmV3Tm9kZSwgcmVmZXJlbmNlTm9kZSl7XG4gIHBhcmVudE5vZGUuaW5zZXJ0QmVmb3JlKG5ld05vZGUsIHJlZmVyZW5jZU5vZGUpO1xufVxuXG5cbmZ1bmN0aW9uIHJlbW92ZUNoaWxkKG5vZGUsIGNoaWxkKXtcbiAgbm9kZS5yZW1vdmVDaGlsZChjaGlsZCk7XG59XG5cbmZ1bmN0aW9uIGFwcGVuZENoaWxkKG5vZGUsIGNoaWxkKXtcbiAgbm9kZS5hcHBlbmRDaGlsZChjaGlsZCk7XG59XG5cbmZ1bmN0aW9uIHBhcmVudE5vZGUobm9kZSl7XG4gIHJldHVybiBub2RlLnBhcmVudEVsZW1lbnQ7XG59XG5cbmZ1bmN0aW9uIG5leHRTaWJsaW5nKG5vZGUpe1xuICByZXR1cm4gbm9kZS5uZXh0U2libGluZztcbn1cblxuZnVuY3Rpb24gdGFnTmFtZShub2RlKXtcbiAgcmV0dXJuIG5vZGUudGFnTmFtZTtcbn1cblxuZnVuY3Rpb24gc2V0VGV4dENvbnRlbnQobm9kZSwgdGV4dCl7XG4gIG5vZGUudGV4dENvbnRlbnQgPSB0ZXh0O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgY3JlYXRlRWxlbWVudDogY3JlYXRlRWxlbWVudCxcbiAgY3JlYXRlRWxlbWVudE5TOiBjcmVhdGVFbGVtZW50TlMsXG4gIGNyZWF0ZVRleHROb2RlOiBjcmVhdGVUZXh0Tm9kZSxcbiAgYXBwZW5kQ2hpbGQ6IGFwcGVuZENoaWxkLFxuICByZW1vdmVDaGlsZDogcmVtb3ZlQ2hpbGQsXG4gIGluc2VydEJlZm9yZTogaW5zZXJ0QmVmb3JlLFxuICBwYXJlbnROb2RlOiBwYXJlbnROb2RlLFxuICBuZXh0U2libGluZzogbmV4dFNpYmxpbmcsXG4gIHRhZ05hbWU6IHRhZ05hbWUsXG4gIHNldFRleHRDb250ZW50OiBzZXRUZXh0Q29udGVudFxufTtcbiIsIm1vZHVsZS5leHBvcnRzID0ge1xuICBhcnJheTogQXJyYXkuaXNBcnJheSxcbiAgcHJpbWl0aXZlOiBmdW5jdGlvbihzKSB7IHJldHVybiB0eXBlb2YgcyA9PT0gJ3N0cmluZycgfHwgdHlwZW9mIHMgPT09ICdudW1iZXInOyB9LFxufTtcbiIsIi8vIGpzaGludCBuZXdjYXA6IGZhbHNlXG4vKiBnbG9iYWwgcmVxdWlyZSwgbW9kdWxlLCBkb2N1bWVudCwgTm9kZSAqL1xuJ3VzZSBzdHJpY3QnO1xuXG52YXIgVk5vZGUgPSByZXF1aXJlKCcuL3Zub2RlJyk7XG52YXIgaXMgPSByZXF1aXJlKCcuL2lzJyk7XG52YXIgZG9tQXBpID0gcmVxdWlyZSgnLi9odG1sZG9tYXBpJyk7XG5cbmZ1bmN0aW9uIGlzVW5kZWYocykgeyByZXR1cm4gcyA9PT0gdW5kZWZpbmVkOyB9XG5mdW5jdGlvbiBpc0RlZihzKSB7IHJldHVybiBzICE9PSB1bmRlZmluZWQ7IH1cblxudmFyIGVtcHR5Tm9kZSA9IFZOb2RlKCcnLCB7fSwgW10sIHVuZGVmaW5lZCwgdW5kZWZpbmVkKTtcblxuZnVuY3Rpb24gc2FtZVZub2RlKHZub2RlMSwgdm5vZGUyKSB7XG4gIHJldHVybiB2bm9kZTEua2V5ID09PSB2bm9kZTIua2V5ICYmIHZub2RlMS5zZWwgPT09IHZub2RlMi5zZWw7XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZUtleVRvT2xkSWR4KGNoaWxkcmVuLCBiZWdpbklkeCwgZW5kSWR4KSB7XG4gIHZhciBpLCBtYXAgPSB7fSwga2V5O1xuICBmb3IgKGkgPSBiZWdpbklkeDsgaSA8PSBlbmRJZHg7ICsraSkge1xuICAgIGtleSA9IGNoaWxkcmVuW2ldLmtleTtcbiAgICBpZiAoaXNEZWYoa2V5KSkgbWFwW2tleV0gPSBpO1xuICB9XG4gIHJldHVybiBtYXA7XG59XG5cbnZhciBob29rcyA9IFsnY3JlYXRlJywgJ3VwZGF0ZScsICdyZW1vdmUnLCAnZGVzdHJveScsICdwcmUnLCAncG9zdCddO1xuXG5mdW5jdGlvbiBpbml0KG1vZHVsZXMsIGFwaSkge1xuICB2YXIgaSwgaiwgY2JzID0ge307XG5cbiAgaWYgKGlzVW5kZWYoYXBpKSkgYXBpID0gZG9tQXBpO1xuXG4gIGZvciAoaSA9IDA7IGkgPCBob29rcy5sZW5ndGg7ICsraSkge1xuICAgIGNic1tob29rc1tpXV0gPSBbXTtcbiAgICBmb3IgKGogPSAwOyBqIDwgbW9kdWxlcy5sZW5ndGg7ICsraikge1xuICAgICAgaWYgKG1vZHVsZXNbal1baG9va3NbaV1dICE9PSB1bmRlZmluZWQpIGNic1tob29rc1tpXV0ucHVzaChtb2R1bGVzW2pdW2hvb2tzW2ldXSk7XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gZW1wdHlOb2RlQXQoZWxtKSB7XG4gICAgcmV0dXJuIFZOb2RlKGFwaS50YWdOYW1lKGVsbSkudG9Mb3dlckNhc2UoKSwge30sIFtdLCB1bmRlZmluZWQsIGVsbSk7XG4gIH1cblxuICBmdW5jdGlvbiBjcmVhdGVSbUNiKGNoaWxkRWxtLCBsaXN0ZW5lcnMpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICBpZiAoLS1saXN0ZW5lcnMgPT09IDApIHtcbiAgICAgICAgdmFyIHBhcmVudCA9IGFwaS5wYXJlbnROb2RlKGNoaWxkRWxtKTtcbiAgICAgICAgYXBpLnJlbW92ZUNoaWxkKHBhcmVudCwgY2hpbGRFbG0pO1xuICAgICAgfVxuICAgIH07XG4gIH1cblxuICBmdW5jdGlvbiBjcmVhdGVFbG0odm5vZGUsIGluc2VydGVkVm5vZGVRdWV1ZSkge1xuICAgIHZhciBpLCBkYXRhID0gdm5vZGUuZGF0YTtcbiAgICBpZiAoaXNEZWYoZGF0YSkpIHtcbiAgICAgIGlmIChpc0RlZihpID0gZGF0YS5ob29rKSAmJiBpc0RlZihpID0gaS5pbml0KSkge1xuICAgICAgICBpKHZub2RlKTtcbiAgICAgICAgZGF0YSA9IHZub2RlLmRhdGE7XG4gICAgICB9XG4gICAgfVxuICAgIHZhciBlbG0sIGNoaWxkcmVuID0gdm5vZGUuY2hpbGRyZW4sIHNlbCA9IHZub2RlLnNlbDtcbiAgICBpZiAoaXNEZWYoc2VsKSkge1xuICAgICAgLy8gUGFyc2Ugc2VsZWN0b3JcbiAgICAgIHZhciBoYXNoSWR4ID0gc2VsLmluZGV4T2YoJyMnKTtcbiAgICAgIHZhciBkb3RJZHggPSBzZWwuaW5kZXhPZignLicsIGhhc2hJZHgpO1xuICAgICAgdmFyIGhhc2ggPSBoYXNoSWR4ID4gMCA/IGhhc2hJZHggOiBzZWwubGVuZ3RoO1xuICAgICAgdmFyIGRvdCA9IGRvdElkeCA+IDAgPyBkb3RJZHggOiBzZWwubGVuZ3RoO1xuICAgICAgdmFyIHRhZyA9IGhhc2hJZHggIT09IC0xIHx8IGRvdElkeCAhPT0gLTEgPyBzZWwuc2xpY2UoMCwgTWF0aC5taW4oaGFzaCwgZG90KSkgOiBzZWw7XG4gICAgICBlbG0gPSB2bm9kZS5lbG0gPSBpc0RlZihkYXRhKSAmJiBpc0RlZihpID0gZGF0YS5ucykgPyBhcGkuY3JlYXRlRWxlbWVudE5TKGksIHRhZylcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA6IGFwaS5jcmVhdGVFbGVtZW50KHRhZyk7XG4gICAgICBpZiAoaGFzaCA8IGRvdCkgZWxtLmlkID0gc2VsLnNsaWNlKGhhc2ggKyAxLCBkb3QpO1xuICAgICAgaWYgKGRvdElkeCA+IDApIGVsbS5jbGFzc05hbWUgPSBzZWwuc2xpY2UoZG90ICsgMSkucmVwbGFjZSgvXFwuL2csICcgJyk7XG4gICAgICBpZiAoaXMuYXJyYXkoY2hpbGRyZW4pKSB7XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBjaGlsZHJlbi5sZW5ndGg7ICsraSkge1xuICAgICAgICAgIGFwaS5hcHBlbmRDaGlsZChlbG0sIGNyZWF0ZUVsbShjaGlsZHJlbltpXSwgaW5zZXJ0ZWRWbm9kZVF1ZXVlKSk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAoaXMucHJpbWl0aXZlKHZub2RlLnRleHQpKSB7XG4gICAgICAgIGFwaS5hcHBlbmRDaGlsZChlbG0sIGFwaS5jcmVhdGVUZXh0Tm9kZSh2bm9kZS50ZXh0KSk7XG4gICAgICB9XG4gICAgICBmb3IgKGkgPSAwOyBpIDwgY2JzLmNyZWF0ZS5sZW5ndGg7ICsraSkgY2JzLmNyZWF0ZVtpXShlbXB0eU5vZGUsIHZub2RlKTtcbiAgICAgIGkgPSB2bm9kZS5kYXRhLmhvb2s7IC8vIFJldXNlIHZhcmlhYmxlXG4gICAgICBpZiAoaXNEZWYoaSkpIHtcbiAgICAgICAgaWYgKGkuY3JlYXRlKSBpLmNyZWF0ZShlbXB0eU5vZGUsIHZub2RlKTtcbiAgICAgICAgaWYgKGkuaW5zZXJ0KSBpbnNlcnRlZFZub2RlUXVldWUucHVzaCh2bm9kZSk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGVsbSA9IHZub2RlLmVsbSA9IGFwaS5jcmVhdGVUZXh0Tm9kZSh2bm9kZS50ZXh0KTtcbiAgICB9XG4gICAgcmV0dXJuIHZub2RlLmVsbTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGFkZFZub2RlcyhwYXJlbnRFbG0sIGJlZm9yZSwgdm5vZGVzLCBzdGFydElkeCwgZW5kSWR4LCBpbnNlcnRlZFZub2RlUXVldWUpIHtcbiAgICBmb3IgKDsgc3RhcnRJZHggPD0gZW5kSWR4OyArK3N0YXJ0SWR4KSB7XG4gICAgICBhcGkuaW5zZXJ0QmVmb3JlKHBhcmVudEVsbSwgY3JlYXRlRWxtKHZub2Rlc1tzdGFydElkeF0sIGluc2VydGVkVm5vZGVRdWV1ZSksIGJlZm9yZSk7XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gaW52b2tlRGVzdHJveUhvb2sodm5vZGUpIHtcbiAgICB2YXIgaSwgaiwgZGF0YSA9IHZub2RlLmRhdGE7XG4gICAgaWYgKGlzRGVmKGRhdGEpKSB7XG4gICAgICBpZiAoaXNEZWYoaSA9IGRhdGEuaG9vaykgJiYgaXNEZWYoaSA9IGkuZGVzdHJveSkpIGkodm5vZGUpO1xuICAgICAgZm9yIChpID0gMDsgaSA8IGNicy5kZXN0cm95Lmxlbmd0aDsgKytpKSBjYnMuZGVzdHJveVtpXSh2bm9kZSk7XG4gICAgICBpZiAoaXNEZWYoaSA9IHZub2RlLmNoaWxkcmVuKSkge1xuICAgICAgICBmb3IgKGogPSAwOyBqIDwgdm5vZGUuY2hpbGRyZW4ubGVuZ3RoOyArK2opIHtcbiAgICAgICAgICBpbnZva2VEZXN0cm95SG9vayh2bm9kZS5jaGlsZHJlbltqXSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiByZW1vdmVWbm9kZXMocGFyZW50RWxtLCB2bm9kZXMsIHN0YXJ0SWR4LCBlbmRJZHgpIHtcbiAgICBmb3IgKDsgc3RhcnRJZHggPD0gZW5kSWR4OyArK3N0YXJ0SWR4KSB7XG4gICAgICB2YXIgaSwgbGlzdGVuZXJzLCBybSwgY2ggPSB2bm9kZXNbc3RhcnRJZHhdO1xuICAgICAgaWYgKGlzRGVmKGNoKSkge1xuICAgICAgICBpZiAoaXNEZWYoY2guc2VsKSkge1xuICAgICAgICAgIGludm9rZURlc3Ryb3lIb29rKGNoKTtcbiAgICAgICAgICBsaXN0ZW5lcnMgPSBjYnMucmVtb3ZlLmxlbmd0aCArIDE7XG4gICAgICAgICAgcm0gPSBjcmVhdGVSbUNiKGNoLmVsbSwgbGlzdGVuZXJzKTtcbiAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgY2JzLnJlbW92ZS5sZW5ndGg7ICsraSkgY2JzLnJlbW92ZVtpXShjaCwgcm0pO1xuICAgICAgICAgIGlmIChpc0RlZihpID0gY2guZGF0YSkgJiYgaXNEZWYoaSA9IGkuaG9vaykgJiYgaXNEZWYoaSA9IGkucmVtb3ZlKSkge1xuICAgICAgICAgICAgaShjaCwgcm0pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBybSgpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHsgLy8gVGV4dCBub2RlXG4gICAgICAgICAgYXBpLnJlbW92ZUNoaWxkKHBhcmVudEVsbSwgY2guZWxtKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIHVwZGF0ZUNoaWxkcmVuKHBhcmVudEVsbSwgb2xkQ2gsIG5ld0NoLCBpbnNlcnRlZFZub2RlUXVldWUpIHtcbiAgICB2YXIgb2xkU3RhcnRJZHggPSAwLCBuZXdTdGFydElkeCA9IDA7XG4gICAgdmFyIG9sZEVuZElkeCA9IG9sZENoLmxlbmd0aCAtIDE7XG4gICAgdmFyIG9sZFN0YXJ0Vm5vZGUgPSBvbGRDaFswXTtcbiAgICB2YXIgb2xkRW5kVm5vZGUgPSBvbGRDaFtvbGRFbmRJZHhdO1xuICAgIHZhciBuZXdFbmRJZHggPSBuZXdDaC5sZW5ndGggLSAxO1xuICAgIHZhciBuZXdTdGFydFZub2RlID0gbmV3Q2hbMF07XG4gICAgdmFyIG5ld0VuZFZub2RlID0gbmV3Q2hbbmV3RW5kSWR4XTtcbiAgICB2YXIgb2xkS2V5VG9JZHgsIGlkeEluT2xkLCBlbG1Ub01vdmUsIGJlZm9yZTtcblxuICAgIHdoaWxlIChvbGRTdGFydElkeCA8PSBvbGRFbmRJZHggJiYgbmV3U3RhcnRJZHggPD0gbmV3RW5kSWR4KSB7XG4gICAgICBpZiAoaXNVbmRlZihvbGRTdGFydFZub2RlKSkge1xuICAgICAgICBvbGRTdGFydFZub2RlID0gb2xkQ2hbKytvbGRTdGFydElkeF07IC8vIFZub2RlIGhhcyBiZWVuIG1vdmVkIGxlZnRcbiAgICAgIH0gZWxzZSBpZiAoaXNVbmRlZihvbGRFbmRWbm9kZSkpIHtcbiAgICAgICAgb2xkRW5kVm5vZGUgPSBvbGRDaFstLW9sZEVuZElkeF07XG4gICAgICB9IGVsc2UgaWYgKHNhbWVWbm9kZShvbGRTdGFydFZub2RlLCBuZXdTdGFydFZub2RlKSkge1xuICAgICAgICBwYXRjaFZub2RlKG9sZFN0YXJ0Vm5vZGUsIG5ld1N0YXJ0Vm5vZGUsIGluc2VydGVkVm5vZGVRdWV1ZSk7XG4gICAgICAgIG9sZFN0YXJ0Vm5vZGUgPSBvbGRDaFsrK29sZFN0YXJ0SWR4XTtcbiAgICAgICAgbmV3U3RhcnRWbm9kZSA9IG5ld0NoWysrbmV3U3RhcnRJZHhdO1xuICAgICAgfSBlbHNlIGlmIChzYW1lVm5vZGUob2xkRW5kVm5vZGUsIG5ld0VuZFZub2RlKSkge1xuICAgICAgICBwYXRjaFZub2RlKG9sZEVuZFZub2RlLCBuZXdFbmRWbm9kZSwgaW5zZXJ0ZWRWbm9kZVF1ZXVlKTtcbiAgICAgICAgb2xkRW5kVm5vZGUgPSBvbGRDaFstLW9sZEVuZElkeF07XG4gICAgICAgIG5ld0VuZFZub2RlID0gbmV3Q2hbLS1uZXdFbmRJZHhdO1xuICAgICAgfSBlbHNlIGlmIChzYW1lVm5vZGUob2xkU3RhcnRWbm9kZSwgbmV3RW5kVm5vZGUpKSB7IC8vIFZub2RlIG1vdmVkIHJpZ2h0XG4gICAgICAgIHBhdGNoVm5vZGUob2xkU3RhcnRWbm9kZSwgbmV3RW5kVm5vZGUsIGluc2VydGVkVm5vZGVRdWV1ZSk7XG4gICAgICAgIGFwaS5pbnNlcnRCZWZvcmUocGFyZW50RWxtLCBvbGRTdGFydFZub2RlLmVsbSwgYXBpLm5leHRTaWJsaW5nKG9sZEVuZFZub2RlLmVsbSkpO1xuICAgICAgICBvbGRTdGFydFZub2RlID0gb2xkQ2hbKytvbGRTdGFydElkeF07XG4gICAgICAgIG5ld0VuZFZub2RlID0gbmV3Q2hbLS1uZXdFbmRJZHhdO1xuICAgICAgfSBlbHNlIGlmIChzYW1lVm5vZGUob2xkRW5kVm5vZGUsIG5ld1N0YXJ0Vm5vZGUpKSB7IC8vIFZub2RlIG1vdmVkIGxlZnRcbiAgICAgICAgcGF0Y2hWbm9kZShvbGRFbmRWbm9kZSwgbmV3U3RhcnRWbm9kZSwgaW5zZXJ0ZWRWbm9kZVF1ZXVlKTtcbiAgICAgICAgYXBpLmluc2VydEJlZm9yZShwYXJlbnRFbG0sIG9sZEVuZFZub2RlLmVsbSwgb2xkU3RhcnRWbm9kZS5lbG0pO1xuICAgICAgICBvbGRFbmRWbm9kZSA9IG9sZENoWy0tb2xkRW5kSWR4XTtcbiAgICAgICAgbmV3U3RhcnRWbm9kZSA9IG5ld0NoWysrbmV3U3RhcnRJZHhdO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKGlzVW5kZWYob2xkS2V5VG9JZHgpKSBvbGRLZXlUb0lkeCA9IGNyZWF0ZUtleVRvT2xkSWR4KG9sZENoLCBvbGRTdGFydElkeCwgb2xkRW5kSWR4KTtcbiAgICAgICAgaWR4SW5PbGQgPSBvbGRLZXlUb0lkeFtuZXdTdGFydFZub2RlLmtleV07XG4gICAgICAgIGlmIChpc1VuZGVmKGlkeEluT2xkKSkgeyAvLyBOZXcgZWxlbWVudFxuICAgICAgICAgIGFwaS5pbnNlcnRCZWZvcmUocGFyZW50RWxtLCBjcmVhdGVFbG0obmV3U3RhcnRWbm9kZSwgaW5zZXJ0ZWRWbm9kZVF1ZXVlKSwgb2xkU3RhcnRWbm9kZS5lbG0pO1xuICAgICAgICAgIG5ld1N0YXJ0Vm5vZGUgPSBuZXdDaFsrK25ld1N0YXJ0SWR4XTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBlbG1Ub01vdmUgPSBvbGRDaFtpZHhJbk9sZF07XG4gICAgICAgICAgcGF0Y2hWbm9kZShlbG1Ub01vdmUsIG5ld1N0YXJ0Vm5vZGUsIGluc2VydGVkVm5vZGVRdWV1ZSk7XG4gICAgICAgICAgb2xkQ2hbaWR4SW5PbGRdID0gdW5kZWZpbmVkO1xuICAgICAgICAgIGFwaS5pbnNlcnRCZWZvcmUocGFyZW50RWxtLCBlbG1Ub01vdmUuZWxtLCBvbGRTdGFydFZub2RlLmVsbSk7XG4gICAgICAgICAgbmV3U3RhcnRWbm9kZSA9IG5ld0NoWysrbmV3U3RhcnRJZHhdO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIGlmIChvbGRTdGFydElkeCA+IG9sZEVuZElkeCkge1xuICAgICAgYmVmb3JlID0gaXNVbmRlZihuZXdDaFtuZXdFbmRJZHgrMV0pID8gbnVsbCA6IG5ld0NoW25ld0VuZElkeCsxXS5lbG07XG4gICAgICBhZGRWbm9kZXMocGFyZW50RWxtLCBiZWZvcmUsIG5ld0NoLCBuZXdTdGFydElkeCwgbmV3RW5kSWR4LCBpbnNlcnRlZFZub2RlUXVldWUpO1xuICAgIH0gZWxzZSBpZiAobmV3U3RhcnRJZHggPiBuZXdFbmRJZHgpIHtcbiAgICAgIHJlbW92ZVZub2RlcyhwYXJlbnRFbG0sIG9sZENoLCBvbGRTdGFydElkeCwgb2xkRW5kSWR4KTtcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBwYXRjaFZub2RlKG9sZFZub2RlLCB2bm9kZSwgaW5zZXJ0ZWRWbm9kZVF1ZXVlKSB7XG4gICAgdmFyIGksIGhvb2s7XG4gICAgaWYgKGlzRGVmKGkgPSB2bm9kZS5kYXRhKSAmJiBpc0RlZihob29rID0gaS5ob29rKSAmJiBpc0RlZihpID0gaG9vay5wcmVwYXRjaCkpIHtcbiAgICAgIGkob2xkVm5vZGUsIHZub2RlKTtcbiAgICB9XG4gICAgdmFyIGVsbSA9IHZub2RlLmVsbSA9IG9sZFZub2RlLmVsbSwgb2xkQ2ggPSBvbGRWbm9kZS5jaGlsZHJlbiwgY2ggPSB2bm9kZS5jaGlsZHJlbjtcbiAgICBpZiAob2xkVm5vZGUgPT09IHZub2RlKSByZXR1cm47XG4gICAgaWYgKCFzYW1lVm5vZGUob2xkVm5vZGUsIHZub2RlKSkge1xuICAgICAgdmFyIHBhcmVudEVsbSA9IGFwaS5wYXJlbnROb2RlKG9sZFZub2RlLmVsbSk7XG4gICAgICBlbG0gPSBjcmVhdGVFbG0odm5vZGUsIGluc2VydGVkVm5vZGVRdWV1ZSk7XG4gICAgICBhcGkuaW5zZXJ0QmVmb3JlKHBhcmVudEVsbSwgZWxtLCBvbGRWbm9kZS5lbG0pO1xuICAgICAgcmVtb3ZlVm5vZGVzKHBhcmVudEVsbSwgW29sZFZub2RlXSwgMCwgMCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmIChpc0RlZih2bm9kZS5kYXRhKSkge1xuICAgICAgZm9yIChpID0gMDsgaSA8IGNicy51cGRhdGUubGVuZ3RoOyArK2kpIGNicy51cGRhdGVbaV0ob2xkVm5vZGUsIHZub2RlKTtcbiAgICAgIGkgPSB2bm9kZS5kYXRhLmhvb2s7XG4gICAgICBpZiAoaXNEZWYoaSkgJiYgaXNEZWYoaSA9IGkudXBkYXRlKSkgaShvbGRWbm9kZSwgdm5vZGUpO1xuICAgIH1cbiAgICBpZiAoaXNVbmRlZih2bm9kZS50ZXh0KSkge1xuICAgICAgaWYgKGlzRGVmKG9sZENoKSAmJiBpc0RlZihjaCkpIHtcbiAgICAgICAgaWYgKG9sZENoICE9PSBjaCkgdXBkYXRlQ2hpbGRyZW4oZWxtLCBvbGRDaCwgY2gsIGluc2VydGVkVm5vZGVRdWV1ZSk7XG4gICAgICB9IGVsc2UgaWYgKGlzRGVmKGNoKSkge1xuICAgICAgICBpZiAoaXNEZWYob2xkVm5vZGUudGV4dCkpIGFwaS5zZXRUZXh0Q29udGVudChlbG0sICcnKTtcbiAgICAgICAgYWRkVm5vZGVzKGVsbSwgbnVsbCwgY2gsIDAsIGNoLmxlbmd0aCAtIDEsIGluc2VydGVkVm5vZGVRdWV1ZSk7XG4gICAgICB9IGVsc2UgaWYgKGlzRGVmKG9sZENoKSkge1xuICAgICAgICByZW1vdmVWbm9kZXMoZWxtLCBvbGRDaCwgMCwgb2xkQ2gubGVuZ3RoIC0gMSk7XG4gICAgICB9IGVsc2UgaWYgKGlzRGVmKG9sZFZub2RlLnRleHQpKSB7XG4gICAgICAgIGFwaS5zZXRUZXh0Q29udGVudChlbG0sICcnKTtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKG9sZFZub2RlLnRleHQgIT09IHZub2RlLnRleHQpIHtcbiAgICAgIGFwaS5zZXRUZXh0Q29udGVudChlbG0sIHZub2RlLnRleHQpO1xuICAgIH1cbiAgICBpZiAoaXNEZWYoaG9vaykgJiYgaXNEZWYoaSA9IGhvb2sucG9zdHBhdGNoKSkge1xuICAgICAgaShvbGRWbm9kZSwgdm5vZGUpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmdW5jdGlvbihvbGRWbm9kZSwgdm5vZGUpIHtcbiAgICB2YXIgaSwgZWxtLCBwYXJlbnQ7XG4gICAgdmFyIGluc2VydGVkVm5vZGVRdWV1ZSA9IFtdO1xuICAgIGZvciAoaSA9IDA7IGkgPCBjYnMucHJlLmxlbmd0aDsgKytpKSBjYnMucHJlW2ldKCk7XG5cbiAgICBpZiAoaXNVbmRlZihvbGRWbm9kZS5zZWwpKSB7XG4gICAgICBvbGRWbm9kZSA9IGVtcHR5Tm9kZUF0KG9sZFZub2RlKTtcbiAgICB9XG5cbiAgICBpZiAoc2FtZVZub2RlKG9sZFZub2RlLCB2bm9kZSkpIHtcbiAgICAgIHBhdGNoVm5vZGUob2xkVm5vZGUsIHZub2RlLCBpbnNlcnRlZFZub2RlUXVldWUpO1xuICAgIH0gZWxzZSB7XG4gICAgICBlbG0gPSBvbGRWbm9kZS5lbG07XG4gICAgICBwYXJlbnQgPSBhcGkucGFyZW50Tm9kZShlbG0pO1xuXG4gICAgICBjcmVhdGVFbG0odm5vZGUsIGluc2VydGVkVm5vZGVRdWV1ZSk7XG5cbiAgICAgIGlmIChwYXJlbnQgIT09IG51bGwpIHtcbiAgICAgICAgYXBpLmluc2VydEJlZm9yZShwYXJlbnQsIHZub2RlLmVsbSwgYXBpLm5leHRTaWJsaW5nKGVsbSkpO1xuICAgICAgICByZW1vdmVWbm9kZXMocGFyZW50LCBbb2xkVm5vZGVdLCAwLCAwKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBmb3IgKGkgPSAwOyBpIDwgaW5zZXJ0ZWRWbm9kZVF1ZXVlLmxlbmd0aDsgKytpKSB7XG4gICAgICBpbnNlcnRlZFZub2RlUXVldWVbaV0uZGF0YS5ob29rLmluc2VydChpbnNlcnRlZFZub2RlUXVldWVbaV0pO1xuICAgIH1cbiAgICBmb3IgKGkgPSAwOyBpIDwgY2JzLnBvc3QubGVuZ3RoOyArK2kpIGNicy5wb3N0W2ldKCk7XG4gICAgcmV0dXJuIHZub2RlO1xuICB9O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtpbml0OiBpbml0fTtcbiIsIm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oc2VsLCBkYXRhLCBjaGlsZHJlbiwgdGV4dCwgZWxtKSB7XG4gIHZhciBrZXkgPSBkYXRhID09PSB1bmRlZmluZWQgPyB1bmRlZmluZWQgOiBkYXRhLmtleTtcbiAgcmV0dXJuIHtzZWw6IHNlbCwgZGF0YTogZGF0YSwgY2hpbGRyZW46IGNoaWxkcmVuLFxuICAgICAgICAgIHRleHQ6IHRleHQsIGVsbTogZWxtLCBrZXk6IGtleX07XG59O1xuIl19\n"],"sourceRoot":"/source/"} \ No newline at end of file +{"version":3,"sources":["snabbdom.js"],"names":["f","exports","module","define","amd","g","window","global","self","this","snabbdom","e","t","n","r","s","o","u","a","require","i","Error","code","l","call","length","1","createElement","tagName","document","createElementNS","namespaceURI","qualifiedName","createTextNode","text","insertBefore","parentNode","newNode","referenceNode","removeChild","node","child","appendChild","parentElement","nextSibling","setTextContent","textContent","2","array","Array","isArray","primitive","3","isUndef","undefined","isDef","sameVnode","vnode1","vnode2","key","sel","createKeyToOldIdx","children","beginIdx","endIdx","map","init","modules","api","emptyNodeAt","elm","id","c","className","split","join","VNode","toLowerCase","createRmCb","childElm","listeners","parent","createElm","vnode","insertedVnodeQueue","data","hook","hashIdx","indexOf","dotIdx","hash","dot","tag","slice","Math","min","ns","replace","is","cbs","create","emptyNode","insert","push","addVnodes","parentElm","before","vnodes","startIdx","invokeDestroyHook","j","destroy","removeVnodes","rm","ch","remove","updateChildren","oldCh","newCh","oldKeyToIdx","idxInOld","elmToMove","oldStartIdx","newStartIdx","oldEndIdx","oldStartVnode","oldEndVnode","newEndIdx","newStartVnode","newEndVnode","patchVnode","oldVnode","prepatch","update","postpatch","domApi","hooks","pre","post","./htmldomapi","./is","./vnode","4"],"mappings":"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","file":"snabbdom.min.js","sourcesContent":["(function(f){if(typeof exports===\"object\"&&typeof module!==\"undefined\"){module.exports=f()}else if(typeof define===\"function\"&&define.amd){define([],f)}else{var g;if(typeof window!==\"undefined\"){g=window}else if(typeof global!==\"undefined\"){g=global}else if(typeof self!==\"undefined\"){g=self}else{g=this}g.snabbdom = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o 0 ? hashIdx : sel.length;\n var dot = dotIdx > 0 ? dotIdx : sel.length;\n var tag = hashIdx !== -1 || dotIdx !== -1 ? sel.slice(0, Math.min(hash, dot)) : sel;\n elm = vnode.elm = isDef(data) && isDef(i = data.ns) ? api.createElementNS(i, tag)\n : api.createElement(tag);\n if (hash < dot) elm.id = sel.slice(hash + 1, dot);\n if (dotIdx > 0) elm.className = sel.slice(dot + 1).replace(/\\./g, ' ');\n if (is.array(children)) {\n for (i = 0; i < children.length; ++i) {\n api.appendChild(elm, createElm(children[i], insertedVnodeQueue));\n }\n } else if (is.primitive(vnode.text)) {\n api.appendChild(elm, api.createTextNode(vnode.text));\n }\n for (i = 0; i < cbs.create.length; ++i) cbs.create[i](emptyNode, vnode);\n i = vnode.data.hook; // Reuse variable\n if (isDef(i)) {\n if (i.create) i.create(emptyNode, vnode);\n if (i.insert) insertedVnodeQueue.push(vnode);\n }\n } else {\n elm = vnode.elm = api.createTextNode(vnode.text);\n }\n return vnode.elm;\n }\n\n function addVnodes(parentElm, before, vnodes, startIdx, endIdx, insertedVnodeQueue) {\n for (; startIdx <= endIdx; ++startIdx) {\n api.insertBefore(parentElm, createElm(vnodes[startIdx], insertedVnodeQueue), before);\n }\n }\n\n function invokeDestroyHook(vnode) {\n var i, j, data = vnode.data;\n if (isDef(data)) {\n if (isDef(i = data.hook) && isDef(i = i.destroy)) i(vnode);\n for (i = 0; i < cbs.destroy.length; ++i) cbs.destroy[i](vnode);\n if (isDef(i = vnode.children)) {\n for (j = 0; j < vnode.children.length; ++j) {\n invokeDestroyHook(vnode.children[j]);\n }\n }\n }\n }\n\n function removeVnodes(parentElm, vnodes, startIdx, endIdx) {\n for (; startIdx <= endIdx; ++startIdx) {\n var i, listeners, rm, ch = vnodes[startIdx];\n if (isDef(ch)) {\n if (isDef(ch.sel)) {\n invokeDestroyHook(ch);\n listeners = cbs.remove.length + 1;\n rm = createRmCb(ch.elm, listeners);\n for (i = 0; i < cbs.remove.length; ++i) cbs.remove[i](ch, rm);\n if (isDef(i = ch.data) && isDef(i = i.hook) && isDef(i = i.remove)) {\n i(ch, rm);\n } else {\n rm();\n }\n } else { // Text node\n api.removeChild(parentElm, ch.elm);\n }\n }\n }\n }\n\n function updateChildren(parentElm, oldCh, newCh, insertedVnodeQueue) {\n var oldStartIdx = 0, newStartIdx = 0;\n var oldEndIdx = oldCh.length - 1;\n var oldStartVnode = oldCh[0];\n var oldEndVnode = oldCh[oldEndIdx];\n var newEndIdx = newCh.length - 1;\n var newStartVnode = newCh[0];\n var newEndVnode = newCh[newEndIdx];\n var oldKeyToIdx, idxInOld, elmToMove, before;\n\n while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) {\n if (isUndef(oldStartVnode)) {\n oldStartVnode = oldCh[++oldStartIdx]; // Vnode has been moved left\n } else if (isUndef(oldEndVnode)) {\n oldEndVnode = oldCh[--oldEndIdx];\n } else if (sameVnode(oldStartVnode, newStartVnode)) {\n patchVnode(oldStartVnode, newStartVnode, insertedVnodeQueue);\n oldStartVnode = oldCh[++oldStartIdx];\n newStartVnode = newCh[++newStartIdx];\n } else if (sameVnode(oldEndVnode, newEndVnode)) {\n patchVnode(oldEndVnode, newEndVnode, insertedVnodeQueue);\n oldEndVnode = oldCh[--oldEndIdx];\n newEndVnode = newCh[--newEndIdx];\n } else if (sameVnode(oldStartVnode, newEndVnode)) { // Vnode moved right\n patchVnode(oldStartVnode, newEndVnode, insertedVnodeQueue);\n api.insertBefore(parentElm, oldStartVnode.elm, api.nextSibling(oldEndVnode.elm));\n oldStartVnode = oldCh[++oldStartIdx];\n newEndVnode = newCh[--newEndIdx];\n } else if (sameVnode(oldEndVnode, newStartVnode)) { // Vnode moved left\n patchVnode(oldEndVnode, newStartVnode, insertedVnodeQueue);\n api.insertBefore(parentElm, oldEndVnode.elm, oldStartVnode.elm);\n oldEndVnode = oldCh[--oldEndIdx];\n newStartVnode = newCh[++newStartIdx];\n } else {\n if (isUndef(oldKeyToIdx)) oldKeyToIdx = createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx);\n idxInOld = oldKeyToIdx[newStartVnode.key];\n if (isUndef(idxInOld)) { // New element\n api.insertBefore(parentElm, createElm(newStartVnode, insertedVnodeQueue), oldStartVnode.elm);\n newStartVnode = newCh[++newStartIdx];\n } else {\n elmToMove = oldCh[idxInOld];\n patchVnode(elmToMove, newStartVnode, insertedVnodeQueue);\n oldCh[idxInOld] = undefined;\n api.insertBefore(parentElm, elmToMove.elm, oldStartVnode.elm);\n newStartVnode = newCh[++newStartIdx];\n }\n }\n }\n if (oldStartIdx > oldEndIdx) {\n before = isUndef(newCh[newEndIdx+1]) ? null : newCh[newEndIdx+1].elm;\n addVnodes(parentElm, before, newCh, newStartIdx, newEndIdx, insertedVnodeQueue);\n } else if (newStartIdx > newEndIdx) {\n removeVnodes(parentElm, oldCh, oldStartIdx, oldEndIdx);\n }\n }\n\n function patchVnode(oldVnode, vnode, insertedVnodeQueue) {\n var i, hook;\n if (isDef(i = vnode.data) && isDef(hook = i.hook) && isDef(i = hook.prepatch)) {\n i(oldVnode, vnode);\n }\n var elm = vnode.elm = oldVnode.elm, oldCh = oldVnode.children, ch = vnode.children;\n if (oldVnode === vnode) return;\n if (!sameVnode(oldVnode, vnode)) {\n var parentElm = api.parentNode(oldVnode.elm);\n elm = createElm(vnode, insertedVnodeQueue);\n api.insertBefore(parentElm, elm, oldVnode.elm);\n removeVnodes(parentElm, [oldVnode], 0, 0);\n return;\n }\n if (isDef(vnode.data)) {\n for (i = 0; i < cbs.update.length; ++i) cbs.update[i](oldVnode, vnode);\n i = vnode.data.hook;\n if (isDef(i) && isDef(i = i.update)) i(oldVnode, vnode);\n }\n if (isUndef(vnode.text)) {\n if (isDef(oldCh) && isDef(ch)) {\n if (oldCh !== ch) updateChildren(elm, oldCh, ch, insertedVnodeQueue);\n } else if (isDef(ch)) {\n if (isDef(oldVnode.text)) api.setTextContent(elm, '');\n addVnodes(elm, null, ch, 0, ch.length - 1, insertedVnodeQueue);\n } else if (isDef(oldCh)) {\n removeVnodes(elm, oldCh, 0, oldCh.length - 1);\n } else if (isDef(oldVnode.text)) {\n api.setTextContent(elm, '');\n }\n } else if (oldVnode.text !== vnode.text) {\n api.setTextContent(elm, vnode.text);\n }\n if (isDef(hook) && isDef(i = hook.postpatch)) {\n i(oldVnode, vnode);\n }\n }\n\n return function(oldVnode, vnode) {\n var i, elm, parent;\n var insertedVnodeQueue = [];\n for (i = 0; i < cbs.pre.length; ++i) cbs.pre[i]();\n\n if (isUndef(oldVnode.sel)) {\n oldVnode = emptyNodeAt(oldVnode);\n }\n\n if (sameVnode(oldVnode, vnode)) {\n patchVnode(oldVnode, vnode, insertedVnodeQueue);\n } else {\n elm = oldVnode.elm;\n parent = api.parentNode(elm);\n\n createElm(vnode, insertedVnodeQueue);\n\n if (parent !== null) {\n api.insertBefore(parent, vnode.elm, api.nextSibling(elm));\n removeVnodes(parent, [oldVnode], 0, 0);\n }\n }\n\n for (i = 0; i < insertedVnodeQueue.length; ++i) {\n insertedVnodeQueue[i].data.hook.insert(insertedVnodeQueue[i]);\n }\n for (i = 0; i < cbs.post.length; ++i) cbs.post[i]();\n return vnode;\n };\n}\n\nmodule.exports = {init: init};\n\n},{\"./htmldomapi\":1,\"./is\":2,\"./vnode\":4}],4:[function(require,module,exports){\nmodule.exports = function(sel, data, children, text, elm) {\n var key = data === undefined ? undefined : data.key;\n return {sel: sel, data: data, children: children,\n text: text, elm: elm, key: key};\n};\n\n},{}]},{},[3])(3)\n});\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJodG1sZG9tYXBpLmpzIiwiaXMuanMiLCJzbmFiYmRvbS5qcyIsInZub2RlLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FDQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdERBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDSkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BRQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbiBlKHQsbixyKXtmdW5jdGlvbiBzKG8sdSl7aWYoIW5bb10pe2lmKCF0W29dKXt2YXIgYT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2lmKCF1JiZhKXJldHVybiBhKG8sITApO2lmKGkpcmV0dXJuIGkobywhMCk7dmFyIGY9bmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIitvK1wiJ1wiKTt0aHJvdyBmLmNvZGU9XCJNT0RVTEVfTk9UX0ZPVU5EXCIsZn12YXIgbD1uW29dPXtleHBvcnRzOnt9fTt0W29dWzBdLmNhbGwobC5leHBvcnRzLGZ1bmN0aW9uKGUpe3ZhciBuPXRbb11bMV1bZV07cmV0dXJuIHMobj9uOmUpfSxsLGwuZXhwb3J0cyxlLHQsbixyKX1yZXR1cm4gbltvXS5leHBvcnRzfXZhciBpPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7Zm9yKHZhciBvPTA7bzxyLmxlbmd0aDtvKyspcyhyW29dKTtyZXR1cm4gc30pIiwiZnVuY3Rpb24gY3JlYXRlRWxlbWVudCh0YWdOYW1lKXtcbiAgcmV0dXJuIGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQodGFnTmFtZSk7XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZUVsZW1lbnROUyhuYW1lc3BhY2VVUkksIHF1YWxpZmllZE5hbWUpe1xuICByZXR1cm4gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKG5hbWVzcGFjZVVSSSwgcXVhbGlmaWVkTmFtZSk7XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZVRleHROb2RlKHRleHQpe1xuICByZXR1cm4gZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUodGV4dCk7XG59XG5cblxuZnVuY3Rpb24gaW5zZXJ0QmVmb3JlKHBhcmVudE5vZGUsIG5ld05vZGUsIHJlZmVyZW5jZU5vZGUpe1xuICBwYXJlbnROb2RlLmluc2VydEJlZm9yZShuZXdOb2RlLCByZWZlcmVuY2VOb2RlKTtcbn1cblxuXG5mdW5jdGlvbiByZW1vdmVDaGlsZChub2RlLCBjaGlsZCl7XG4gIG5vZGUucmVtb3ZlQ2hpbGQoY2hpbGQpO1xufVxuXG5mdW5jdGlvbiBhcHBlbmRDaGlsZChub2RlLCBjaGlsZCl7XG4gIG5vZGUuYXBwZW5kQ2hpbGQoY2hpbGQpO1xufVxuXG5mdW5jdGlvbiBwYXJlbnROb2RlKG5vZGUpe1xuICByZXR1cm4gbm9kZS5wYXJlbnRFbGVtZW50O1xufVxuXG5mdW5jdGlvbiBuZXh0U2libGluZyhub2RlKXtcbiAgcmV0dXJuIG5vZGUubmV4dFNpYmxpbmc7XG59XG5cbmZ1bmN0aW9uIHRhZ05hbWUobm9kZSl7XG4gIHJldHVybiBub2RlLnRhZ05hbWU7XG59XG5cbmZ1bmN0aW9uIHNldFRleHRDb250ZW50KG5vZGUsIHRleHQpe1xuICBub2RlLnRleHRDb250ZW50ID0gdGV4dDtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gIGNyZWF0ZUVsZW1lbnQ6IGNyZWF0ZUVsZW1lbnQsXG4gIGNyZWF0ZUVsZW1lbnROUzogY3JlYXRlRWxlbWVudE5TLFxuICBjcmVhdGVUZXh0Tm9kZTogY3JlYXRlVGV4dE5vZGUsXG4gIGFwcGVuZENoaWxkOiBhcHBlbmRDaGlsZCxcbiAgcmVtb3ZlQ2hpbGQ6IHJlbW92ZUNoaWxkLFxuICBpbnNlcnRCZWZvcmU6IGluc2VydEJlZm9yZSxcbiAgcGFyZW50Tm9kZTogcGFyZW50Tm9kZSxcbiAgbmV4dFNpYmxpbmc6IG5leHRTaWJsaW5nLFxuICB0YWdOYW1lOiB0YWdOYW1lLFxuICBzZXRUZXh0Q29udGVudDogc2V0VGV4dENvbnRlbnRcbn07XG4iLCJtb2R1bGUuZXhwb3J0cyA9IHtcbiAgYXJyYXk6IEFycmF5LmlzQXJyYXksXG4gIHByaW1pdGl2ZTogZnVuY3Rpb24ocykgeyByZXR1cm4gdHlwZW9mIHMgPT09ICdzdHJpbmcnIHx8IHR5cGVvZiBzID09PSAnbnVtYmVyJzsgfSxcbn07XG4iLCIvLyBqc2hpbnQgbmV3Y2FwOiBmYWxzZVxuLyogZ2xvYmFsIHJlcXVpcmUsIG1vZHVsZSwgZG9jdW1lbnQsIE5vZGUgKi9cbid1c2Ugc3RyaWN0JztcblxudmFyIFZOb2RlID0gcmVxdWlyZSgnLi92bm9kZScpO1xudmFyIGlzID0gcmVxdWlyZSgnLi9pcycpO1xudmFyIGRvbUFwaSA9IHJlcXVpcmUoJy4vaHRtbGRvbWFwaScpO1xuXG5mdW5jdGlvbiBpc1VuZGVmKHMpIHsgcmV0dXJuIHMgPT09IHVuZGVmaW5lZDsgfVxuZnVuY3Rpb24gaXNEZWYocykgeyByZXR1cm4gcyAhPT0gdW5kZWZpbmVkOyB9XG5cbnZhciBlbXB0eU5vZGUgPSBWTm9kZSgnJywge30sIFtdLCB1bmRlZmluZWQsIHVuZGVmaW5lZCk7XG5cbmZ1bmN0aW9uIHNhbWVWbm9kZSh2bm9kZTEsIHZub2RlMikge1xuICByZXR1cm4gdm5vZGUxLmtleSA9PT0gdm5vZGUyLmtleSAmJiB2bm9kZTEuc2VsID09PSB2bm9kZTIuc2VsO1xufVxuXG5mdW5jdGlvbiBjcmVhdGVLZXlUb09sZElkeChjaGlsZHJlbiwgYmVnaW5JZHgsIGVuZElkeCkge1xuICB2YXIgaSwgbWFwID0ge30sIGtleTtcbiAgZm9yIChpID0gYmVnaW5JZHg7IGkgPD0gZW5kSWR4OyArK2kpIHtcbiAgICBrZXkgPSBjaGlsZHJlbltpXS5rZXk7XG4gICAgaWYgKGlzRGVmKGtleSkpIG1hcFtrZXldID0gaTtcbiAgfVxuICByZXR1cm4gbWFwO1xufVxuXG52YXIgaG9va3MgPSBbJ2NyZWF0ZScsICd1cGRhdGUnLCAncmVtb3ZlJywgJ2Rlc3Ryb3knLCAncHJlJywgJ3Bvc3QnXTtcblxuZnVuY3Rpb24gaW5pdChtb2R1bGVzLCBhcGkpIHtcbiAgdmFyIGksIGosIGNicyA9IHt9O1xuXG4gIGlmIChpc1VuZGVmKGFwaSkpIGFwaSA9IGRvbUFwaTtcblxuICBmb3IgKGkgPSAwOyBpIDwgaG9va3MubGVuZ3RoOyArK2kpIHtcbiAgICBjYnNbaG9va3NbaV1dID0gW107XG4gICAgZm9yIChqID0gMDsgaiA8IG1vZHVsZXMubGVuZ3RoOyArK2opIHtcbiAgICAgIGlmIChtb2R1bGVzW2pdW2hvb2tzW2ldXSAhPT0gdW5kZWZpbmVkKSBjYnNbaG9va3NbaV1dLnB1c2gobW9kdWxlc1tqXVtob29rc1tpXV0pO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIGVtcHR5Tm9kZUF0KGVsbSkge1xuICAgIHZhciBpZCA9IGVsbS5pZCA/ICcjJyArIGVsbS5pZCA6ICcnO1xuICAgIHZhciBjID0gZWxtLmNsYXNzTmFtZSA/ICcuJyArIGVsbS5jbGFzc05hbWUuc3BsaXQoJyAnKS5qb2luKCcuJykgOiAnJztcbiAgICByZXR1cm4gVk5vZGUoYXBpLnRhZ05hbWUoZWxtKS50b0xvd2VyQ2FzZSgpICsgaWQgKyBjLCB7fSwgW10sIHVuZGVmaW5lZCwgZWxtKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNyZWF0ZVJtQ2IoY2hpbGRFbG0sIGxpc3RlbmVycykge1xuICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgIGlmICgtLWxpc3RlbmVycyA9PT0gMCkge1xuICAgICAgICB2YXIgcGFyZW50ID0gYXBpLnBhcmVudE5vZGUoY2hpbGRFbG0pO1xuICAgICAgICBhcGkucmVtb3ZlQ2hpbGQocGFyZW50LCBjaGlsZEVsbSk7XG4gICAgICB9XG4gICAgfTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNyZWF0ZUVsbSh2bm9kZSwgaW5zZXJ0ZWRWbm9kZVF1ZXVlKSB7XG4gICAgdmFyIGksIGRhdGEgPSB2bm9kZS5kYXRhO1xuICAgIGlmIChpc0RlZihkYXRhKSkge1xuICAgICAgaWYgKGlzRGVmKGkgPSBkYXRhLmhvb2spICYmIGlzRGVmKGkgPSBpLmluaXQpKSB7XG4gICAgICAgIGkodm5vZGUpO1xuICAgICAgICBkYXRhID0gdm5vZGUuZGF0YTtcbiAgICAgIH1cbiAgICB9XG4gICAgdmFyIGVsbSwgY2hpbGRyZW4gPSB2bm9kZS5jaGlsZHJlbiwgc2VsID0gdm5vZGUuc2VsO1xuICAgIGlmIChpc0RlZihzZWwpKSB7XG4gICAgICAvLyBQYXJzZSBzZWxlY3RvclxuICAgICAgdmFyIGhhc2hJZHggPSBzZWwuaW5kZXhPZignIycpO1xuICAgICAgdmFyIGRvdElkeCA9IHNlbC5pbmRleE9mKCcuJywgaGFzaElkeCk7XG4gICAgICB2YXIgaGFzaCA9IGhhc2hJZHggPiAwID8gaGFzaElkeCA6IHNlbC5sZW5ndGg7XG4gICAgICB2YXIgZG90ID0gZG90SWR4ID4gMCA/IGRvdElkeCA6IHNlbC5sZW5ndGg7XG4gICAgICB2YXIgdGFnID0gaGFzaElkeCAhPT0gLTEgfHwgZG90SWR4ICE9PSAtMSA/IHNlbC5zbGljZSgwLCBNYXRoLm1pbihoYXNoLCBkb3QpKSA6IHNlbDtcbiAgICAgIGVsbSA9IHZub2RlLmVsbSA9IGlzRGVmKGRhdGEpICYmIGlzRGVmKGkgPSBkYXRhLm5zKSA/IGFwaS5jcmVhdGVFbGVtZW50TlMoaSwgdGFnKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogYXBpLmNyZWF0ZUVsZW1lbnQodGFnKTtcbiAgICAgIGlmIChoYXNoIDwgZG90KSBlbG0uaWQgPSBzZWwuc2xpY2UoaGFzaCArIDEsIGRvdCk7XG4gICAgICBpZiAoZG90SWR4ID4gMCkgZWxtLmNsYXNzTmFtZSA9IHNlbC5zbGljZShkb3QgKyAxKS5yZXBsYWNlKC9cXC4vZywgJyAnKTtcbiAgICAgIGlmIChpcy5hcnJheShjaGlsZHJlbikpIHtcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IGNoaWxkcmVuLmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAgYXBpLmFwcGVuZENoaWxkKGVsbSwgY3JlYXRlRWxtKGNoaWxkcmVuW2ldLCBpbnNlcnRlZFZub2RlUXVldWUpKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmIChpcy5wcmltaXRpdmUodm5vZGUudGV4dCkpIHtcbiAgICAgICAgYXBpLmFwcGVuZENoaWxkKGVsbSwgYXBpLmNyZWF0ZVRleHROb2RlKHZub2RlLnRleHQpKTtcbiAgICAgIH1cbiAgICAgIGZvciAoaSA9IDA7IGkgPCBjYnMuY3JlYXRlLmxlbmd0aDsgKytpKSBjYnMuY3JlYXRlW2ldKGVtcHR5Tm9kZSwgdm5vZGUpO1xuICAgICAgaSA9IHZub2RlLmRhdGEuaG9vazsgLy8gUmV1c2UgdmFyaWFibGVcbiAgICAgIGlmIChpc0RlZihpKSkge1xuICAgICAgICBpZiAoaS5jcmVhdGUpIGkuY3JlYXRlKGVtcHR5Tm9kZSwgdm5vZGUpO1xuICAgICAgICBpZiAoaS5pbnNlcnQpIGluc2VydGVkVm5vZGVRdWV1ZS5wdXNoKHZub2RlKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgZWxtID0gdm5vZGUuZWxtID0gYXBpLmNyZWF0ZVRleHROb2RlKHZub2RlLnRleHQpO1xuICAgIH1cbiAgICByZXR1cm4gdm5vZGUuZWxtO1xuICB9XG5cbiAgZnVuY3Rpb24gYWRkVm5vZGVzKHBhcmVudEVsbSwgYmVmb3JlLCB2bm9kZXMsIHN0YXJ0SWR4LCBlbmRJZHgsIGluc2VydGVkVm5vZGVRdWV1ZSkge1xuICAgIGZvciAoOyBzdGFydElkeCA8PSBlbmRJZHg7ICsrc3RhcnRJZHgpIHtcbiAgICAgIGFwaS5pbnNlcnRCZWZvcmUocGFyZW50RWxtLCBjcmVhdGVFbG0odm5vZGVzW3N0YXJ0SWR4XSwgaW5zZXJ0ZWRWbm9kZVF1ZXVlKSwgYmVmb3JlKTtcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBpbnZva2VEZXN0cm95SG9vayh2bm9kZSkge1xuICAgIHZhciBpLCBqLCBkYXRhID0gdm5vZGUuZGF0YTtcbiAgICBpZiAoaXNEZWYoZGF0YSkpIHtcbiAgICAgIGlmIChpc0RlZihpID0gZGF0YS5ob29rKSAmJiBpc0RlZihpID0gaS5kZXN0cm95KSkgaSh2bm9kZSk7XG4gICAgICBmb3IgKGkgPSAwOyBpIDwgY2JzLmRlc3Ryb3kubGVuZ3RoOyArK2kpIGNicy5kZXN0cm95W2ldKHZub2RlKTtcbiAgICAgIGlmIChpc0RlZihpID0gdm5vZGUuY2hpbGRyZW4pKSB7XG4gICAgICAgIGZvciAoaiA9IDA7IGogPCB2bm9kZS5jaGlsZHJlbi5sZW5ndGg7ICsraikge1xuICAgICAgICAgIGludm9rZURlc3Ryb3lIb29rKHZub2RlLmNoaWxkcmVuW2pdKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIHJlbW92ZVZub2RlcyhwYXJlbnRFbG0sIHZub2Rlcywgc3RhcnRJZHgsIGVuZElkeCkge1xuICAgIGZvciAoOyBzdGFydElkeCA8PSBlbmRJZHg7ICsrc3RhcnRJZHgpIHtcbiAgICAgIHZhciBpLCBsaXN0ZW5lcnMsIHJtLCBjaCA9IHZub2Rlc1tzdGFydElkeF07XG4gICAgICBpZiAoaXNEZWYoY2gpKSB7XG4gICAgICAgIGlmIChpc0RlZihjaC5zZWwpKSB7XG4gICAgICAgICAgaW52b2tlRGVzdHJveUhvb2soY2gpO1xuICAgICAgICAgIGxpc3RlbmVycyA9IGNicy5yZW1vdmUubGVuZ3RoICsgMTtcbiAgICAgICAgICBybSA9IGNyZWF0ZVJtQ2IoY2guZWxtLCBsaXN0ZW5lcnMpO1xuICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBjYnMucmVtb3ZlLmxlbmd0aDsgKytpKSBjYnMucmVtb3ZlW2ldKGNoLCBybSk7XG4gICAgICAgICAgaWYgKGlzRGVmKGkgPSBjaC5kYXRhKSAmJiBpc0RlZihpID0gaS5ob29rKSAmJiBpc0RlZihpID0gaS5yZW1vdmUpKSB7XG4gICAgICAgICAgICBpKGNoLCBybSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJtKCk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgeyAvLyBUZXh0IG5vZGVcbiAgICAgICAgICBhcGkucmVtb3ZlQ2hpbGQocGFyZW50RWxtLCBjaC5lbG0pO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gdXBkYXRlQ2hpbGRyZW4ocGFyZW50RWxtLCBvbGRDaCwgbmV3Q2gsIGluc2VydGVkVm5vZGVRdWV1ZSkge1xuICAgIHZhciBvbGRTdGFydElkeCA9IDAsIG5ld1N0YXJ0SWR4ID0gMDtcbiAgICB2YXIgb2xkRW5kSWR4ID0gb2xkQ2gubGVuZ3RoIC0gMTtcbiAgICB2YXIgb2xkU3RhcnRWbm9kZSA9IG9sZENoWzBdO1xuICAgIHZhciBvbGRFbmRWbm9kZSA9IG9sZENoW29sZEVuZElkeF07XG4gICAgdmFyIG5ld0VuZElkeCA9IG5ld0NoLmxlbmd0aCAtIDE7XG4gICAgdmFyIG5ld1N0YXJ0Vm5vZGUgPSBuZXdDaFswXTtcbiAgICB2YXIgbmV3RW5kVm5vZGUgPSBuZXdDaFtuZXdFbmRJZHhdO1xuICAgIHZhciBvbGRLZXlUb0lkeCwgaWR4SW5PbGQsIGVsbVRvTW92ZSwgYmVmb3JlO1xuXG4gICAgd2hpbGUgKG9sZFN0YXJ0SWR4IDw9IG9sZEVuZElkeCAmJiBuZXdTdGFydElkeCA8PSBuZXdFbmRJZHgpIHtcbiAgICAgIGlmIChpc1VuZGVmKG9sZFN0YXJ0Vm5vZGUpKSB7XG4gICAgICAgIG9sZFN0YXJ0Vm5vZGUgPSBvbGRDaFsrK29sZFN0YXJ0SWR4XTsgLy8gVm5vZGUgaGFzIGJlZW4gbW92ZWQgbGVmdFxuICAgICAgfSBlbHNlIGlmIChpc1VuZGVmKG9sZEVuZFZub2RlKSkge1xuICAgICAgICBvbGRFbmRWbm9kZSA9IG9sZENoWy0tb2xkRW5kSWR4XTtcbiAgICAgIH0gZWxzZSBpZiAoc2FtZVZub2RlKG9sZFN0YXJ0Vm5vZGUsIG5ld1N0YXJ0Vm5vZGUpKSB7XG4gICAgICAgIHBhdGNoVm5vZGUob2xkU3RhcnRWbm9kZSwgbmV3U3RhcnRWbm9kZSwgaW5zZXJ0ZWRWbm9kZVF1ZXVlKTtcbiAgICAgICAgb2xkU3RhcnRWbm9kZSA9IG9sZENoWysrb2xkU3RhcnRJZHhdO1xuICAgICAgICBuZXdTdGFydFZub2RlID0gbmV3Q2hbKytuZXdTdGFydElkeF07XG4gICAgICB9IGVsc2UgaWYgKHNhbWVWbm9kZShvbGRFbmRWbm9kZSwgbmV3RW5kVm5vZGUpKSB7XG4gICAgICAgIHBhdGNoVm5vZGUob2xkRW5kVm5vZGUsIG5ld0VuZFZub2RlLCBpbnNlcnRlZFZub2RlUXVldWUpO1xuICAgICAgICBvbGRFbmRWbm9kZSA9IG9sZENoWy0tb2xkRW5kSWR4XTtcbiAgICAgICAgbmV3RW5kVm5vZGUgPSBuZXdDaFstLW5ld0VuZElkeF07XG4gICAgICB9IGVsc2UgaWYgKHNhbWVWbm9kZShvbGRTdGFydFZub2RlLCBuZXdFbmRWbm9kZSkpIHsgLy8gVm5vZGUgbW92ZWQgcmlnaHRcbiAgICAgICAgcGF0Y2hWbm9kZShvbGRTdGFydFZub2RlLCBuZXdFbmRWbm9kZSwgaW5zZXJ0ZWRWbm9kZVF1ZXVlKTtcbiAgICAgICAgYXBpLmluc2VydEJlZm9yZShwYXJlbnRFbG0sIG9sZFN0YXJ0Vm5vZGUuZWxtLCBhcGkubmV4dFNpYmxpbmcob2xkRW5kVm5vZGUuZWxtKSk7XG4gICAgICAgIG9sZFN0YXJ0Vm5vZGUgPSBvbGRDaFsrK29sZFN0YXJ0SWR4XTtcbiAgICAgICAgbmV3RW5kVm5vZGUgPSBuZXdDaFstLW5ld0VuZElkeF07XG4gICAgICB9IGVsc2UgaWYgKHNhbWVWbm9kZShvbGRFbmRWbm9kZSwgbmV3U3RhcnRWbm9kZSkpIHsgLy8gVm5vZGUgbW92ZWQgbGVmdFxuICAgICAgICBwYXRjaFZub2RlKG9sZEVuZFZub2RlLCBuZXdTdGFydFZub2RlLCBpbnNlcnRlZFZub2RlUXVldWUpO1xuICAgICAgICBhcGkuaW5zZXJ0QmVmb3JlKHBhcmVudEVsbSwgb2xkRW5kVm5vZGUuZWxtLCBvbGRTdGFydFZub2RlLmVsbSk7XG4gICAgICAgIG9sZEVuZFZub2RlID0gb2xkQ2hbLS1vbGRFbmRJZHhdO1xuICAgICAgICBuZXdTdGFydFZub2RlID0gbmV3Q2hbKytuZXdTdGFydElkeF07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZiAoaXNVbmRlZihvbGRLZXlUb0lkeCkpIG9sZEtleVRvSWR4ID0gY3JlYXRlS2V5VG9PbGRJZHgob2xkQ2gsIG9sZFN0YXJ0SWR4LCBvbGRFbmRJZHgpO1xuICAgICAgICBpZHhJbk9sZCA9IG9sZEtleVRvSWR4W25ld1N0YXJ0Vm5vZGUua2V5XTtcbiAgICAgICAgaWYgKGlzVW5kZWYoaWR4SW5PbGQpKSB7IC8vIE5ldyBlbGVtZW50XG4gICAgICAgICAgYXBpLmluc2VydEJlZm9yZShwYXJlbnRFbG0sIGNyZWF0ZUVsbShuZXdTdGFydFZub2RlLCBpbnNlcnRlZFZub2RlUXVldWUpLCBvbGRTdGFydFZub2RlLmVsbSk7XG4gICAgICAgICAgbmV3U3RhcnRWbm9kZSA9IG5ld0NoWysrbmV3U3RhcnRJZHhdO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGVsbVRvTW92ZSA9IG9sZENoW2lkeEluT2xkXTtcbiAgICAgICAgICBwYXRjaFZub2RlKGVsbVRvTW92ZSwgbmV3U3RhcnRWbm9kZSwgaW5zZXJ0ZWRWbm9kZVF1ZXVlKTtcbiAgICAgICAgICBvbGRDaFtpZHhJbk9sZF0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgYXBpLmluc2VydEJlZm9yZShwYXJlbnRFbG0sIGVsbVRvTW92ZS5lbG0sIG9sZFN0YXJ0Vm5vZGUuZWxtKTtcbiAgICAgICAgICBuZXdTdGFydFZub2RlID0gbmV3Q2hbKytuZXdTdGFydElkeF07XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKG9sZFN0YXJ0SWR4ID4gb2xkRW5kSWR4KSB7XG4gICAgICBiZWZvcmUgPSBpc1VuZGVmKG5ld0NoW25ld0VuZElkeCsxXSkgPyBudWxsIDogbmV3Q2hbbmV3RW5kSWR4KzFdLmVsbTtcbiAgICAgIGFkZFZub2RlcyhwYXJlbnRFbG0sIGJlZm9yZSwgbmV3Q2gsIG5ld1N0YXJ0SWR4LCBuZXdFbmRJZHgsIGluc2VydGVkVm5vZGVRdWV1ZSk7XG4gICAgfSBlbHNlIGlmIChuZXdTdGFydElkeCA+IG5ld0VuZElkeCkge1xuICAgICAgcmVtb3ZlVm5vZGVzKHBhcmVudEVsbSwgb2xkQ2gsIG9sZFN0YXJ0SWR4LCBvbGRFbmRJZHgpO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIHBhdGNoVm5vZGUob2xkVm5vZGUsIHZub2RlLCBpbnNlcnRlZFZub2RlUXVldWUpIHtcbiAgICB2YXIgaSwgaG9vaztcbiAgICBpZiAoaXNEZWYoaSA9IHZub2RlLmRhdGEpICYmIGlzRGVmKGhvb2sgPSBpLmhvb2spICYmIGlzRGVmKGkgPSBob29rLnByZXBhdGNoKSkge1xuICAgICAgaShvbGRWbm9kZSwgdm5vZGUpO1xuICAgIH1cbiAgICB2YXIgZWxtID0gdm5vZGUuZWxtID0gb2xkVm5vZGUuZWxtLCBvbGRDaCA9IG9sZFZub2RlLmNoaWxkcmVuLCBjaCA9IHZub2RlLmNoaWxkcmVuO1xuICAgIGlmIChvbGRWbm9kZSA9PT0gdm5vZGUpIHJldHVybjtcbiAgICBpZiAoIXNhbWVWbm9kZShvbGRWbm9kZSwgdm5vZGUpKSB7XG4gICAgICB2YXIgcGFyZW50RWxtID0gYXBpLnBhcmVudE5vZGUob2xkVm5vZGUuZWxtKTtcbiAgICAgIGVsbSA9IGNyZWF0ZUVsbSh2bm9kZSwgaW5zZXJ0ZWRWbm9kZVF1ZXVlKTtcbiAgICAgIGFwaS5pbnNlcnRCZWZvcmUocGFyZW50RWxtLCBlbG0sIG9sZFZub2RlLmVsbSk7XG4gICAgICByZW1vdmVWbm9kZXMocGFyZW50RWxtLCBbb2xkVm5vZGVdLCAwLCAwKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKGlzRGVmKHZub2RlLmRhdGEpKSB7XG4gICAgICBmb3IgKGkgPSAwOyBpIDwgY2JzLnVwZGF0ZS5sZW5ndGg7ICsraSkgY2JzLnVwZGF0ZVtpXShvbGRWbm9kZSwgdm5vZGUpO1xuICAgICAgaSA9IHZub2RlLmRhdGEuaG9vaztcbiAgICAgIGlmIChpc0RlZihpKSAmJiBpc0RlZihpID0gaS51cGRhdGUpKSBpKG9sZFZub2RlLCB2bm9kZSk7XG4gICAgfVxuICAgIGlmIChpc1VuZGVmKHZub2RlLnRleHQpKSB7XG4gICAgICBpZiAoaXNEZWYob2xkQ2gpICYmIGlzRGVmKGNoKSkge1xuICAgICAgICBpZiAob2xkQ2ggIT09IGNoKSB1cGRhdGVDaGlsZHJlbihlbG0sIG9sZENoLCBjaCwgaW5zZXJ0ZWRWbm9kZVF1ZXVlKTtcbiAgICAgIH0gZWxzZSBpZiAoaXNEZWYoY2gpKSB7XG4gICAgICAgIGlmIChpc0RlZihvbGRWbm9kZS50ZXh0KSkgYXBpLnNldFRleHRDb250ZW50KGVsbSwgJycpO1xuICAgICAgICBhZGRWbm9kZXMoZWxtLCBudWxsLCBjaCwgMCwgY2gubGVuZ3RoIC0gMSwgaW5zZXJ0ZWRWbm9kZVF1ZXVlKTtcbiAgICAgIH0gZWxzZSBpZiAoaXNEZWYob2xkQ2gpKSB7XG4gICAgICAgIHJlbW92ZVZub2RlcyhlbG0sIG9sZENoLCAwLCBvbGRDaC5sZW5ndGggLSAxKTtcbiAgICAgIH0gZWxzZSBpZiAoaXNEZWYob2xkVm5vZGUudGV4dCkpIHtcbiAgICAgICAgYXBpLnNldFRleHRDb250ZW50KGVsbSwgJycpO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAob2xkVm5vZGUudGV4dCAhPT0gdm5vZGUudGV4dCkge1xuICAgICAgYXBpLnNldFRleHRDb250ZW50KGVsbSwgdm5vZGUudGV4dCk7XG4gICAgfVxuICAgIGlmIChpc0RlZihob29rKSAmJiBpc0RlZihpID0gaG9vay5wb3N0cGF0Y2gpKSB7XG4gICAgICBpKG9sZFZub2RlLCB2bm9kZSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGZ1bmN0aW9uKG9sZFZub2RlLCB2bm9kZSkge1xuICAgIHZhciBpLCBlbG0sIHBhcmVudDtcbiAgICB2YXIgaW5zZXJ0ZWRWbm9kZVF1ZXVlID0gW107XG4gICAgZm9yIChpID0gMDsgaSA8IGNicy5wcmUubGVuZ3RoOyArK2kpIGNicy5wcmVbaV0oKTtcblxuICAgIGlmIChpc1VuZGVmKG9sZFZub2RlLnNlbCkpIHtcbiAgICAgIG9sZFZub2RlID0gZW1wdHlOb2RlQXQob2xkVm5vZGUpO1xuICAgIH1cblxuICAgIGlmIChzYW1lVm5vZGUob2xkVm5vZGUsIHZub2RlKSkge1xuICAgICAgcGF0Y2hWbm9kZShvbGRWbm9kZSwgdm5vZGUsIGluc2VydGVkVm5vZGVRdWV1ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGVsbSA9IG9sZFZub2RlLmVsbTtcbiAgICAgIHBhcmVudCA9IGFwaS5wYXJlbnROb2RlKGVsbSk7XG5cbiAgICAgIGNyZWF0ZUVsbSh2bm9kZSwgaW5zZXJ0ZWRWbm9kZVF1ZXVlKTtcblxuICAgICAgaWYgKHBhcmVudCAhPT0gbnVsbCkge1xuICAgICAgICBhcGkuaW5zZXJ0QmVmb3JlKHBhcmVudCwgdm5vZGUuZWxtLCBhcGkubmV4dFNpYmxpbmcoZWxtKSk7XG4gICAgICAgIHJlbW92ZVZub2RlcyhwYXJlbnQsIFtvbGRWbm9kZV0sIDAsIDApO1xuICAgICAgfVxuICAgIH1cblxuICAgIGZvciAoaSA9IDA7IGkgPCBpbnNlcnRlZFZub2RlUXVldWUubGVuZ3RoOyArK2kpIHtcbiAgICAgIGluc2VydGVkVm5vZGVRdWV1ZVtpXS5kYXRhLmhvb2suaW5zZXJ0KGluc2VydGVkVm5vZGVRdWV1ZVtpXSk7XG4gICAgfVxuICAgIGZvciAoaSA9IDA7IGkgPCBjYnMucG9zdC5sZW5ndGg7ICsraSkgY2JzLnBvc3RbaV0oKTtcbiAgICByZXR1cm4gdm5vZGU7XG4gIH07XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge2luaXQ6IGluaXR9O1xuIiwibW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihzZWwsIGRhdGEsIGNoaWxkcmVuLCB0ZXh0LCBlbG0pIHtcbiAgdmFyIGtleSA9IGRhdGEgPT09IHVuZGVmaW5lZCA/IHVuZGVmaW5lZCA6IGRhdGEua2V5O1xuICByZXR1cm4ge3NlbDogc2VsLCBkYXRhOiBkYXRhLCBjaGlsZHJlbjogY2hpbGRyZW4sXG4gICAgICAgICAgdGV4dDogdGV4dCwgZWxtOiBlbG0sIGtleToga2V5fTtcbn07XG4iXX0=\n"]} \ No newline at end of file diff --git a/dist/snabbdom_attributes.js b/dist/snabbdom_attributes.js index bbfc262..efbfb6e 100644 --- a/dist/snabbdom_attributes.js +++ b/dist/snabbdom_attributes.js @@ -1,20 +1,24 @@ (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.snabbdom_attributes = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;oi;i++)a[o[i]]=!0;t.exports={create:n,update:n}},{}]},{},[1])(1)}); -//# sourceMappingURL=snabbdom_attributes.min.js.map +!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var t;t="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,t.snabbdom_attributes=e()}}(function(){return function e(t,r,n){function o(a,d){if(!r[a]){if(!t[a]){var f="function"==typeof require&&require;if(!d&&f)return f(a,!0);if(i)return i(a,!0);var u=new Error("Cannot find module '"+a+"'");throw u.code="MODULE_NOT_FOUND",u}var l=r[a]={exports:{}};t[a][0].call(l.exports,function(e){var r=t[a][1][e];return o(r?r:e)},l,l.exports,e,t,r,n)}return r[a].exports}for(var i="function"==typeof require&&require,a=0;a Date: Mon, 17 Oct 2016 20:54:53 +0300 Subject: [PATCH 26/32] Cycle.js instead of Motorcycle.js in README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ef1fb28..64ff4ae 100644 --- a/README.md +++ b/README.md @@ -629,9 +629,9 @@ Here are some approaches to building applications with Snabbdom. * [functional-frontend-architecture](https://github.com/paldepind/functional-frontend-architecture) – a repository containing several example applications that demonstrates an architecture that uses Snabbdom. -* [Motorcycle.js](https://github.com/motorcyclejs/core) – - is a variant of the functional and reactive Javascript framework - [Cycle.js](http://cycle.js.org/) that uses Snabbdom. +* [Cycle.js](https://cycle.js.org/) – + "A functional and reactive JavaScript framework for cleaner code" + uses Snabbdom Be sure to share it if you're building an application in another way using Snabbdom. From 12bd7dd7703d173682634cdb65eba7c468c02e73 Mon Sep 17 00:00:00 2001 From: Matt Kaemmerer Date: Mon, 17 Oct 2016 13:09:59 -0500 Subject: [PATCH 27/32] Call setAttributeNS instead of setAttribute for keys with a known namespace --- modules/attributes.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/modules/attributes.js b/modules/attributes.js index 9a50259..7456277 100644 --- a/modules/attributes.js +++ b/modules/attributes.js @@ -1,3 +1,7 @@ +var NamespaceURIs = { + "xlink": "http://www.w3.org/1999/xlink" +}; + var booleanAttrs = ["allowfullscreen", "async", "autofocus", "autoplay", "checked", "compact", "controls", "declare", "default", "defaultchecked", "defaultmuted", "defaultselected", "defer", "disabled", "draggable", "enabled", "formnovalidate", "hidden", "indeterminate", "inert", "ismap", "itemscope", "loop", "multiple", @@ -12,7 +16,7 @@ for(var i=0, len = booleanAttrs.length; i < len; i++) { function updateAttrs(oldVnode, vnode) { var key, cur, old, elm = vnode.elm, - oldAttrs = oldVnode.data.attrs, attrs = vnode.data.attrs; + oldAttrs = oldVnode.data.attrs, attrs = vnode.data.attrs, namespace; if (!oldAttrs && !attrs) return; oldAttrs = oldAttrs || {}; @@ -22,10 +26,12 @@ function updateAttrs(oldVnode, vnode) { for (key in attrs) { cur = attrs[key]; old = oldAttrs[key]; + namespace = key.split(":")[0]; if (old !== cur) { - // TODO: add support to namespaced attributes (setAttributeNS) if(!cur && booleanAttrsDict[key]) elm.removeAttribute(key); + else if(key.match(/:/) && NamespaceURIs.hasOwnProperty(namespace)) + elm.setAttributeNS(NamespaceURIs[namespace], key, cur); else elm.setAttribute(key, cur); } From 73996327956ebe7581ee8e919d0847a4c8d2bfa4 Mon Sep 17 00:00:00 2001 From: Matt Kaemmerer Date: Mon, 17 Oct 2016 13:16:07 -0500 Subject: [PATCH 28/32] Add test for namespaced attributes --- test/attributes.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/attributes.js b/test/attributes.js index 1ab372c..532ac42 100644 --- a/test/attributes.js +++ b/test/attributes.js @@ -26,6 +26,11 @@ describe('attributes', function() { assert.strictEqual(elm.getAttribute('minlength'), '0'); assert.strictEqual(elm.getAttribute('value'), 'false'); }); + it('are set correctly when namespaced', function() { + var vnode1 = h('div', {attrs: {'xlink:href': '#foo'}}); + elm = patch(vnode0, vnode1).elm; + assert.strictEqual(elm.getAttributeNS('http://www.w3.org/1999/xlink', 'href'), '#foo'); + }); describe('boolean attribute', function() { it('is present if the value is truthy', function() { var vnode1 = h('div', {attrs: {required: true, readonly: 1, noresize: 'truthy'}}); From e1d93dca976c26ce33e7be98e5011c7b81b91c02 Mon Sep 17 00:00:00 2001 From: Matt Kaemmerer Date: Wed, 19 Oct 2016 22:24:43 -0500 Subject: [PATCH 29/32] Defer splitting namespace until needed --- modules/attributes.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/modules/attributes.js b/modules/attributes.js index 7456277..e486bc7 100644 --- a/modules/attributes.js +++ b/modules/attributes.js @@ -16,7 +16,7 @@ for(var i=0, len = booleanAttrs.length; i < len; i++) { function updateAttrs(oldVnode, vnode) { var key, cur, old, elm = vnode.elm, - oldAttrs = oldVnode.data.attrs, attrs = vnode.data.attrs, namespace; + oldAttrs = oldVnode.data.attrs, attrs = vnode.data.attrs, namespaceSplit; if (!oldAttrs && !attrs) return; oldAttrs = oldAttrs || {}; @@ -26,14 +26,16 @@ function updateAttrs(oldVnode, vnode) { for (key in attrs) { cur = attrs[key]; old = oldAttrs[key]; - namespace = key.split(":")[0]; if (old !== cur) { if(!cur && booleanAttrsDict[key]) elm.removeAttribute(key); - else if(key.match(/:/) && NamespaceURIs.hasOwnProperty(namespace)) - elm.setAttributeNS(NamespaceURIs[namespace], key, cur); - else - elm.setAttribute(key, cur); + else { + namespaceSplit = key.split(":"); + if(namespaceSplit.length > 1 && NamespaceURIs.hasOwnProperty(namespaceSplit[0])) + elm.setAttributeNS(NamespaceURIs[namespaceSplit[0]], key, cur); + else + elm.setAttribute(key, cur); + } } } //remove removed attributes From 0fbcfd3278a80177e23190e131ff871a73acbbcd Mon Sep 17 00:00:00 2001 From: paldepind Date: Thu, 20 Oct 2016 18:31:03 +0200 Subject: [PATCH 30/32] Version 0.5.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6db5ef7..1aceea4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "snabbdom", - "version": "0.5.3", + "version": "0.5.4", "description": "A virtual DOM library with focus on simplicity, modularity, powerful features and performance.", "main": "snabbdom.js", "typings": "type-definitions/snabbdom.d.ts", From 685fb99755be03d0a124f660071db878ebaf2b2d Mon Sep 17 00:00:00 2001 From: Amirouche Date: Thu, 13 Oct 2016 19:44:53 +0200 Subject: [PATCH 31/32] =?UTF-8?q?Add=20`vue.js`=20and=20`scheme-todomvc`?= =?UTF-8?q?=20in=20=E2=80=9CStructuring=20applications=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 64ff4ae..7de1d00 100644 --- a/README.md +++ b/README.md @@ -632,6 +632,10 @@ Here are some approaches to building applications with Snabbdom. * [Cycle.js](https://cycle.js.org/) – "A functional and reactive JavaScript framework for cleaner code" uses Snabbdom +* [Vue.js](http://vuejs.org/) use a fork of snabbdom. +* [scheme-todomvc](https://github.com/amirouche/scheme-todomvc/) build + redux-like architecture on top of snabbdom bindings. Be sure to share it if you're building an application in another way using Snabbdom. + From 8f30755a6abe01c55f5e25083162166f3bf335c8 Mon Sep 17 00:00:00 2001 From: AlexGalays Date: Wed, 26 Oct 2016 10:17:15 +0200 Subject: [PATCH 32/32] README: Add one more example in "Structuring application" --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 7de1d00..1c29816 100644 --- a/README.md +++ b/README.md @@ -635,6 +635,8 @@ Here are some approaches to building applications with Snabbdom. * [Vue.js](http://vuejs.org/) use a fork of snabbdom. * [scheme-todomvc](https://github.com/amirouche/scheme-todomvc/) build redux-like architecture on top of snabbdom bindings. +* [kaiju](https://github.com/AlexGalays/kaiju) - + Stateful components and observables on top of snabbdom Be sure to share it if you're building an application in another way using Snabbdom.