@zenithbuild/core 0.6.0 → 0.6.2
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/cli/commands/dev.ts +7 -6
- package/compiler/spa-build.ts +1 -1
- package/compiler/ssg-build.ts +1 -1
- package/dist/cli.js +1 -0
- package/dist/zen-build.js +5 -3
- package/dist/zen-dev.js +5 -3
- package/dist/zen-preview.js +5 -3
- package/dist/zenith.js +5 -3
- package/package.json +2 -1
- package/router/index.ts +10 -58
- package/runtime/bundle-generator.ts +304 -0
package/cli/commands/dev.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import path from 'path'
|
|
2
2
|
import fs from 'fs'
|
|
3
|
-
import os from 'os'
|
|
4
3
|
import { serve, type ServerWebSocket } from 'bun'
|
|
5
4
|
import { requireProject } from '../utils/project'
|
|
6
5
|
import * as logger from '../utils/logger'
|
|
@@ -40,21 +39,23 @@ async function bundlePageScript(script: string, projectRoot: string): Promise<st
|
|
|
40
39
|
return script
|
|
41
40
|
}
|
|
42
41
|
|
|
43
|
-
//
|
|
44
|
-
const tempDir =
|
|
45
|
-
|
|
42
|
+
// Write temp file in PROJECT directory so Bun can find node_modules
|
|
43
|
+
const tempDir = path.join(projectRoot, '.zenith-cache')
|
|
44
|
+
if (!fs.existsSync(tempDir)) {
|
|
45
|
+
fs.mkdirSync(tempDir, { recursive: true })
|
|
46
|
+
}
|
|
47
|
+
const tempFile = path.join(tempDir, `bundle-${Date.now()}.js`)
|
|
46
48
|
|
|
47
49
|
try {
|
|
48
50
|
// Write script to temp file
|
|
49
51
|
fs.writeFileSync(tempFile, script, 'utf-8')
|
|
50
52
|
|
|
51
|
-
// Use Bun.build to bundle with npm resolution
|
|
53
|
+
// Use Bun.build to bundle with npm resolution from project's node_modules
|
|
52
54
|
const result = await Bun.build({
|
|
53
55
|
entrypoints: [tempFile],
|
|
54
56
|
target: 'browser',
|
|
55
57
|
format: 'esm',
|
|
56
58
|
minify: false,
|
|
57
|
-
// Resolve modules from the project's node_modules
|
|
58
59
|
external: [], // Bundle everything
|
|
59
60
|
})
|
|
60
61
|
|
package/compiler/spa-build.ts
CHANGED
package/compiler/ssg-build.ts
CHANGED
|
@@ -16,7 +16,7 @@ import path from "path"
|
|
|
16
16
|
import { compileZenSource } from "./index"
|
|
17
17
|
import { discoverLayouts } from "./discovery/layouts"
|
|
18
18
|
import { processLayout } from "./transform/layoutProcessor"
|
|
19
|
-
import { discoverPages, generateRouteDefinition } from "
|
|
19
|
+
import { discoverPages, generateRouteDefinition } from "@zenithbuild/router/manifest"
|
|
20
20
|
import { analyzePageSource, getAnalysisSummary, getBuildOutputType, type PageAnalysis } from "./build-analyzer"
|
|
21
21
|
import { generateBundleJS } from "../runtime/bundle-generator"
|
|
22
22
|
import { loadContent } from "../cli/utils/content"
|
package/dist/cli.js
CHANGED
package/dist/zen-build.js
CHANGED
|
@@ -9285,7 +9285,6 @@ import process2 from "process";
|
|
|
9285
9285
|
// cli/commands/dev.ts
|
|
9286
9286
|
import path8 from "path";
|
|
9287
9287
|
import fs8 from "fs";
|
|
9288
|
-
import os from "os";
|
|
9289
9288
|
var {serve } = globalThis.Bun;
|
|
9290
9289
|
|
|
9291
9290
|
// cli/utils/project.ts
|
|
@@ -19671,8 +19670,11 @@ async function bundlePageScript(script, projectRoot) {
|
|
|
19671
19670
|
if (!script.includes("import ")) {
|
|
19672
19671
|
return script;
|
|
19673
19672
|
}
|
|
19674
|
-
const tempDir =
|
|
19675
|
-
|
|
19673
|
+
const tempDir = path8.join(projectRoot, ".zenith-cache");
|
|
19674
|
+
if (!fs8.existsSync(tempDir)) {
|
|
19675
|
+
fs8.mkdirSync(tempDir, { recursive: true });
|
|
19676
|
+
}
|
|
19677
|
+
const tempFile = path8.join(tempDir, `bundle-${Date.now()}.js`);
|
|
19676
19678
|
try {
|
|
19677
19679
|
fs8.writeFileSync(tempFile, script, "utf-8");
|
|
19678
19680
|
const result = await Bun.build({
|
package/dist/zen-dev.js
CHANGED
|
@@ -9285,7 +9285,6 @@ import process2 from "process";
|
|
|
9285
9285
|
// cli/commands/dev.ts
|
|
9286
9286
|
import path8 from "path";
|
|
9287
9287
|
import fs8 from "fs";
|
|
9288
|
-
import os from "os";
|
|
9289
9288
|
var {serve } = globalThis.Bun;
|
|
9290
9289
|
|
|
9291
9290
|
// cli/utils/project.ts
|
|
@@ -19671,8 +19670,11 @@ async function bundlePageScript(script, projectRoot) {
|
|
|
19671
19670
|
if (!script.includes("import ")) {
|
|
19672
19671
|
return script;
|
|
19673
19672
|
}
|
|
19674
|
-
const tempDir =
|
|
19675
|
-
|
|
19673
|
+
const tempDir = path8.join(projectRoot, ".zenith-cache");
|
|
19674
|
+
if (!fs8.existsSync(tempDir)) {
|
|
19675
|
+
fs8.mkdirSync(tempDir, { recursive: true });
|
|
19676
|
+
}
|
|
19677
|
+
const tempFile = path8.join(tempDir, `bundle-${Date.now()}.js`);
|
|
19676
19678
|
try {
|
|
19677
19679
|
fs8.writeFileSync(tempFile, script, "utf-8");
|
|
19678
19680
|
const result = await Bun.build({
|
package/dist/zen-preview.js
CHANGED
|
@@ -9285,7 +9285,6 @@ import process2 from "process";
|
|
|
9285
9285
|
// cli/commands/dev.ts
|
|
9286
9286
|
import path8 from "path";
|
|
9287
9287
|
import fs8 from "fs";
|
|
9288
|
-
import os from "os";
|
|
9289
9288
|
var {serve } = globalThis.Bun;
|
|
9290
9289
|
|
|
9291
9290
|
// cli/utils/project.ts
|
|
@@ -19671,8 +19670,11 @@ async function bundlePageScript(script, projectRoot) {
|
|
|
19671
19670
|
if (!script.includes("import ")) {
|
|
19672
19671
|
return script;
|
|
19673
19672
|
}
|
|
19674
|
-
const tempDir =
|
|
19675
|
-
|
|
19673
|
+
const tempDir = path8.join(projectRoot, ".zenith-cache");
|
|
19674
|
+
if (!fs8.existsSync(tempDir)) {
|
|
19675
|
+
fs8.mkdirSync(tempDir, { recursive: true });
|
|
19676
|
+
}
|
|
19677
|
+
const tempFile = path8.join(tempDir, `bundle-${Date.now()}.js`);
|
|
19676
19678
|
try {
|
|
19677
19679
|
fs8.writeFileSync(tempFile, script, "utf-8");
|
|
19678
19680
|
const result = await Bun.build({
|
package/dist/zenith.js
CHANGED
|
@@ -9285,7 +9285,6 @@ import process2 from "process";
|
|
|
9285
9285
|
// cli/commands/dev.ts
|
|
9286
9286
|
import path8 from "path";
|
|
9287
9287
|
import fs8 from "fs";
|
|
9288
|
-
import os from "os";
|
|
9289
9288
|
var {serve } = globalThis.Bun;
|
|
9290
9289
|
|
|
9291
9290
|
// cli/utils/project.ts
|
|
@@ -19671,8 +19670,11 @@ async function bundlePageScript(script, projectRoot) {
|
|
|
19671
19670
|
if (!script.includes("import ")) {
|
|
19672
19671
|
return script;
|
|
19673
19672
|
}
|
|
19674
|
-
const tempDir =
|
|
19675
|
-
|
|
19673
|
+
const tempDir = path8.join(projectRoot, ".zenith-cache");
|
|
19674
|
+
if (!fs8.existsSync(tempDir)) {
|
|
19675
|
+
fs8.mkdirSync(tempDir, { recursive: true });
|
|
19676
|
+
}
|
|
19677
|
+
const tempFile = path8.join(tempDir, `bundle-${Date.now()}.js`);
|
|
19676
19678
|
try {
|
|
19677
19679
|
fs8.writeFileSync(tempFile, script, "utf-8");
|
|
19678
19680
|
const result = await Bun.build({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zenithbuild/core",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.2",
|
|
4
4
|
"description": "Core library for the Zenith framework",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -59,6 +59,7 @@
|
|
|
59
59
|
"typescript": "^5"
|
|
60
60
|
},
|
|
61
61
|
"dependencies": {
|
|
62
|
+
"@zenithbuild/router": "latest",
|
|
62
63
|
"@types/acorn": "^6.0.4",
|
|
63
64
|
"@types/marked": "^6.0.0",
|
|
64
65
|
"@types/parse5": "^7.0.0",
|
package/router/index.ts
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Zenith Router
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* This module re-exports from @zenithbuild/router package.
|
|
5
|
+
*
|
|
6
|
+
* The router has been extracted to its own package for:
|
|
7
|
+
* - Independent versioning
|
|
8
|
+
* - Better separation of concerns
|
|
9
|
+
* - Easier maintenance
|
|
6
10
|
*
|
|
7
11
|
* @example
|
|
8
12
|
* ```ts
|
|
@@ -16,61 +20,9 @@
|
|
|
16
20
|
* console.log('On blog section')
|
|
17
21
|
* }
|
|
18
22
|
* ```
|
|
23
|
+
*
|
|
24
|
+
* @deprecated Import directly from '@zenithbuild/router' for new projects
|
|
19
25
|
*/
|
|
20
26
|
|
|
21
|
-
//
|
|
22
|
-
export * from "
|
|
23
|
-
export * from "./manifest"
|
|
24
|
-
|
|
25
|
-
// Router runtime (core router implementation)
|
|
26
|
-
// These are the primary exports for router functionality
|
|
27
|
-
export {
|
|
28
|
-
initRouter,
|
|
29
|
-
resolveRoute,
|
|
30
|
-
navigate,
|
|
31
|
-
getRoute,
|
|
32
|
-
onRouteChange,
|
|
33
|
-
beforeEach,
|
|
34
|
-
afterEach,
|
|
35
|
-
isActive,
|
|
36
|
-
prefetch,
|
|
37
|
-
isPrefetched
|
|
38
|
-
} from "./runtime"
|
|
39
|
-
|
|
40
|
-
// Navigation utilities (additional helpers and zen* prefixed exports)
|
|
41
|
-
// Note: Some functions like navigate, isActive, prefetch are also in runtime
|
|
42
|
-
// We export runtime's versions above, and navigation's unique functions here
|
|
43
|
-
export {
|
|
44
|
-
// Navigation API (zen* prefixed names)
|
|
45
|
-
zenNavigate,
|
|
46
|
-
zenBack,
|
|
47
|
-
zenForward,
|
|
48
|
-
zenGo,
|
|
49
|
-
zenIsActive,
|
|
50
|
-
zenPrefetch,
|
|
51
|
-
zenIsPrefetched,
|
|
52
|
-
zenGetRoute,
|
|
53
|
-
zenGetParam,
|
|
54
|
-
zenGetQuery,
|
|
55
|
-
createZenLink,
|
|
56
|
-
zenLink,
|
|
57
|
-
// Additional navigation utilities (not in runtime)
|
|
58
|
-
back,
|
|
59
|
-
forward,
|
|
60
|
-
go,
|
|
61
|
-
getParam,
|
|
62
|
-
getQuery,
|
|
63
|
-
isExternalUrl,
|
|
64
|
-
shouldUseSPANavigation,
|
|
65
|
-
normalizePath,
|
|
66
|
-
setGlobalTransition,
|
|
67
|
-
getGlobalTransition,
|
|
68
|
-
createTransitionContext
|
|
69
|
-
} from "./navigation/index"
|
|
70
|
-
|
|
71
|
-
// Navigation-specific types
|
|
72
|
-
export type {
|
|
73
|
-
ZenLinkProps,
|
|
74
|
-
TransitionContext,
|
|
75
|
-
TransitionHandler
|
|
76
|
-
} from "./navigation/index"
|
|
27
|
+
// Re-export everything from @zenithbuild/router
|
|
28
|
+
export * from "@zenithbuild/router"
|
|
@@ -876,6 +876,310 @@ export function generateBundleJS(): string {
|
|
|
876
876
|
global.processRawSections = processRawSections;
|
|
877
877
|
global.slugify = slugify;
|
|
878
878
|
|
|
879
|
+
// ============================================
|
|
880
|
+
// SPA Router Runtime
|
|
881
|
+
// ============================================
|
|
882
|
+
|
|
883
|
+
(function() {
|
|
884
|
+
'use strict';
|
|
885
|
+
|
|
886
|
+
// Current route state
|
|
887
|
+
var currentRoute = {
|
|
888
|
+
path: '/',
|
|
889
|
+
params: {},
|
|
890
|
+
query: {}
|
|
891
|
+
};
|
|
892
|
+
|
|
893
|
+
// Route listeners
|
|
894
|
+
var routeListeners = new Set();
|
|
895
|
+
|
|
896
|
+
// Router outlet element
|
|
897
|
+
var routerOutlet = null;
|
|
898
|
+
|
|
899
|
+
// Page modules registry
|
|
900
|
+
var pageModules = {};
|
|
901
|
+
|
|
902
|
+
// Route manifest
|
|
903
|
+
var routeManifest = [];
|
|
904
|
+
|
|
905
|
+
/**
|
|
906
|
+
* Parse query string
|
|
907
|
+
*/
|
|
908
|
+
function parseQueryString(search) {
|
|
909
|
+
var query = {};
|
|
910
|
+
if (!search || search === '?') return query;
|
|
911
|
+
var params = new URLSearchParams(search);
|
|
912
|
+
params.forEach(function(value, key) { query[key] = value; });
|
|
913
|
+
return query;
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
/**
|
|
917
|
+
* Resolve route from pathname
|
|
918
|
+
*/
|
|
919
|
+
function resolveRoute(pathname) {
|
|
920
|
+
var normalizedPath = pathname === '' ? '/' : pathname;
|
|
921
|
+
|
|
922
|
+
for (var i = 0; i < routeManifest.length; i++) {
|
|
923
|
+
var route = routeManifest[i];
|
|
924
|
+
var match = route.regex.exec(normalizedPath);
|
|
925
|
+
if (match) {
|
|
926
|
+
var params = {};
|
|
927
|
+
for (var j = 0; j < route.paramNames.length; j++) {
|
|
928
|
+
var paramValue = match[j + 1];
|
|
929
|
+
if (paramValue !== undefined) {
|
|
930
|
+
params[route.paramNames[j]] = decodeURIComponent(paramValue);
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
return { record: route, params: params };
|
|
934
|
+
}
|
|
935
|
+
}
|
|
936
|
+
return null;
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
/**
|
|
940
|
+
* Clean up previous page
|
|
941
|
+
*/
|
|
942
|
+
function cleanupPreviousPage() {
|
|
943
|
+
// Trigger unmount lifecycle hooks
|
|
944
|
+
if (global.__zenith && global.__zenith.triggerUnmount) {
|
|
945
|
+
global.__zenith.triggerUnmount();
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
// Remove previous page styles
|
|
949
|
+
var prevStyles = document.querySelectorAll('style[data-zen-page-style]');
|
|
950
|
+
prevStyles.forEach(function(s) { s.remove(); });
|
|
951
|
+
|
|
952
|
+
// Clean up window properties
|
|
953
|
+
if (global.__zenith_cleanup) {
|
|
954
|
+
global.__zenith_cleanup.forEach(function(key) {
|
|
955
|
+
try { delete global[key]; } catch(e) {}
|
|
956
|
+
});
|
|
957
|
+
}
|
|
958
|
+
global.__zenith_cleanup = [];
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
/**
|
|
962
|
+
* Inject styles
|
|
963
|
+
*/
|
|
964
|
+
function injectStyles(styles) {
|
|
965
|
+
styles.forEach(function(content, i) {
|
|
966
|
+
var style = document.createElement('style');
|
|
967
|
+
style.setAttribute('data-zen-page-style', String(i));
|
|
968
|
+
style.textContent = content;
|
|
969
|
+
document.head.appendChild(style);
|
|
970
|
+
});
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
/**
|
|
974
|
+
* Execute scripts
|
|
975
|
+
*/
|
|
976
|
+
function executeScripts(scripts) {
|
|
977
|
+
scripts.forEach(function(content) {
|
|
978
|
+
try {
|
|
979
|
+
var fn = new Function(content);
|
|
980
|
+
fn();
|
|
981
|
+
} catch (e) {
|
|
982
|
+
console.error('[Zenith Router] Script error:', e);
|
|
983
|
+
}
|
|
984
|
+
});
|
|
985
|
+
}
|
|
986
|
+
|
|
987
|
+
/**
|
|
988
|
+
* Render page
|
|
989
|
+
*/
|
|
990
|
+
function renderPage(pageModule) {
|
|
991
|
+
if (!routerOutlet) {
|
|
992
|
+
console.warn('[Zenith Router] No router outlet');
|
|
993
|
+
return;
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
cleanupPreviousPage();
|
|
997
|
+
routerOutlet.innerHTML = pageModule.html;
|
|
998
|
+
injectStyles(pageModule.styles);
|
|
999
|
+
executeScripts(pageModule.scripts);
|
|
1000
|
+
|
|
1001
|
+
// Trigger mount lifecycle hooks after scripts are executed
|
|
1002
|
+
if (global.__zenith && global.__zenith.triggerMount) {
|
|
1003
|
+
global.__zenith.triggerMount();
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
|
|
1007
|
+
/**
|
|
1008
|
+
* Notify listeners
|
|
1009
|
+
*/
|
|
1010
|
+
function notifyListeners(route, prevRoute) {
|
|
1011
|
+
routeListeners.forEach(function(listener) {
|
|
1012
|
+
try { listener(route, prevRoute); } catch(e) {}
|
|
1013
|
+
});
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
/**
|
|
1017
|
+
* Resolve and render
|
|
1018
|
+
*/
|
|
1019
|
+
function resolveAndRender(path, query, updateHistory, replace) {
|
|
1020
|
+
replace = replace || false;
|
|
1021
|
+
var prevRoute = Object.assign({}, currentRoute);
|
|
1022
|
+
var resolved = resolveRoute(path);
|
|
1023
|
+
|
|
1024
|
+
if (resolved) {
|
|
1025
|
+
currentRoute = {
|
|
1026
|
+
path: path,
|
|
1027
|
+
params: resolved.params,
|
|
1028
|
+
query: query,
|
|
1029
|
+
matched: resolved.record
|
|
1030
|
+
};
|
|
1031
|
+
|
|
1032
|
+
var pageModule = pageModules[resolved.record.path];
|
|
1033
|
+
if (pageModule) {
|
|
1034
|
+
renderPage(pageModule);
|
|
1035
|
+
}
|
|
1036
|
+
} else {
|
|
1037
|
+
currentRoute = { path: path, params: {}, query: query, matched: undefined };
|
|
1038
|
+
console.warn('[Zenith Router] No route matched:', path);
|
|
1039
|
+
|
|
1040
|
+
// Render 404 if available
|
|
1041
|
+
if (routerOutlet) {
|
|
1042
|
+
routerOutlet.innerHTML = '<div style="padding: 2rem; text-align: center;"><h1>404</h1><p>Page not found</p></div>';
|
|
1043
|
+
}
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1046
|
+
if (updateHistory) {
|
|
1047
|
+
var url = path + (Object.keys(query).length ? '?' + new URLSearchParams(query) : '');
|
|
1048
|
+
if (replace) {
|
|
1049
|
+
history.replaceState(null, '', url);
|
|
1050
|
+
} else {
|
|
1051
|
+
history.pushState(null, '', url);
|
|
1052
|
+
}
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
notifyListeners(currentRoute, prevRoute);
|
|
1056
|
+
global.__zenith_route = currentRoute;
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1059
|
+
/**
|
|
1060
|
+
* Handle popstate
|
|
1061
|
+
*/
|
|
1062
|
+
function handlePopState() {
|
|
1063
|
+
resolveAndRender(
|
|
1064
|
+
location.pathname,
|
|
1065
|
+
parseQueryString(location.search),
|
|
1066
|
+
false,
|
|
1067
|
+
false
|
|
1068
|
+
);
|
|
1069
|
+
}
|
|
1070
|
+
|
|
1071
|
+
/**
|
|
1072
|
+
* Navigate (public API)
|
|
1073
|
+
*/
|
|
1074
|
+
function navigate(to, options) {
|
|
1075
|
+
options = options || {};
|
|
1076
|
+
var path, query = {};
|
|
1077
|
+
|
|
1078
|
+
if (to.includes('?')) {
|
|
1079
|
+
var parts = to.split('?');
|
|
1080
|
+
path = parts[0];
|
|
1081
|
+
query = parseQueryString('?' + parts[1]);
|
|
1082
|
+
} else {
|
|
1083
|
+
path = to;
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
if (!path.startsWith('/')) {
|
|
1087
|
+
var currentDir = currentRoute.path.split('/').slice(0, -1).join('/');
|
|
1088
|
+
path = currentDir + '/' + path;
|
|
1089
|
+
}
|
|
1090
|
+
|
|
1091
|
+
var normalizedPath = path === '' ? '/' : path;
|
|
1092
|
+
var currentPath = currentRoute.path === '' ? '/' : currentRoute.path;
|
|
1093
|
+
var isSamePath = normalizedPath === currentPath;
|
|
1094
|
+
|
|
1095
|
+
if (isSamePath && JSON.stringify(query) === JSON.stringify(currentRoute.query)) {
|
|
1096
|
+
return;
|
|
1097
|
+
}
|
|
1098
|
+
|
|
1099
|
+
resolveAndRender(path, query, true, options.replace || false);
|
|
1100
|
+
}
|
|
1101
|
+
|
|
1102
|
+
/**
|
|
1103
|
+
* Get current route
|
|
1104
|
+
*/
|
|
1105
|
+
function getRoute() {
|
|
1106
|
+
return Object.assign({}, currentRoute);
|
|
1107
|
+
}
|
|
1108
|
+
|
|
1109
|
+
/**
|
|
1110
|
+
* Subscribe to route changes
|
|
1111
|
+
*/
|
|
1112
|
+
function onRouteChange(listener) {
|
|
1113
|
+
routeListeners.add(listener);
|
|
1114
|
+
return function() { routeListeners.delete(listener); };
|
|
1115
|
+
}
|
|
1116
|
+
|
|
1117
|
+
/**
|
|
1118
|
+
* Check if path is active
|
|
1119
|
+
*/
|
|
1120
|
+
function isActive(path, exact) {
|
|
1121
|
+
if (exact) return currentRoute.path === path;
|
|
1122
|
+
return currentRoute.path.startsWith(path);
|
|
1123
|
+
}
|
|
1124
|
+
|
|
1125
|
+
/**
|
|
1126
|
+
* Prefetch a route
|
|
1127
|
+
*/
|
|
1128
|
+
var prefetchedRoutes = new Set();
|
|
1129
|
+
function prefetch(path) {
|
|
1130
|
+
var normalizedPath = path === '' ? '/' : path;
|
|
1131
|
+
|
|
1132
|
+
if (prefetchedRoutes.has(normalizedPath)) {
|
|
1133
|
+
return Promise.resolve();
|
|
1134
|
+
}
|
|
1135
|
+
prefetchedRoutes.add(normalizedPath);
|
|
1136
|
+
|
|
1137
|
+
var resolved = resolveRoute(normalizedPath);
|
|
1138
|
+
if (!resolved) {
|
|
1139
|
+
return Promise.resolve();
|
|
1140
|
+
}
|
|
1141
|
+
|
|
1142
|
+
// In SPA build, all modules are already loaded
|
|
1143
|
+
return Promise.resolve();
|
|
1144
|
+
}
|
|
1145
|
+
|
|
1146
|
+
/**
|
|
1147
|
+
* Initialize router
|
|
1148
|
+
*/
|
|
1149
|
+
function initRouter(manifest, modules, outlet) {
|
|
1150
|
+
routeManifest = manifest;
|
|
1151
|
+
Object.assign(pageModules, modules);
|
|
1152
|
+
|
|
1153
|
+
if (outlet) {
|
|
1154
|
+
routerOutlet = typeof outlet === 'string'
|
|
1155
|
+
? document.querySelector(outlet)
|
|
1156
|
+
: outlet;
|
|
1157
|
+
}
|
|
1158
|
+
|
|
1159
|
+
window.addEventListener('popstate', handlePopState);
|
|
1160
|
+
|
|
1161
|
+
// Initial route resolution
|
|
1162
|
+
resolveAndRender(
|
|
1163
|
+
location.pathname,
|
|
1164
|
+
parseQueryString(location.search),
|
|
1165
|
+
false
|
|
1166
|
+
);
|
|
1167
|
+
}
|
|
1168
|
+
|
|
1169
|
+
// Expose router API globally
|
|
1170
|
+
global.__zenith_router = {
|
|
1171
|
+
navigate: navigate,
|
|
1172
|
+
getRoute: getRoute,
|
|
1173
|
+
onRouteChange: onRouteChange,
|
|
1174
|
+
isActive: isActive,
|
|
1175
|
+
prefetch: prefetch,
|
|
1176
|
+
initRouter: initRouter
|
|
1177
|
+
};
|
|
1178
|
+
|
|
1179
|
+
// Also expose navigate directly for convenience
|
|
1180
|
+
global.navigate = navigate;
|
|
1181
|
+
})();
|
|
1182
|
+
|
|
879
1183
|
// ============================================
|
|
880
1184
|
// HMR Client (Development Only)
|
|
881
1185
|
// ============================================
|