@zenithbuild/core 0.6.1 → 0.6.3
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/compiler/runtime/transformIR.ts +3 -3
- package/compiler/spa-build.ts +1 -1
- package/compiler/ssg-build.ts +1 -1
- package/dist/cli.js +2 -0
- package/dist/zen-build.js +539 -269
- package/dist/zen-dev.js +539 -269
- package/dist/zen-preview.js +539 -269
- package/dist/zenith.js +539 -269
- package/package.json +3 -2
- package/router/index.ts +10 -58
- package/runtime/bundle-generator.ts +314 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zenithbuild/core",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.3",
|
|
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",
|
|
@@ -68,4 +69,4 @@
|
|
|
68
69
|
"parse5": "^8.0.0",
|
|
69
70
|
"picocolors": "^1.1.1"
|
|
70
71
|
}
|
|
71
|
-
}
|
|
72
|
+
}
|
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,320 @@ export function generateBundleJS(): string {
|
|
|
876
876
|
global.processRawSections = processRawSections;
|
|
877
877
|
global.slugify = slugify;
|
|
878
878
|
|
|
879
|
+
// ============================================
|
|
880
|
+
// SPA Router Runtime
|
|
881
|
+
// ============================================
|
|
882
|
+
|
|
883
|
+
// Router state
|
|
884
|
+
// Current route state
|
|
885
|
+
var currentRoute = {
|
|
886
|
+
path: '/',
|
|
887
|
+
params: {},
|
|
888
|
+
query: {}
|
|
889
|
+
};
|
|
890
|
+
|
|
891
|
+
// Route listeners
|
|
892
|
+
var routeListeners = new Set();
|
|
893
|
+
|
|
894
|
+
// Router outlet element
|
|
895
|
+
var routerOutlet = null;
|
|
896
|
+
|
|
897
|
+
// Page modules registry
|
|
898
|
+
var pageModules = {};
|
|
899
|
+
|
|
900
|
+
// Route manifest
|
|
901
|
+
var routeManifest = [];
|
|
902
|
+
|
|
903
|
+
/**
|
|
904
|
+
* Parse query string
|
|
905
|
+
*/
|
|
906
|
+
function parseQueryString(search) {
|
|
907
|
+
var query = {};
|
|
908
|
+
if (!search || search === '?') return query;
|
|
909
|
+
var params = new URLSearchParams(search);
|
|
910
|
+
params.forEach(function(value, key) { query[key] = value; });
|
|
911
|
+
return query;
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
/**
|
|
915
|
+
* Resolve route from pathname
|
|
916
|
+
*/
|
|
917
|
+
function resolveRoute(pathname) {
|
|
918
|
+
var normalizedPath = pathname === '' ? '/' : pathname;
|
|
919
|
+
|
|
920
|
+
for (var i = 0; i < routeManifest.length; i++) {
|
|
921
|
+
var route = routeManifest[i];
|
|
922
|
+
var match = route.regex.exec(normalizedPath);
|
|
923
|
+
if (match) {
|
|
924
|
+
var params = {};
|
|
925
|
+
for (var j = 0; j < route.paramNames.length; j++) {
|
|
926
|
+
var paramValue = match[j + 1];
|
|
927
|
+
if (paramValue !== undefined) {
|
|
928
|
+
params[route.paramNames[j]] = decodeURIComponent(paramValue);
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
return { record: route, params: params };
|
|
932
|
+
}
|
|
933
|
+
}
|
|
934
|
+
return null;
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
/**
|
|
938
|
+
* Clean up previous page
|
|
939
|
+
*/
|
|
940
|
+
function cleanupPreviousPage() {
|
|
941
|
+
// Trigger unmount lifecycle hooks
|
|
942
|
+
if (global.__zenith && global.__zenith.triggerUnmount) {
|
|
943
|
+
global.__zenith.triggerUnmount();
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
// Remove previous page styles
|
|
947
|
+
var prevStyles = document.querySelectorAll('style[data-zen-page-style]');
|
|
948
|
+
prevStyles.forEach(function(s) { s.remove(); });
|
|
949
|
+
|
|
950
|
+
// Clean up window properties
|
|
951
|
+
if (global.__zenith_cleanup) {
|
|
952
|
+
global.__zenith_cleanup.forEach(function(key) {
|
|
953
|
+
try { delete global[key]; } catch(e) {}
|
|
954
|
+
});
|
|
955
|
+
}
|
|
956
|
+
global.__zenith_cleanup = [];
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
/**
|
|
960
|
+
* Inject styles
|
|
961
|
+
*/
|
|
962
|
+
function injectStyles(styles) {
|
|
963
|
+
styles.forEach(function(content, i) {
|
|
964
|
+
var style = document.createElement('style');
|
|
965
|
+
style.setAttribute('data-zen-page-style', String(i));
|
|
966
|
+
style.textContent = content;
|
|
967
|
+
document.head.appendChild(style);
|
|
968
|
+
});
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
/**
|
|
972
|
+
* Execute scripts
|
|
973
|
+
*/
|
|
974
|
+
function executeScripts(scripts) {
|
|
975
|
+
scripts.forEach(function(content) {
|
|
976
|
+
try {
|
|
977
|
+
var fn = new Function(content);
|
|
978
|
+
fn();
|
|
979
|
+
} catch (e) {
|
|
980
|
+
console.error('[Zenith Router] Script error:', e);
|
|
981
|
+
}
|
|
982
|
+
});
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
/**
|
|
986
|
+
* Render page
|
|
987
|
+
*/
|
|
988
|
+
function renderPage(pageModule) {
|
|
989
|
+
if (!routerOutlet) {
|
|
990
|
+
console.warn('[Zenith Router] No router outlet');
|
|
991
|
+
return;
|
|
992
|
+
}
|
|
993
|
+
|
|
994
|
+
cleanupPreviousPage();
|
|
995
|
+
routerOutlet.innerHTML = pageModule.html;
|
|
996
|
+
injectStyles(pageModule.styles);
|
|
997
|
+
executeScripts(pageModule.scripts);
|
|
998
|
+
|
|
999
|
+
// Trigger mount lifecycle hooks after scripts are executed
|
|
1000
|
+
if (global.__zenith && global.__zenith.triggerMount) {
|
|
1001
|
+
global.__zenith.triggerMount();
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
|
|
1005
|
+
/**
|
|
1006
|
+
* Notify listeners
|
|
1007
|
+
*/
|
|
1008
|
+
function notifyListeners(route, prevRoute) {
|
|
1009
|
+
routeListeners.forEach(function(listener) {
|
|
1010
|
+
try { listener(route, prevRoute); } catch(e) {}
|
|
1011
|
+
});
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
/**
|
|
1015
|
+
* Resolve and render
|
|
1016
|
+
*/
|
|
1017
|
+
function resolveAndRender(path, query, updateHistory, replace) {
|
|
1018
|
+
replace = replace || false;
|
|
1019
|
+
var prevRoute = Object.assign({}, currentRoute);
|
|
1020
|
+
var resolved = resolveRoute(path);
|
|
1021
|
+
|
|
1022
|
+
if (resolved) {
|
|
1023
|
+
currentRoute = {
|
|
1024
|
+
path: path,
|
|
1025
|
+
params: resolved.params,
|
|
1026
|
+
query: query,
|
|
1027
|
+
matched: resolved.record
|
|
1028
|
+
};
|
|
1029
|
+
|
|
1030
|
+
var pageModule = pageModules[resolved.record.path];
|
|
1031
|
+
if (pageModule) {
|
|
1032
|
+
renderPage(pageModule);
|
|
1033
|
+
}
|
|
1034
|
+
} else {
|
|
1035
|
+
currentRoute = { path: path, params: {}, query: query, matched: undefined };
|
|
1036
|
+
console.warn('[Zenith Router] No route matched:', path);
|
|
1037
|
+
|
|
1038
|
+
// Render 404 if available
|
|
1039
|
+
if (routerOutlet) {
|
|
1040
|
+
routerOutlet.innerHTML = '<div style="padding: 2rem; text-align: center;"><h1>404</h1><p>Page not found</p></div>';
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
if (updateHistory) {
|
|
1045
|
+
var url = path + (Object.keys(query).length ? '?' + new URLSearchParams(query) : '');
|
|
1046
|
+
if (replace) {
|
|
1047
|
+
history.replaceState(null, '', url);
|
|
1048
|
+
} else {
|
|
1049
|
+
history.pushState(null, '', url);
|
|
1050
|
+
}
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
notifyListeners(currentRoute, prevRoute);
|
|
1054
|
+
global.__zenith_route = currentRoute;
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1057
|
+
/**
|
|
1058
|
+
* Handle popstate
|
|
1059
|
+
*/
|
|
1060
|
+
function handlePopState() {
|
|
1061
|
+
resolveAndRender(
|
|
1062
|
+
location.pathname,
|
|
1063
|
+
parseQueryString(location.search),
|
|
1064
|
+
false,
|
|
1065
|
+
false
|
|
1066
|
+
);
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
/**
|
|
1070
|
+
* Navigate (public API)
|
|
1071
|
+
*/
|
|
1072
|
+
function navigate(to, options) {
|
|
1073
|
+
options = options || {};
|
|
1074
|
+
var path, query = {};
|
|
1075
|
+
|
|
1076
|
+
if (to.includes('?')) {
|
|
1077
|
+
var parts = to.split('?');
|
|
1078
|
+
path = parts[0];
|
|
1079
|
+
query = parseQueryString('?' + parts[1]);
|
|
1080
|
+
} else {
|
|
1081
|
+
path = to;
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
if (!path.startsWith('/')) {
|
|
1085
|
+
var currentDir = currentRoute.path.split('/').slice(0, -1).join('/');
|
|
1086
|
+
path = currentDir + '/' + path;
|
|
1087
|
+
}
|
|
1088
|
+
|
|
1089
|
+
var normalizedPath = path === '' ? '/' : path;
|
|
1090
|
+
var currentPath = currentRoute.path === '' ? '/' : currentRoute.path;
|
|
1091
|
+
var isSamePath = normalizedPath === currentPath;
|
|
1092
|
+
|
|
1093
|
+
if (isSamePath && JSON.stringify(query) === JSON.stringify(currentRoute.query)) {
|
|
1094
|
+
return;
|
|
1095
|
+
}
|
|
1096
|
+
|
|
1097
|
+
// Dev mode: If no route manifest is loaded, use browser navigation
|
|
1098
|
+
// This allows ZenLink to work in dev server where pages are served fresh
|
|
1099
|
+
if (routeManifest.length === 0) {
|
|
1100
|
+
var url = normalizedPath + (Object.keys(query).length ? '?' + new URLSearchParams(query) : '');
|
|
1101
|
+
if (options.replace) {
|
|
1102
|
+
location.replace(url);
|
|
1103
|
+
} else {
|
|
1104
|
+
location.href = url;
|
|
1105
|
+
}
|
|
1106
|
+
return;
|
|
1107
|
+
}
|
|
1108
|
+
|
|
1109
|
+
resolveAndRender(path, query, true, options.replace || false);
|
|
1110
|
+
}
|
|
1111
|
+
|
|
1112
|
+
/**
|
|
1113
|
+
* Get current route
|
|
1114
|
+
*/
|
|
1115
|
+
function getRoute() {
|
|
1116
|
+
return Object.assign({}, currentRoute);
|
|
1117
|
+
}
|
|
1118
|
+
|
|
1119
|
+
/**
|
|
1120
|
+
* Subscribe to route changes
|
|
1121
|
+
*/
|
|
1122
|
+
function onRouteChange(listener) {
|
|
1123
|
+
routeListeners.add(listener);
|
|
1124
|
+
return function() { routeListeners.delete(listener); };
|
|
1125
|
+
}
|
|
1126
|
+
|
|
1127
|
+
/**
|
|
1128
|
+
* Check if path is active
|
|
1129
|
+
*/
|
|
1130
|
+
function isActive(path, exact) {
|
|
1131
|
+
if (exact) return currentRoute.path === path;
|
|
1132
|
+
return currentRoute.path.startsWith(path);
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1135
|
+
/**
|
|
1136
|
+
* Prefetch a route
|
|
1137
|
+
*/
|
|
1138
|
+
var prefetchedRoutes = new Set();
|
|
1139
|
+
function prefetch(path) {
|
|
1140
|
+
var normalizedPath = path === '' ? '/' : path;
|
|
1141
|
+
|
|
1142
|
+
if (prefetchedRoutes.has(normalizedPath)) {
|
|
1143
|
+
return Promise.resolve();
|
|
1144
|
+
}
|
|
1145
|
+
prefetchedRoutes.add(normalizedPath);
|
|
1146
|
+
|
|
1147
|
+
var resolved = resolveRoute(normalizedPath);
|
|
1148
|
+
if (!resolved) {
|
|
1149
|
+
return Promise.resolve();
|
|
1150
|
+
}
|
|
1151
|
+
|
|
1152
|
+
// In SPA build, all modules are already loaded
|
|
1153
|
+
return Promise.resolve();
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1156
|
+
/**
|
|
1157
|
+
* Initialize router
|
|
1158
|
+
*/
|
|
1159
|
+
function initRouter(manifest, modules, outlet) {
|
|
1160
|
+
routeManifest = manifest;
|
|
1161
|
+
Object.assign(pageModules, modules);
|
|
1162
|
+
|
|
1163
|
+
if (outlet) {
|
|
1164
|
+
routerOutlet = typeof outlet === 'string'
|
|
1165
|
+
? document.querySelector(outlet)
|
|
1166
|
+
: outlet;
|
|
1167
|
+
}
|
|
1168
|
+
|
|
1169
|
+
window.addEventListener('popstate', handlePopState);
|
|
1170
|
+
|
|
1171
|
+
// Initial route resolution
|
|
1172
|
+
resolveAndRender(
|
|
1173
|
+
location.pathname,
|
|
1174
|
+
parseQueryString(location.search),
|
|
1175
|
+
false
|
|
1176
|
+
);
|
|
1177
|
+
}
|
|
1178
|
+
|
|
1179
|
+
// Expose router API globally
|
|
1180
|
+
global.__zenith_router = {
|
|
1181
|
+
navigate: navigate,
|
|
1182
|
+
getRoute: getRoute,
|
|
1183
|
+
onRouteChange: onRouteChange,
|
|
1184
|
+
isActive: isActive,
|
|
1185
|
+
prefetch: prefetch,
|
|
1186
|
+
initRouter: initRouter
|
|
1187
|
+
};
|
|
1188
|
+
|
|
1189
|
+
// Also expose navigate directly for convenience
|
|
1190
|
+
global.navigate = navigate;
|
|
1191
|
+
|
|
1192
|
+
|
|
879
1193
|
// ============================================
|
|
880
1194
|
// HMR Client (Development Only)
|
|
881
1195
|
// ============================================
|