mnfst 0.5.29 → 0.5.31
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.appwrite.auth.js +12 -1
- package/dist/manifest.components.js +49 -1
- package/dist/manifest.data.js +47 -19
- package/dist/manifest.dropdowns.js +1 -1
- package/dist/manifest.localization.js +8 -2
- package/dist/manifest.markdown.js +4 -4
- package/dist/manifest.router.js +70 -18
- package/dist/manifest.tooltips.js +5 -10
- package/package.json +6 -7
|
@@ -18,7 +18,8 @@ async function ensureManifest() {
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
try {
|
|
21
|
-
const
|
|
21
|
+
const manifestUrl = (document.querySelector('link[rel="manifest"]')?.getAttribute('href')) || '/manifest.json';
|
|
22
|
+
const response = await fetch(manifestUrl);
|
|
22
23
|
return await response.json();
|
|
23
24
|
} catch (error) {
|
|
24
25
|
return null;
|
|
@@ -221,6 +222,16 @@ function initializeAuthStore() {
|
|
|
221
222
|
_updatingTeam: null, // Team ID being updated (null when not updating)
|
|
222
223
|
_deletingTeam: null, // Team ID being deleted (null when not deleting)
|
|
223
224
|
_creatingTeam: false, // Boolean flag for team creation
|
|
225
|
+
// Stub team convenience methods (replaced by teams.convenience.js; prevent "is not a function" before init)
|
|
226
|
+
isCreatingTeam() { return this._creatingTeam === true; },
|
|
227
|
+
isUpdatingTeam() { return false; },
|
|
228
|
+
isDeletingTeam() { return false; },
|
|
229
|
+
isInvitingMember() { return false; },
|
|
230
|
+
isUpdatingMember() { return false; },
|
|
231
|
+
isDeletingMember() { return false; },
|
|
232
|
+
isUpdatingRole() { return false; },
|
|
233
|
+
isDeletingRole() { return false; },
|
|
234
|
+
isCreatingRole() { return false; },
|
|
224
235
|
// Member operation-specific loading states
|
|
225
236
|
_updatingMember: null, // Membership ID being updated (null when not updating)
|
|
226
237
|
_deletingMember: null, // Membership ID being deleted (null when not deleting)
|
|
@@ -1,5 +1,51 @@
|
|
|
1
1
|
/* Manifest Components */
|
|
2
2
|
|
|
3
|
+
// Base URL for manifest-relative paths (e.g. "../" when viewing dist/index.html). Used by component loader, data loaders, localization.
|
|
4
|
+
window.getManifestBase = function getManifestBase() {
|
|
5
|
+
const href = (document.querySelector('link[rel="manifest"]')?.getAttribute('href')) || '/manifest.json';
|
|
6
|
+
const lastSlash = href.lastIndexOf('/');
|
|
7
|
+
return lastSlash >= 0 ? href.slice(0, lastSlash + 1) : '/';
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
// Absolute pathname prefix for the app root (e.g. "/src/dist"). Used by router for links and route matching.
|
|
11
|
+
// Prerender injects <meta name="manifest:router-base" content="/path"> from manifest.prerender.routerBase or root+output. If present, use it; else fall back to depth or manifest link.
|
|
12
|
+
window.getManifestBasePath = function getManifestBasePath() {
|
|
13
|
+
const baseMeta = document.querySelector('meta[name="manifest:router-base"]');
|
|
14
|
+
const content = baseMeta?.getAttribute('content');
|
|
15
|
+
if (content != null && content !== '') {
|
|
16
|
+
const base = '/' + String(content).replace(/^\/+|\/+$/g, '').trim();
|
|
17
|
+
return base || '';
|
|
18
|
+
}
|
|
19
|
+
const meta = document.querySelector('meta[name="manifest:router-base-depth"]');
|
|
20
|
+
const depth = meta ? parseInt(meta.getAttribute('content'), 10) : NaN;
|
|
21
|
+
if (!Number.isNaN(depth) && depth >= 0) {
|
|
22
|
+
const pathname = (window.location.pathname || '/').replace(/\/$/, '') || '/';
|
|
23
|
+
const segments = pathname.split('/').filter(Boolean);
|
|
24
|
+
if (depth === 0) {
|
|
25
|
+
try {
|
|
26
|
+
const link = document.querySelector('link[rel="manifest"]');
|
|
27
|
+
const href = (link?.getAttribute('href')) || '/manifest.json';
|
|
28
|
+
const url = new URL(href, window.location.href);
|
|
29
|
+
const basePath = url.pathname.replace(/\/[^/]*$/, '') || '/';
|
|
30
|
+
return basePath === '/' ? '' : basePath;
|
|
31
|
+
} catch {
|
|
32
|
+
return '';
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
const keep = Math.max(0, segments.length - depth);
|
|
36
|
+
return keep === 0 ? '' : '/' + segments.slice(0, keep).join('/');
|
|
37
|
+
}
|
|
38
|
+
try {
|
|
39
|
+
const link = document.querySelector('link[rel="manifest"]');
|
|
40
|
+
const href = (link?.getAttribute('href')) || '/manifest.json';
|
|
41
|
+
const url = new URL(href, window.location.href);
|
|
42
|
+
const pathname = url.pathname.replace(/\/[^/]*$/, '') || '/';
|
|
43
|
+
return pathname === '/' ? '' : pathname;
|
|
44
|
+
} catch {
|
|
45
|
+
return '';
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
|
|
3
49
|
// Components registry
|
|
4
50
|
window.ManifestComponentsRegistry = {
|
|
5
51
|
manifest: null,
|
|
@@ -78,9 +124,11 @@ window.ManifestComponentsLoader = {
|
|
|
78
124
|
console.warn('[Manifest] Component', name, 'not found in manifest.');
|
|
79
125
|
return null;
|
|
80
126
|
}
|
|
127
|
+
const base = (typeof window.getManifestBase === 'function' ? window.getManifestBase() : '') || '/';
|
|
128
|
+
const url = path.startsWith('/') || path.startsWith('http') ? path : base + path;
|
|
81
129
|
const promise = (async () => {
|
|
82
130
|
try {
|
|
83
|
-
const response = await fetch(
|
|
131
|
+
const response = await fetch(url);
|
|
84
132
|
if (!response.ok) {
|
|
85
133
|
console.warn('[Manifest] HTML file not found for component', name, 'at path:', path, '(HTTP', response.status + ')');
|
|
86
134
|
return null;
|
package/dist/manifest.data.js
CHANGED
|
@@ -10,7 +10,8 @@ async function ensureManifest() {
|
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
try {
|
|
13
|
-
const
|
|
13
|
+
const manifestUrl = (document.querySelector('link[rel="manifest"]')?.getAttribute('href')) || '/manifest.json';
|
|
14
|
+
const response = await fetch(manifestUrl);
|
|
14
15
|
return await response.json();
|
|
15
16
|
} catch (error) {
|
|
16
17
|
console.error('[Manifest Data] Failed to load manifest:', error);
|
|
@@ -1354,7 +1355,10 @@ function parseCSVToNestedObject(csvText, options = {}) {
|
|
|
1354
1355
|
});
|
|
1355
1356
|
|
|
1356
1357
|
if (parsed.errors && parsed.errors.length > 0) {
|
|
1357
|
-
|
|
1358
|
+
const serious = parsed.errors.filter(e => e.code !== 'TooFewFields');
|
|
1359
|
+
if (serious.length > 0) {
|
|
1360
|
+
console.warn('[Manifest Data] CSV parsing warnings:', serious);
|
|
1361
|
+
}
|
|
1358
1362
|
}
|
|
1359
1363
|
|
|
1360
1364
|
if (!parsed.data || parsed.data.length === 0) {
|
|
@@ -1558,30 +1562,41 @@ function parseCSVToNestedObject(csvText, options = {}) {
|
|
|
1558
1562
|
}
|
|
1559
1563
|
}
|
|
1560
1564
|
|
|
1565
|
+
// Load a local file (JSON, YAML, CSV). Resolves manifest-relative paths when viewing from dist.
|
|
1566
|
+
function resolveDataPath(filePath) {
|
|
1567
|
+
if (!filePath || typeof filePath !== 'string' || filePath.startsWith('http')) {
|
|
1568
|
+
return filePath;
|
|
1569
|
+
}
|
|
1570
|
+
const base = typeof window.getManifestBase === 'function' ? window.getManifestBase() : '';
|
|
1571
|
+
const pathOnly = filePath.startsWith('/') ? filePath.slice(1) : filePath;
|
|
1572
|
+
return base ? base + pathOnly : filePath;
|
|
1573
|
+
}
|
|
1574
|
+
|
|
1561
1575
|
// Load a local file (JSON, YAML, CSV)
|
|
1562
1576
|
async function loadLocalFile(filePath, options = {}) {
|
|
1563
|
-
const
|
|
1577
|
+
const resolved = resolveDataPath(filePath);
|
|
1578
|
+
const response = await fetch(resolved);
|
|
1564
1579
|
|
|
1565
1580
|
// Check if file exists
|
|
1566
1581
|
if (!response.ok) {
|
|
1567
|
-
throw new Error(`[Manifest Data] File not found: ${
|
|
1582
|
+
throw new Error(`[Manifest Data] File not found: ${resolved} (${response.status})`);
|
|
1568
1583
|
}
|
|
1569
1584
|
|
|
1570
1585
|
const contentType = response.headers.get('content-type');
|
|
1571
1586
|
|
|
1572
1587
|
// Handle CSV files
|
|
1573
|
-
if (
|
|
1588
|
+
if (resolved.endsWith('.csv') || contentType?.includes('text/csv')) {
|
|
1574
1589
|
const text = await response.text();
|
|
1575
1590
|
const csvParser = await loadCSVParser();
|
|
1576
1591
|
// Pass currentLocale if provided in options
|
|
1577
1592
|
return parseCSVToNestedObject(text, { currentLocale: options.currentLocale });
|
|
1578
1593
|
}
|
|
1579
1594
|
// Handle JSON files
|
|
1580
|
-
else if (contentType?.includes('application/json') ||
|
|
1595
|
+
else if (contentType?.includes('application/json') || resolved.endsWith('.json')) {
|
|
1581
1596
|
return await response.json();
|
|
1582
1597
|
}
|
|
1583
1598
|
// Handle YAML files
|
|
1584
|
-
else if (contentType?.includes('text/yaml') ||
|
|
1599
|
+
else if (contentType?.includes('text/yaml') || resolved.endsWith('.yaml') || resolved.endsWith('.yml')) {
|
|
1585
1600
|
const text = await response.text();
|
|
1586
1601
|
const yamlLib = await loadYamlLibrary();
|
|
1587
1602
|
return yamlLib.load(text);
|
|
@@ -1609,6 +1624,7 @@ window.ManifestDataLoaders = {
|
|
|
1609
1624
|
loadCSVParser,
|
|
1610
1625
|
deepMergeWithFallback,
|
|
1611
1626
|
parseCSVToNestedObject,
|
|
1627
|
+
resolveDataPath,
|
|
1612
1628
|
loadLocalFile
|
|
1613
1629
|
};
|
|
1614
1630
|
|
|
@@ -4865,18 +4881,24 @@ if (!window.ManifestDataRouteProxyUpdateQueue) {
|
|
|
4865
4881
|
|
|
4866
4882
|
// Debounce all updates
|
|
4867
4883
|
this.timeout = setTimeout(() => {
|
|
4868
|
-
|
|
4869
|
-
this.pending.clear();
|
|
4870
|
-
|
|
4871
|
-
// Update all pending proxies
|
|
4872
|
-
proxiesToUpdate.forEach(updateFn => {
|
|
4873
|
-
try {
|
|
4874
|
-
updateFn();
|
|
4875
|
-
} catch (error) {
|
|
4876
|
-
console.error('[Manifest Data] Error updating route proxy:', error);
|
|
4877
|
-
}
|
|
4878
|
-
});
|
|
4884
|
+
this.flushSync();
|
|
4879
4885
|
}, 0);
|
|
4886
|
+
},
|
|
4887
|
+
// Run all pending proxy updates immediately (e.g. on route change so content updates without refresh)
|
|
4888
|
+
flushSync() {
|
|
4889
|
+
if (this.timeout) {
|
|
4890
|
+
clearTimeout(this.timeout);
|
|
4891
|
+
this.timeout = null;
|
|
4892
|
+
}
|
|
4893
|
+
const proxiesToUpdate = Array.from(this.pending);
|
|
4894
|
+
this.pending.clear();
|
|
4895
|
+
proxiesToUpdate.forEach(updateFn => {
|
|
4896
|
+
try {
|
|
4897
|
+
updateFn();
|
|
4898
|
+
} catch (error) {
|
|
4899
|
+
console.error('[Manifest Data] Error updating route proxy:', error);
|
|
4900
|
+
}
|
|
4901
|
+
});
|
|
4880
4902
|
}
|
|
4881
4903
|
};
|
|
4882
4904
|
}
|
|
@@ -11535,8 +11557,14 @@ function setupUrlChangeListeners() {
|
|
|
11535
11557
|
|
|
11536
11558
|
// Listen to router's route change event (primary integration point)
|
|
11537
11559
|
window.addEventListener('manifest:route-change', (event) => {
|
|
11538
|
-
const newUrl = event.detail?.to
|
|
11560
|
+
const newUrl = event.detail?.to ?? window.ManifestRoutingNavigation?.getCurrentRoute?.() ?? window.location.pathname;
|
|
11539
11561
|
updateCurrentUrl(newUrl);
|
|
11562
|
+
// Flush route proxies after other listeners have queued their updates, so $x.*.$route('path') content updates without refresh
|
|
11563
|
+
setTimeout(() => {
|
|
11564
|
+
if (window.ManifestDataRouteProxyUpdateQueue?.flushSync) {
|
|
11565
|
+
window.ManifestDataRouteProxyUpdateQueue.flushSync();
|
|
11566
|
+
}
|
|
11567
|
+
}, 0);
|
|
11540
11568
|
});
|
|
11541
11569
|
|
|
11542
11570
|
// Also listen for popstate (browser back/forward)
|
|
@@ -161,7 +161,10 @@ function initializeLocalizationPlugin() {
|
|
|
161
161
|
// Check for single-file multi-locale CSV (e.g., {"locales": "/path/to/file.csv"})
|
|
162
162
|
if (collection.locales && typeof collection.locales === 'string' && collection.locales.endsWith('.csv')) {
|
|
163
163
|
try {
|
|
164
|
-
const
|
|
164
|
+
const base = typeof window.getManifestBase === 'function' ? window.getManifestBase() : '';
|
|
165
|
+
const localesPath = collection.locales.startsWith('/') ? collection.locales.slice(1) : collection.locales;
|
|
166
|
+
const localesUrl = (collection.locales.startsWith('http')) ? collection.locales : (base + localesPath);
|
|
167
|
+
const csvResponse = await fetch(localesUrl);
|
|
165
168
|
if (csvResponse.ok) {
|
|
166
169
|
const csvText = await csvResponse.text();
|
|
167
170
|
// Parse CSV header to get locale columns
|
|
@@ -195,7 +198,10 @@ function initializeLocalizationPlugin() {
|
|
|
195
198
|
} else if (typeof collection === 'string' && collection.endsWith('.csv')) {
|
|
196
199
|
// Simple CSV file path - check if it has locale columns
|
|
197
200
|
try {
|
|
198
|
-
const
|
|
201
|
+
const base = typeof window.getManifestBase === 'function' ? window.getManifestBase() : '';
|
|
202
|
+
const csvPath = collection.startsWith('/') ? collection.slice(1) : collection;
|
|
203
|
+
const csvUrl = collection.startsWith('http') ? collection : (base + csvPath);
|
|
204
|
+
const csvResponse = await fetch(csvUrl);
|
|
199
205
|
if (csvResponse.ok) {
|
|
200
206
|
const csvText = await csvResponse.text();
|
|
201
207
|
const lines = csvText.split('\n').filter(line => line.trim());
|
|
@@ -466,12 +466,12 @@ async function initializeMarkdownPlugin() {
|
|
|
466
466
|
// If it's a file path, fetch the content (with caching)
|
|
467
467
|
if (isFilePath) {
|
|
468
468
|
try {
|
|
469
|
-
//
|
|
469
|
+
// Resolve path: relative paths are relative to manifest base (project root), not document root
|
|
470
470
|
let resolvedPath = pathOrContent;
|
|
471
|
-
|
|
472
|
-
// If it's a relative path (doesn't start with /), make it absolute from root
|
|
473
471
|
if (!pathOrContent.startsWith('/')) {
|
|
474
|
-
|
|
472
|
+
const base = (typeof window.getManifestBase === 'function' ? window.getManifestBase() : '') || '';
|
|
473
|
+
const basePath = base.replace(/\/$/, '') || '';
|
|
474
|
+
resolvedPath = (basePath ? basePath + '/' : '/') + pathOrContent;
|
|
475
475
|
}
|
|
476
476
|
|
|
477
477
|
// Check cache first
|
package/dist/manifest.router.js
CHANGED
|
@@ -159,13 +159,30 @@ window.ManifestRoutingPosition = {
|
|
|
159
159
|
|
|
160
160
|
// Router navigation
|
|
161
161
|
|
|
162
|
-
// Current route state
|
|
162
|
+
// Current route state (logical path, e.g. /gadget; not full pathname when app is in a subpath)
|
|
163
163
|
let currentRoute = '/';
|
|
164
164
|
let isInternalNavigation = false;
|
|
165
165
|
|
|
166
|
+
function getBasePath() {
|
|
167
|
+
return (typeof window.getManifestBasePath === 'function' ? window.getManifestBasePath() : '') || '';
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function pathnameToLogical(pathname) {
|
|
171
|
+
const base = getBasePath();
|
|
172
|
+
if (!base || pathname === base || pathname === base + '/') return '/';
|
|
173
|
+
if (pathname.startsWith(base + '/')) {
|
|
174
|
+
let logical = pathname.slice(base.length) || '/';
|
|
175
|
+
if (logical === '/index.html' || logical === '/index') logical = '/';
|
|
176
|
+
return logical;
|
|
177
|
+
}
|
|
178
|
+
if (pathname === base + '/index.html' || pathname === base + '/index') return '/';
|
|
179
|
+
return pathname;
|
|
180
|
+
}
|
|
181
|
+
|
|
166
182
|
// Handle route changes
|
|
167
183
|
async function handleRouteChange() {
|
|
168
|
-
const
|
|
184
|
+
const pathname = window.location.pathname;
|
|
185
|
+
const newRoute = pathnameToLogical(pathname);
|
|
169
186
|
if (newRoute === currentRoute) return;
|
|
170
187
|
|
|
171
188
|
currentRoute = newRoute;
|
|
@@ -215,6 +232,36 @@ async function handleRouteChange() {
|
|
|
215
232
|
}));
|
|
216
233
|
}
|
|
217
234
|
|
|
235
|
+
// Resolve internal link to absolute pathname for pushState. Relative hrefs (e.g. "gadget") are resolved against the app base, not the current URL, so we never get additive paths like /src/dist/widget/gadget/widget/...
|
|
236
|
+
function resolveHref(href) {
|
|
237
|
+
if (!href || href.startsWith('#') || href.startsWith('mailto:') || href.startsWith('tel:')) return href;
|
|
238
|
+
try {
|
|
239
|
+
const base = getBasePath();
|
|
240
|
+
const baseUrl = base ? (window.location.origin + base + '/') : (window.location.origin + '/');
|
|
241
|
+
const url = new URL(href, baseUrl);
|
|
242
|
+
if (url.origin !== window.location.origin) return href;
|
|
243
|
+
let path = url.pathname.replace(/\/$/, '') || '/';
|
|
244
|
+
if (!base) return path.startsWith('/') ? path : '/' + path;
|
|
245
|
+
if (path === base || path.startsWith(base + '/')) return path;
|
|
246
|
+
// path may be above base (e.g. /gadget when base is /src/dist) or unrelated; take only the route part and put under base so we never stack.
|
|
247
|
+
if (path.startsWith('/')) {
|
|
248
|
+
const pathSegs = path.split('/').filter(Boolean);
|
|
249
|
+
const baseSegs = base.split('/').filter(Boolean);
|
|
250
|
+
let i = 0;
|
|
251
|
+
while (i < baseSegs.length && i < pathSegs.length && baseSegs[i] === pathSegs[i]) i++;
|
|
252
|
+
const routeSegs = pathSegs.slice(i);
|
|
253
|
+
if (routeSegs.length) return base + '/' + routeSegs.join('/');
|
|
254
|
+
}
|
|
255
|
+
const out = base + (path.startsWith('/') ? path : '/' + path);
|
|
256
|
+
return out.startsWith('/') ? out : '/' + out;
|
|
257
|
+
} catch {
|
|
258
|
+
const base = getBasePath();
|
|
259
|
+
const safe = (href || '').trim();
|
|
260
|
+
if (!safe) return base || '/';
|
|
261
|
+
return base ? (base + (safe.startsWith('/') ? safe : '/' + safe)) : (safe.startsWith('/') ? safe : '/' + safe);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
218
265
|
// Intercept link clicks to prevent page reloads
|
|
219
266
|
function interceptLinkClicks() {
|
|
220
267
|
// Use capture phase to intercept before other handlers
|
|
@@ -247,6 +294,7 @@ function interceptLinkClicks() {
|
|
|
247
294
|
// Handle links with both route and anchor (e.g., /page#section)
|
|
248
295
|
if (href.includes('#')) {
|
|
249
296
|
const [path, hash] = href.split('#');
|
|
297
|
+
const fullHref = resolveHref(path) + (hash ? '#' + hash : '');
|
|
250
298
|
|
|
251
299
|
event.preventDefault();
|
|
252
300
|
event.stopPropagation();
|
|
@@ -255,8 +303,8 @@ function interceptLinkClicks() {
|
|
|
255
303
|
// Set flag to prevent recursive calls
|
|
256
304
|
isInternalNavigation = true;
|
|
257
305
|
|
|
258
|
-
// Update URL without page reload
|
|
259
|
-
history.pushState(null, '',
|
|
306
|
+
// Update URL without page reload (use base path when app is in a subpath)
|
|
307
|
+
history.pushState(null, '', fullHref);
|
|
260
308
|
|
|
261
309
|
// Handle route change (but don't scroll to top since there's an anchor)
|
|
262
310
|
handleRouteChange();
|
|
@@ -282,8 +330,9 @@ function interceptLinkClicks() {
|
|
|
282
330
|
// Set flag to prevent recursive calls
|
|
283
331
|
isInternalNavigation = true;
|
|
284
332
|
|
|
285
|
-
// Update URL without page reload
|
|
286
|
-
|
|
333
|
+
// Update URL without page reload (use base path when app is in a subpath, e.g. /src/dist/gadget)
|
|
334
|
+
const fullHref = resolveHref(href);
|
|
335
|
+
history.pushState(null, '', fullHref);
|
|
287
336
|
|
|
288
337
|
// Handle route change
|
|
289
338
|
handleRouteChange();
|
|
@@ -296,8 +345,8 @@ function interceptLinkClicks() {
|
|
|
296
345
|
|
|
297
346
|
// Initialize navigation
|
|
298
347
|
function initializeNavigation() {
|
|
299
|
-
// Set initial route
|
|
300
|
-
currentRoute = window.location.pathname;
|
|
348
|
+
// Set initial route (logical path for matching)
|
|
349
|
+
currentRoute = pathnameToLogical(window.location.pathname);
|
|
301
350
|
|
|
302
351
|
// Intercept link clicks
|
|
303
352
|
interceptLinkClicks();
|
|
@@ -323,7 +372,10 @@ if (document.readyState === 'loading') {
|
|
|
323
372
|
// Export navigation interface
|
|
324
373
|
window.ManifestRoutingNavigation = {
|
|
325
374
|
initialize: initializeNavigation,
|
|
326
|
-
getCurrentRoute: () => currentRoute
|
|
375
|
+
getCurrentRoute: () => currentRoute,
|
|
376
|
+
getBasePath,
|
|
377
|
+
resolveHref,
|
|
378
|
+
pathnameToLogical
|
|
327
379
|
};
|
|
328
380
|
|
|
329
381
|
// Router visibility
|
|
@@ -456,8 +508,8 @@ function initializeVisibility() {
|
|
|
456
508
|
// Add x-cloak to route elements to prevent flash
|
|
457
509
|
addXCloakToRouteElements();
|
|
458
510
|
|
|
459
|
-
// Process initial visibility
|
|
460
|
-
const currentPath = window.location.pathname;
|
|
511
|
+
// Process initial visibility (use logical path when app is in a subpath)
|
|
512
|
+
const currentPath = window.ManifestRoutingNavigation?.getCurrentRoute() ?? window.location.pathname;
|
|
461
513
|
const normalizedPath = currentPath === '/' ? '/' : currentPath.replace(/^\/|\/$/g, '');
|
|
462
514
|
processRouteVisibility(normalizedPath);
|
|
463
515
|
|
|
@@ -471,7 +523,7 @@ function initializeVisibility() {
|
|
|
471
523
|
// Add x-cloak to any new route elements
|
|
472
524
|
addXCloakToRouteElements();
|
|
473
525
|
|
|
474
|
-
const currentPath = window.location.pathname;
|
|
526
|
+
const currentPath = window.ManifestRoutingNavigation?.getCurrentRoute() ?? window.location.pathname;
|
|
475
527
|
const normalizedPath = currentPath === '/' ? '/' : currentPath.replace(/^\/|\/$/g, '');
|
|
476
528
|
processRouteVisibility(normalizedPath);
|
|
477
529
|
});
|
|
@@ -687,7 +739,7 @@ function initializeHeadContent() {
|
|
|
687
739
|
function processHeadContentAfterComponentsReady() {
|
|
688
740
|
// Process initial head content after a longer delay to let components settle
|
|
689
741
|
setTimeout(() => {
|
|
690
|
-
const currentPath = window.location.pathname;
|
|
742
|
+
const currentPath = window.ManifestRoutingNavigation?.getCurrentRoute() ?? window.location.pathname;
|
|
691
743
|
const normalizedPath = currentPath === '/' ? '/' : currentPath.replace(/^\/|\/$/g, '');
|
|
692
744
|
|
|
693
745
|
// Debug: Check if about component exists
|
|
@@ -706,7 +758,7 @@ function initializeHeadContent() {
|
|
|
706
758
|
|
|
707
759
|
// Function to process head content immediately (for projects without components)
|
|
708
760
|
function processHeadContentImmediately() {
|
|
709
|
-
const currentPath = window.location.pathname;
|
|
761
|
+
const currentPath = window.ManifestRoutingNavigation?.getCurrentRoute() ?? window.location.pathname;
|
|
710
762
|
const normalizedPath = currentPath === '/' ? '/' : currentPath.replace(/^\/|\/$/g, '');
|
|
711
763
|
processAllHeadContent(normalizedPath);
|
|
712
764
|
}
|
|
@@ -740,7 +792,7 @@ function initializeHeadContent() {
|
|
|
740
792
|
// Wait a bit for components to settle after route change
|
|
741
793
|
setTimeout(() => {
|
|
742
794
|
// Process head content immediately to catch components before they're reverted
|
|
743
|
-
const currentPath = window.location.pathname;
|
|
795
|
+
const currentPath = window.ManifestRoutingNavigation?.getCurrentRoute() ?? window.location.pathname;
|
|
744
796
|
const normalizedPath = currentPath === '/' ? '/' : currentPath.replace(/^\/|\/$/g, '');
|
|
745
797
|
|
|
746
798
|
// Debug: Check if about component exists
|
|
@@ -1126,9 +1178,9 @@ function initializeRouterMagic() {
|
|
|
1126
1178
|
return;
|
|
1127
1179
|
}
|
|
1128
1180
|
|
|
1129
|
-
// Create a reactive object for route data
|
|
1181
|
+
// Create a reactive object for route data (use logical path when app is in a subpath)
|
|
1130
1182
|
const route = Alpine.reactive({
|
|
1131
|
-
current: window.location.pathname,
|
|
1183
|
+
current: window.ManifestRoutingNavigation?.getCurrentRoute() || window.location.pathname,
|
|
1132
1184
|
segments: [],
|
|
1133
1185
|
params: {},
|
|
1134
1186
|
matches: null
|
|
@@ -1136,7 +1188,7 @@ function initializeRouterMagic() {
|
|
|
1136
1188
|
|
|
1137
1189
|
// Update route when route changes
|
|
1138
1190
|
const updateRoute = () => {
|
|
1139
|
-
const currentRoute = window.ManifestRoutingNavigation?.getCurrentRoute()
|
|
1191
|
+
const currentRoute = window.ManifestRoutingNavigation?.getCurrentRoute() ?? window.location.pathname;
|
|
1140
1192
|
|
|
1141
1193
|
// Strip localization codes and other injected segments to get the logical route
|
|
1142
1194
|
let logicalRoute = currentRoute;
|
|
@@ -294,16 +294,11 @@ function ensureTooltipPluginInitialized() {
|
|
|
294
294
|
|
|
295
295
|
tooltipPluginInitialized = true;
|
|
296
296
|
initializeTooltipPlugin();
|
|
297
|
-
|
|
298
|
-
//
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
if (!el.__x) {
|
|
303
|
-
window.Alpine.initTree(el);
|
|
304
|
-
}
|
|
305
|
-
});
|
|
306
|
-
}
|
|
297
|
+
// Do not call Alpine.initTree() on [x-tooltip] elements here. That initializes
|
|
298
|
+
// them in isolation and breaks scope (e.g. "tab is not defined"). Alpine will
|
|
299
|
+
// process the full tree from the root, so [x-tooltip] elements get the correct
|
|
300
|
+
// scope. Dynamically loaded components are already initialized by the component
|
|
301
|
+
// processor with initTree on the swapped-in root.
|
|
307
302
|
}
|
|
308
303
|
|
|
309
304
|
// Expose on window for loader to call if needed
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mnfst",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.31",
|
|
4
4
|
"private": false,
|
|
5
5
|
"workspaces": [
|
|
6
6
|
"templates/starter"
|
|
@@ -19,6 +19,9 @@
|
|
|
19
19
|
"start:src": "cd src && browser-sync start --config bs-config.js",
|
|
20
20
|
"start:docs": "cd docs && browser-sync start --config bs-config.js",
|
|
21
21
|
"start:starter": "cd templates/starter && browser-sync start --config bs-config.js --port 3001",
|
|
22
|
+
"prerender": "node src/prerender.mjs --root src",
|
|
23
|
+
"prerender:docs": "node src/prerender.mjs --root docs",
|
|
24
|
+
"prerender:starter": "node src/prerender.mjs --root templates/starter",
|
|
22
25
|
"publish:starter": "cd packages/create-starter && npm publish --auth-type=web",
|
|
23
26
|
"prepublishOnly": "npm run build",
|
|
24
27
|
"test": "echo 'No tests configured'",
|
|
@@ -30,8 +33,8 @@
|
|
|
30
33
|
"@rollup/plugin-terser": "^0.4.4",
|
|
31
34
|
"browser-sync": "^3.0.3",
|
|
32
35
|
"cssnano": "^7.1.1",
|
|
33
|
-
"
|
|
34
|
-
"
|
|
36
|
+
"glob": "^11.0.2",
|
|
37
|
+
"puppeteer": "^24.15.0",
|
|
35
38
|
"rimraf": "^5.0.0",
|
|
36
39
|
"rollup": "^4.24.2"
|
|
37
40
|
},
|
|
@@ -55,9 +58,5 @@
|
|
|
55
58
|
},
|
|
56
59
|
"bugs": {
|
|
57
60
|
"url": "https://github.com/andrewmatlock/manifest/issues"
|
|
58
|
-
},
|
|
59
|
-
"dependencies": {
|
|
60
|
-
"commander": "^14.0.1",
|
|
61
|
-
"glob": "^11.0.2"
|
|
62
61
|
}
|
|
63
62
|
}
|