|
@@ -1,4 +1,3 @@
|
|
-import { dom, createElement, textOrComment} from './dom.js'
|
|
|
|
|
|
|
|
let resolveStep = () => {}
|
|
let resolveStep = () => {}
|
|
|
|
|
|
@@ -13,19 +12,13 @@ export function morph(from, toHtml, options) {
|
|
|
|
|
|
let fromEl
|
|
let fromEl
|
|
let toEl
|
|
let toEl
|
|
- let key
|
|
|
|
- ,lookahead
|
|
|
|
- ,updating
|
|
|
|
- ,updated
|
|
|
|
- ,removing
|
|
|
|
- ,removed
|
|
|
|
- ,adding
|
|
|
|
- ,added
|
|
|
|
|
|
+ let key, lookahead, updating, updated, removing, removed, adding, added
|
|
|
|
|
|
function assignOptions(options = {}) {
|
|
function assignOptions(options = {}) {
|
|
let defaultGetKey = el => el.getAttribute('key')
|
|
let defaultGetKey = el => el.getAttribute('key')
|
|
let noop = () => {}
|
|
let noop = () => {}
|
|
|
|
|
|
|
|
+ console.log(options.key)
|
|
updating = options.updating || noop
|
|
updating = options.updating || noop
|
|
updated = options.updated || noop
|
|
updated = options.updated || noop
|
|
removing = options.removing || noop
|
|
removing = options.removing || noop
|
|
@@ -37,25 +30,22 @@ export function morph(from, toHtml, options) {
|
|
}
|
|
}
|
|
|
|
|
|
function patch(from, to) {
|
|
function patch(from, to) {
|
|
- // This is a time saver, however, it won't catch differences in nested <template> tags.
|
|
|
|
- // I'm leaving this here as I believe it's an important speed improvement, I just
|
|
|
|
- // don't see a way to enable it currently:
|
|
|
|
- //
|
|
|
|
- // if (from.isEqualNode(to)) return
|
|
|
|
-
|
|
|
|
if (differentElementNamesTypesOrKeys(from, to)) {
|
|
if (differentElementNamesTypesOrKeys(from, to)) {
|
|
- // Swap elements...
|
|
|
|
- return patchElement(from, to)
|
|
|
|
|
|
+ return swapElements(from, to)
|
|
}
|
|
}
|
|
|
|
|
|
let updateChildrenOnly = false
|
|
let updateChildrenOnly = false
|
|
|
|
|
|
if (shouldSkip(updating, from, to, () => updateChildrenOnly = true)) return
|
|
if (shouldSkip(updating, from, to, () => updateChildrenOnly = true)) return
|
|
|
|
|
|
- window.Alpine && initializeAlpineOnTo(from, to, () => updateChildrenOnly = true)
|
|
|
|
|
|
+ // Initialize the server-side HTML element with Alpine...
|
|
|
|
+ if (from.nodeType === 1 && window.Alpine) {
|
|
|
|
+ window.Alpine.cloneNode(from, to)
|
|
|
|
+ }
|
|
|
|
|
|
if (textOrComment(to)) {
|
|
if (textOrComment(to)) {
|
|
patchNodeValue(from, to)
|
|
patchNodeValue(from, to)
|
|
|
|
+
|
|
updated(from, to)
|
|
updated(from, to)
|
|
|
|
|
|
return
|
|
return
|
|
@@ -67,9 +57,7 @@ export function morph(from, toHtml, options) {
|
|
|
|
|
|
updated(from, to)
|
|
updated(from, to)
|
|
|
|
|
|
- patchChildren(Array.from(from.childNodes), Array.from(to.childNodes), (toAppend) => {
|
|
|
|
- from.appendChild(toAppend)
|
|
|
|
- })
|
|
|
|
|
|
+ patchChildren(from, to)
|
|
}
|
|
}
|
|
|
|
|
|
function differentElementNamesTypesOrKeys(from, to) {
|
|
function differentElementNamesTypesOrKeys(from, to) {
|
|
@@ -78,14 +66,14 @@ export function morph(from, toHtml, options) {
|
|
|| getKey(from) != getKey(to)
|
|
|| getKey(from) != getKey(to)
|
|
}
|
|
}
|
|
|
|
|
|
- function patchElement(from, to) {
|
|
|
|
|
|
+ function swapElements(from, to) {
|
|
if (shouldSkip(removing, from)) return
|
|
if (shouldSkip(removing, from)) return
|
|
|
|
|
|
let toCloned = to.cloneNode(true)
|
|
let toCloned = to.cloneNode(true)
|
|
|
|
|
|
if (shouldSkip(adding, toCloned)) return
|
|
if (shouldSkip(adding, toCloned)) return
|
|
|
|
|
|
- dom.replace([from], from, toCloned)
|
|
|
|
|
|
+ from.replaceWith(toCloned)
|
|
|
|
|
|
removed(from)
|
|
removed(from)
|
|
added(toCloned)
|
|
added(toCloned)
|
|
@@ -132,36 +120,37 @@ export function morph(from, toHtml, options) {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- function patchChildren(fromChildren, toChildren, appendFn) {
|
|
|
|
- let fromKeyDomNodeMap = keyToMap(fromChildren)
|
|
|
|
|
|
+ function patchChildren(from, to) {
|
|
|
|
+ let fromKeys = keyToMap(from.children)
|
|
let fromKeyHoldovers = {}
|
|
let fromKeyHoldovers = {}
|
|
|
|
|
|
- let currentTo = dom.first(toChildren)
|
|
|
|
- let currentFrom = dom.first(fromChildren)
|
|
|
|
|
|
+ let currentTo = getFirstNode(to)
|
|
|
|
+ let currentFrom = getFirstNode(from)
|
|
|
|
|
|
while (currentTo) {
|
|
while (currentTo) {
|
|
let toKey = getKey(currentTo)
|
|
let toKey = getKey(currentTo)
|
|
let fromKey = getKey(currentFrom)
|
|
let fromKey = getKey(currentFrom)
|
|
|
|
|
|
- // Add new elements
|
|
|
|
|
|
+ // Add new elements...
|
|
if (! currentFrom) {
|
|
if (! currentFrom) {
|
|
if (toKey && fromKeyHoldovers[toKey]) {
|
|
if (toKey && fromKeyHoldovers[toKey]) {
|
|
// Add element (from key)...
|
|
// Add element (from key)...
|
|
let holdover = fromKeyHoldovers[toKey]
|
|
let holdover = fromKeyHoldovers[toKey]
|
|
|
|
|
|
- fromChildren = dom.append(fromChildren, holdover, appendFn)
|
|
|
|
|
|
+ from.appendChild(holdover)
|
|
|
|
+
|
|
currentFrom = holdover
|
|
currentFrom = holdover
|
|
} else {
|
|
} else {
|
|
if(! shouldSkip(adding, currentTo)) {
|
|
if(! shouldSkip(adding, currentTo)) {
|
|
// Add element...
|
|
// Add element...
|
|
let clone = currentTo.cloneNode(true)
|
|
let clone = currentTo.cloneNode(true)
|
|
|
|
|
|
- fromChildren = dom.append(fromChildren, clone, appendFn)
|
|
|
|
|
|
+ from.appendChild(clone)
|
|
|
|
|
|
added(clone)
|
|
added(clone)
|
|
}
|
|
}
|
|
|
|
|
|
- currentTo = dom.next(toChildren, currentTo)
|
|
|
|
|
|
+ currentTo = getNextSibling(to, currentTo)
|
|
|
|
|
|
continue
|
|
continue
|
|
}
|
|
}
|
|
@@ -172,54 +161,61 @@ export function morph(from, toHtml, options) {
|
|
let isEnd = node => node && node.nodeType === 8 && node.textContent === ' __ENDBLOCK__ '
|
|
let isEnd = node => node && node.nodeType === 8 && node.textContent === ' __ENDBLOCK__ '
|
|
|
|
|
|
if (isIf(currentTo) && isIf(currentFrom)) {
|
|
if (isIf(currentTo) && isIf(currentFrom)) {
|
|
- let newFromChildren = []
|
|
|
|
- let appendPoint
|
|
|
|
let nestedIfCount = 0
|
|
let nestedIfCount = 0
|
|
|
|
+
|
|
|
|
+ let fromBlockStart = currentFrom
|
|
|
|
+
|
|
while (currentFrom) {
|
|
while (currentFrom) {
|
|
- let next = dom.next(fromChildren, currentFrom)
|
|
|
|
|
|
+ let next = getNextSibling(from, currentFrom)
|
|
|
|
|
|
if (isIf(next)) {
|
|
if (isIf(next)) {
|
|
nestedIfCount++
|
|
nestedIfCount++
|
|
} else if (isEnd(next) && nestedIfCount > 0) {
|
|
} else if (isEnd(next) && nestedIfCount > 0) {
|
|
nestedIfCount--
|
|
nestedIfCount--
|
|
} else if (isEnd(next) && nestedIfCount === 0) {
|
|
} else if (isEnd(next) && nestedIfCount === 0) {
|
|
- currentFrom = dom.next(fromChildren, next)
|
|
|
|
- appendPoint = next
|
|
|
|
|
|
+ currentFrom = next
|
|
|
|
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
- newFromChildren.push(next)
|
|
|
|
currentFrom = next
|
|
currentFrom = next
|
|
}
|
|
}
|
|
|
|
|
|
- let newToChildren = []
|
|
|
|
|
|
+ let fromBlockEnd = currentFrom
|
|
|
|
+
|
|
nestedIfCount = 0
|
|
nestedIfCount = 0
|
|
|
|
+
|
|
|
|
+ let toBlockStart = currentTo
|
|
|
|
+
|
|
while (currentTo) {
|
|
while (currentTo) {
|
|
- let next = dom.next(toChildren, currentTo)
|
|
|
|
|
|
+ let next = getNextSibling(to, currentTo)
|
|
|
|
|
|
if (isIf(next)) {
|
|
if (isIf(next)) {
|
|
nestedIfCount++
|
|
nestedIfCount++
|
|
} else if (isEnd(next) && nestedIfCount > 0) {
|
|
} else if (isEnd(next) && nestedIfCount > 0) {
|
|
nestedIfCount--
|
|
nestedIfCount--
|
|
} else if (isEnd(next) && nestedIfCount === 0) {
|
|
} else if (isEnd(next) && nestedIfCount === 0) {
|
|
- currentTo = dom.next(toChildren, next)
|
|
|
|
|
|
+ currentTo = next
|
|
|
|
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
- newToChildren.push(next)
|
|
|
|
currentTo = next
|
|
currentTo = next
|
|
}
|
|
}
|
|
|
|
|
|
- patchChildren(newFromChildren, newToChildren, node => appendPoint.before(node))
|
|
|
|
|
|
+ let toBlockEnd = currentTo
|
|
|
|
+
|
|
|
|
+ let fromBlock = new Block(fromBlockStart, fromBlockEnd)
|
|
|
|
+ let toBlock = new Block(toBlockStart, toBlockEnd)
|
|
|
|
+
|
|
|
|
+ patchChildren(fromBlock, toBlock)
|
|
|
|
|
|
continue
|
|
continue
|
|
}
|
|
}
|
|
|
|
|
|
// Lookaheads should only apply to non-text-or-comment elements...
|
|
// Lookaheads should only apply to non-text-or-comment elements...
|
|
if (currentFrom.nodeType === 1 && lookahead && ! currentFrom.isEqualNode(currentTo)) {
|
|
if (currentFrom.nodeType === 1 && lookahead && ! currentFrom.isEqualNode(currentTo)) {
|
|
- let nextToElementSibling = dom.next(toChildren, currentTo)
|
|
|
|
|
|
+ let nextToElementSibling = getNextSibling(to, currentTo)
|
|
|
|
|
|
let found = false
|
|
let found = false
|
|
|
|
|
|
@@ -227,12 +223,12 @@ export function morph(from, toHtml, options) {
|
|
if (nextToElementSibling.nodeType === 1 && currentFrom.isEqualNode(nextToElementSibling)) {
|
|
if (nextToElementSibling.nodeType === 1 && currentFrom.isEqualNode(nextToElementSibling)) {
|
|
found = true; // This ";" needs to be here...
|
|
found = true; // This ";" needs to be here...
|
|
|
|
|
|
- [fromChildren, currentFrom] = addNodeBefore(fromChildren, currentTo, currentFrom)
|
|
|
|
|
|
+ currentFrom = addNodeBefore(from, currentTo, currentFrom)
|
|
|
|
|
|
fromKey = getKey(currentFrom)
|
|
fromKey = getKey(currentFrom)
|
|
}
|
|
}
|
|
|
|
|
|
- nextToElementSibling = dom.next(toChildren, nextToElementSibling)
|
|
|
|
|
|
+ nextToElementSibling = getNextSibling(to, nextToElementSibling)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -240,37 +236,37 @@ export function morph(from, toHtml, options) {
|
|
if (! toKey && fromKey) {
|
|
if (! toKey && fromKey) {
|
|
// No "to" key...
|
|
// No "to" key...
|
|
fromKeyHoldovers[fromKey] = currentFrom; // This ";" needs to be here...
|
|
fromKeyHoldovers[fromKey] = currentFrom; // This ";" needs to be here...
|
|
- [fromChildren, currentFrom] = addNodeBefore(fromChildren, currentTo, currentFrom)
|
|
|
|
- fromChildren = dom.remove(fromChildren, fromKeyHoldovers[fromKey])
|
|
|
|
- currentFrom = dom.next(fromChildren, currentFrom)
|
|
|
|
- currentTo = dom.next(toChildren, currentTo)
|
|
|
|
|
|
+ currentFrom = addNodeBefore(from, currentTo, currentFrom)
|
|
|
|
+ fromKeyHoldovers[fromKey].remove()
|
|
|
|
+ currentFrom = getNextSibling(from, currentFrom)
|
|
|
|
+ currentTo = getNextSibling(to, currentTo)
|
|
|
|
|
|
continue
|
|
continue
|
|
}
|
|
}
|
|
|
|
|
|
if (toKey && ! fromKey) {
|
|
if (toKey && ! fromKey) {
|
|
- if (fromKeyDomNodeMap[toKey]) {
|
|
|
|
|
|
+ if (fromKeys[toKey]) {
|
|
// No "from" key...
|
|
// No "from" key...
|
|
- fromChildren = dom.replace(fromChildren, currentFrom, fromKeyDomNodeMap[toKey])
|
|
|
|
- currentFrom = fromKeyDomNodeMap[toKey]
|
|
|
|
|
|
+ currentFrom.replaceWith(fromKeys[toKey])
|
|
|
|
+ currentFrom = fromKeys[toKey]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if (toKey && fromKey) {
|
|
if (toKey && fromKey) {
|
|
- let fromKeyNode = fromKeyDomNodeMap[toKey]
|
|
|
|
|
|
+ let fromKeyNode = fromKeys[toKey]
|
|
|
|
|
|
if (fromKeyNode) {
|
|
if (fromKeyNode) {
|
|
// Move "from" key...
|
|
// Move "from" key...
|
|
fromKeyHoldovers[fromKey] = currentFrom
|
|
fromKeyHoldovers[fromKey] = currentFrom
|
|
- fromChildren = dom.replace(fromChildren, currentFrom, fromKeyNode)
|
|
|
|
|
|
+ currentFrom.replaceWith(fromKeyNode)
|
|
currentFrom = fromKeyNode
|
|
currentFrom = fromKeyNode
|
|
} else {
|
|
} else {
|
|
// Swap elements with keys...
|
|
// Swap elements with keys...
|
|
fromKeyHoldovers[fromKey] = currentFrom; // This ";" needs to be here...
|
|
fromKeyHoldovers[fromKey] = currentFrom; // This ";" needs to be here...
|
|
- [fromChildren, currentFrom] = addNodeBefore(fromChildren, currentTo, currentFrom)
|
|
|
|
- fromChildren = dom.remove(fromChildren, fromKeyHoldovers[fromKey])
|
|
|
|
- currentFrom = dom.next(fromChildren, currentFrom)
|
|
|
|
- currentTo = dom.next(toChildren, currentTo)
|
|
|
|
|
|
+ currentFrom = addNodeBefore(from, currentTo, currentFrom)
|
|
|
|
+ fromKeyHoldovers[fromKey].remove()
|
|
|
|
+ currentFrom = getNextSibling(from, currentFrom)
|
|
|
|
+ currentTo = getNextSibling(to, currentTo)
|
|
|
|
|
|
continue
|
|
continue
|
|
}
|
|
}
|
|
@@ -278,12 +274,13 @@ export function morph(from, toHtml, options) {
|
|
}
|
|
}
|
|
|
|
|
|
// Get next from sibling before patching in case the node is replaced
|
|
// Get next from sibling before patching in case the node is replaced
|
|
- let currentFromNext = currentFrom && dom.next(fromChildren, currentFrom)
|
|
|
|
|
|
+ let currentFromNext = currentFrom && getNextSibling(from, currentFrom) //dom.next(from, fromChildren, currentFrom))
|
|
|
|
|
|
// Patch elements
|
|
// Patch elements
|
|
patch(currentFrom, currentTo)
|
|
patch(currentFrom, currentTo)
|
|
|
|
|
|
- currentTo = currentTo && dom.next(toChildren, currentTo)
|
|
|
|
|
|
+ currentTo = currentTo && getNextSibling(to, currentTo) // dom.next(from, toChildren, currentTo))
|
|
|
|
+
|
|
currentFrom = currentFromNext
|
|
currentFrom = currentFromNext
|
|
}
|
|
}
|
|
|
|
|
|
@@ -293,9 +290,10 @@ export function morph(from, toHtml, options) {
|
|
// We need to collect the "removals" first before actually
|
|
// We need to collect the "removals" first before actually
|
|
// removing them so we don't mess with the order of things.
|
|
// removing them so we don't mess with the order of things.
|
|
while (currentFrom) {
|
|
while (currentFrom) {
|
|
- if(! shouldSkip(removing, currentFrom)) removals.push(currentFrom)
|
|
|
|
|
|
+ if (! shouldSkip(removing, currentFrom)) removals.push(currentFrom)
|
|
|
|
|
|
- currentFrom = dom.next(fromChildren, currentFrom)
|
|
|
|
|
|
+ // currentFrom = dom.next(fromChildren, currentFrom)
|
|
|
|
+ currentFrom = getNextSibling(from, currentFrom)
|
|
}
|
|
}
|
|
|
|
|
|
// Now we can do the actual removals.
|
|
// Now we can do the actual removals.
|
|
@@ -315,29 +313,29 @@ export function morph(from, toHtml, options) {
|
|
function keyToMap(els) {
|
|
function keyToMap(els) {
|
|
let map = {}
|
|
let map = {}
|
|
|
|
|
|
- els.forEach(el => {
|
|
|
|
|
|
+ for (let el of els) {
|
|
let theKey = getKey(el)
|
|
let theKey = getKey(el)
|
|
|
|
|
|
if (theKey) {
|
|
if (theKey) {
|
|
map[theKey] = el
|
|
map[theKey] = el
|
|
}
|
|
}
|
|
- })
|
|
|
|
|
|
+ }
|
|
|
|
|
|
return map
|
|
return map
|
|
}
|
|
}
|
|
|
|
|
|
- function addNodeBefore(children, node, beforeMe) {
|
|
|
|
|
|
+ function addNodeBefore(parent, node, beforeMe) {
|
|
if(! shouldSkip(adding, node)) {
|
|
if(! shouldSkip(adding, node)) {
|
|
let clone = node.cloneNode(true)
|
|
let clone = node.cloneNode(true)
|
|
|
|
|
|
- children = dom.before(children, beforeMe, clone)
|
|
|
|
|
|
+ parent.insertBefore(clone, beforeMe)
|
|
|
|
|
|
added(clone)
|
|
added(clone)
|
|
|
|
|
|
- return [children, clone]
|
|
|
|
|
|
+ return clone
|
|
}
|
|
}
|
|
|
|
|
|
- return [children, node]
|
|
|
|
|
|
+ return node
|
|
}
|
|
}
|
|
|
|
|
|
// Finally we morph the element
|
|
// Finally we morph the element
|
|
@@ -347,12 +345,14 @@ export function morph(from, toHtml, options) {
|
|
fromEl = from
|
|
fromEl = from
|
|
toEl = typeof toHtml === 'string' ? createElement(toHtml) : toHtml
|
|
toEl = typeof toHtml === 'string' ? createElement(toHtml) : toHtml
|
|
|
|
|
|
- // If there is no x-data on the element we're morphing,
|
|
|
|
- // let's seed it with the outer Alpine scope on the page.
|
|
|
|
if (window.Alpine && window.Alpine.closestDataStack && ! from._x_dataStack) {
|
|
if (window.Alpine && window.Alpine.closestDataStack && ! from._x_dataStack) {
|
|
|
|
+ // Just in case a part of this template uses Alpine scope from somewhere
|
|
|
|
+ // higher in the DOM tree, we'll find that state and replace it on the root
|
|
|
|
+ // element so everything is synced up accurately.
|
|
toEl._x_dataStack = window.Alpine.closestDataStack(from)
|
|
toEl._x_dataStack = window.Alpine.closestDataStack(from)
|
|
|
|
|
|
- toEl._x_dataStack && window.Alpine.clone(from, toEl)
|
|
|
|
|
|
+ // We will kick off a clone on the root element.
|
|
|
|
+ toEl._x_dataStack && window.Alpine.cloneNode(from, toEl)
|
|
}
|
|
}
|
|
|
|
|
|
patch(from, toEl)
|
|
patch(from, toEl)
|
|
@@ -364,10 +364,9 @@ export function morph(from, toHtml, options) {
|
|
return from
|
|
return from
|
|
}
|
|
}
|
|
|
|
|
|
-morph.step = () => resolveStep()
|
|
|
|
-morph.log = (theLogger) => {
|
|
|
|
- logger = theLogger
|
|
|
|
-}
|
|
|
|
|
|
+// These are legacy holdovers that don't do anything anymore...
|
|
|
|
+morph.step = () => {}
|
|
|
|
+morph.log = () => {}
|
|
|
|
|
|
function shouldSkip(hook, ...args) {
|
|
function shouldSkip(hook, ...args) {
|
|
let skip = false
|
|
let skip = false
|
|
@@ -377,18 +376,91 @@ function shouldSkip(hook, ...args) {
|
|
return skip
|
|
return skip
|
|
}
|
|
}
|
|
|
|
|
|
-function initializeAlpineOnTo(from, to, childrenOnly) {
|
|
|
|
- if (from.nodeType !== 1) return
|
|
|
|
|
|
+let patched = false
|
|
|
|
+
|
|
|
|
+export function createElement(html) {
|
|
|
|
+ const template = document.createElement('template')
|
|
|
|
+ template.innerHTML = html
|
|
|
|
+ return template.content.firstElementChild
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+export function textOrComment(el) {
|
|
|
|
+ return el.nodeType === 3
|
|
|
|
+ || el.nodeType === 8
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// "Block"s are used when morphing with conditional markers.
|
|
|
|
+// They allow us to patch isolated portions of a list of
|
|
|
|
+// siblings in a DOM tree...
|
|
|
|
+class Block {
|
|
|
|
+ constructor(start, end) {
|
|
|
|
+ // We're assuming here that the start and end caps are comment blocks...
|
|
|
|
+ this.startComment = start
|
|
|
|
+ this.endComment = end
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ get children() {
|
|
|
|
+ let children = [];
|
|
|
|
+
|
|
|
|
+ let currentNode = this.startComment.nextSibling
|
|
|
|
+
|
|
|
|
+ while (currentNode !== undefined && currentNode !== this.endComment) {
|
|
|
|
+ children.push(currentNode)
|
|
|
|
|
|
- // If the element we are updating is an Alpine component...
|
|
|
|
- if (from._x_dataStack) {
|
|
|
|
- // Then temporarily clone it (with it's data) to the "to" element.
|
|
|
|
- // This should simulate backend Livewire being aware of Alpine changes.
|
|
|
|
- window.Alpine.clone(from, to)
|
|
|
|
|
|
+ currentNode = currentNode.nextSibling
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return children
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ appendChild(child) {
|
|
|
|
+ this.endComment.before(child)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ get firstChild() {
|
|
|
|
+ let first = this.startComment.nextSibling
|
|
|
|
+
|
|
|
|
+ if (first === this.endComment) return
|
|
|
|
+
|
|
|
|
+ return first
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ nextNode(reference) {
|
|
|
|
+ let next = reference.nextSibling
|
|
|
|
+
|
|
|
|
+ if (next === this.endComment) return
|
|
|
|
+
|
|
|
|
+ return next
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ insertBefore(newNode, reference) {
|
|
|
|
+ reference.before(newNode)
|
|
|
|
+
|
|
|
|
+ return newNode
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-let patched = false
|
|
|
|
|
|
+function getFirstNode(parent) {
|
|
|
|
+ return parent.firstChild
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function getNextSibling(parent, reference) {
|
|
|
|
+ if (reference._x_teleport) {
|
|
|
|
+ return reference._x_teleport
|
|
|
|
+ } else if (reference.teleportBack) {
|
|
|
|
+ return reference.teleportBack
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ let next
|
|
|
|
+
|
|
|
|
+ if (parent instanceof Block) {
|
|
|
|
+ next = parent.nextNode(reference)
|
|
|
|
+ } else {
|
|
|
|
+ next = reference.nextSibling
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return next
|
|
|
|
+}
|
|
|
|
|
|
function monkeyPatchDomSetAttributeToAllowAtSymbols() {
|
|
function monkeyPatchDomSetAttributeToAllowAtSymbols() {
|
|
if (patched) return
|
|
if (patched) return
|