jails-js 6.9.2 → 6.9.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +707 -465
- package/dist/index.js.map +1 -1
- package/dist/jails.js +1 -1
- package/dist/jails.js.map +1 -1
- package/package.json +2 -2
- package/src/component.ts +9 -13
- package/src/template-system.ts +0 -3
package/dist/index.js
CHANGED
|
@@ -14,513 +14,762 @@ var __spreadValues = (a, b) => {
|
|
|
14
14
|
}
|
|
15
15
|
return a;
|
|
16
16
|
};
|
|
17
|
-
var
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
17
|
+
var Idiomorph = (function() {
|
|
18
|
+
const noOp = () => {
|
|
19
|
+
};
|
|
20
|
+
const defaults = {
|
|
21
|
+
morphStyle: "outerHTML",
|
|
22
|
+
callbacks: {
|
|
23
|
+
beforeNodeAdded: noOp,
|
|
24
|
+
afterNodeAdded: noOp,
|
|
25
|
+
beforeNodeMorphed: noOp,
|
|
26
|
+
afterNodeMorphed: noOp,
|
|
27
|
+
beforeNodeRemoved: noOp,
|
|
28
|
+
afterNodeRemoved: noOp,
|
|
29
|
+
beforeAttributeUpdated: noOp
|
|
30
|
+
},
|
|
31
|
+
head: {
|
|
32
|
+
style: "merge",
|
|
33
|
+
shouldPreserve: (elt) => elt.getAttribute("im-preserve") === "true",
|
|
34
|
+
shouldReAppend: (elt) => elt.getAttribute("im-re-append") === "true",
|
|
35
|
+
shouldRemove: noOp,
|
|
36
|
+
afterHeadMorphed: noOp
|
|
37
|
+
},
|
|
38
|
+
restoreFocus: true
|
|
39
|
+
};
|
|
40
|
+
function morph(oldNode, newContent, config2 = {}) {
|
|
41
|
+
oldNode = normalizeElement(oldNode);
|
|
42
|
+
const newNode = normalizeParent(newContent);
|
|
43
|
+
const ctx = createMorphContext(oldNode, newNode, config2);
|
|
44
|
+
const morphedNodes = saveAndRestoreFocus(ctx, () => {
|
|
45
|
+
return withHeadBlocking(
|
|
46
|
+
ctx,
|
|
47
|
+
oldNode,
|
|
48
|
+
newNode,
|
|
49
|
+
/** @param {MorphContext} ctx */
|
|
50
|
+
(ctx2) => {
|
|
51
|
+
if (ctx2.morphStyle === "innerHTML") {
|
|
52
|
+
morphChildren(ctx2, oldNode, newNode);
|
|
53
|
+
return Array.from(oldNode.childNodes);
|
|
54
|
+
} else {
|
|
55
|
+
return morphOuterHTML(ctx2, oldNode, newNode);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
);
|
|
59
|
+
});
|
|
60
|
+
ctx.pantry.remove();
|
|
61
|
+
return morphedNodes;
|
|
27
62
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
}
|
|
42
|
-
} else {
|
|
43
|
-
fromValue = fromNode.getAttribute(attrName);
|
|
44
|
-
if (fromValue !== attrValue) {
|
|
45
|
-
fromNode.setAttribute(attrName, attrValue);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
63
|
+
function morphOuterHTML(ctx, oldNode, newNode) {
|
|
64
|
+
const oldParent = normalizeParent(oldNode);
|
|
65
|
+
morphChildren(
|
|
66
|
+
ctx,
|
|
67
|
+
oldParent,
|
|
68
|
+
newNode,
|
|
69
|
+
// these two optional params are the secret sauce
|
|
70
|
+
oldNode,
|
|
71
|
+
// start point for iteration
|
|
72
|
+
oldNode.nextSibling
|
|
73
|
+
// end point for iteration
|
|
74
|
+
);
|
|
75
|
+
return Array.from(oldParent.childNodes);
|
|
48
76
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
}
|
|
59
|
-
} else {
|
|
60
|
-
if (!toNode.hasAttribute(attrName)) {
|
|
61
|
-
fromNode.removeAttribute(attrName);
|
|
62
|
-
}
|
|
77
|
+
function saveAndRestoreFocus(ctx, fn) {
|
|
78
|
+
var _a;
|
|
79
|
+
if (!ctx.config.restoreFocus) return fn();
|
|
80
|
+
let activeElement = (
|
|
81
|
+
/** @type {HTMLInputElement|HTMLTextAreaElement|null} */
|
|
82
|
+
document.activeElement
|
|
83
|
+
);
|
|
84
|
+
if (!(activeElement instanceof HTMLInputElement || activeElement instanceof HTMLTextAreaElement)) {
|
|
85
|
+
return fn();
|
|
63
86
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
var template2 = doc.createElement("template");
|
|
73
|
-
template2.innerHTML = str;
|
|
74
|
-
return template2.content.childNodes[0];
|
|
75
|
-
}
|
|
76
|
-
function createFragmentFromRange(str) {
|
|
77
|
-
if (!range) {
|
|
78
|
-
range = doc.createRange();
|
|
79
|
-
range.selectNode(doc.body);
|
|
80
|
-
}
|
|
81
|
-
var fragment = range.createContextualFragment(str);
|
|
82
|
-
return fragment.childNodes[0];
|
|
83
|
-
}
|
|
84
|
-
function createFragmentFromWrap(str) {
|
|
85
|
-
var fragment = doc.createElement("body");
|
|
86
|
-
fragment.innerHTML = str;
|
|
87
|
-
return fragment.childNodes[0];
|
|
88
|
-
}
|
|
89
|
-
function toElement(str) {
|
|
90
|
-
str = str.trim();
|
|
91
|
-
if (HAS_TEMPLATE_SUPPORT) {
|
|
92
|
-
return createFragmentFromTemplate(str);
|
|
93
|
-
} else if (HAS_RANGE_SUPPORT) {
|
|
94
|
-
return createFragmentFromRange(str);
|
|
95
|
-
}
|
|
96
|
-
return createFragmentFromWrap(str);
|
|
97
|
-
}
|
|
98
|
-
function compareNodeNames(fromEl, toEl) {
|
|
99
|
-
var fromNodeName = fromEl.nodeName;
|
|
100
|
-
var toNodeName = toEl.nodeName;
|
|
101
|
-
var fromCodeStart, toCodeStart;
|
|
102
|
-
if (fromNodeName === toNodeName) {
|
|
103
|
-
return true;
|
|
104
|
-
}
|
|
105
|
-
fromCodeStart = fromNodeName.charCodeAt(0);
|
|
106
|
-
toCodeStart = toNodeName.charCodeAt(0);
|
|
107
|
-
if (fromCodeStart <= 90 && toCodeStart >= 97) {
|
|
108
|
-
return fromNodeName === toNodeName.toUpperCase();
|
|
109
|
-
} else if (toCodeStart <= 90 && fromCodeStart >= 97) {
|
|
110
|
-
return toNodeName === fromNodeName.toUpperCase();
|
|
111
|
-
} else {
|
|
112
|
-
return false;
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
function createElementNS(name, namespaceURI) {
|
|
116
|
-
return !namespaceURI || namespaceURI === NS_XHTML ? doc.createElement(name) : doc.createElementNS(namespaceURI, name);
|
|
117
|
-
}
|
|
118
|
-
function moveChildren(fromEl, toEl) {
|
|
119
|
-
var curChild = fromEl.firstChild;
|
|
120
|
-
while (curChild) {
|
|
121
|
-
var nextChild = curChild.nextSibling;
|
|
122
|
-
toEl.appendChild(curChild);
|
|
123
|
-
curChild = nextChild;
|
|
124
|
-
}
|
|
125
|
-
return toEl;
|
|
126
|
-
}
|
|
127
|
-
function syncBooleanAttrProp(fromEl, toEl, name) {
|
|
128
|
-
if (fromEl[name] !== toEl[name]) {
|
|
129
|
-
fromEl[name] = toEl[name];
|
|
130
|
-
if (fromEl[name]) {
|
|
131
|
-
fromEl.setAttribute(name, "");
|
|
132
|
-
} else {
|
|
133
|
-
fromEl.removeAttribute(name);
|
|
87
|
+
const { id: activeElementId, selectionStart, selectionEnd } = activeElement;
|
|
88
|
+
const results = fn();
|
|
89
|
+
if (activeElementId && activeElementId !== ((_a = document.activeElement) == null ? void 0 : _a.getAttribute("id"))) {
|
|
90
|
+
activeElement = ctx.target.querySelector(`[id="${activeElementId}"]`);
|
|
91
|
+
activeElement == null ? void 0 : activeElement.focus();
|
|
92
|
+
}
|
|
93
|
+
if (activeElement && !activeElement.selectionEnd && selectionEnd) {
|
|
94
|
+
activeElement.setSelectionRange(selectionStart, selectionEnd);
|
|
134
95
|
}
|
|
96
|
+
return results;
|
|
135
97
|
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
var parentName = parentNode.nodeName.toUpperCase();
|
|
142
|
-
if (parentName === "OPTGROUP") {
|
|
143
|
-
parentNode = parentNode.parentNode;
|
|
144
|
-
parentName = parentNode && parentNode.nodeName.toUpperCase();
|
|
145
|
-
}
|
|
146
|
-
if (parentName === "SELECT" && !parentNode.hasAttribute("multiple")) {
|
|
147
|
-
if (fromEl.hasAttribute("selected") && !toEl.selected) {
|
|
148
|
-
fromEl.setAttribute("selected", "selected");
|
|
149
|
-
fromEl.removeAttribute("selected");
|
|
150
|
-
}
|
|
151
|
-
parentNode.selectedIndex = -1;
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
syncBooleanAttrProp(fromEl, toEl, "selected");
|
|
155
|
-
},
|
|
156
|
-
/**
|
|
157
|
-
* The "value" attribute is special for the <input> element since it sets
|
|
158
|
-
* the initial value. Changing the "value" attribute without changing the
|
|
159
|
-
* "value" property will have no effect since it is only used to the set the
|
|
160
|
-
* initial value. Similar for the "checked" attribute, and "disabled".
|
|
161
|
-
*/
|
|
162
|
-
INPUT: function(fromEl, toEl) {
|
|
163
|
-
syncBooleanAttrProp(fromEl, toEl, "checked");
|
|
164
|
-
syncBooleanAttrProp(fromEl, toEl, "disabled");
|
|
165
|
-
if (fromEl.value !== toEl.value) {
|
|
166
|
-
fromEl.value = toEl.value;
|
|
167
|
-
}
|
|
168
|
-
if (!toEl.hasAttribute("value")) {
|
|
169
|
-
fromEl.removeAttribute("value");
|
|
170
|
-
}
|
|
171
|
-
},
|
|
172
|
-
TEXTAREA: function(fromEl, toEl) {
|
|
173
|
-
var newValue = toEl.value;
|
|
174
|
-
if (fromEl.value !== newValue) {
|
|
175
|
-
fromEl.value = newValue;
|
|
176
|
-
}
|
|
177
|
-
var firstChild = fromEl.firstChild;
|
|
178
|
-
if (firstChild) {
|
|
179
|
-
var oldValue = firstChild.nodeValue;
|
|
180
|
-
if (oldValue == newValue || !newValue && oldValue == fromEl.placeholder) {
|
|
181
|
-
return;
|
|
98
|
+
const morphChildren = /* @__PURE__ */ (function() {
|
|
99
|
+
function morphChildren2(ctx, oldParent, newParent, insertionPoint = null, endPoint = null) {
|
|
100
|
+
if (oldParent instanceof HTMLTemplateElement && newParent instanceof HTMLTemplateElement) {
|
|
101
|
+
oldParent = oldParent.content;
|
|
102
|
+
newParent = newParent.content;
|
|
182
103
|
}
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
if (nodeName === "OPTGROUP") {
|
|
196
|
-
optgroup = curChild;
|
|
197
|
-
curChild = optgroup.firstChild;
|
|
198
|
-
if (!curChild) {
|
|
199
|
-
curChild = optgroup.nextSibling;
|
|
200
|
-
optgroup = null;
|
|
201
|
-
}
|
|
202
|
-
} else {
|
|
203
|
-
if (nodeName === "OPTION") {
|
|
204
|
-
if (curChild.hasAttribute("selected")) {
|
|
205
|
-
selectedIndex = i;
|
|
206
|
-
break;
|
|
104
|
+
insertionPoint || (insertionPoint = oldParent.firstChild);
|
|
105
|
+
for (const newChild of newParent.childNodes) {
|
|
106
|
+
if (insertionPoint && insertionPoint != endPoint) {
|
|
107
|
+
const bestMatch = findBestMatch(
|
|
108
|
+
ctx,
|
|
109
|
+
newChild,
|
|
110
|
+
insertionPoint,
|
|
111
|
+
endPoint
|
|
112
|
+
);
|
|
113
|
+
if (bestMatch) {
|
|
114
|
+
if (bestMatch !== insertionPoint) {
|
|
115
|
+
removeNodesBetween(ctx, insertionPoint, bestMatch);
|
|
207
116
|
}
|
|
208
|
-
|
|
117
|
+
morphNode(bestMatch, newChild, ctx);
|
|
118
|
+
insertionPoint = bestMatch.nextSibling;
|
|
119
|
+
continue;
|
|
209
120
|
}
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
121
|
+
}
|
|
122
|
+
if (newChild instanceof Element) {
|
|
123
|
+
const newChildId = (
|
|
124
|
+
/** @type {String} */
|
|
125
|
+
newChild.getAttribute("id")
|
|
126
|
+
);
|
|
127
|
+
if (ctx.persistentIds.has(newChildId)) {
|
|
128
|
+
const movedChild = moveBeforeById(
|
|
129
|
+
oldParent,
|
|
130
|
+
newChildId,
|
|
131
|
+
insertionPoint,
|
|
132
|
+
ctx
|
|
133
|
+
);
|
|
134
|
+
morphNode(movedChild, newChild, ctx);
|
|
135
|
+
insertionPoint = movedChild.nextSibling;
|
|
136
|
+
continue;
|
|
214
137
|
}
|
|
215
138
|
}
|
|
139
|
+
const insertedNode = createNode(
|
|
140
|
+
oldParent,
|
|
141
|
+
newChild,
|
|
142
|
+
insertionPoint,
|
|
143
|
+
ctx
|
|
144
|
+
);
|
|
145
|
+
if (insertedNode) {
|
|
146
|
+
insertionPoint = insertedNode.nextSibling;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
while (insertionPoint && insertionPoint != endPoint) {
|
|
150
|
+
const tempNode = insertionPoint;
|
|
151
|
+
insertionPoint = insertionPoint.nextSibling;
|
|
152
|
+
removeNode(ctx, tempNode);
|
|
216
153
|
}
|
|
217
|
-
fromEl.selectedIndex = selectedIndex;
|
|
218
154
|
}
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
function morphdomFactory(morphAttrs2) {
|
|
233
|
-
return function morphdom2(fromNode, toNode, options) {
|
|
234
|
-
if (!options) {
|
|
235
|
-
options = {};
|
|
236
|
-
}
|
|
237
|
-
if (typeof toNode === "string") {
|
|
238
|
-
if (fromNode.nodeName === "#document" || fromNode.nodeName === "HTML" || fromNode.nodeName === "BODY") {
|
|
239
|
-
var toNodeHtml = toNode;
|
|
240
|
-
toNode = doc.createElement("html");
|
|
241
|
-
toNode.innerHTML = toNodeHtml;
|
|
155
|
+
function createNode(oldParent, newChild, insertionPoint, ctx) {
|
|
156
|
+
if (ctx.callbacks.beforeNodeAdded(newChild) === false) return null;
|
|
157
|
+
if (ctx.idMap.has(newChild)) {
|
|
158
|
+
const newEmptyChild = document.createElement(
|
|
159
|
+
/** @type {Element} */
|
|
160
|
+
newChild.tagName
|
|
161
|
+
);
|
|
162
|
+
oldParent.insertBefore(newEmptyChild, insertionPoint);
|
|
163
|
+
morphNode(newEmptyChild, newChild, ctx);
|
|
164
|
+
ctx.callbacks.afterNodeAdded(newEmptyChild);
|
|
165
|
+
return newEmptyChild;
|
|
242
166
|
} else {
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
keyedRemovalList.push(key);
|
|
265
|
-
}
|
|
266
|
-
function walkDiscardedChildNodes(node, skipKeyedNodes) {
|
|
267
|
-
if (node.nodeType === ELEMENT_NODE) {
|
|
268
|
-
var curChild = node.firstChild;
|
|
269
|
-
while (curChild) {
|
|
270
|
-
var key = void 0;
|
|
271
|
-
if (skipKeyedNodes && (key = getNodeKey(curChild))) {
|
|
272
|
-
addKeyedRemoval(key);
|
|
273
|
-
} else {
|
|
274
|
-
onNodeDiscarded(curChild);
|
|
275
|
-
if (curChild.firstChild) {
|
|
276
|
-
walkDiscardedChildNodes(curChild, skipKeyedNodes);
|
|
167
|
+
const newClonedChild = document.importNode(newChild, true);
|
|
168
|
+
oldParent.insertBefore(newClonedChild, insertionPoint);
|
|
169
|
+
ctx.callbacks.afterNodeAdded(newClonedChild);
|
|
170
|
+
return newClonedChild;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
const findBestMatch = /* @__PURE__ */ (function() {
|
|
174
|
+
function findBestMatch2(ctx, node, startPoint, endPoint) {
|
|
175
|
+
let softMatch = null;
|
|
176
|
+
let nextSibling = node.nextSibling;
|
|
177
|
+
let siblingSoftMatchCount = 0;
|
|
178
|
+
let cursor = startPoint;
|
|
179
|
+
while (cursor && cursor != endPoint) {
|
|
180
|
+
if (isSoftMatch(cursor, node)) {
|
|
181
|
+
if (isIdSetMatch(ctx, cursor, node)) {
|
|
182
|
+
return cursor;
|
|
183
|
+
}
|
|
184
|
+
if (softMatch === null) {
|
|
185
|
+
if (!ctx.idMap.has(cursor)) {
|
|
186
|
+
softMatch = cursor;
|
|
187
|
+
}
|
|
277
188
|
}
|
|
278
189
|
}
|
|
279
|
-
|
|
190
|
+
if (softMatch === null && nextSibling && isSoftMatch(cursor, nextSibling)) {
|
|
191
|
+
siblingSoftMatchCount++;
|
|
192
|
+
nextSibling = nextSibling.nextSibling;
|
|
193
|
+
if (siblingSoftMatchCount >= 2) {
|
|
194
|
+
softMatch = void 0;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
if (ctx.activeElementAndParents.includes(cursor)) break;
|
|
198
|
+
cursor = cursor.nextSibling;
|
|
280
199
|
}
|
|
200
|
+
return softMatch || null;
|
|
281
201
|
}
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
return;
|
|
202
|
+
function isIdSetMatch(ctx, oldNode, newNode) {
|
|
203
|
+
let oldSet = ctx.idMap.get(oldNode);
|
|
204
|
+
let newSet = ctx.idMap.get(newNode);
|
|
205
|
+
if (!newSet || !oldSet) return false;
|
|
206
|
+
for (const id of oldSet) {
|
|
207
|
+
if (newSet.has(id)) {
|
|
208
|
+
return true;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
return false;
|
|
286
212
|
}
|
|
287
|
-
|
|
288
|
-
|
|
213
|
+
function isSoftMatch(oldNode, newNode) {
|
|
214
|
+
var _a, _b, _c;
|
|
215
|
+
const oldElt = (
|
|
216
|
+
/** @type {Element} */
|
|
217
|
+
oldNode
|
|
218
|
+
);
|
|
219
|
+
const newElt = (
|
|
220
|
+
/** @type {Element} */
|
|
221
|
+
newNode
|
|
222
|
+
);
|
|
223
|
+
return oldElt.nodeType === newElt.nodeType && oldElt.tagName === newElt.tagName && // If oldElt has an `id` with possible state and it doesn't match newElt.id then avoid morphing.
|
|
224
|
+
// We'll still match an anonymous node with an IDed newElt, though, because if it got this far,
|
|
225
|
+
// its not persistent, and new nodes can't have any hidden state.
|
|
226
|
+
// We can't use .id because of form input shadowing, and we can't count on .getAttribute's presence because it could be a document-fragment
|
|
227
|
+
(!((_a = oldElt.getAttribute) == null ? void 0 : _a.call(oldElt, "id")) || ((_b = oldElt.getAttribute) == null ? void 0 : _b.call(oldElt, "id")) === ((_c = newElt.getAttribute) == null ? void 0 : _c.call(newElt, "id")));
|
|
228
|
+
}
|
|
229
|
+
return findBestMatch2;
|
|
230
|
+
})();
|
|
231
|
+
function removeNode(ctx, node) {
|
|
232
|
+
var _a;
|
|
233
|
+
if (ctx.idMap.has(node)) {
|
|
234
|
+
moveBefore(ctx.pantry, node, null);
|
|
235
|
+
} else {
|
|
236
|
+
if (ctx.callbacks.beforeNodeRemoved(node) === false) return;
|
|
237
|
+
(_a = node.parentNode) == null ? void 0 : _a.removeChild(node);
|
|
238
|
+
ctx.callbacks.afterNodeRemoved(node);
|
|
289
239
|
}
|
|
290
|
-
onNodeDiscarded(node);
|
|
291
|
-
walkDiscardedChildNodes(node, skipKeyedNodes);
|
|
292
240
|
}
|
|
293
|
-
function
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
241
|
+
function removeNodesBetween(ctx, startInclusive, endExclusive) {
|
|
242
|
+
let cursor = startInclusive;
|
|
243
|
+
while (cursor && cursor !== endExclusive) {
|
|
244
|
+
let tempNode = (
|
|
245
|
+
/** @type {Node} */
|
|
246
|
+
cursor
|
|
247
|
+
);
|
|
248
|
+
cursor = cursor.nextSibling;
|
|
249
|
+
removeNode(ctx, tempNode);
|
|
250
|
+
}
|
|
251
|
+
return cursor;
|
|
252
|
+
}
|
|
253
|
+
function moveBeforeById(parentNode, id, after, ctx) {
|
|
254
|
+
var _a, _b;
|
|
255
|
+
const target = (
|
|
256
|
+
/** @type {Element} - will always be found */
|
|
257
|
+
// ctx.target.id unsafe because of form input shadowing
|
|
258
|
+
// ctx.target could be a document fragment which doesn't have `getAttribute`
|
|
259
|
+
((_b = (_a = ctx.target).getAttribute) == null ? void 0 : _b.call(_a, "id")) === id && ctx.target || ctx.target.querySelector(`[id="${id}"]`) || ctx.pantry.querySelector(`[id="${id}"]`)
|
|
260
|
+
);
|
|
261
|
+
removeElementFromAncestorsIdMaps(target, ctx);
|
|
262
|
+
moveBefore(parentNode, target, after);
|
|
263
|
+
return target;
|
|
264
|
+
}
|
|
265
|
+
function removeElementFromAncestorsIdMaps(element, ctx) {
|
|
266
|
+
const id = (
|
|
267
|
+
/** @type {String} */
|
|
268
|
+
element.getAttribute("id")
|
|
269
|
+
);
|
|
270
|
+
while (element = element.parentNode) {
|
|
271
|
+
let idSet = ctx.idMap.get(element);
|
|
272
|
+
if (idSet) {
|
|
273
|
+
idSet.delete(id);
|
|
274
|
+
if (!idSet.size) {
|
|
275
|
+
ctx.idMap.delete(element);
|
|
320
276
|
}
|
|
321
|
-
} else {
|
|
322
|
-
handleNodeAdded(curChild);
|
|
323
277
|
}
|
|
324
|
-
curChild = nextSibling;
|
|
325
278
|
}
|
|
326
279
|
}
|
|
327
|
-
function
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
removeNode(
|
|
334
|
-
curFromNodeChild,
|
|
335
|
-
fromEl,
|
|
336
|
-
true
|
|
337
|
-
/* skip keyed nodes */
|
|
338
|
-
);
|
|
280
|
+
function moveBefore(parentNode, element, after) {
|
|
281
|
+
if (parentNode.moveBefore) {
|
|
282
|
+
try {
|
|
283
|
+
parentNode.moveBefore(element, after);
|
|
284
|
+
} catch (e) {
|
|
285
|
+
parentNode.insertBefore(element, after);
|
|
339
286
|
}
|
|
340
|
-
|
|
287
|
+
} else {
|
|
288
|
+
parentNode.insertBefore(element, after);
|
|
341
289
|
}
|
|
342
290
|
}
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
291
|
+
return morphChildren2;
|
|
292
|
+
})();
|
|
293
|
+
const morphNode = /* @__PURE__ */ (function() {
|
|
294
|
+
function morphNode2(oldNode, newContent, ctx) {
|
|
295
|
+
if (ctx.ignoreActive && oldNode === document.activeElement) {
|
|
296
|
+
return null;
|
|
347
297
|
}
|
|
348
|
-
if (
|
|
349
|
-
|
|
350
|
-
if (beforeUpdateResult === false) {
|
|
351
|
-
return;
|
|
352
|
-
} else if (beforeUpdateResult instanceof HTMLElement) {
|
|
353
|
-
fromEl = beforeUpdateResult;
|
|
354
|
-
indexTree(fromEl);
|
|
355
|
-
}
|
|
356
|
-
morphAttrs2(fromEl, toEl);
|
|
357
|
-
onElUpdated(fromEl);
|
|
358
|
-
if (onBeforeElChildrenUpdated(fromEl, toEl) === false) {
|
|
359
|
-
return;
|
|
360
|
-
}
|
|
298
|
+
if (ctx.callbacks.beforeNodeMorphed(oldNode, newContent) === false) {
|
|
299
|
+
return oldNode;
|
|
361
300
|
}
|
|
362
|
-
if (
|
|
363
|
-
|
|
301
|
+
if (oldNode instanceof HTMLHeadElement && ctx.head.ignore) ;
|
|
302
|
+
else if (oldNode instanceof HTMLHeadElement && ctx.head.style !== "morph") {
|
|
303
|
+
handleHeadElement(
|
|
304
|
+
oldNode,
|
|
305
|
+
/** @type {HTMLHeadElement} */
|
|
306
|
+
newContent,
|
|
307
|
+
ctx
|
|
308
|
+
);
|
|
364
309
|
} else {
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
310
|
+
morphAttributes(oldNode, newContent, ctx);
|
|
311
|
+
if (!ignoreValueOfActiveElement(oldNode, ctx)) {
|
|
312
|
+
morphChildren(ctx, oldNode, newContent);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
ctx.callbacks.afterNodeMorphed(oldNode, newContent);
|
|
316
|
+
return oldNode;
|
|
317
|
+
}
|
|
318
|
+
function morphAttributes(oldNode, newNode, ctx) {
|
|
319
|
+
let type = newNode.nodeType;
|
|
320
|
+
if (type === 1) {
|
|
321
|
+
const oldElt = (
|
|
322
|
+
/** @type {Element} */
|
|
323
|
+
oldNode
|
|
324
|
+
);
|
|
325
|
+
const newElt = (
|
|
326
|
+
/** @type {Element} */
|
|
327
|
+
newNode
|
|
328
|
+
);
|
|
329
|
+
const oldAttributes = oldElt.attributes;
|
|
330
|
+
const newAttributes = newElt.attributes;
|
|
331
|
+
for (const newAttribute of newAttributes) {
|
|
332
|
+
if (ignoreAttribute(newAttribute.name, oldElt, "update", ctx)) {
|
|
333
|
+
continue;
|
|
386
334
|
}
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
} else {
|
|
398
|
-
fromEl.insertBefore(matchingFromEl, curFromNodeChild);
|
|
399
|
-
if (curFromNodeKey) {
|
|
400
|
-
addKeyedRemoval(curFromNodeKey);
|
|
401
|
-
} else {
|
|
402
|
-
removeNode(
|
|
403
|
-
curFromNodeChild,
|
|
404
|
-
fromEl,
|
|
405
|
-
true
|
|
406
|
-
/* skip keyed nodes */
|
|
407
|
-
);
|
|
408
|
-
}
|
|
409
|
-
curFromNodeChild = matchingFromEl;
|
|
410
|
-
curFromNodeKey = getNodeKey(curFromNodeChild);
|
|
411
|
-
}
|
|
412
|
-
} else {
|
|
413
|
-
isCompatible = false;
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
} else if (curFromNodeKey) {
|
|
417
|
-
isCompatible = false;
|
|
418
|
-
}
|
|
419
|
-
isCompatible = isCompatible !== false && compareNodeNames(curFromNodeChild, curToNodeChild);
|
|
420
|
-
if (isCompatible) {
|
|
421
|
-
morphEl(curFromNodeChild, curToNodeChild);
|
|
422
|
-
}
|
|
423
|
-
} else if (curFromNodeType === TEXT_NODE || curFromNodeType == COMMENT_NODE) {
|
|
424
|
-
isCompatible = true;
|
|
425
|
-
if (curFromNodeChild.nodeValue !== curToNodeChild.nodeValue) {
|
|
426
|
-
curFromNodeChild.nodeValue = curToNodeChild.nodeValue;
|
|
427
|
-
}
|
|
335
|
+
if (oldElt.getAttribute(newAttribute.name) !== newAttribute.value) {
|
|
336
|
+
oldElt.setAttribute(newAttribute.name, newAttribute.value);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
for (let i = oldAttributes.length - 1; 0 <= i; i--) {
|
|
340
|
+
const oldAttribute = oldAttributes[i];
|
|
341
|
+
if (!oldAttribute) continue;
|
|
342
|
+
if (!newElt.hasAttribute(oldAttribute.name)) {
|
|
343
|
+
if (ignoreAttribute(oldAttribute.name, oldElt, "remove", ctx)) {
|
|
344
|
+
continue;
|
|
428
345
|
}
|
|
346
|
+
oldElt.removeAttribute(oldAttribute.name);
|
|
429
347
|
}
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
348
|
+
}
|
|
349
|
+
if (!ignoreValueOfActiveElement(oldElt, ctx)) {
|
|
350
|
+
syncInputValue(oldElt, newElt, ctx);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
if (type === 8 || type === 3) {
|
|
354
|
+
if (oldNode.nodeValue !== newNode.nodeValue) {
|
|
355
|
+
oldNode.nodeValue = newNode.nodeValue;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
function syncInputValue(oldElement, newElement, ctx) {
|
|
360
|
+
if (oldElement instanceof HTMLInputElement && newElement instanceof HTMLInputElement && newElement.type !== "file") {
|
|
361
|
+
let newValue = newElement.value;
|
|
362
|
+
let oldValue = oldElement.value;
|
|
363
|
+
syncBooleanAttribute(oldElement, newElement, "checked", ctx);
|
|
364
|
+
syncBooleanAttribute(oldElement, newElement, "disabled", ctx);
|
|
365
|
+
if (!newElement.hasAttribute("value")) {
|
|
366
|
+
if (!ignoreAttribute("value", oldElement, "remove", ctx)) {
|
|
367
|
+
oldElement.value = "";
|
|
368
|
+
oldElement.removeAttribute("value");
|
|
434
369
|
}
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
curFromNodeChild,
|
|
440
|
-
fromEl,
|
|
441
|
-
true
|
|
442
|
-
/* skip keyed nodes */
|
|
443
|
-
);
|
|
370
|
+
} else if (oldValue !== newValue) {
|
|
371
|
+
if (!ignoreAttribute("value", oldElement, "update", ctx)) {
|
|
372
|
+
oldElement.setAttribute("value", newValue);
|
|
373
|
+
oldElement.value = newValue;
|
|
444
374
|
}
|
|
445
|
-
curFromNodeChild = fromNextSibling;
|
|
446
375
|
}
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
376
|
+
} else if (oldElement instanceof HTMLOptionElement && newElement instanceof HTMLOptionElement) {
|
|
377
|
+
syncBooleanAttribute(oldElement, newElement, "selected", ctx);
|
|
378
|
+
} else if (oldElement instanceof HTMLTextAreaElement && newElement instanceof HTMLTextAreaElement) {
|
|
379
|
+
let newValue = newElement.value;
|
|
380
|
+
let oldValue = oldElement.value;
|
|
381
|
+
if (ignoreAttribute("value", oldElement, "update", ctx)) {
|
|
382
|
+
return;
|
|
383
|
+
}
|
|
384
|
+
if (newValue !== oldValue) {
|
|
385
|
+
oldElement.value = newValue;
|
|
386
|
+
}
|
|
387
|
+
if (oldElement.firstChild && oldElement.firstChild.nodeValue !== newValue) {
|
|
388
|
+
oldElement.firstChild.nodeValue = newValue;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
function syncBooleanAttribute(oldElement, newElement, attributeName, ctx) {
|
|
393
|
+
const newLiveValue = newElement[attributeName], oldLiveValue = oldElement[attributeName];
|
|
394
|
+
if (newLiveValue !== oldLiveValue) {
|
|
395
|
+
const ignoreUpdate = ignoreAttribute(
|
|
396
|
+
attributeName,
|
|
397
|
+
oldElement,
|
|
398
|
+
"update",
|
|
399
|
+
ctx
|
|
400
|
+
);
|
|
401
|
+
if (!ignoreUpdate) {
|
|
402
|
+
oldElement[attributeName] = newElement[attributeName];
|
|
403
|
+
}
|
|
404
|
+
if (newLiveValue) {
|
|
405
|
+
if (!ignoreUpdate) {
|
|
406
|
+
oldElement.setAttribute(attributeName, "");
|
|
450
407
|
}
|
|
451
|
-
morphEl(matchingFromEl, curToNodeChild);
|
|
452
408
|
} else {
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
if (onBeforeNodeAddedResult) {
|
|
456
|
-
curToNodeChild = onBeforeNodeAddedResult;
|
|
457
|
-
}
|
|
458
|
-
if (curToNodeChild.actualize) {
|
|
459
|
-
curToNodeChild = curToNodeChild.actualize(fromEl.ownerDocument || doc);
|
|
460
|
-
}
|
|
461
|
-
addChild(fromEl, curToNodeChild);
|
|
462
|
-
handleNodeAdded(curToNodeChild);
|
|
409
|
+
if (!ignoreAttribute(attributeName, oldElement, "remove", ctx)) {
|
|
410
|
+
oldElement.removeAttribute(attributeName);
|
|
463
411
|
}
|
|
464
412
|
}
|
|
465
|
-
curToNodeChild = toNextSibling;
|
|
466
|
-
curFromNodeChild = fromNextSibling;
|
|
467
413
|
}
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
if (
|
|
471
|
-
|
|
414
|
+
}
|
|
415
|
+
function ignoreAttribute(attr, element, updateType, ctx) {
|
|
416
|
+
if (attr === "value" && ctx.ignoreActiveValue && element === document.activeElement) {
|
|
417
|
+
return true;
|
|
418
|
+
}
|
|
419
|
+
return ctx.callbacks.beforeAttributeUpdated(attr, element, updateType) === false;
|
|
420
|
+
}
|
|
421
|
+
function ignoreValueOfActiveElement(possibleActiveElement, ctx) {
|
|
422
|
+
return !!ctx.ignoreActiveValue && possibleActiveElement === document.activeElement && possibleActiveElement !== document.body;
|
|
423
|
+
}
|
|
424
|
+
return morphNode2;
|
|
425
|
+
})();
|
|
426
|
+
function withHeadBlocking(ctx, oldNode, newNode, callback) {
|
|
427
|
+
if (ctx.head.block) {
|
|
428
|
+
const oldHead = oldNode.querySelector("head");
|
|
429
|
+
const newHead = newNode.querySelector("head");
|
|
430
|
+
if (oldHead && newHead) {
|
|
431
|
+
const promises = handleHeadElement(oldHead, newHead, ctx);
|
|
432
|
+
return Promise.all(promises).then(() => {
|
|
433
|
+
const newCtx = Object.assign(ctx, {
|
|
434
|
+
head: {
|
|
435
|
+
block: false,
|
|
436
|
+
ignore: true
|
|
437
|
+
}
|
|
438
|
+
});
|
|
439
|
+
return callback(newCtx);
|
|
440
|
+
});
|
|
472
441
|
}
|
|
473
442
|
}
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
443
|
+
return callback(ctx);
|
|
444
|
+
}
|
|
445
|
+
function handleHeadElement(oldHead, newHead, ctx) {
|
|
446
|
+
let added = [];
|
|
447
|
+
let removed = [];
|
|
448
|
+
let preserved = [];
|
|
449
|
+
let nodesToAppend = [];
|
|
450
|
+
let srcToNewHeadNodes = /* @__PURE__ */ new Map();
|
|
451
|
+
for (const newHeadChild of newHead.children) {
|
|
452
|
+
srcToNewHeadNodes.set(newHeadChild.outerHTML, newHeadChild);
|
|
453
|
+
}
|
|
454
|
+
for (const currentHeadElt of oldHead.children) {
|
|
455
|
+
let inNewContent = srcToNewHeadNodes.has(currentHeadElt.outerHTML);
|
|
456
|
+
let isReAppended = ctx.head.shouldReAppend(currentHeadElt);
|
|
457
|
+
let isPreserved = ctx.head.shouldPreserve(currentHeadElt);
|
|
458
|
+
if (inNewContent || isPreserved) {
|
|
459
|
+
if (isReAppended) {
|
|
460
|
+
removed.push(currentHeadElt);
|
|
484
461
|
} else {
|
|
485
|
-
|
|
462
|
+
srcToNewHeadNodes.delete(currentHeadElt.outerHTML);
|
|
463
|
+
preserved.push(currentHeadElt);
|
|
486
464
|
}
|
|
487
|
-
} else
|
|
488
|
-
if (
|
|
489
|
-
if (
|
|
490
|
-
|
|
465
|
+
} else {
|
|
466
|
+
if (ctx.head.style === "append") {
|
|
467
|
+
if (isReAppended) {
|
|
468
|
+
removed.push(currentHeadElt);
|
|
469
|
+
nodesToAppend.push(currentHeadElt);
|
|
491
470
|
}
|
|
492
|
-
return morphedNode;
|
|
493
471
|
} else {
|
|
494
|
-
|
|
472
|
+
if (ctx.head.shouldRemove(currentHeadElt) !== false) {
|
|
473
|
+
removed.push(currentHeadElt);
|
|
474
|
+
}
|
|
495
475
|
}
|
|
496
476
|
}
|
|
497
477
|
}
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
478
|
+
nodesToAppend.push(...srcToNewHeadNodes.values());
|
|
479
|
+
let promises = [];
|
|
480
|
+
for (const newNode of nodesToAppend) {
|
|
481
|
+
let newElt = (
|
|
482
|
+
/** @type {ChildNode} */
|
|
483
|
+
document.createRange().createContextualFragment(newNode.outerHTML).firstChild
|
|
484
|
+
);
|
|
485
|
+
if (ctx.callbacks.beforeNodeAdded(newElt) !== false) {
|
|
486
|
+
if ("href" in newElt && newElt.href || "src" in newElt && newElt.src) {
|
|
487
|
+
let resolve;
|
|
488
|
+
let promise = new Promise(function(_resolve) {
|
|
489
|
+
resolve = _resolve;
|
|
490
|
+
});
|
|
491
|
+
newElt.addEventListener("load", function() {
|
|
492
|
+
resolve();
|
|
493
|
+
});
|
|
494
|
+
promises.push(promise);
|
|
495
|
+
}
|
|
496
|
+
oldHead.appendChild(newElt);
|
|
497
|
+
ctx.callbacks.afterNodeAdded(newElt);
|
|
498
|
+
added.push(newElt);
|
|
503
499
|
}
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
500
|
+
}
|
|
501
|
+
for (const removedElement of removed) {
|
|
502
|
+
if (ctx.callbacks.beforeNodeRemoved(removedElement) !== false) {
|
|
503
|
+
oldHead.removeChild(removedElement);
|
|
504
|
+
ctx.callbacks.afterNodeRemoved(removedElement);
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
ctx.head.afterHeadMorphed(oldHead, {
|
|
508
|
+
added,
|
|
509
|
+
kept: preserved,
|
|
510
|
+
removed
|
|
511
|
+
});
|
|
512
|
+
return promises;
|
|
513
|
+
}
|
|
514
|
+
const createMorphContext = /* @__PURE__ */ (function() {
|
|
515
|
+
function createMorphContext2(oldNode, newContent, config2) {
|
|
516
|
+
const { persistentIds, idMap } = createIdMaps(oldNode, newContent);
|
|
517
|
+
const mergedConfig = mergeDefaults(config2);
|
|
518
|
+
const morphStyle = mergedConfig.morphStyle || "outerHTML";
|
|
519
|
+
if (!["innerHTML", "outerHTML"].includes(morphStyle)) {
|
|
520
|
+
throw `Do not understand how to morph style ${morphStyle}`;
|
|
521
|
+
}
|
|
522
|
+
return {
|
|
523
|
+
target: oldNode,
|
|
524
|
+
newContent,
|
|
525
|
+
config: mergedConfig,
|
|
526
|
+
morphStyle,
|
|
527
|
+
ignoreActive: mergedConfig.ignoreActive,
|
|
528
|
+
ignoreActiveValue: mergedConfig.ignoreActiveValue,
|
|
529
|
+
restoreFocus: mergedConfig.restoreFocus,
|
|
530
|
+
idMap,
|
|
531
|
+
persistentIds,
|
|
532
|
+
pantry: createPantry(),
|
|
533
|
+
activeElementAndParents: createActiveElementAndParents(oldNode),
|
|
534
|
+
callbacks: mergedConfig.callbacks,
|
|
535
|
+
head: mergedConfig.head
|
|
536
|
+
};
|
|
537
|
+
}
|
|
538
|
+
function mergeDefaults(config2) {
|
|
539
|
+
let finalConfig = Object.assign({}, defaults);
|
|
540
|
+
Object.assign(finalConfig, config2);
|
|
541
|
+
finalConfig.callbacks = Object.assign(
|
|
542
|
+
{},
|
|
543
|
+
defaults.callbacks,
|
|
544
|
+
config2.callbacks
|
|
545
|
+
);
|
|
546
|
+
finalConfig.head = Object.assign({}, defaults.head, config2.head);
|
|
547
|
+
return finalConfig;
|
|
548
|
+
}
|
|
549
|
+
function createPantry() {
|
|
550
|
+
const pantry = document.createElement("div");
|
|
551
|
+
pantry.hidden = true;
|
|
552
|
+
document.body.insertAdjacentElement("afterend", pantry);
|
|
553
|
+
return pantry;
|
|
554
|
+
}
|
|
555
|
+
function createActiveElementAndParents(oldNode) {
|
|
556
|
+
let activeElementAndParents = [];
|
|
557
|
+
let elt = document.activeElement;
|
|
558
|
+
if ((elt == null ? void 0 : elt.tagName) !== "BODY" && oldNode.contains(elt)) {
|
|
559
|
+
while (elt) {
|
|
560
|
+
activeElementAndParents.push(elt);
|
|
561
|
+
if (elt === oldNode) break;
|
|
562
|
+
elt = elt.parentElement;
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
return activeElementAndParents;
|
|
566
|
+
}
|
|
567
|
+
function findIdElements(root) {
|
|
568
|
+
var _a;
|
|
569
|
+
let elements = Array.from(root.querySelectorAll("[id]"));
|
|
570
|
+
if ((_a = root.getAttribute) == null ? void 0 : _a.call(root, "id")) {
|
|
571
|
+
elements.push(root);
|
|
572
|
+
}
|
|
573
|
+
return elements;
|
|
574
|
+
}
|
|
575
|
+
function populateIdMapWithTree(idMap, persistentIds, root, elements) {
|
|
576
|
+
for (const elt of elements) {
|
|
577
|
+
const id = (
|
|
578
|
+
/** @type {String} */
|
|
579
|
+
elt.getAttribute("id")
|
|
580
|
+
);
|
|
581
|
+
if (persistentIds.has(id)) {
|
|
582
|
+
let current = elt;
|
|
583
|
+
while (current) {
|
|
584
|
+
let idSet = idMap.get(current);
|
|
585
|
+
if (idSet == null) {
|
|
586
|
+
idSet = /* @__PURE__ */ new Set();
|
|
587
|
+
idMap.set(current, idSet);
|
|
588
|
+
}
|
|
589
|
+
idSet.add(id);
|
|
590
|
+
if (current === root) break;
|
|
591
|
+
current = current.parentElement;
|
|
510
592
|
}
|
|
511
593
|
}
|
|
512
594
|
}
|
|
513
595
|
}
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
596
|
+
function createIdMaps(oldContent, newContent) {
|
|
597
|
+
const oldIdElements = findIdElements(oldContent);
|
|
598
|
+
const newIdElements = findIdElements(newContent);
|
|
599
|
+
const persistentIds = createPersistentIds(oldIdElements, newIdElements);
|
|
600
|
+
let idMap = /* @__PURE__ */ new Map();
|
|
601
|
+
populateIdMapWithTree(idMap, persistentIds, oldContent, oldIdElements);
|
|
602
|
+
const newRoot = newContent.__idiomorphRoot || newContent;
|
|
603
|
+
populateIdMapWithTree(idMap, persistentIds, newRoot, newIdElements);
|
|
604
|
+
return { persistentIds, idMap };
|
|
605
|
+
}
|
|
606
|
+
function createPersistentIds(oldIdElements, newIdElements) {
|
|
607
|
+
let duplicateIds = /* @__PURE__ */ new Set();
|
|
608
|
+
let oldIdTagNameMap = /* @__PURE__ */ new Map();
|
|
609
|
+
for (const { id, tagName } of oldIdElements) {
|
|
610
|
+
if (oldIdTagNameMap.has(id)) {
|
|
611
|
+
duplicateIds.add(id);
|
|
612
|
+
} else {
|
|
613
|
+
oldIdTagNameMap.set(id, tagName);
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
let persistentIds = /* @__PURE__ */ new Set();
|
|
617
|
+
for (const { id, tagName } of newIdElements) {
|
|
618
|
+
if (persistentIds.has(id)) {
|
|
619
|
+
duplicateIds.add(id);
|
|
620
|
+
} else if (oldIdTagNameMap.get(id) === tagName) {
|
|
621
|
+
persistentIds.add(id);
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
for (const id of duplicateIds) {
|
|
625
|
+
persistentIds.delete(id);
|
|
626
|
+
}
|
|
627
|
+
return persistentIds;
|
|
628
|
+
}
|
|
629
|
+
return createMorphContext2;
|
|
630
|
+
})();
|
|
631
|
+
const { normalizeElement, normalizeParent } = /* @__PURE__ */ (function() {
|
|
632
|
+
const generatedByIdiomorph = /* @__PURE__ */ new WeakSet();
|
|
633
|
+
function normalizeElement2(content) {
|
|
634
|
+
if (content instanceof Document) {
|
|
635
|
+
return content.documentElement;
|
|
636
|
+
} else {
|
|
637
|
+
return content;
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
function normalizeParent2(newContent) {
|
|
641
|
+
if (newContent == null) {
|
|
642
|
+
return document.createElement("div");
|
|
643
|
+
} else if (typeof newContent === "string") {
|
|
644
|
+
return normalizeParent2(parseContent(newContent));
|
|
645
|
+
} else if (generatedByIdiomorph.has(
|
|
646
|
+
/** @type {Element} */
|
|
647
|
+
newContent
|
|
648
|
+
)) {
|
|
649
|
+
return (
|
|
650
|
+
/** @type {Element} */
|
|
651
|
+
newContent
|
|
652
|
+
);
|
|
653
|
+
} else if (newContent instanceof Node) {
|
|
654
|
+
if (newContent.parentNode) {
|
|
655
|
+
return (
|
|
656
|
+
/** @type {any} */
|
|
657
|
+
new SlicedParentNode(newContent)
|
|
658
|
+
);
|
|
659
|
+
} else {
|
|
660
|
+
const dummyParent = document.createElement("div");
|
|
661
|
+
dummyParent.append(newContent);
|
|
662
|
+
return dummyParent;
|
|
663
|
+
}
|
|
664
|
+
} else {
|
|
665
|
+
const dummyParent = document.createElement("div");
|
|
666
|
+
for (const elt of [...newContent]) {
|
|
667
|
+
dummyParent.append(elt);
|
|
668
|
+
}
|
|
669
|
+
return dummyParent;
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
class SlicedParentNode {
|
|
673
|
+
/** @param {Node} node */
|
|
674
|
+
constructor(node) {
|
|
675
|
+
this.originalNode = node;
|
|
676
|
+
this.realParentNode = /** @type {Element} */
|
|
677
|
+
node.parentNode;
|
|
678
|
+
this.previousSibling = node.previousSibling;
|
|
679
|
+
this.nextSibling = node.nextSibling;
|
|
680
|
+
}
|
|
681
|
+
/** @returns {Node[]} */
|
|
682
|
+
get childNodes() {
|
|
683
|
+
const nodes = [];
|
|
684
|
+
let cursor = this.previousSibling ? this.previousSibling.nextSibling : this.realParentNode.firstChild;
|
|
685
|
+
while (cursor && cursor != this.nextSibling) {
|
|
686
|
+
nodes.push(cursor);
|
|
687
|
+
cursor = cursor.nextSibling;
|
|
688
|
+
}
|
|
689
|
+
return nodes;
|
|
690
|
+
}
|
|
691
|
+
/**
|
|
692
|
+
* @param {string} selector
|
|
693
|
+
* @returns {Element[]}
|
|
694
|
+
*/
|
|
695
|
+
querySelectorAll(selector) {
|
|
696
|
+
return this.childNodes.reduce(
|
|
697
|
+
(results, node) => {
|
|
698
|
+
if (node instanceof Element) {
|
|
699
|
+
if (node.matches(selector)) results.push(node);
|
|
700
|
+
const nodeList = node.querySelectorAll(selector);
|
|
701
|
+
for (let i = 0; i < nodeList.length; i++) {
|
|
702
|
+
results.push(nodeList[i]);
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
return results;
|
|
706
|
+
},
|
|
707
|
+
/** @type {Element[]} */
|
|
708
|
+
[]
|
|
709
|
+
);
|
|
710
|
+
}
|
|
711
|
+
/**
|
|
712
|
+
* @param {Node} node
|
|
713
|
+
* @param {Node} referenceNode
|
|
714
|
+
* @returns {Node}
|
|
715
|
+
*/
|
|
716
|
+
insertBefore(node, referenceNode) {
|
|
717
|
+
return this.realParentNode.insertBefore(node, referenceNode);
|
|
718
|
+
}
|
|
719
|
+
/**
|
|
720
|
+
* @param {Node} node
|
|
721
|
+
* @param {Node} referenceNode
|
|
722
|
+
* @returns {Node}
|
|
723
|
+
*/
|
|
724
|
+
moveBefore(node, referenceNode) {
|
|
725
|
+
return this.realParentNode.moveBefore(node, referenceNode);
|
|
726
|
+
}
|
|
727
|
+
/**
|
|
728
|
+
* for later use with populateIdMapWithTree to halt upwards iteration
|
|
729
|
+
* @returns {Node}
|
|
730
|
+
*/
|
|
731
|
+
get __idiomorphRoot() {
|
|
732
|
+
return this.originalNode;
|
|
517
733
|
}
|
|
518
|
-
fromNode.parentNode.replaceChild(morphedNode, fromNode);
|
|
519
734
|
}
|
|
520
|
-
|
|
735
|
+
function parseContent(newContent) {
|
|
736
|
+
let parser = new DOMParser();
|
|
737
|
+
let contentWithSvgsRemoved = newContent.replace(
|
|
738
|
+
/<svg(\s[^>]*>|>)([\s\S]*?)<\/svg>/gim,
|
|
739
|
+
""
|
|
740
|
+
);
|
|
741
|
+
if (contentWithSvgsRemoved.match(/<\/html>/) || contentWithSvgsRemoved.match(/<\/head>/) || contentWithSvgsRemoved.match(/<\/body>/)) {
|
|
742
|
+
let content = parser.parseFromString(newContent, "text/html");
|
|
743
|
+
if (contentWithSvgsRemoved.match(/<\/html>/)) {
|
|
744
|
+
generatedByIdiomorph.add(content);
|
|
745
|
+
return content;
|
|
746
|
+
} else {
|
|
747
|
+
let htmlElement = content.firstChild;
|
|
748
|
+
if (htmlElement) {
|
|
749
|
+
generatedByIdiomorph.add(htmlElement);
|
|
750
|
+
}
|
|
751
|
+
return htmlElement;
|
|
752
|
+
}
|
|
753
|
+
} else {
|
|
754
|
+
let responseDoc = parser.parseFromString(
|
|
755
|
+
"<body><template>" + newContent + "</template></body>",
|
|
756
|
+
"text/html"
|
|
757
|
+
);
|
|
758
|
+
let content = (
|
|
759
|
+
/** @type {HTMLTemplateElement} */
|
|
760
|
+
responseDoc.body.querySelector("template").content
|
|
761
|
+
);
|
|
762
|
+
generatedByIdiomorph.add(content);
|
|
763
|
+
return content;
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
return { normalizeElement: normalizeElement2, normalizeParent: normalizeParent2 };
|
|
767
|
+
})();
|
|
768
|
+
return {
|
|
769
|
+
morph,
|
|
770
|
+
defaults
|
|
521
771
|
};
|
|
522
|
-
}
|
|
523
|
-
var morphdom = morphdomFactory(morphAttrs);
|
|
772
|
+
})();
|
|
524
773
|
let textarea;
|
|
525
774
|
const g = {
|
|
526
775
|
scope: {}
|
|
@@ -638,7 +887,7 @@ const Component = ({ name, module, dependencies, node, templates: templates2, si
|
|
|
638
887
|
} else {
|
|
639
888
|
Object.assign(state, data);
|
|
640
889
|
}
|
|
641
|
-
const newstate = Object.assign({}, state
|
|
890
|
+
const newstate = Object.assign({}, state);
|
|
642
891
|
return new Promise((resolve) => {
|
|
643
892
|
render(newstate, () => resolve(newstate));
|
|
644
893
|
});
|
|
@@ -757,7 +1006,7 @@ const Component = ({ name, module, dependencies, node, templates: templates2, si
|
|
|
757
1006
|
const clone = element.cloneNode();
|
|
758
1007
|
const html = html_ ? html_ : target;
|
|
759
1008
|
clone.innerHTML = html;
|
|
760
|
-
|
|
1009
|
+
Idiomorph.morph(element, clone);
|
|
761
1010
|
}
|
|
762
1011
|
};
|
|
763
1012
|
const render = (data, callback = (() => {
|
|
@@ -765,7 +1014,7 @@ const Component = ({ name, module, dependencies, node, templates: templates2, si
|
|
|
765
1014
|
clearTimeout(tick);
|
|
766
1015
|
tick = setTimeout(() => {
|
|
767
1016
|
const html = tpl.render.call(__spreadValues(__spreadValues({}, data), view(data)), node, safe, g);
|
|
768
|
-
|
|
1017
|
+
Idiomorph.morph(node, html, morphOptions(node, register2));
|
|
769
1018
|
Promise.resolve().then(() => {
|
|
770
1019
|
node.querySelectorAll("[tplid]").forEach((element) => {
|
|
771
1020
|
const child = register2.get(element);
|
|
@@ -774,7 +1023,7 @@ const Component = ({ name, module, dependencies, node, templates: templates2, si
|
|
|
774
1023
|
child.state.protected().forEach((key) => delete data[key]);
|
|
775
1024
|
const useEffect = child.effect();
|
|
776
1025
|
if (useEffect) {
|
|
777
|
-
const promise = useEffect(data);
|
|
1026
|
+
const promise = useEffect(__spreadValues(__spreadValues({}, data), scope2));
|
|
778
1027
|
if (promise && promise.then) {
|
|
779
1028
|
promise.then(() => child.state.set(__spreadValues(__spreadValues({}, data), scope2)));
|
|
780
1029
|
} else {
|
|
@@ -797,13 +1046,9 @@ const Component = ({ name, module, dependencies, node, templates: templates2, si
|
|
|
797
1046
|
};
|
|
798
1047
|
const morphOptions = (parent, register2, data) => {
|
|
799
1048
|
return {
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
}
|
|
804
|
-
},
|
|
805
|
-
onBeforeElUpdated: update(parent, register2),
|
|
806
|
-
onBeforeChildElUpdated: update(parent, register2)
|
|
1049
|
+
callbacks: {
|
|
1050
|
+
beforeNodeMorphed: update(parent, register2)
|
|
1051
|
+
}
|
|
807
1052
|
};
|
|
808
1053
|
};
|
|
809
1054
|
const update = (parent, register2, data) => (node, newnode) => {
|
|
@@ -821,7 +1066,7 @@ const update = (parent, register2, data) => (node, newnode) => {
|
|
|
821
1066
|
}
|
|
822
1067
|
};
|
|
823
1068
|
const register$1 = /* @__PURE__ */ new WeakMap();
|
|
824
|
-
const Element = ({ component, templates: templates2, start: start2 }) => {
|
|
1069
|
+
const Element$1 = ({ component, templates: templates2, start: start2 }) => {
|
|
825
1070
|
const { name, module, dependencies } = component;
|
|
826
1071
|
return class extends HTMLElement {
|
|
827
1072
|
constructor() {
|
|
@@ -894,9 +1139,6 @@ const tagElements = (target, keys, components) => {
|
|
|
894
1139
|
tagElements(node.content, keys, components);
|
|
895
1140
|
return;
|
|
896
1141
|
}
|
|
897
|
-
if (node.hasAttribute("html-if") && !node.id) {
|
|
898
|
-
node.id = uuid();
|
|
899
|
-
}
|
|
900
1142
|
if (isComponent(node.localName)) {
|
|
901
1143
|
node.setAttribute("tplid", uuid());
|
|
902
1144
|
}
|
|
@@ -1005,7 +1247,7 @@ const start = (target) => {
|
|
|
1005
1247
|
const templates2 = template(target, { components });
|
|
1006
1248
|
Object.values(components).forEach(({ name, module, dependencies }) => {
|
|
1007
1249
|
if (!customElements.get(name)) {
|
|
1008
|
-
customElements.define(name, Element({ component: { name, module, dependencies }, templates: templates2, start }));
|
|
1250
|
+
customElements.define(name, Element$1({ component: { name, module, dependencies }, templates: templates2, start }));
|
|
1009
1251
|
}
|
|
1010
1252
|
});
|
|
1011
1253
|
};
|