@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.js
CHANGED
|
@@ -32,6 +32,7 @@ __export(index_exports, {
|
|
|
32
32
|
jsx: () => h,
|
|
33
33
|
jsxs: () => h,
|
|
34
34
|
logger: () => import_wsx_logger4.logger,
|
|
35
|
+
parseHTMLToNodes: () => parseHTMLToNodes,
|
|
35
36
|
registerComponent: () => registerComponent,
|
|
36
37
|
state: () => state
|
|
37
38
|
});
|
|
@@ -44,6 +45,7 @@ function parseHTMLToNodes(html) {
|
|
|
44
45
|
temp.innerHTML = html;
|
|
45
46
|
return Array.from(temp.childNodes).map((node) => {
|
|
46
47
|
if (node instanceof HTMLElement || node instanceof SVGElement) {
|
|
48
|
+
node.__wsxManaged = true;
|
|
47
49
|
return node;
|
|
48
50
|
} else {
|
|
49
51
|
return node.textContent || "";
|
|
@@ -56,7 +58,13 @@ function isHTMLString(str) {
|
|
|
56
58
|
const htmlTagPattern = /<[a-z][a-z0-9]*(\s[^>]*)?(\/>|>)/i;
|
|
57
59
|
const looksLikeMath = /^[^<]*<[^>]*>[^>]*$/.test(trimmed) && !htmlTagPattern.test(trimmed);
|
|
58
60
|
if (looksLikeMath) return false;
|
|
59
|
-
|
|
61
|
+
const result = htmlTagPattern.test(trimmed);
|
|
62
|
+
if (result) {
|
|
63
|
+
console.log(`[WSX Debug] isHTMLString("${trimmed.substring(0, 50)}..."): ${result}`, {
|
|
64
|
+
looksLikeMath
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
return result;
|
|
60
68
|
}
|
|
61
69
|
function flattenChildren(children, skipHTMLDetection = false, depth = 0) {
|
|
62
70
|
if (depth > 10) {
|
|
@@ -97,6 +105,17 @@ function flattenChildren(children, skipHTMLDetection = false, depth = 0) {
|
|
|
97
105
|
} else {
|
|
98
106
|
result.push(child);
|
|
99
107
|
}
|
|
108
|
+
} else if (child instanceof DocumentFragment) {
|
|
109
|
+
const fragmentChildren = Array.from(child.childNodes);
|
|
110
|
+
for (const fragChild of fragmentChildren) {
|
|
111
|
+
if (fragChild instanceof HTMLElement || fragChild instanceof SVGElement) {
|
|
112
|
+
result.push(fragChild);
|
|
113
|
+
} else if (fragChild.nodeType === Node.TEXT_NODE) {
|
|
114
|
+
result.push(fragChild.textContent || "");
|
|
115
|
+
} else if (fragChild instanceof DocumentFragment) {
|
|
116
|
+
result.push(...flattenChildren([fragChild], skipHTMLDetection, depth + 1));
|
|
117
|
+
}
|
|
118
|
+
}
|
|
100
119
|
} else {
|
|
101
120
|
result.push(child);
|
|
102
121
|
}
|
|
@@ -197,12 +216,12 @@ function isCreatedByH(element) {
|
|
|
197
216
|
}
|
|
198
217
|
function shouldPreserveElement(element) {
|
|
199
218
|
if (!(element instanceof HTMLElement || element instanceof SVGElement)) {
|
|
200
|
-
return
|
|
219
|
+
return false;
|
|
201
220
|
}
|
|
202
|
-
if (!isCreatedByH(element)) {
|
|
221
|
+
if (!isCreatedByH(element) && element.__wsxManaged !== true) {
|
|
203
222
|
return true;
|
|
204
223
|
}
|
|
205
|
-
if (element.hasAttribute("data-wsx-preserve")) {
|
|
224
|
+
if (element instanceof HTMLElement && element.hasAttribute("data-wsx-preserve")) {
|
|
206
225
|
return true;
|
|
207
226
|
}
|
|
208
227
|
return false;
|
|
@@ -648,7 +667,9 @@ function appendChildrenToElement(element, children) {
|
|
|
648
667
|
return;
|
|
649
668
|
}
|
|
650
669
|
if (typeof child === "string" || typeof child === "number") {
|
|
651
|
-
|
|
670
|
+
const textNode = document.createTextNode(String(child));
|
|
671
|
+
textNode.__wsxManaged = true;
|
|
672
|
+
element.appendChild(textNode);
|
|
652
673
|
} else if (child instanceof HTMLElement || child instanceof SVGElement) {
|
|
653
674
|
element.appendChild(child);
|
|
654
675
|
} else if (child instanceof DocumentFragment) {
|
|
@@ -668,6 +689,9 @@ function collectPreservedElements(element) {
|
|
|
668
689
|
const preserved = [];
|
|
669
690
|
for (let i = 0; i < element.childNodes.length; i++) {
|
|
670
691
|
const child = element.childNodes[i];
|
|
692
|
+
if (child.nodeType === Node.TEXT_NODE) {
|
|
693
|
+
continue;
|
|
694
|
+
}
|
|
671
695
|
if (shouldPreserveElement(child)) {
|
|
672
696
|
preserved.push(child);
|
|
673
697
|
}
|
|
@@ -701,38 +725,40 @@ function findElementNode(oldChild, parent) {
|
|
|
701
725
|
}
|
|
702
726
|
return null;
|
|
703
727
|
}
|
|
704
|
-
function findTextNode(parent, domIndex) {
|
|
705
|
-
|
|
706
|
-
const node = parent.childNodes[
|
|
707
|
-
if (node.nodeType === Node.TEXT_NODE && node.
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
return textNode;
|
|
728
|
+
function findTextNode(parent, domIndex, processedNodes) {
|
|
729
|
+
for (let i = domIndex.value; i < parent.childNodes.length; i++) {
|
|
730
|
+
const node = parent.childNodes[i];
|
|
731
|
+
if (node.nodeType === Node.TEXT_NODE && node.__wsxManaged === true && !processedNodes.has(node)) {
|
|
732
|
+
domIndex.value = i + 1;
|
|
733
|
+
return node;
|
|
711
734
|
}
|
|
712
|
-
domIndex.value++;
|
|
713
735
|
}
|
|
714
736
|
return null;
|
|
715
737
|
}
|
|
716
|
-
function updateOrCreateTextNode(parent, oldNode, newText) {
|
|
738
|
+
function updateOrCreateTextNode(parent, oldNode, newText, insertBeforeNode) {
|
|
739
|
+
if (shouldPreserveElement(parent)) {
|
|
740
|
+
if (oldNode && oldNode.nodeType === Node.TEXT_NODE) {
|
|
741
|
+
return oldNode;
|
|
742
|
+
}
|
|
743
|
+
return document.createTextNode(newText);
|
|
744
|
+
}
|
|
717
745
|
if (oldNode && oldNode.nodeType === Node.TEXT_NODE) {
|
|
718
746
|
if (oldNode.textContent !== newText) {
|
|
719
747
|
oldNode.textContent = newText;
|
|
720
748
|
}
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
for (let i = 0; i < parent.childNodes.length; i++) {
|
|
725
|
-
const node = parent.childNodes[i];
|
|
726
|
-
if (node.nodeType === Node.TEXT_NODE && node.parentNode === parent && node.textContent === newText) {
|
|
727
|
-
return node;
|
|
728
|
-
}
|
|
749
|
+
if (insertBeforeNode !== void 0) {
|
|
750
|
+
if (oldNode !== insertBeforeNode && oldNode.nextSibling !== insertBeforeNode) {
|
|
751
|
+
parent.insertBefore(oldNode, insertBeforeNode);
|
|
729
752
|
}
|
|
730
753
|
}
|
|
754
|
+
return oldNode;
|
|
755
|
+
} else {
|
|
731
756
|
const newTextNode = document.createTextNode(newText);
|
|
757
|
+
newTextNode.__wsxManaged = true;
|
|
732
758
|
if (oldNode && !shouldPreserveElement(oldNode)) {
|
|
733
759
|
parent.replaceChild(newTextNode, oldNode);
|
|
734
760
|
} else {
|
|
735
|
-
parent.insertBefore(newTextNode,
|
|
761
|
+
parent.insertBefore(newTextNode, insertBeforeNode ?? null);
|
|
736
762
|
}
|
|
737
763
|
return newTextNode;
|
|
738
764
|
}
|
|
@@ -742,25 +768,36 @@ function removeNodeIfNotPreserved(parent, node) {
|
|
|
742
768
|
parent.removeChild(node);
|
|
743
769
|
}
|
|
744
770
|
}
|
|
745
|
-
function
|
|
746
|
-
const targetNextSibling = oldNode && shouldPreserveElement(oldNode) ? oldNode : oldNode?.nextSibling || null;
|
|
747
|
-
replaceOrInsertElementAtPosition(parent, newChild, oldNode, targetNextSibling);
|
|
748
|
-
}
|
|
749
|
-
function replaceOrInsertElementAtPosition(parent, newChild, oldNode, targetNextSibling) {
|
|
771
|
+
function replaceOrInsertElementAtPosition(parent, newChild, oldNode, targetNextSibling, processedNodes) {
|
|
750
772
|
if (newChild.parentNode && newChild.parentNode !== parent) {
|
|
751
773
|
newChild.parentNode.removeChild(newChild);
|
|
752
774
|
}
|
|
753
|
-
const isInCorrectPosition = newChild.parentNode === parent && newChild.nextSibling === targetNextSibling;
|
|
775
|
+
const isInCorrectPosition = newChild.parentNode === parent && (newChild.nextSibling === targetNextSibling || targetNextSibling === newChild);
|
|
754
776
|
if (isInCorrectPosition) {
|
|
777
|
+
if (processedNodes) processedNodes.add(newChild);
|
|
755
778
|
return;
|
|
756
779
|
}
|
|
757
780
|
if (newChild.parentNode === parent) {
|
|
758
781
|
parent.insertBefore(newChild, targetNextSibling);
|
|
782
|
+
if (processedNodes) processedNodes.add(newChild);
|
|
759
783
|
return;
|
|
760
784
|
}
|
|
761
785
|
if (oldNode && oldNode.parentNode === parent && !shouldPreserveElement(oldNode)) {
|
|
762
786
|
if (oldNode !== newChild) {
|
|
787
|
+
const oldCacheKey = getElementCacheKey(oldNode);
|
|
788
|
+
const newCacheKey = getElementCacheKey(newChild);
|
|
789
|
+
if (!oldCacheKey && !newCacheKey && oldNode.__wsxManaged === true) {
|
|
790
|
+
const oldTag = oldNode.tagName.toLowerCase();
|
|
791
|
+
const newTag = newChild.tagName.toLowerCase();
|
|
792
|
+
if (oldTag === newTag && oldNode.textContent === newChild.textContent) {
|
|
793
|
+
if (processedNodes) processedNodes.add(oldNode);
|
|
794
|
+
return;
|
|
795
|
+
}
|
|
796
|
+
}
|
|
763
797
|
parent.replaceChild(newChild, oldNode);
|
|
798
|
+
if (processedNodes) processedNodes.add(newChild);
|
|
799
|
+
} else {
|
|
800
|
+
if (processedNodes) processedNodes.add(newChild);
|
|
764
801
|
}
|
|
765
802
|
} else {
|
|
766
803
|
if (newChild.parentNode === parent) {
|
|
@@ -775,6 +812,12 @@ function replaceOrInsertElementAtPosition(parent, newChild, oldNode, targetNextS
|
|
|
775
812
|
if (existingNode instanceof HTMLElement || existingNode instanceof SVGElement) {
|
|
776
813
|
const existingCacheKey = getElementCacheKey(existingNode);
|
|
777
814
|
if (!existingCacheKey && existingNode.tagName.toLowerCase() === newChildTag && existingNode.textContent === newChildContent && existingNode !== newChild) {
|
|
815
|
+
console.log(
|
|
816
|
+
"[WSX Debug] Found duplicate content, keeping existing:",
|
|
817
|
+
existingNode.tagName,
|
|
818
|
+
existingNode.textContent
|
|
819
|
+
);
|
|
820
|
+
if (processedNodes) processedNodes.add(existingNode);
|
|
778
821
|
return;
|
|
779
822
|
}
|
|
780
823
|
}
|
|
@@ -789,6 +832,7 @@ function appendNewChild(parent, child, processedNodes) {
|
|
|
789
832
|
}
|
|
790
833
|
if (typeof child === "string" || typeof child === "number") {
|
|
791
834
|
const newTextNode = document.createTextNode(String(child));
|
|
835
|
+
newTextNode.__wsxManaged = true;
|
|
792
836
|
parent.appendChild(newTextNode);
|
|
793
837
|
if (processedNodes) {
|
|
794
838
|
processedNodes.add(newTextNode);
|
|
@@ -805,6 +849,11 @@ function appendNewChild(parent, child, processedNodes) {
|
|
|
805
849
|
processedNodes.add(child);
|
|
806
850
|
}
|
|
807
851
|
} else if (child instanceof DocumentFragment) {
|
|
852
|
+
if (processedNodes) {
|
|
853
|
+
for (let i = 0; i < child.childNodes.length; i++) {
|
|
854
|
+
processedNodes.add(child.childNodes[i]);
|
|
855
|
+
}
|
|
856
|
+
}
|
|
808
857
|
parent.appendChild(child);
|
|
809
858
|
}
|
|
810
859
|
}
|
|
@@ -825,21 +874,32 @@ function buildNewChildrenMaps(flatNew) {
|
|
|
825
874
|
return { elementSet, cacheKeyMap };
|
|
826
875
|
}
|
|
827
876
|
function shouldRemoveNode(node, elementSet, cacheKeyMap, processedNodes) {
|
|
828
|
-
if (
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
if (node.nodeType === Node.TEXT_NODE && processedNodes && processedNodes.has(node)) {
|
|
832
|
-
return false;
|
|
833
|
-
}
|
|
834
|
-
if (node.nodeType === Node.TEXT_NODE && processedNodes) {
|
|
835
|
-
let parent = node.parentNode;
|
|
836
|
-
while (parent) {
|
|
837
|
-
if (processedNodes.has(parent) && parent.parentNode) {
|
|
877
|
+
if (node.nodeType === Node.TEXT_NODE) {
|
|
878
|
+
if (node.__wsxManaged === true) {
|
|
879
|
+
if (processedNodes && processedNodes.has(node)) {
|
|
838
880
|
return false;
|
|
839
881
|
}
|
|
840
|
-
|
|
882
|
+
return true;
|
|
883
|
+
}
|
|
884
|
+
const parent = node.parentNode;
|
|
885
|
+
if (parent && (parent instanceof HTMLElement || parent instanceof SVGElement)) {
|
|
886
|
+
if (shouldPreserveElement(parent)) {
|
|
887
|
+
return false;
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
return true;
|
|
891
|
+
} else {
|
|
892
|
+
if (shouldPreserveElement(node)) {
|
|
893
|
+
return false;
|
|
841
894
|
}
|
|
842
895
|
}
|
|
896
|
+
const isProcessed = processedNodes && processedNodes.has(node);
|
|
897
|
+
if (isProcessed) {
|
|
898
|
+
return false;
|
|
899
|
+
}
|
|
900
|
+
if (shouldPreserveElement(node)) {
|
|
901
|
+
return false;
|
|
902
|
+
}
|
|
843
903
|
if (node instanceof HTMLElement || node instanceof SVGElement || node instanceof DocumentFragment) {
|
|
844
904
|
if (elementSet.has(node)) {
|
|
845
905
|
return false;
|
|
@@ -881,7 +941,8 @@ function collectNodesToRemove(parent, elementSet, cacheKeyMap, processedNodes) {
|
|
|
881
941
|
const nodesToRemove = [];
|
|
882
942
|
for (let i = 0; i < parent.childNodes.length; i++) {
|
|
883
943
|
const node = parent.childNodes[i];
|
|
884
|
-
|
|
944
|
+
const removed = shouldRemoveNode(node, elementSet, cacheKeyMap, processedNodes);
|
|
945
|
+
if (removed) {
|
|
885
946
|
nodesToRemove.push(node);
|
|
886
947
|
}
|
|
887
948
|
}
|
|
@@ -1083,6 +1144,7 @@ function updateChildren(element, oldChildren, newChildren, _cacheManager) {
|
|
|
1083
1144
|
const preservedElements = collectPreservedElements(element);
|
|
1084
1145
|
const minLength = Math.min(flatOld.length, flatNew.length);
|
|
1085
1146
|
const domIndex = { value: 0 };
|
|
1147
|
+
const insertionIndex = { value: 0 };
|
|
1086
1148
|
const processedNodes = /* @__PURE__ */ new Set();
|
|
1087
1149
|
for (let i = 0; i < minLength; i++) {
|
|
1088
1150
|
const oldChild = flatOld[i];
|
|
@@ -1097,48 +1159,54 @@ function updateChildren(element, oldChildren, newChildren, _cacheManager) {
|
|
|
1097
1159
|
}
|
|
1098
1160
|
}
|
|
1099
1161
|
} else if (typeof oldChild === "string" || typeof oldChild === "number") {
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
domIndex.value =
|
|
1108
|
-
break;
|
|
1162
|
+
if (shouldPreserveElement(element)) {
|
|
1163
|
+
oldNode = null;
|
|
1164
|
+
} else {
|
|
1165
|
+
oldNode = findTextNode(element, domIndex, processedNodes);
|
|
1166
|
+
if (oldNode) {
|
|
1167
|
+
const nodeIndex = Array.from(element.childNodes).indexOf(oldNode);
|
|
1168
|
+
if (nodeIndex !== -1 && nodeIndex >= domIndex.value) {
|
|
1169
|
+
domIndex.value = nodeIndex + 1;
|
|
1109
1170
|
}
|
|
1110
1171
|
}
|
|
1111
1172
|
}
|
|
1112
1173
|
}
|
|
1113
1174
|
if (typeof oldChild === "string" || typeof oldChild === "number") {
|
|
1114
1175
|
if (typeof newChild === "string" || typeof newChild === "number") {
|
|
1115
|
-
const oldText = String(oldChild);
|
|
1116
1176
|
const newText = String(newChild);
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
processedNodes.add(node);
|
|
1131
|
-
break;
|
|
1132
|
-
}
|
|
1133
|
-
}
|
|
1134
|
-
}
|
|
1177
|
+
if (shouldPreserveElement(element)) {
|
|
1178
|
+
continue;
|
|
1179
|
+
}
|
|
1180
|
+
const insertBeforeNode = insertionIndex.value < element.childNodes.length ? element.childNodes[insertionIndex.value] : null;
|
|
1181
|
+
const updatedNode = updateOrCreateTextNode(
|
|
1182
|
+
element,
|
|
1183
|
+
oldNode,
|
|
1184
|
+
newText,
|
|
1185
|
+
insertBeforeNode
|
|
1186
|
+
);
|
|
1187
|
+
if (updatedNode) {
|
|
1188
|
+
processedNodes.add(updatedNode);
|
|
1189
|
+
insertionIndex.value++;
|
|
1135
1190
|
}
|
|
1136
1191
|
} else {
|
|
1137
|
-
|
|
1192
|
+
const targetNode = insertionIndex.value < element.childNodes.length ? element.childNodes[insertionIndex.value] : null;
|
|
1138
1193
|
if (newChild instanceof HTMLElement || newChild instanceof SVGElement) {
|
|
1139
|
-
|
|
1194
|
+
if (oldNode && oldNode === targetNode && oldNode.parentNode === element) {
|
|
1195
|
+
element.replaceChild(newChild, oldNode);
|
|
1196
|
+
} else {
|
|
1197
|
+
element.insertBefore(newChild, targetNode);
|
|
1198
|
+
removeNodeIfNotPreserved(element, oldNode);
|
|
1199
|
+
}
|
|
1200
|
+
processedNodes.add(newChild);
|
|
1201
|
+
insertionIndex.value++;
|
|
1140
1202
|
} else if (newChild instanceof DocumentFragment) {
|
|
1141
|
-
|
|
1203
|
+
if (processedNodes) {
|
|
1204
|
+
for (let i2 = 0; i2 < newChild.childNodes.length; i2++) {
|
|
1205
|
+
processedNodes.add(newChild.childNodes[i2]);
|
|
1206
|
+
}
|
|
1207
|
+
}
|
|
1208
|
+
element.insertBefore(newChild, targetNode);
|
|
1209
|
+
removeNodeIfNotPreserved(element, oldNode);
|
|
1142
1210
|
}
|
|
1143
1211
|
}
|
|
1144
1212
|
} else if (oldChild instanceof HTMLElement || oldChild instanceof SVGElement) {
|
|
@@ -1146,49 +1214,36 @@ function updateChildren(element, oldChildren, newChildren, _cacheManager) {
|
|
|
1146
1214
|
continue;
|
|
1147
1215
|
}
|
|
1148
1216
|
if (newChild instanceof HTMLElement || newChild instanceof SVGElement) {
|
|
1149
|
-
|
|
1150
|
-
let foundPreviousElement = false;
|
|
1151
|
-
for (let j = i - 1; j >= 0; j--) {
|
|
1152
|
-
const prevChild = flatNew[j];
|
|
1153
|
-
if (prevChild instanceof HTMLElement || prevChild instanceof SVGElement) {
|
|
1154
|
-
if (prevChild.parentNode === element) {
|
|
1155
|
-
targetNextSibling = prevChild.nextSibling;
|
|
1156
|
-
foundPreviousElement = true;
|
|
1157
|
-
break;
|
|
1158
|
-
}
|
|
1159
|
-
}
|
|
1160
|
-
}
|
|
1161
|
-
if (!foundPreviousElement) {
|
|
1162
|
-
const firstChild = Array.from(element.childNodes).find(
|
|
1163
|
-
(node) => !shouldPreserveElement(node) && !processedNodes.has(node)
|
|
1164
|
-
);
|
|
1165
|
-
targetNextSibling = firstChild || null;
|
|
1166
|
-
}
|
|
1167
|
-
const isInCorrectPosition = newChild.parentNode === element && newChild.nextSibling === targetNextSibling;
|
|
1168
|
-
if (newChild === oldChild && isInCorrectPosition) {
|
|
1169
|
-
if (oldNode) processedNodes.add(oldNode);
|
|
1170
|
-
processedNodes.add(newChild);
|
|
1171
|
-
continue;
|
|
1172
|
-
}
|
|
1173
|
-
const referenceNode = oldNode && oldNode.parentNode === element ? oldNode : null;
|
|
1217
|
+
const insertBeforeNode = insertionIndex.value < element.childNodes.length ? element.childNodes[insertionIndex.value] : null;
|
|
1174
1218
|
replaceOrInsertElementAtPosition(
|
|
1175
1219
|
element,
|
|
1176
1220
|
newChild,
|
|
1177
|
-
|
|
1178
|
-
|
|
1221
|
+
oldNode,
|
|
1222
|
+
insertBeforeNode,
|
|
1223
|
+
processedNodes
|
|
1179
1224
|
);
|
|
1180
|
-
|
|
1181
|
-
processedNodes.delete(oldNode);
|
|
1182
|
-
}
|
|
1183
|
-
processedNodes.add(newChild);
|
|
1225
|
+
insertionIndex.value++;
|
|
1184
1226
|
} else {
|
|
1185
|
-
|
|
1227
|
+
const targetNode = insertionIndex.value < element.childNodes.length ? element.childNodes[insertionIndex.value] : null;
|
|
1186
1228
|
if (typeof newChild === "string" || typeof newChild === "number") {
|
|
1187
1229
|
const newTextNode = document.createTextNode(String(newChild));
|
|
1188
|
-
|
|
1230
|
+
newTextNode.__wsxManaged = true;
|
|
1231
|
+
if (oldNode && oldNode === targetNode && oldNode.parentNode === element) {
|
|
1232
|
+
element.replaceChild(newTextNode, oldNode);
|
|
1233
|
+
} else {
|
|
1234
|
+
element.insertBefore(newTextNode, targetNode);
|
|
1235
|
+
removeNodeIfNotPreserved(element, oldNode);
|
|
1236
|
+
}
|
|
1189
1237
|
processedNodes.add(newTextNode);
|
|
1238
|
+
insertionIndex.value++;
|
|
1190
1239
|
} else if (newChild instanceof DocumentFragment) {
|
|
1191
|
-
|
|
1240
|
+
if (processedNodes) {
|
|
1241
|
+
for (let i2 = 0; i2 < newChild.childNodes.length; i2++) {
|
|
1242
|
+
processedNodes.add(newChild.childNodes[i2]);
|
|
1243
|
+
}
|
|
1244
|
+
}
|
|
1245
|
+
element.insertBefore(newChild, targetNode);
|
|
1246
|
+
removeNodeIfNotPreserved(element, oldNode);
|
|
1192
1247
|
}
|
|
1193
1248
|
}
|
|
1194
1249
|
}
|
|
@@ -1213,6 +1268,55 @@ function updateElement(element, newProps, newChildren, tag, cacheManager) {
|
|
|
1213
1268
|
updateProps(element, oldProps, newProps, tag);
|
|
1214
1269
|
updateChildren(element, oldChildren, newChildren, cacheManager);
|
|
1215
1270
|
}
|
|
1271
|
+
function reconcileElement(oldParent, newParent) {
|
|
1272
|
+
const oldChildren = Array.from(oldParent.childNodes);
|
|
1273
|
+
const newChildren = Array.from(newParent.childNodes);
|
|
1274
|
+
const maxLength = Math.max(oldChildren.length, newChildren.length);
|
|
1275
|
+
for (let i = 0; i < maxLength; i++) {
|
|
1276
|
+
const oldChild = oldChildren[i];
|
|
1277
|
+
const newChild = newChildren[i];
|
|
1278
|
+
if (!newChild) {
|
|
1279
|
+
oldChild?.remove();
|
|
1280
|
+
} else if (!oldChild) {
|
|
1281
|
+
oldParent.appendChild(newChild.cloneNode(true));
|
|
1282
|
+
} else if (oldChild.nodeType !== newChild.nodeType) {
|
|
1283
|
+
oldParent.replaceChild(newChild.cloneNode(true), oldChild);
|
|
1284
|
+
} else if (oldChild.nodeType === Node.TEXT_NODE) {
|
|
1285
|
+
if (oldChild.textContent !== newChild.textContent) {
|
|
1286
|
+
oldChild.textContent = newChild.textContent;
|
|
1287
|
+
}
|
|
1288
|
+
} else if (oldChild.nodeType === Node.ELEMENT_NODE) {
|
|
1289
|
+
const oldEl = oldChild;
|
|
1290
|
+
const newEl = newChild;
|
|
1291
|
+
if (oldEl.tagName !== newEl.tagName) {
|
|
1292
|
+
oldParent.replaceChild(newEl.cloneNode(true), oldEl);
|
|
1293
|
+
} else {
|
|
1294
|
+
Array.from(oldEl.attributes).forEach((attr) => {
|
|
1295
|
+
if (!newEl.hasAttribute(attr.name)) {
|
|
1296
|
+
oldEl.removeAttribute(attr.name);
|
|
1297
|
+
}
|
|
1298
|
+
});
|
|
1299
|
+
Array.from(newEl.attributes).forEach((attr) => {
|
|
1300
|
+
if (oldEl.getAttribute(attr.name) !== attr.value) {
|
|
1301
|
+
oldEl.setAttribute(attr.name, attr.value);
|
|
1302
|
+
}
|
|
1303
|
+
});
|
|
1304
|
+
if (oldEl.className !== newEl.className) {
|
|
1305
|
+
oldEl.className = newEl.className;
|
|
1306
|
+
}
|
|
1307
|
+
if (oldEl instanceof HTMLInputElement && newEl instanceof HTMLInputElement) {
|
|
1308
|
+
if (oldEl.checked !== newEl.checked) {
|
|
1309
|
+
oldEl.checked = newEl.checked;
|
|
1310
|
+
}
|
|
1311
|
+
if (oldEl.value !== newEl.value) {
|
|
1312
|
+
oldEl.value = newEl.value;
|
|
1313
|
+
}
|
|
1314
|
+
}
|
|
1315
|
+
reconcileElement(oldEl, newEl);
|
|
1316
|
+
}
|
|
1317
|
+
}
|
|
1318
|
+
}
|
|
1319
|
+
}
|
|
1216
1320
|
|
|
1217
1321
|
// src/jsx-factory.ts
|
|
1218
1322
|
var logger3 = createLogger("JSX Factory");
|
|
@@ -1310,7 +1414,9 @@ function Fragment(_props, children) {
|
|
|
1310
1414
|
return;
|
|
1311
1415
|
}
|
|
1312
1416
|
if (typeof child === "string" || typeof child === "number") {
|
|
1313
|
-
|
|
1417
|
+
const textNode = document.createTextNode(String(child));
|
|
1418
|
+
textNode.__wsxManaged = true;
|
|
1419
|
+
fragment.appendChild(textNode);
|
|
1314
1420
|
} else if (child instanceof HTMLElement || child instanceof SVGElement) {
|
|
1315
1421
|
fragment.appendChild(child);
|
|
1316
1422
|
} else if (child instanceof DocumentFragment) {
|
|
@@ -1841,7 +1947,7 @@ var BaseComponent = class extends HTMLElement {
|
|
|
1841
1947
|
}
|
|
1842
1948
|
}
|
|
1843
1949
|
if (activeElement) {
|
|
1844
|
-
const isInputElement = activeElement instanceof HTMLInputElement || activeElement instanceof HTMLTextAreaElement || activeElement instanceof HTMLSelectElement || activeElement.hasAttribute("contenteditable");
|
|
1950
|
+
const isInputElement = activeElement instanceof HTMLInputElement && activeElement.type !== "radio" && activeElement.type !== "checkbox" || activeElement instanceof HTMLTextAreaElement || activeElement instanceof HTMLSelectElement || activeElement.hasAttribute("contenteditable");
|
|
1845
1951
|
const forceRender = activeElement.hasAttribute("data-wsx-force-render");
|
|
1846
1952
|
if (isInputElement && !forceRender) {
|
|
1847
1953
|
this._pendingRerender = true;
|
|
@@ -1857,14 +1963,8 @@ var BaseComponent = class extends HTMLElement {
|
|
|
1857
1963
|
}
|
|
1858
1964
|
this._hasScheduledRender = true;
|
|
1859
1965
|
requestAnimationFrame(() => {
|
|
1860
|
-
console.warn("[scheduleRerender] RAF callback:", {
|
|
1861
|
-
component: this.constructor.name,
|
|
1862
|
-
connected: this.connected,
|
|
1863
|
-
isRendering: this._isRendering
|
|
1864
|
-
});
|
|
1865
1966
|
this._hasScheduledRender = false;
|
|
1866
1967
|
if (this.connected && !this._isRendering) {
|
|
1867
|
-
console.warn("[scheduleRerender] calling _rerender()");
|
|
1868
1968
|
this._isRendering = true;
|
|
1869
1969
|
this._rerender();
|
|
1870
1970
|
} else if (!this.connected) {
|
|
@@ -1893,7 +1993,8 @@ var BaseComponent = class extends HTMLElement {
|
|
|
1893
1993
|
clearTimeout(this._rerenderDebounceTimer);
|
|
1894
1994
|
this._rerenderDebounceTimer = null;
|
|
1895
1995
|
}
|
|
1896
|
-
|
|
1996
|
+
const root = this.getActiveRoot();
|
|
1997
|
+
root.removeEventListener("blur", this.handleGlobalBlur, true);
|
|
1897
1998
|
this._pendingRerender = false;
|
|
1898
1999
|
}
|
|
1899
2000
|
/**
|
|
@@ -1901,7 +2002,8 @@ var BaseComponent = class extends HTMLElement {
|
|
|
1901
2002
|
* @internal
|
|
1902
2003
|
*/
|
|
1903
2004
|
initializeEventListeners() {
|
|
1904
|
-
|
|
2005
|
+
const root = this.getActiveRoot();
|
|
2006
|
+
root.addEventListener("blur", this.handleGlobalBlur, true);
|
|
1905
2007
|
}
|
|
1906
2008
|
/**
|
|
1907
2009
|
* 获取配置值
|
|
@@ -2211,7 +2313,7 @@ var WebComponent = class extends BaseComponent {
|
|
|
2211
2313
|
if (!isContentAlreadyInShadowRoot) {
|
|
2212
2314
|
this.shadowRoot.appendChild(content);
|
|
2213
2315
|
}
|
|
2214
|
-
const
|
|
2316
|
+
const oldNodes = Array.from(this.shadowRoot.childNodes).filter((child) => {
|
|
2215
2317
|
if (child === content) {
|
|
2216
2318
|
return false;
|
|
2217
2319
|
}
|
|
@@ -2223,7 +2325,7 @@ var WebComponent = class extends BaseComponent {
|
|
|
2223
2325
|
}
|
|
2224
2326
|
return true;
|
|
2225
2327
|
});
|
|
2226
|
-
|
|
2328
|
+
oldNodes.forEach((node) => node.remove());
|
|
2227
2329
|
const hasStylesAfterDOM = this.shadowRoot.adoptedStyleSheets && this.shadowRoot.adoptedStyleSheets.length > 0;
|
|
2228
2330
|
const hasStyleElementAfterDOM = Array.from(this.shadowRoot.children).some(
|
|
2229
2331
|
(child) => child instanceof HTMLStyleElement
|
|
@@ -2358,6 +2460,10 @@ var LightComponent = class extends BaseComponent {
|
|
|
2358
2460
|
querySelectorAll(selector) {
|
|
2359
2461
|
return HTMLElement.prototype.querySelectorAll.call(this, selector);
|
|
2360
2462
|
}
|
|
2463
|
+
/**
|
|
2464
|
+
* 递归协调子元素
|
|
2465
|
+
* 更新现有子元素的属性和内容,而不是替换整个子树
|
|
2466
|
+
*/
|
|
2361
2467
|
/**
|
|
2362
2468
|
* 内部重渲染实现
|
|
2363
2469
|
* 包含从 rerender() 方法迁移的实际渲染逻辑
|
|
@@ -2374,9 +2480,9 @@ var LightComponent = class extends BaseComponent {
|
|
|
2374
2480
|
this._pendingFocusState = focusState;
|
|
2375
2481
|
const jsxChildren = this.getJSXChildren();
|
|
2376
2482
|
try {
|
|
2377
|
-
const
|
|
2483
|
+
const newContent = RenderContext.runInContext(this, () => this.render());
|
|
2378
2484
|
if (focusState && focusState.key && focusState.value !== void 0) {
|
|
2379
|
-
const target =
|
|
2485
|
+
const target = newContent.querySelector(
|
|
2380
2486
|
`[data-wsx-key="${focusState.key}"]`
|
|
2381
2487
|
);
|
|
2382
2488
|
if (target) {
|
|
@@ -2401,36 +2507,50 @@ var LightComponent = class extends BaseComponent {
|
|
|
2401
2507
|
}
|
|
2402
2508
|
}
|
|
2403
2509
|
requestAnimationFrame(() => {
|
|
2404
|
-
this.appendChild(content);
|
|
2405
2510
|
const oldChildren = Array.from(this.children).filter((child) => {
|
|
2406
|
-
if (child === content) {
|
|
2407
|
-
return false;
|
|
2408
|
-
}
|
|
2409
2511
|
if (stylesToApply && child instanceof HTMLStyleElement && child.getAttribute("data-wsx-light-component") === styleName) {
|
|
2410
2512
|
return false;
|
|
2411
2513
|
}
|
|
2412
2514
|
if (child instanceof HTMLElement && jsxChildren.includes(child)) {
|
|
2413
2515
|
return false;
|
|
2414
2516
|
}
|
|
2415
|
-
if (shouldPreserveElement(child)) {
|
|
2416
|
-
return false;
|
|
2417
|
-
}
|
|
2418
2517
|
return true;
|
|
2419
2518
|
});
|
|
2420
|
-
oldChildren.
|
|
2519
|
+
if (oldChildren.length === 1 && newContent instanceof HTMLElement) {
|
|
2520
|
+
const oldElement = oldChildren[0];
|
|
2521
|
+
if (oldElement instanceof HTMLElement && oldElement.tagName === newContent.tagName) {
|
|
2522
|
+
Array.from(oldElement.attributes).forEach((attr) => {
|
|
2523
|
+
if (!newContent.hasAttribute(attr.name)) {
|
|
2524
|
+
oldElement.removeAttribute(attr.name);
|
|
2525
|
+
}
|
|
2526
|
+
});
|
|
2527
|
+
Array.from(newContent.attributes).forEach((attr) => {
|
|
2528
|
+
if (oldElement.getAttribute(attr.name) !== attr.value) {
|
|
2529
|
+
oldElement.setAttribute(attr.name, attr.value);
|
|
2530
|
+
}
|
|
2531
|
+
});
|
|
2532
|
+
reconcileElement(oldElement, newContent);
|
|
2533
|
+
} else {
|
|
2534
|
+
oldElement.remove();
|
|
2535
|
+
this.appendChild(newContent);
|
|
2536
|
+
}
|
|
2537
|
+
} else {
|
|
2538
|
+
oldChildren.forEach((child) => child.remove());
|
|
2539
|
+
this.appendChild(newContent);
|
|
2540
|
+
}
|
|
2421
2541
|
if (stylesToApply) {
|
|
2422
|
-
let
|
|
2542
|
+
let styleEl = this.querySelector(
|
|
2423
2543
|
`style[data-wsx-light-component="${styleName}"]`
|
|
2424
2544
|
);
|
|
2425
|
-
if (!
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
this.insertBefore(
|
|
2430
|
-
} else if (
|
|
2431
|
-
|
|
2432
|
-
} else if (
|
|
2433
|
-
this.insertBefore(
|
|
2545
|
+
if (!styleEl) {
|
|
2546
|
+
styleEl = document.createElement("style");
|
|
2547
|
+
styleEl.setAttribute("data-wsx-light-component", styleName);
|
|
2548
|
+
styleEl.textContent = stylesToApply;
|
|
2549
|
+
this.insertBefore(styleEl, this.firstChild);
|
|
2550
|
+
} else if (styleEl.textContent !== stylesToApply) {
|
|
2551
|
+
styleEl.textContent = stylesToApply;
|
|
2552
|
+
} else if (styleEl !== this.firstChild) {
|
|
2553
|
+
this.insertBefore(styleEl, this.firstChild);
|
|
2434
2554
|
}
|
|
2435
2555
|
}
|
|
2436
2556
|
requestAnimationFrame(() => {
|
|
@@ -2634,6 +2754,7 @@ function state(targetOrContext, propertyKey) {
|
|
|
2634
2754
|
jsx,
|
|
2635
2755
|
jsxs,
|
|
2636
2756
|
logger,
|
|
2757
|
+
parseHTMLToNodes,
|
|
2637
2758
|
registerComponent,
|
|
2638
2759
|
state
|
|
2639
2760
|
});
|