mnfst 0.5.32 → 0.5.33
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/manifest.js +11 -3
- package/dist/manifest.router.js +101 -31
- package/package.json +1 -1
package/dist/manifest.js
CHANGED
|
@@ -117,10 +117,13 @@
|
|
|
117
117
|
return new Promise((resolve, reject) => {
|
|
118
118
|
const url = getPluginUrl(pluginName, version);
|
|
119
119
|
|
|
120
|
-
//
|
|
120
|
+
// Skip if script with same src already in DOM (e.g. prerendered HTML or second loader run)
|
|
121
121
|
const existing = document.querySelector(`script[src="${url}"]`);
|
|
122
|
-
if (existing
|
|
123
|
-
return resolve();
|
|
122
|
+
if (existing) {
|
|
123
|
+
if (existing.complete) return resolve();
|
|
124
|
+
existing.addEventListener('load', () => resolve());
|
|
125
|
+
existing.addEventListener('error', () => reject(new Error(`Failed to load ${pluginName} from ${url}`)));
|
|
126
|
+
return;
|
|
124
127
|
}
|
|
125
128
|
|
|
126
129
|
const script = document.createElement('script');
|
|
@@ -297,6 +300,11 @@
|
|
|
297
300
|
detectAppwriteFromManifest();
|
|
298
301
|
|
|
299
302
|
if (config && config.plugins.length > 0) {
|
|
303
|
+
if (window.__manifestLoaderStarted) {
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
window.__manifestLoaderStarted = true;
|
|
307
|
+
|
|
300
308
|
const MANIFEST_DEPENDENT_PLUGINS = [
|
|
301
309
|
'data', 'localization', 'components',
|
|
302
310
|
'appwrite-auth', 'appwrite-data', 'appwrite-presence'
|
package/dist/manifest.router.js
CHANGED
|
@@ -597,6 +597,39 @@ function shouldElementBeVisible(element, normalizedPath) {
|
|
|
597
597
|
return true;
|
|
598
598
|
}
|
|
599
599
|
|
|
600
|
+
// Resolve :attr and x-bind:attr whose value is $x.path so injected meta/link have real content (SPA + prerender).
|
|
601
|
+
function resolveDataHeadBindings(element) {
|
|
602
|
+
const x = typeof window !== 'undefined' && window.$x;
|
|
603
|
+
if (!x) return;
|
|
604
|
+
const toResolve = [];
|
|
605
|
+
for (let i = 0; i < element.attributes.length; i++) {
|
|
606
|
+
const attr = element.attributes[i];
|
|
607
|
+
const name = attr.name;
|
|
608
|
+
let bindingAttr = null;
|
|
609
|
+
if (name.startsWith(':')) bindingAttr = name.slice(1);
|
|
610
|
+
else if (name.startsWith('x-bind:')) bindingAttr = name.slice(7);
|
|
611
|
+
if (!bindingAttr) continue;
|
|
612
|
+
const expr = (attr.value || '').trim();
|
|
613
|
+
if (!expr.startsWith('$x.')) continue;
|
|
614
|
+
const path = expr.slice(3).trim();
|
|
615
|
+
if (!path) continue;
|
|
616
|
+
toResolve.push({ bindingName: attr.name, attrName: bindingAttr, path });
|
|
617
|
+
}
|
|
618
|
+
for (const { bindingName, attrName, path } of toResolve) {
|
|
619
|
+
let value;
|
|
620
|
+
try {
|
|
621
|
+
value = path.split('.').reduce(function (obj, key) {
|
|
622
|
+
return obj != null && typeof obj === 'object' ? obj[key] : undefined;
|
|
623
|
+
}, x);
|
|
624
|
+
} catch (e) {
|
|
625
|
+
continue;
|
|
626
|
+
}
|
|
627
|
+
if (value === undefined) continue;
|
|
628
|
+
element.setAttribute(attrName, String(value));
|
|
629
|
+
element.removeAttribute(bindingName);
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
|
|
600
633
|
// Generate unique identifier for head content
|
|
601
634
|
function generateHeadId(element) {
|
|
602
635
|
const position = element.getAttribute('data-order');
|
|
@@ -632,10 +665,14 @@ function processElementHeadContent(element, normalizedPath) {
|
|
|
632
665
|
const isVisible = shouldElementBeVisible(element, normalizedPath);
|
|
633
666
|
|
|
634
667
|
if (isVisible) {
|
|
635
|
-
//
|
|
668
|
+
// Skip if already injected (in-memory) or already present in DOM (e.g. prerendered)
|
|
636
669
|
if (injectedHeadContent.has(headId)) {
|
|
637
670
|
return;
|
|
638
671
|
}
|
|
672
|
+
if (document.head.querySelector(`[data-route-head="${headId}"]`)) {
|
|
673
|
+
injectedHeadContent.add(headId);
|
|
674
|
+
return;
|
|
675
|
+
}
|
|
639
676
|
|
|
640
677
|
// Add new head content
|
|
641
678
|
Array.from(headTemplate.content.children).forEach(child => {
|
|
@@ -646,8 +683,9 @@ function processElementHeadContent(element, normalizedPath) {
|
|
|
646
683
|
script.setAttribute('data-route-head', headId);
|
|
647
684
|
document.head.appendChild(script);
|
|
648
685
|
} else {
|
|
649
|
-
// For other elements, clone and add
|
|
686
|
+
// For other elements, clone and add (resolve $x bindings so meta/link have real values in SPA)
|
|
650
687
|
const clonedChild = child.cloneNode(true);
|
|
688
|
+
resolveDataHeadBindings(clonedChild);
|
|
651
689
|
clonedChild.setAttribute('data-route-head', headId);
|
|
652
690
|
document.head.appendChild(clonedChild);
|
|
653
691
|
}
|
|
@@ -831,6 +869,29 @@ window.ManifestRoutingHead = {
|
|
|
831
869
|
|
|
832
870
|
// Router anchors
|
|
833
871
|
|
|
872
|
+
// Parse pipeline syntax: 'scope | targets' (shared for directive and route-change handler)
|
|
873
|
+
function parseAnchorsExpression(expr) {
|
|
874
|
+
if (!expr || expr.trim() === '') {
|
|
875
|
+
return { scope: '', targets: 'h1, h2, h3, h4, h5, h6' };
|
|
876
|
+
}
|
|
877
|
+
if (expr.includes('|')) {
|
|
878
|
+
const parts = expr.split('|').map(p => p.trim());
|
|
879
|
+
return {
|
|
880
|
+
scope: parts[0] || '',
|
|
881
|
+
targets: parts[1] || 'h1, h2, h3, h4, h5, h6'
|
|
882
|
+
};
|
|
883
|
+
}
|
|
884
|
+
return { scope: '', targets: expr };
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
function isVisible(el) {
|
|
888
|
+
if (!el || !el.getBoundingClientRect) return false;
|
|
889
|
+
const rect = el.getBoundingClientRect();
|
|
890
|
+
if (rect.width === 0 && rect.height === 0) return false;
|
|
891
|
+
const style = window.getComputedStyle(el);
|
|
892
|
+
return style.display !== 'none' && style.visibility !== 'hidden' && style.opacity !== '0';
|
|
893
|
+
}
|
|
894
|
+
|
|
834
895
|
// Anchors functionality
|
|
835
896
|
function initializeAnchors() {
|
|
836
897
|
|
|
@@ -839,24 +900,9 @@ function initializeAnchors() {
|
|
|
839
900
|
|
|
840
901
|
|
|
841
902
|
try {
|
|
842
|
-
|
|
843
|
-
const parseExpression = (expr) => {
|
|
844
|
-
if (!expr || expr.trim() === '') {
|
|
845
|
-
return { scope: '', targets: 'h1, h2, h3, h4, h5, h6' };
|
|
846
|
-
}
|
|
847
|
-
|
|
848
|
-
if (expr.includes('|')) {
|
|
849
|
-
const parts = expr.split('|').map(p => p.trim());
|
|
850
|
-
return {
|
|
851
|
-
scope: parts[0] || '',
|
|
852
|
-
targets: parts[1] || 'h1, h2, h3, h4, h5, h6'
|
|
853
|
-
};
|
|
854
|
-
} else {
|
|
855
|
-
return { scope: '', targets: expr };
|
|
856
|
-
}
|
|
857
|
-
};
|
|
903
|
+
const parseExpression = parseAnchorsExpression;
|
|
858
904
|
|
|
859
|
-
// Extract anchors function
|
|
905
|
+
// Extract anchors function (only from visible scope containers to avoid prior-route content)
|
|
860
906
|
const extractAnchors = (expr) => {
|
|
861
907
|
const parsed = parseExpression(expr);
|
|
862
908
|
|
|
@@ -864,7 +910,8 @@ function initializeAnchors() {
|
|
|
864
910
|
if (!parsed.scope) {
|
|
865
911
|
containers = [document.body];
|
|
866
912
|
} else {
|
|
867
|
-
|
|
913
|
+
const all = Array.from(document.querySelectorAll(parsed.scope));
|
|
914
|
+
containers = all.filter(isVisible);
|
|
868
915
|
}
|
|
869
916
|
|
|
870
917
|
let elements = [];
|
|
@@ -1127,21 +1174,44 @@ document.addEventListener('alpine:init', () => {
|
|
|
1127
1174
|
}
|
|
1128
1175
|
});
|
|
1129
1176
|
|
|
1130
|
-
// Refresh anchors when route changes
|
|
1177
|
+
// Refresh anchors when route changes — wait for scope DOM to update (e.g. x-markdown) to avoid showing prior page's anchors
|
|
1131
1178
|
window.addEventListener('manifest:route-change', () => {
|
|
1132
|
-
// Immediately clear the store to hide the h5 element
|
|
1133
1179
|
Alpine.store('anchors', { count: 0 });
|
|
1134
1180
|
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1181
|
+
const runWhenScopeReady = (el) => {
|
|
1182
|
+
const expression = el.getAttribute('x-anchors');
|
|
1183
|
+
if (!expression || !el._x_anchorRefresh) return;
|
|
1184
|
+
const { scope } = parseAnchorsExpression(expression);
|
|
1185
|
+
if (!scope) {
|
|
1186
|
+
setTimeout(() => el._x_anchorRefresh(), 400);
|
|
1187
|
+
return;
|
|
1188
|
+
}
|
|
1189
|
+
const containers = Array.from(document.querySelectorAll(scope)).filter(isVisible);
|
|
1190
|
+
const container = containers[0];
|
|
1191
|
+
if (!container) {
|
|
1192
|
+
el._x_anchorRefresh();
|
|
1193
|
+
return;
|
|
1194
|
+
}
|
|
1195
|
+
let done = false;
|
|
1196
|
+
const finish = () => {
|
|
1197
|
+
if (done) return;
|
|
1198
|
+
done = true;
|
|
1199
|
+
observer?.disconnect();
|
|
1200
|
+
clearTimeout(fallback);
|
|
1201
|
+
el._x_anchorRefresh();
|
|
1202
|
+
};
|
|
1203
|
+
let t = 0;
|
|
1204
|
+
const observer = new MutationObserver(() => {
|
|
1205
|
+
clearTimeout(t);
|
|
1206
|
+
t = setTimeout(finish, 50);
|
|
1143
1207
|
});
|
|
1144
|
-
|
|
1208
|
+
observer.observe(container, { childList: true, subtree: true });
|
|
1209
|
+
const fallback = setTimeout(finish, 800);
|
|
1210
|
+
};
|
|
1211
|
+
|
|
1212
|
+
requestAnimationFrame(() => {
|
|
1213
|
+
document.querySelectorAll('[x-anchors]').forEach(runWhenScopeReady);
|
|
1214
|
+
});
|
|
1145
1215
|
});
|
|
1146
1216
|
|
|
1147
1217
|
// Refresh anchors when hash changes (for active state updates)
|