@wsxjs/wsx-core 0.0.27 → 0.0.30
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/chunk-2ER76KOQ.mjs +1422 -0
- package/dist/chunk-34PNC5CJ.mjs +1307 -0
- package/dist/chunk-FAPFH5ON.mjs +1372 -0
- package/dist/chunk-HWJ7GZD6.mjs +1327 -0
- package/dist/chunk-U74WFVRE.mjs +1308 -0
- package/dist/chunk-UTWWJJ4C.mjs +1360 -0
- package/dist/chunk-ZY36MEHX.mjs +1306 -0
- package/dist/index.js +259 -138
- package/dist/index.mjs +49 -32
- package/dist/jsx-runtime.js +163 -107
- package/dist/jsx-runtime.mjs +1 -1
- package/dist/jsx.js +163 -107
- package/dist/jsx.mjs +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/base-component.ts +14 -10
- package/src/index.ts +2 -0
- package/src/jsx-factory.ts +3 -1
- package/src/light-component.ts +61 -31
- package/src/utils/dom-utils.ts +32 -1
- package/src/utils/element-creation.ts +3 -1
- package/src/utils/element-marking.ts +9 -5
- package/src/utils/element-update.ts +178 -127
- package/src/utils/update-children-helpers.ts +133 -66
- package/src/web-component.ts +6 -5
package/dist/index.mjs
CHANGED
|
@@ -3,8 +3,10 @@ import {
|
|
|
3
3
|
RenderContext,
|
|
4
4
|
createLogger,
|
|
5
5
|
h,
|
|
6
|
+
parseHTMLToNodes,
|
|
7
|
+
reconcileElement,
|
|
6
8
|
shouldPreserveElement
|
|
7
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-2ER76KOQ.mjs";
|
|
8
10
|
|
|
9
11
|
// src/styles/style-manager.ts
|
|
10
12
|
var StyleManager = class {
|
|
@@ -527,7 +529,7 @@ var BaseComponent = class extends HTMLElement {
|
|
|
527
529
|
}
|
|
528
530
|
}
|
|
529
531
|
if (activeElement) {
|
|
530
|
-
const isInputElement = activeElement instanceof HTMLInputElement || activeElement instanceof HTMLTextAreaElement || activeElement instanceof HTMLSelectElement || activeElement.hasAttribute("contenteditable");
|
|
532
|
+
const isInputElement = activeElement instanceof HTMLInputElement && activeElement.type !== "radio" && activeElement.type !== "checkbox" || activeElement instanceof HTMLTextAreaElement || activeElement instanceof HTMLSelectElement || activeElement.hasAttribute("contenteditable");
|
|
531
533
|
const forceRender = activeElement.hasAttribute("data-wsx-force-render");
|
|
532
534
|
if (isInputElement && !forceRender) {
|
|
533
535
|
this._pendingRerender = true;
|
|
@@ -543,14 +545,8 @@ var BaseComponent = class extends HTMLElement {
|
|
|
543
545
|
}
|
|
544
546
|
this._hasScheduledRender = true;
|
|
545
547
|
requestAnimationFrame(() => {
|
|
546
|
-
console.warn("[scheduleRerender] RAF callback:", {
|
|
547
|
-
component: this.constructor.name,
|
|
548
|
-
connected: this.connected,
|
|
549
|
-
isRendering: this._isRendering
|
|
550
|
-
});
|
|
551
548
|
this._hasScheduledRender = false;
|
|
552
549
|
if (this.connected && !this._isRendering) {
|
|
553
|
-
console.warn("[scheduleRerender] calling _rerender()");
|
|
554
550
|
this._isRendering = true;
|
|
555
551
|
this._rerender();
|
|
556
552
|
} else if (!this.connected) {
|
|
@@ -579,7 +575,8 @@ var BaseComponent = class extends HTMLElement {
|
|
|
579
575
|
clearTimeout(this._rerenderDebounceTimer);
|
|
580
576
|
this._rerenderDebounceTimer = null;
|
|
581
577
|
}
|
|
582
|
-
|
|
578
|
+
const root = this.getActiveRoot();
|
|
579
|
+
root.removeEventListener("blur", this.handleGlobalBlur, true);
|
|
583
580
|
this._pendingRerender = false;
|
|
584
581
|
}
|
|
585
582
|
/**
|
|
@@ -587,7 +584,8 @@ var BaseComponent = class extends HTMLElement {
|
|
|
587
584
|
* @internal
|
|
588
585
|
*/
|
|
589
586
|
initializeEventListeners() {
|
|
590
|
-
|
|
587
|
+
const root = this.getActiveRoot();
|
|
588
|
+
root.addEventListener("blur", this.handleGlobalBlur, true);
|
|
591
589
|
}
|
|
592
590
|
/**
|
|
593
591
|
* 获取配置值
|
|
@@ -897,7 +895,7 @@ var WebComponent = class extends BaseComponent {
|
|
|
897
895
|
if (!isContentAlreadyInShadowRoot) {
|
|
898
896
|
this.shadowRoot.appendChild(content);
|
|
899
897
|
}
|
|
900
|
-
const
|
|
898
|
+
const oldNodes = Array.from(this.shadowRoot.childNodes).filter((child) => {
|
|
901
899
|
if (child === content) {
|
|
902
900
|
return false;
|
|
903
901
|
}
|
|
@@ -909,7 +907,7 @@ var WebComponent = class extends BaseComponent {
|
|
|
909
907
|
}
|
|
910
908
|
return true;
|
|
911
909
|
});
|
|
912
|
-
|
|
910
|
+
oldNodes.forEach((node) => node.remove());
|
|
913
911
|
const hasStylesAfterDOM = this.shadowRoot.adoptedStyleSheets && this.shadowRoot.adoptedStyleSheets.length > 0;
|
|
914
912
|
const hasStyleElementAfterDOM = Array.from(this.shadowRoot.children).some(
|
|
915
913
|
(child) => child instanceof HTMLStyleElement
|
|
@@ -1044,6 +1042,10 @@ var LightComponent = class extends BaseComponent {
|
|
|
1044
1042
|
querySelectorAll(selector) {
|
|
1045
1043
|
return HTMLElement.prototype.querySelectorAll.call(this, selector);
|
|
1046
1044
|
}
|
|
1045
|
+
/**
|
|
1046
|
+
* 递归协调子元素
|
|
1047
|
+
* 更新现有子元素的属性和内容,而不是替换整个子树
|
|
1048
|
+
*/
|
|
1047
1049
|
/**
|
|
1048
1050
|
* 内部重渲染实现
|
|
1049
1051
|
* 包含从 rerender() 方法迁移的实际渲染逻辑
|
|
@@ -1060,9 +1062,9 @@ var LightComponent = class extends BaseComponent {
|
|
|
1060
1062
|
this._pendingFocusState = focusState;
|
|
1061
1063
|
const jsxChildren = this.getJSXChildren();
|
|
1062
1064
|
try {
|
|
1063
|
-
const
|
|
1065
|
+
const newContent = RenderContext.runInContext(this, () => this.render());
|
|
1064
1066
|
if (focusState && focusState.key && focusState.value !== void 0) {
|
|
1065
|
-
const target =
|
|
1067
|
+
const target = newContent.querySelector(
|
|
1066
1068
|
`[data-wsx-key="${focusState.key}"]`
|
|
1067
1069
|
);
|
|
1068
1070
|
if (target) {
|
|
@@ -1087,36 +1089,50 @@ var LightComponent = class extends BaseComponent {
|
|
|
1087
1089
|
}
|
|
1088
1090
|
}
|
|
1089
1091
|
requestAnimationFrame(() => {
|
|
1090
|
-
this.appendChild(content);
|
|
1091
1092
|
const oldChildren = Array.from(this.children).filter((child) => {
|
|
1092
|
-
if (child === content) {
|
|
1093
|
-
return false;
|
|
1094
|
-
}
|
|
1095
1093
|
if (stylesToApply && child instanceof HTMLStyleElement && child.getAttribute("data-wsx-light-component") === styleName) {
|
|
1096
1094
|
return false;
|
|
1097
1095
|
}
|
|
1098
1096
|
if (child instanceof HTMLElement && jsxChildren.includes(child)) {
|
|
1099
1097
|
return false;
|
|
1100
1098
|
}
|
|
1101
|
-
if (shouldPreserveElement(child)) {
|
|
1102
|
-
return false;
|
|
1103
|
-
}
|
|
1104
1099
|
return true;
|
|
1105
1100
|
});
|
|
1106
|
-
oldChildren.
|
|
1101
|
+
if (oldChildren.length === 1 && newContent instanceof HTMLElement) {
|
|
1102
|
+
const oldElement = oldChildren[0];
|
|
1103
|
+
if (oldElement instanceof HTMLElement && oldElement.tagName === newContent.tagName) {
|
|
1104
|
+
Array.from(oldElement.attributes).forEach((attr) => {
|
|
1105
|
+
if (!newContent.hasAttribute(attr.name)) {
|
|
1106
|
+
oldElement.removeAttribute(attr.name);
|
|
1107
|
+
}
|
|
1108
|
+
});
|
|
1109
|
+
Array.from(newContent.attributes).forEach((attr) => {
|
|
1110
|
+
if (oldElement.getAttribute(attr.name) !== attr.value) {
|
|
1111
|
+
oldElement.setAttribute(attr.name, attr.value);
|
|
1112
|
+
}
|
|
1113
|
+
});
|
|
1114
|
+
reconcileElement(oldElement, newContent);
|
|
1115
|
+
} else {
|
|
1116
|
+
oldElement.remove();
|
|
1117
|
+
this.appendChild(newContent);
|
|
1118
|
+
}
|
|
1119
|
+
} else {
|
|
1120
|
+
oldChildren.forEach((child) => child.remove());
|
|
1121
|
+
this.appendChild(newContent);
|
|
1122
|
+
}
|
|
1107
1123
|
if (stylesToApply) {
|
|
1108
|
-
let
|
|
1124
|
+
let styleEl = this.querySelector(
|
|
1109
1125
|
`style[data-wsx-light-component="${styleName}"]`
|
|
1110
1126
|
);
|
|
1111
|
-
if (!
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
this.insertBefore(
|
|
1116
|
-
} else if (
|
|
1117
|
-
|
|
1118
|
-
} else if (
|
|
1119
|
-
this.insertBefore(
|
|
1127
|
+
if (!styleEl) {
|
|
1128
|
+
styleEl = document.createElement("style");
|
|
1129
|
+
styleEl.setAttribute("data-wsx-light-component", styleName);
|
|
1130
|
+
styleEl.textContent = stylesToApply;
|
|
1131
|
+
this.insertBefore(styleEl, this.firstChild);
|
|
1132
|
+
} else if (styleEl.textContent !== stylesToApply) {
|
|
1133
|
+
styleEl.textContent = stylesToApply;
|
|
1134
|
+
} else if (styleEl !== this.firstChild) {
|
|
1135
|
+
this.insertBefore(styleEl, this.firstChild);
|
|
1120
1136
|
}
|
|
1121
1137
|
}
|
|
1122
1138
|
requestAnimationFrame(() => {
|
|
@@ -1319,6 +1335,7 @@ export {
|
|
|
1319
1335
|
h as jsx,
|
|
1320
1336
|
h as jsxs,
|
|
1321
1337
|
logger5 as logger,
|
|
1338
|
+
parseHTMLToNodes,
|
|
1322
1339
|
registerComponent,
|
|
1323
1340
|
state
|
|
1324
1341
|
};
|
package/dist/jsx-runtime.js
CHANGED
|
@@ -33,6 +33,7 @@ function parseHTMLToNodes(html) {
|
|
|
33
33
|
temp.innerHTML = html;
|
|
34
34
|
return Array.from(temp.childNodes).map((node) => {
|
|
35
35
|
if (node instanceof HTMLElement || node instanceof SVGElement) {
|
|
36
|
+
node.__wsxManaged = true;
|
|
36
37
|
return node;
|
|
37
38
|
} else {
|
|
38
39
|
return node.textContent || "";
|
|
@@ -45,7 +46,13 @@ function isHTMLString(str) {
|
|
|
45
46
|
const htmlTagPattern = /<[a-z][a-z0-9]*(\s[^>]*)?(\/>|>)/i;
|
|
46
47
|
const looksLikeMath = /^[^<]*<[^>]*>[^>]*$/.test(trimmed) && !htmlTagPattern.test(trimmed);
|
|
47
48
|
if (looksLikeMath) return false;
|
|
48
|
-
|
|
49
|
+
const result = htmlTagPattern.test(trimmed);
|
|
50
|
+
if (result) {
|
|
51
|
+
console.log(`[WSX Debug] isHTMLString("${trimmed.substring(0, 50)}..."): ${result}`, {
|
|
52
|
+
looksLikeMath
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
return result;
|
|
49
56
|
}
|
|
50
57
|
function flattenChildren(children, skipHTMLDetection = false, depth = 0) {
|
|
51
58
|
if (depth > 10) {
|
|
@@ -86,6 +93,17 @@ function flattenChildren(children, skipHTMLDetection = false, depth = 0) {
|
|
|
86
93
|
} else {
|
|
87
94
|
result.push(child);
|
|
88
95
|
}
|
|
96
|
+
} else if (child instanceof DocumentFragment) {
|
|
97
|
+
const fragmentChildren = Array.from(child.childNodes);
|
|
98
|
+
for (const fragChild of fragmentChildren) {
|
|
99
|
+
if (fragChild instanceof HTMLElement || fragChild instanceof SVGElement) {
|
|
100
|
+
result.push(fragChild);
|
|
101
|
+
} else if (fragChild.nodeType === Node.TEXT_NODE) {
|
|
102
|
+
result.push(fragChild.textContent || "");
|
|
103
|
+
} else if (fragChild instanceof DocumentFragment) {
|
|
104
|
+
result.push(...flattenChildren([fragChild], skipHTMLDetection, depth + 1));
|
|
105
|
+
}
|
|
106
|
+
}
|
|
89
107
|
} else {
|
|
90
108
|
result.push(child);
|
|
91
109
|
}
|
|
@@ -186,12 +204,12 @@ function isCreatedByH(element) {
|
|
|
186
204
|
}
|
|
187
205
|
function shouldPreserveElement(element) {
|
|
188
206
|
if (!(element instanceof HTMLElement || element instanceof SVGElement)) {
|
|
189
|
-
return
|
|
207
|
+
return false;
|
|
190
208
|
}
|
|
191
|
-
if (!isCreatedByH(element)) {
|
|
209
|
+
if (!isCreatedByH(element) && element.__wsxManaged !== true) {
|
|
192
210
|
return true;
|
|
193
211
|
}
|
|
194
|
-
if (element.hasAttribute("data-wsx-preserve")) {
|
|
212
|
+
if (element instanceof HTMLElement && element.hasAttribute("data-wsx-preserve")) {
|
|
195
213
|
return true;
|
|
196
214
|
}
|
|
197
215
|
return false;
|
|
@@ -637,7 +655,9 @@ function appendChildrenToElement(element, children) {
|
|
|
637
655
|
return;
|
|
638
656
|
}
|
|
639
657
|
if (typeof child === "string" || typeof child === "number") {
|
|
640
|
-
|
|
658
|
+
const textNode = document.createTextNode(String(child));
|
|
659
|
+
textNode.__wsxManaged = true;
|
|
660
|
+
element.appendChild(textNode);
|
|
641
661
|
} else if (child instanceof HTMLElement || child instanceof SVGElement) {
|
|
642
662
|
element.appendChild(child);
|
|
643
663
|
} else if (child instanceof DocumentFragment) {
|
|
@@ -657,6 +677,9 @@ function collectPreservedElements(element) {
|
|
|
657
677
|
const preserved = [];
|
|
658
678
|
for (let i = 0; i < element.childNodes.length; i++) {
|
|
659
679
|
const child = element.childNodes[i];
|
|
680
|
+
if (child.nodeType === Node.TEXT_NODE) {
|
|
681
|
+
continue;
|
|
682
|
+
}
|
|
660
683
|
if (shouldPreserveElement(child)) {
|
|
661
684
|
preserved.push(child);
|
|
662
685
|
}
|
|
@@ -690,38 +713,40 @@ function findElementNode(oldChild, parent) {
|
|
|
690
713
|
}
|
|
691
714
|
return null;
|
|
692
715
|
}
|
|
693
|
-
function findTextNode(parent, domIndex) {
|
|
694
|
-
|
|
695
|
-
const node = parent.childNodes[
|
|
696
|
-
if (node.nodeType === Node.TEXT_NODE && node.
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
return textNode;
|
|
716
|
+
function findTextNode(parent, domIndex, processedNodes) {
|
|
717
|
+
for (let i = domIndex.value; i < parent.childNodes.length; i++) {
|
|
718
|
+
const node = parent.childNodes[i];
|
|
719
|
+
if (node.nodeType === Node.TEXT_NODE && node.__wsxManaged === true && !processedNodes.has(node)) {
|
|
720
|
+
domIndex.value = i + 1;
|
|
721
|
+
return node;
|
|
700
722
|
}
|
|
701
|
-
domIndex.value++;
|
|
702
723
|
}
|
|
703
724
|
return null;
|
|
704
725
|
}
|
|
705
|
-
function updateOrCreateTextNode(parent, oldNode, newText) {
|
|
726
|
+
function updateOrCreateTextNode(parent, oldNode, newText, insertBeforeNode) {
|
|
727
|
+
if (shouldPreserveElement(parent)) {
|
|
728
|
+
if (oldNode && oldNode.nodeType === Node.TEXT_NODE) {
|
|
729
|
+
return oldNode;
|
|
730
|
+
}
|
|
731
|
+
return document.createTextNode(newText);
|
|
732
|
+
}
|
|
706
733
|
if (oldNode && oldNode.nodeType === Node.TEXT_NODE) {
|
|
707
734
|
if (oldNode.textContent !== newText) {
|
|
708
735
|
oldNode.textContent = newText;
|
|
709
736
|
}
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
for (let i = 0; i < parent.childNodes.length; i++) {
|
|
714
|
-
const node = parent.childNodes[i];
|
|
715
|
-
if (node.nodeType === Node.TEXT_NODE && node.parentNode === parent && node.textContent === newText) {
|
|
716
|
-
return node;
|
|
717
|
-
}
|
|
737
|
+
if (insertBeforeNode !== void 0) {
|
|
738
|
+
if (oldNode !== insertBeforeNode && oldNode.nextSibling !== insertBeforeNode) {
|
|
739
|
+
parent.insertBefore(oldNode, insertBeforeNode);
|
|
718
740
|
}
|
|
719
741
|
}
|
|
742
|
+
return oldNode;
|
|
743
|
+
} else {
|
|
720
744
|
const newTextNode = document.createTextNode(newText);
|
|
745
|
+
newTextNode.__wsxManaged = true;
|
|
721
746
|
if (oldNode && !shouldPreserveElement(oldNode)) {
|
|
722
747
|
parent.replaceChild(newTextNode, oldNode);
|
|
723
748
|
} else {
|
|
724
|
-
parent.insertBefore(newTextNode,
|
|
749
|
+
parent.insertBefore(newTextNode, insertBeforeNode ?? null);
|
|
725
750
|
}
|
|
726
751
|
return newTextNode;
|
|
727
752
|
}
|
|
@@ -731,25 +756,36 @@ function removeNodeIfNotPreserved(parent, node) {
|
|
|
731
756
|
parent.removeChild(node);
|
|
732
757
|
}
|
|
733
758
|
}
|
|
734
|
-
function
|
|
735
|
-
const targetNextSibling = oldNode && shouldPreserveElement(oldNode) ? oldNode : oldNode?.nextSibling || null;
|
|
736
|
-
replaceOrInsertElementAtPosition(parent, newChild, oldNode, targetNextSibling);
|
|
737
|
-
}
|
|
738
|
-
function replaceOrInsertElementAtPosition(parent, newChild, oldNode, targetNextSibling) {
|
|
759
|
+
function replaceOrInsertElementAtPosition(parent, newChild, oldNode, targetNextSibling, processedNodes) {
|
|
739
760
|
if (newChild.parentNode && newChild.parentNode !== parent) {
|
|
740
761
|
newChild.parentNode.removeChild(newChild);
|
|
741
762
|
}
|
|
742
|
-
const isInCorrectPosition = newChild.parentNode === parent && newChild.nextSibling === targetNextSibling;
|
|
763
|
+
const isInCorrectPosition = newChild.parentNode === parent && (newChild.nextSibling === targetNextSibling || targetNextSibling === newChild);
|
|
743
764
|
if (isInCorrectPosition) {
|
|
765
|
+
if (processedNodes) processedNodes.add(newChild);
|
|
744
766
|
return;
|
|
745
767
|
}
|
|
746
768
|
if (newChild.parentNode === parent) {
|
|
747
769
|
parent.insertBefore(newChild, targetNextSibling);
|
|
770
|
+
if (processedNodes) processedNodes.add(newChild);
|
|
748
771
|
return;
|
|
749
772
|
}
|
|
750
773
|
if (oldNode && oldNode.parentNode === parent && !shouldPreserveElement(oldNode)) {
|
|
751
774
|
if (oldNode !== newChild) {
|
|
775
|
+
const oldCacheKey = getElementCacheKey(oldNode);
|
|
776
|
+
const newCacheKey = getElementCacheKey(newChild);
|
|
777
|
+
if (!oldCacheKey && !newCacheKey && oldNode.__wsxManaged === true) {
|
|
778
|
+
const oldTag = oldNode.tagName.toLowerCase();
|
|
779
|
+
const newTag = newChild.tagName.toLowerCase();
|
|
780
|
+
if (oldTag === newTag && oldNode.textContent === newChild.textContent) {
|
|
781
|
+
if (processedNodes) processedNodes.add(oldNode);
|
|
782
|
+
return;
|
|
783
|
+
}
|
|
784
|
+
}
|
|
752
785
|
parent.replaceChild(newChild, oldNode);
|
|
786
|
+
if (processedNodes) processedNodes.add(newChild);
|
|
787
|
+
} else {
|
|
788
|
+
if (processedNodes) processedNodes.add(newChild);
|
|
753
789
|
}
|
|
754
790
|
} else {
|
|
755
791
|
if (newChild.parentNode === parent) {
|
|
@@ -764,6 +800,12 @@ function replaceOrInsertElementAtPosition(parent, newChild, oldNode, targetNextS
|
|
|
764
800
|
if (existingNode instanceof HTMLElement || existingNode instanceof SVGElement) {
|
|
765
801
|
const existingCacheKey = getElementCacheKey(existingNode);
|
|
766
802
|
if (!existingCacheKey && existingNode.tagName.toLowerCase() === newChildTag && existingNode.textContent === newChildContent && existingNode !== newChild) {
|
|
803
|
+
console.log(
|
|
804
|
+
"[WSX Debug] Found duplicate content, keeping existing:",
|
|
805
|
+
existingNode.tagName,
|
|
806
|
+
existingNode.textContent
|
|
807
|
+
);
|
|
808
|
+
if (processedNodes) processedNodes.add(existingNode);
|
|
767
809
|
return;
|
|
768
810
|
}
|
|
769
811
|
}
|
|
@@ -778,6 +820,7 @@ function appendNewChild(parent, child, processedNodes) {
|
|
|
778
820
|
}
|
|
779
821
|
if (typeof child === "string" || typeof child === "number") {
|
|
780
822
|
const newTextNode = document.createTextNode(String(child));
|
|
823
|
+
newTextNode.__wsxManaged = true;
|
|
781
824
|
parent.appendChild(newTextNode);
|
|
782
825
|
if (processedNodes) {
|
|
783
826
|
processedNodes.add(newTextNode);
|
|
@@ -794,6 +837,11 @@ function appendNewChild(parent, child, processedNodes) {
|
|
|
794
837
|
processedNodes.add(child);
|
|
795
838
|
}
|
|
796
839
|
} else if (child instanceof DocumentFragment) {
|
|
840
|
+
if (processedNodes) {
|
|
841
|
+
for (let i = 0; i < child.childNodes.length; i++) {
|
|
842
|
+
processedNodes.add(child.childNodes[i]);
|
|
843
|
+
}
|
|
844
|
+
}
|
|
797
845
|
parent.appendChild(child);
|
|
798
846
|
}
|
|
799
847
|
}
|
|
@@ -814,20 +862,31 @@ function buildNewChildrenMaps(flatNew) {
|
|
|
814
862
|
return { elementSet, cacheKeyMap };
|
|
815
863
|
}
|
|
816
864
|
function shouldRemoveNode(node, elementSet, cacheKeyMap, processedNodes) {
|
|
817
|
-
if (
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
if (node.nodeType === Node.TEXT_NODE && processedNodes && processedNodes.has(node)) {
|
|
821
|
-
return false;
|
|
822
|
-
}
|
|
823
|
-
if (node.nodeType === Node.TEXT_NODE && processedNodes) {
|
|
824
|
-
let parent = node.parentNode;
|
|
825
|
-
while (parent) {
|
|
826
|
-
if (processedNodes.has(parent) && parent.parentNode) {
|
|
865
|
+
if (node.nodeType === Node.TEXT_NODE) {
|
|
866
|
+
if (node.__wsxManaged === true) {
|
|
867
|
+
if (processedNodes && processedNodes.has(node)) {
|
|
827
868
|
return false;
|
|
828
869
|
}
|
|
829
|
-
|
|
870
|
+
return true;
|
|
830
871
|
}
|
|
872
|
+
const parent = node.parentNode;
|
|
873
|
+
if (parent && (parent instanceof HTMLElement || parent instanceof SVGElement)) {
|
|
874
|
+
if (shouldPreserveElement(parent)) {
|
|
875
|
+
return false;
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
return true;
|
|
879
|
+
} else {
|
|
880
|
+
if (shouldPreserveElement(node)) {
|
|
881
|
+
return false;
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
const isProcessed = processedNodes && processedNodes.has(node);
|
|
885
|
+
if (isProcessed) {
|
|
886
|
+
return false;
|
|
887
|
+
}
|
|
888
|
+
if (shouldPreserveElement(node)) {
|
|
889
|
+
return false;
|
|
831
890
|
}
|
|
832
891
|
if (node instanceof HTMLElement || node instanceof SVGElement || node instanceof DocumentFragment) {
|
|
833
892
|
if (elementSet.has(node)) {
|
|
@@ -870,7 +929,8 @@ function collectNodesToRemove(parent, elementSet, cacheKeyMap, processedNodes) {
|
|
|
870
929
|
const nodesToRemove = [];
|
|
871
930
|
for (let i = 0; i < parent.childNodes.length; i++) {
|
|
872
931
|
const node = parent.childNodes[i];
|
|
873
|
-
|
|
932
|
+
const removed = shouldRemoveNode(node, elementSet, cacheKeyMap, processedNodes);
|
|
933
|
+
if (removed) {
|
|
874
934
|
nodesToRemove.push(node);
|
|
875
935
|
}
|
|
876
936
|
}
|
|
@@ -1072,6 +1132,7 @@ function updateChildren(element, oldChildren, newChildren, _cacheManager) {
|
|
|
1072
1132
|
const preservedElements = collectPreservedElements(element);
|
|
1073
1133
|
const minLength = Math.min(flatOld.length, flatNew.length);
|
|
1074
1134
|
const domIndex = { value: 0 };
|
|
1135
|
+
const insertionIndex = { value: 0 };
|
|
1075
1136
|
const processedNodes = /* @__PURE__ */ new Set();
|
|
1076
1137
|
for (let i = 0; i < minLength; i++) {
|
|
1077
1138
|
const oldChild = flatOld[i];
|
|
@@ -1086,48 +1147,54 @@ function updateChildren(element, oldChildren, newChildren, _cacheManager) {
|
|
|
1086
1147
|
}
|
|
1087
1148
|
}
|
|
1088
1149
|
} else if (typeof oldChild === "string" || typeof oldChild === "number") {
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
domIndex.value =
|
|
1097
|
-
break;
|
|
1150
|
+
if (shouldPreserveElement(element)) {
|
|
1151
|
+
oldNode = null;
|
|
1152
|
+
} else {
|
|
1153
|
+
oldNode = findTextNode(element, domIndex, processedNodes);
|
|
1154
|
+
if (oldNode) {
|
|
1155
|
+
const nodeIndex = Array.from(element.childNodes).indexOf(oldNode);
|
|
1156
|
+
if (nodeIndex !== -1 && nodeIndex >= domIndex.value) {
|
|
1157
|
+
domIndex.value = nodeIndex + 1;
|
|
1098
1158
|
}
|
|
1099
1159
|
}
|
|
1100
1160
|
}
|
|
1101
1161
|
}
|
|
1102
1162
|
if (typeof oldChild === "string" || typeof oldChild === "number") {
|
|
1103
1163
|
if (typeof newChild === "string" || typeof newChild === "number") {
|
|
1104
|
-
const oldText = String(oldChild);
|
|
1105
1164
|
const newText = String(newChild);
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
processedNodes.add(node);
|
|
1120
|
-
break;
|
|
1121
|
-
}
|
|
1122
|
-
}
|
|
1123
|
-
}
|
|
1165
|
+
if (shouldPreserveElement(element)) {
|
|
1166
|
+
continue;
|
|
1167
|
+
}
|
|
1168
|
+
const insertBeforeNode = insertionIndex.value < element.childNodes.length ? element.childNodes[insertionIndex.value] : null;
|
|
1169
|
+
const updatedNode = updateOrCreateTextNode(
|
|
1170
|
+
element,
|
|
1171
|
+
oldNode,
|
|
1172
|
+
newText,
|
|
1173
|
+
insertBeforeNode
|
|
1174
|
+
);
|
|
1175
|
+
if (updatedNode) {
|
|
1176
|
+
processedNodes.add(updatedNode);
|
|
1177
|
+
insertionIndex.value++;
|
|
1124
1178
|
}
|
|
1125
1179
|
} else {
|
|
1126
|
-
|
|
1180
|
+
const targetNode = insertionIndex.value < element.childNodes.length ? element.childNodes[insertionIndex.value] : null;
|
|
1127
1181
|
if (newChild instanceof HTMLElement || newChild instanceof SVGElement) {
|
|
1128
|
-
|
|
1182
|
+
if (oldNode && oldNode === targetNode && oldNode.parentNode === element) {
|
|
1183
|
+
element.replaceChild(newChild, oldNode);
|
|
1184
|
+
} else {
|
|
1185
|
+
element.insertBefore(newChild, targetNode);
|
|
1186
|
+
removeNodeIfNotPreserved(element, oldNode);
|
|
1187
|
+
}
|
|
1188
|
+
processedNodes.add(newChild);
|
|
1189
|
+
insertionIndex.value++;
|
|
1129
1190
|
} else if (newChild instanceof DocumentFragment) {
|
|
1130
|
-
|
|
1191
|
+
if (processedNodes) {
|
|
1192
|
+
for (let i2 = 0; i2 < newChild.childNodes.length; i2++) {
|
|
1193
|
+
processedNodes.add(newChild.childNodes[i2]);
|
|
1194
|
+
}
|
|
1195
|
+
}
|
|
1196
|
+
element.insertBefore(newChild, targetNode);
|
|
1197
|
+
removeNodeIfNotPreserved(element, oldNode);
|
|
1131
1198
|
}
|
|
1132
1199
|
}
|
|
1133
1200
|
} else if (oldChild instanceof HTMLElement || oldChild instanceof SVGElement) {
|
|
@@ -1135,49 +1202,36 @@ function updateChildren(element, oldChildren, newChildren, _cacheManager) {
|
|
|
1135
1202
|
continue;
|
|
1136
1203
|
}
|
|
1137
1204
|
if (newChild instanceof HTMLElement || newChild instanceof SVGElement) {
|
|
1138
|
-
|
|
1139
|
-
let foundPreviousElement = false;
|
|
1140
|
-
for (let j = i - 1; j >= 0; j--) {
|
|
1141
|
-
const prevChild = flatNew[j];
|
|
1142
|
-
if (prevChild instanceof HTMLElement || prevChild instanceof SVGElement) {
|
|
1143
|
-
if (prevChild.parentNode === element) {
|
|
1144
|
-
targetNextSibling = prevChild.nextSibling;
|
|
1145
|
-
foundPreviousElement = true;
|
|
1146
|
-
break;
|
|
1147
|
-
}
|
|
1148
|
-
}
|
|
1149
|
-
}
|
|
1150
|
-
if (!foundPreviousElement) {
|
|
1151
|
-
const firstChild = Array.from(element.childNodes).find(
|
|
1152
|
-
(node) => !shouldPreserveElement(node) && !processedNodes.has(node)
|
|
1153
|
-
);
|
|
1154
|
-
targetNextSibling = firstChild || null;
|
|
1155
|
-
}
|
|
1156
|
-
const isInCorrectPosition = newChild.parentNode === element && newChild.nextSibling === targetNextSibling;
|
|
1157
|
-
if (newChild === oldChild && isInCorrectPosition) {
|
|
1158
|
-
if (oldNode) processedNodes.add(oldNode);
|
|
1159
|
-
processedNodes.add(newChild);
|
|
1160
|
-
continue;
|
|
1161
|
-
}
|
|
1162
|
-
const referenceNode = oldNode && oldNode.parentNode === element ? oldNode : null;
|
|
1205
|
+
const insertBeforeNode = insertionIndex.value < element.childNodes.length ? element.childNodes[insertionIndex.value] : null;
|
|
1163
1206
|
replaceOrInsertElementAtPosition(
|
|
1164
1207
|
element,
|
|
1165
1208
|
newChild,
|
|
1166
|
-
|
|
1167
|
-
|
|
1209
|
+
oldNode,
|
|
1210
|
+
insertBeforeNode,
|
|
1211
|
+
processedNodes
|
|
1168
1212
|
);
|
|
1169
|
-
|
|
1170
|
-
processedNodes.delete(oldNode);
|
|
1171
|
-
}
|
|
1172
|
-
processedNodes.add(newChild);
|
|
1213
|
+
insertionIndex.value++;
|
|
1173
1214
|
} else {
|
|
1174
|
-
|
|
1215
|
+
const targetNode = insertionIndex.value < element.childNodes.length ? element.childNodes[insertionIndex.value] : null;
|
|
1175
1216
|
if (typeof newChild === "string" || typeof newChild === "number") {
|
|
1176
1217
|
const newTextNode = document.createTextNode(String(newChild));
|
|
1177
|
-
|
|
1218
|
+
newTextNode.__wsxManaged = true;
|
|
1219
|
+
if (oldNode && oldNode === targetNode && oldNode.parentNode === element) {
|
|
1220
|
+
element.replaceChild(newTextNode, oldNode);
|
|
1221
|
+
} else {
|
|
1222
|
+
element.insertBefore(newTextNode, targetNode);
|
|
1223
|
+
removeNodeIfNotPreserved(element, oldNode);
|
|
1224
|
+
}
|
|
1178
1225
|
processedNodes.add(newTextNode);
|
|
1226
|
+
insertionIndex.value++;
|
|
1179
1227
|
} else if (newChild instanceof DocumentFragment) {
|
|
1180
|
-
|
|
1228
|
+
if (processedNodes) {
|
|
1229
|
+
for (let i2 = 0; i2 < newChild.childNodes.length; i2++) {
|
|
1230
|
+
processedNodes.add(newChild.childNodes[i2]);
|
|
1231
|
+
}
|
|
1232
|
+
}
|
|
1233
|
+
element.insertBefore(newChild, targetNode);
|
|
1234
|
+
removeNodeIfNotPreserved(element, oldNode);
|
|
1181
1235
|
}
|
|
1182
1236
|
}
|
|
1183
1237
|
}
|
|
@@ -1299,7 +1353,9 @@ function Fragment(_props, children) {
|
|
|
1299
1353
|
return;
|
|
1300
1354
|
}
|
|
1301
1355
|
if (typeof child === "string" || typeof child === "number") {
|
|
1302
|
-
|
|
1356
|
+
const textNode = document.createTextNode(String(child));
|
|
1357
|
+
textNode.__wsxManaged = true;
|
|
1358
|
+
fragment.appendChild(textNode);
|
|
1303
1359
|
} else if (child instanceof HTMLElement || child instanceof SVGElement) {
|
|
1304
1360
|
fragment.appendChild(child);
|
|
1305
1361
|
} else if (child instanceof DocumentFragment) {
|