@aerobuilt/core 0.2.9 → 0.3.0
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/build-script-analysis-Bd9EyItC.mjs +193 -0
- package/dist/{entry-dev.d.ts → entry-dev.d.mts} +6 -16
- package/dist/entry-dev.mjs +127 -0
- package/dist/{entry-editor.d.ts → entry-editor.d.mts} +24 -22
- package/dist/entry-editor.mjs +3 -0
- package/dist/entry-prod.d.mts +10 -0
- package/dist/entry-prod.mjs +15 -0
- package/dist/routing-Bai79LCq.mjs +198 -0
- package/dist/runtime/index.d.mts +65 -0
- package/dist/runtime/index.mjs +207 -0
- package/dist/runtime/instance.d.mts +19 -0
- package/dist/runtime/instance.mjs +45 -0
- package/dist/types-CLHGhnGA.d.mts +209 -0
- package/dist/types.d.mts +2 -0
- package/dist/types.mjs +1 -0
- package/dist/utils/aliases.d.mts +38 -0
- package/dist/utils/aliases.mjs +117 -0
- package/dist/utils/{redirects.d.ts → redirects.d.mts} +7 -12
- package/dist/utils/redirects.mjs +21 -0
- package/dist/vite/{index.d.ts → index.d.mts} +5 -12
- package/dist/vite/index.mjs +1890 -0
- package/package.json +25 -20
- package/dist/chunk-4DAK56WB.js +0 -36
- package/dist/chunk-5ZNUGZOW.js +0 -238
- package/dist/chunk-F7MXQXLM.js +0 -15
- package/dist/chunk-JAMYN2VX.js +0 -133
- package/dist/chunk-VTEG2UU3.js +0 -184
- package/dist/entry-dev.js +0 -101
- package/dist/entry-editor.js +0 -14
- package/dist/entry-prod.d.ts +0 -19
- package/dist/entry-prod.js +0 -19
- package/dist/runtime/index.d.ts +0 -74
- package/dist/runtime/index.js +0 -7
- package/dist/runtime/instance.d.ts +0 -31
- package/dist/runtime/instance.js +0 -10
- package/dist/types.d.ts +0 -202
- package/dist/types.js +0 -0
- package/dist/utils/redirects.js +0 -6
- package/dist/vite/index.js +0 -1991
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aerobuilt/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Jamie Wilson",
|
|
@@ -11,43 +11,48 @@
|
|
|
11
11
|
},
|
|
12
12
|
"homepage": "https://github.com/aerobuilt/aero",
|
|
13
13
|
"private": false,
|
|
14
|
-
"types": "./dist/entry-dev.d.
|
|
14
|
+
"types": "./dist/entry-dev.d.mts",
|
|
15
15
|
"files": [
|
|
16
16
|
"dist"
|
|
17
17
|
],
|
|
18
18
|
"exports": {
|
|
19
19
|
".": {
|
|
20
|
-
"types": "./dist/entry-dev.d.
|
|
21
|
-
"default": "./dist/entry-dev.
|
|
20
|
+
"types": "./dist/entry-dev.d.mts",
|
|
21
|
+
"default": "./dist/entry-dev.mjs"
|
|
22
22
|
},
|
|
23
23
|
"./entry-prod": {
|
|
24
|
-
"types": "./dist/entry-prod.d.
|
|
25
|
-
"default": "./dist/entry-prod.
|
|
24
|
+
"types": "./dist/entry-prod.d.mts",
|
|
25
|
+
"default": "./dist/entry-prod.mjs"
|
|
26
26
|
},
|
|
27
27
|
"./vite": {
|
|
28
|
-
"types": "./dist/vite/index.d.
|
|
29
|
-
"default": "./dist/vite/index.
|
|
28
|
+
"types": "./dist/vite/index.d.mts",
|
|
29
|
+
"default": "./dist/vite/index.mjs"
|
|
30
30
|
},
|
|
31
31
|
"./runtime": {
|
|
32
|
-
"types": "./dist/runtime/index.d.
|
|
33
|
-
"default": "./dist/runtime/index.
|
|
32
|
+
"types": "./dist/runtime/index.d.mts",
|
|
33
|
+
"default": "./dist/runtime/index.mjs"
|
|
34
34
|
},
|
|
35
35
|
"./runtime/instance": {
|
|
36
|
-
"types": "./dist/runtime/instance.d.
|
|
37
|
-
"default": "./dist/runtime/instance.
|
|
36
|
+
"types": "./dist/runtime/instance.d.mts",
|
|
37
|
+
"default": "./dist/runtime/instance.mjs"
|
|
38
|
+
},
|
|
39
|
+
"./types": "./dist/types.d.mts",
|
|
40
|
+
"./utils/aliases": {
|
|
41
|
+
"types": "./dist/utils/aliases.d.mts",
|
|
42
|
+
"default": "./dist/utils/aliases.mjs"
|
|
38
43
|
},
|
|
39
|
-
"./types": "./dist/types.d.ts",
|
|
40
44
|
"./utils/redirects": {
|
|
41
|
-
"types": "./dist/utils/redirects.d.
|
|
42
|
-
"default": "./dist/utils/redirects.
|
|
45
|
+
"types": "./dist/utils/redirects.d.mts",
|
|
46
|
+
"default": "./dist/utils/redirects.mjs"
|
|
43
47
|
},
|
|
44
48
|
"./editor": {
|
|
45
|
-
"types": "./dist/entry-editor.d.
|
|
46
|
-
"default": "./dist/entry-editor.
|
|
49
|
+
"types": "./dist/entry-editor.d.mts",
|
|
50
|
+
"default": "./dist/entry-editor.mjs"
|
|
47
51
|
}
|
|
48
52
|
},
|
|
49
53
|
"dependencies": {
|
|
50
54
|
"get-tsconfig": "^4.13.6",
|
|
55
|
+
"oxc-resolver": "^11.19.0",
|
|
51
56
|
"html-minifier-next": "^5.1.1",
|
|
52
57
|
"linkedom": "^0.18.12",
|
|
53
58
|
"nitro": "^3.0.1-alpha.2",
|
|
@@ -55,7 +60,7 @@
|
|
|
55
60
|
"sharp": "^0.34.5",
|
|
56
61
|
"svgo": "^4.0.0",
|
|
57
62
|
"vite-plugin-image-optimizer": "^2.0.3",
|
|
58
|
-
"@aerobuilt/interpolation": "0.
|
|
63
|
+
"@aerobuilt/interpolation": "0.3.0"
|
|
59
64
|
},
|
|
60
65
|
"peerDependencies": {
|
|
61
66
|
"vite": "^8.0.0-0"
|
|
@@ -67,12 +72,12 @@
|
|
|
67
72
|
},
|
|
68
73
|
"devDependencies": {
|
|
69
74
|
"@types/node": "^25.3.0",
|
|
70
|
-
"
|
|
75
|
+
"tsdown": "^0.21.0-beta.2",
|
|
71
76
|
"typescript": "^5.9.3",
|
|
72
77
|
"vitest": "^4.0.18"
|
|
73
78
|
},
|
|
74
79
|
"scripts": {
|
|
75
|
-
"build": "
|
|
80
|
+
"build": "tsdown src/entry-dev.ts src/entry-prod.ts src/entry-editor.ts src/types.ts src/vite/index.ts src/utils/aliases.ts src/utils/redirects.ts src/runtime/index.ts src/runtime/instance.ts --format esm --dts --clean --out-dir dist --external @content/site",
|
|
76
81
|
"typecheck": "tsc --noEmit",
|
|
77
82
|
"test": "vitest run"
|
|
78
83
|
}
|
package/dist/chunk-4DAK56WB.js
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Aero
|
|
3
|
-
} from "./chunk-5ZNUGZOW.js";
|
|
4
|
-
|
|
5
|
-
// src/runtime/instance.ts
|
|
6
|
-
var instance = globalThis.__AERO_INSTANCE__ || new Aero();
|
|
7
|
-
var listeners = globalThis.__AERO_LISTENERS__ || /* @__PURE__ */ new Set();
|
|
8
|
-
var aero = instance;
|
|
9
|
-
var onUpdate = (cb) => {
|
|
10
|
-
listeners.add(cb);
|
|
11
|
-
return () => listeners.delete(cb);
|
|
12
|
-
};
|
|
13
|
-
var notify = () => {
|
|
14
|
-
listeners.forEach((cb) => cb());
|
|
15
|
-
};
|
|
16
|
-
if (!globalThis.__AERO_INSTANCE__) {
|
|
17
|
-
globalThis.__AERO_INSTANCE__ = instance;
|
|
18
|
-
}
|
|
19
|
-
if (!globalThis.__AERO_LISTENERS__) {
|
|
20
|
-
globalThis.__AERO_LISTENERS__ = listeners;
|
|
21
|
-
}
|
|
22
|
-
var components = import.meta.glob("@components/**/*.html", { eager: true });
|
|
23
|
-
var layouts = import.meta.glob("@layouts/*.html", { eager: true });
|
|
24
|
-
var pages = import.meta.glob("@pages/**/*.html", { eager: true });
|
|
25
|
-
aero.registerPages(components);
|
|
26
|
-
aero.registerPages(layouts);
|
|
27
|
-
aero.registerPages(pages);
|
|
28
|
-
notify();
|
|
29
|
-
if (import.meta.hot) {
|
|
30
|
-
import.meta.hot.accept();
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export {
|
|
34
|
-
aero,
|
|
35
|
-
onUpdate
|
|
36
|
-
};
|
package/dist/chunk-5ZNUGZOW.js
DELETED
|
@@ -1,238 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
pagePathToKey,
|
|
3
|
-
resolvePageTarget
|
|
4
|
-
} from "./chunk-JAMYN2VX.js";
|
|
5
|
-
|
|
6
|
-
// src/runtime/index.ts
|
|
7
|
-
var Aero = class {
|
|
8
|
-
/** Global values merged into template context (e.g. from content modules). */
|
|
9
|
-
globals = {};
|
|
10
|
-
/** Map from page name (or path) to module. Keys include both canonical name and full path for lookup. */
|
|
11
|
-
pagesMap = {};
|
|
12
|
-
/** Set by client entry when running in the browser; used to attach the app to a DOM root. */
|
|
13
|
-
mount;
|
|
14
|
-
/**
|
|
15
|
-
* Register a global value available in all templates as `name`.
|
|
16
|
-
*
|
|
17
|
-
* @param name - Key used in templates (e.g. `site`).
|
|
18
|
-
* @param value - Any value (object, string, etc.).
|
|
19
|
-
*/
|
|
20
|
-
global(name, value) {
|
|
21
|
-
this.globals[name] = value;
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* Register page/layout modules from a Vite glob (e.g. `import.meta.glob('@pages/**\/*.html')`).
|
|
25
|
-
* Derives a lookup key from each path via pagePathToKey; also stores by full path for resolution.
|
|
26
|
-
*
|
|
27
|
-
* @param pages - Record of resolved path → module (default export is the render function).
|
|
28
|
-
*/
|
|
29
|
-
registerPages(pages) {
|
|
30
|
-
for (const [path, mod] of Object.entries(pages)) {
|
|
31
|
-
const key = pagePathToKey(path);
|
|
32
|
-
this.pagesMap[key] = mod;
|
|
33
|
-
this.pagesMap[path] = mod;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
/** Type guard: true if value looks like an `AeroRenderInput` (has at least one of props, slots, request, url, params, routePath). */
|
|
37
|
-
isRenderInput(value) {
|
|
38
|
-
if (!value || typeof value !== "object") return false;
|
|
39
|
-
return ["props", "slots", "request", "url", "params", "routePath"].some(
|
|
40
|
-
(key) => key in value
|
|
41
|
-
);
|
|
42
|
-
}
|
|
43
|
-
/** Coerce various call signatures into a single `AeroRenderInput` (e.g. plain object → `{ props }`). */
|
|
44
|
-
normalizeRenderInput(input) {
|
|
45
|
-
if (!input) return {};
|
|
46
|
-
if (this.isRenderInput(input)) return input;
|
|
47
|
-
if (typeof input === "object") return { props: input };
|
|
48
|
-
return { props: {} };
|
|
49
|
-
}
|
|
50
|
-
/** Convert a page name to a route path (e.g. `index` → `'/'`, `about` → `'/about'`). */
|
|
51
|
-
toRoutePath(pageName = "index") {
|
|
52
|
-
if (!pageName || pageName === "index" || pageName === "home") return "/";
|
|
53
|
-
if (pageName.endsWith("/index")) {
|
|
54
|
-
return "/" + pageName.slice(0, -"/index".length);
|
|
55
|
-
}
|
|
56
|
-
return pageName.startsWith("/") ? pageName : "/" + pageName;
|
|
57
|
-
}
|
|
58
|
-
/** Build a URL from route path and optional raw URL. Uses `http://localhost` as base when only a path is given. */
|
|
59
|
-
toURL(routePath, rawUrl) {
|
|
60
|
-
if (rawUrl instanceof URL) return rawUrl;
|
|
61
|
-
if (typeof rawUrl === "string" && rawUrl.length > 0) {
|
|
62
|
-
return new URL(rawUrl, "http://localhost");
|
|
63
|
-
}
|
|
64
|
-
return new URL(routePath, "http://localhost");
|
|
65
|
-
}
|
|
66
|
-
/** Build template context: globals, props, slots, request, url, params, site, and `renderComponent` / `nextPassDataId`. */
|
|
67
|
-
createContext(input) {
|
|
68
|
-
const routePath = input.routePath || "/";
|
|
69
|
-
const url = this.toURL(routePath, input.url);
|
|
70
|
-
const request = input.request || new Request(url.toString(), { method: "GET" });
|
|
71
|
-
let _passDataId = 0;
|
|
72
|
-
const context = {
|
|
73
|
-
...this.globals,
|
|
74
|
-
props: input.props || {},
|
|
75
|
-
slots: input.slots || {},
|
|
76
|
-
request,
|
|
77
|
-
url,
|
|
78
|
-
params: input.params || {},
|
|
79
|
-
site: input.site ?? "",
|
|
80
|
-
styles: input.styles,
|
|
81
|
-
scripts: input.scripts,
|
|
82
|
-
headScripts: input.headScripts,
|
|
83
|
-
nextPassDataId: () => `__aero_${_passDataId++}`,
|
|
84
|
-
renderComponent: this.renderComponent.bind(this)
|
|
85
|
-
};
|
|
86
|
-
return context;
|
|
87
|
-
}
|
|
88
|
-
/** True if entry params and request params have the same keys and stringified values. */
|
|
89
|
-
paramsMatch(entryParams, requestParams) {
|
|
90
|
-
const entryKeys = Object.keys(entryParams);
|
|
91
|
-
if (entryKeys.length !== Object.keys(requestParams).length) return false;
|
|
92
|
-
for (const key of entryKeys) {
|
|
93
|
-
if (String(entryParams[key]) !== String(requestParams[key])) return false;
|
|
94
|
-
}
|
|
95
|
-
return true;
|
|
96
|
-
}
|
|
97
|
-
/**
|
|
98
|
-
* Render a page or layout to HTML.
|
|
99
|
-
*
|
|
100
|
-
* @remarks
|
|
101
|
-
* Resolves `component` (page name string or module) via `pagesMap`, with fallbacks: directory index
|
|
102
|
-
* (`foo` → `foo/index`), `index` → `home`, dynamic routes, and trailing-slash stripping. If the module
|
|
103
|
-
* exports `getStaticPaths` and no props are provided, finds the matching static path and uses its props.
|
|
104
|
-
* For root-level renders, injects accumulated styles and scripts into the document and fixes content
|
|
105
|
-
* that ends up after `</html>` when using layouts (moves it into `</body>`).
|
|
106
|
-
*
|
|
107
|
-
* @param component - Page name (e.g. `'index'`, `'about'`) or the module object.
|
|
108
|
-
* @param input - Render input (props, request, url, params, etc.). Can be a plain object (treated as props).
|
|
109
|
-
* @returns HTML string, or `null` if the page is not found or no static path match.
|
|
110
|
-
*/
|
|
111
|
-
async render(component, input = {}) {
|
|
112
|
-
const renderInput = this.normalizeRenderInput(input);
|
|
113
|
-
const isRootRender = !renderInput.styles;
|
|
114
|
-
if (isRootRender) {
|
|
115
|
-
renderInput.styles = /* @__PURE__ */ new Set();
|
|
116
|
-
renderInput.scripts = /* @__PURE__ */ new Set();
|
|
117
|
-
renderInput.headScripts = /* @__PURE__ */ new Set();
|
|
118
|
-
}
|
|
119
|
-
const resolved = resolvePageTarget(component, this.pagesMap);
|
|
120
|
-
if (!resolved) return null;
|
|
121
|
-
let target = resolved.module;
|
|
122
|
-
const matchedPageName = resolved.pageName;
|
|
123
|
-
const dynamicParams = resolved.params;
|
|
124
|
-
if (typeof target === "function" && target.length === 0) {
|
|
125
|
-
target = await target();
|
|
126
|
-
}
|
|
127
|
-
if (typeof target.getStaticPaths === "function" && Object.keys(renderInput.props || {}).length === 0) {
|
|
128
|
-
const staticPaths = await target.getStaticPaths();
|
|
129
|
-
const combinedParams = { ...dynamicParams, ...renderInput.params || {} };
|
|
130
|
-
const match = staticPaths.find((entry) => this.paramsMatch(entry.params, combinedParams));
|
|
131
|
-
if (!match) {
|
|
132
|
-
console.warn(
|
|
133
|
-
`[aero] 404: Route params ${JSON.stringify(combinedParams)} not found in getStaticPaths for ${matchedPageName}`
|
|
134
|
-
);
|
|
135
|
-
return null;
|
|
136
|
-
}
|
|
137
|
-
if (match.props) {
|
|
138
|
-
renderInput.props = match.props;
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
const routePath = renderInput.routePath || this.toRoutePath(matchedPageName);
|
|
142
|
-
const context = this.createContext({
|
|
143
|
-
props: renderInput.props || {},
|
|
144
|
-
slots: renderInput.slots || {},
|
|
145
|
-
request: renderInput.request,
|
|
146
|
-
url: renderInput.url,
|
|
147
|
-
params: { ...dynamicParams, ...renderInput.params || {} },
|
|
148
|
-
routePath,
|
|
149
|
-
site: renderInput.site,
|
|
150
|
-
styles: renderInput.styles,
|
|
151
|
-
scripts: renderInput.scripts,
|
|
152
|
-
headScripts: renderInput.headScripts
|
|
153
|
-
});
|
|
154
|
-
let renderFn = target;
|
|
155
|
-
if (target.default) renderFn = target.default;
|
|
156
|
-
if (typeof renderFn === "function") {
|
|
157
|
-
let html = await renderFn(context);
|
|
158
|
-
if (isRootRender) {
|
|
159
|
-
if (html.includes("</html>")) {
|
|
160
|
-
const afterHtml = html.split("</html>")[1]?.trim();
|
|
161
|
-
if (afterHtml && html.includes("</body>")) {
|
|
162
|
-
html = html.split("</html>")[0] + "</html>";
|
|
163
|
-
html = html.replace("</body>", `
|
|
164
|
-
${afterHtml}
|
|
165
|
-
</body>`);
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
let headInjections = "";
|
|
169
|
-
if (context.styles && context.styles.size > 0) {
|
|
170
|
-
headInjections += Array.from(context.styles).join("\n") + "\n";
|
|
171
|
-
}
|
|
172
|
-
if (context.headScripts && context.headScripts.size > 0) {
|
|
173
|
-
headInjections += Array.from(context.headScripts).join("\n") + "\n";
|
|
174
|
-
}
|
|
175
|
-
if (headInjections) {
|
|
176
|
-
if (html.includes("</head>")) {
|
|
177
|
-
html = html.replace("</head>", `
|
|
178
|
-
${headInjections}</head>`);
|
|
179
|
-
} else if (html.includes("<body")) {
|
|
180
|
-
html = html.replace(/(<body[^>]*>)/i, `<head>
|
|
181
|
-
${headInjections}</head>
|
|
182
|
-
$1`);
|
|
183
|
-
} else {
|
|
184
|
-
html = `${headInjections}${html}`;
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
if (context.scripts && context.scripts.size > 0) {
|
|
188
|
-
const scriptsHtml = Array.from(context.scripts).join("\n");
|
|
189
|
-
if (html.includes("</body>")) {
|
|
190
|
-
html = html.replace("</body>", `
|
|
191
|
-
${scriptsHtml}
|
|
192
|
-
</body>`);
|
|
193
|
-
} else {
|
|
194
|
-
html = `${html}
|
|
195
|
-
${scriptsHtml}`;
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
return html;
|
|
200
|
-
}
|
|
201
|
-
return "";
|
|
202
|
-
}
|
|
203
|
-
/**
|
|
204
|
-
* Render a child component (layout or component) with the given props and slots.
|
|
205
|
-
* Used by compiled templates via context.renderComponent.
|
|
206
|
-
*
|
|
207
|
-
* @param component - Render function or module with `default` render function.
|
|
208
|
-
* @param props - Props object for the component.
|
|
209
|
-
* @param slots - Named slot content (key → HTML string).
|
|
210
|
-
* @param input - Optional request/url/params for context; `headScripts` is not passed through.
|
|
211
|
-
* @returns HTML string from the component's render function, or empty string if not invokable.
|
|
212
|
-
*/
|
|
213
|
-
async renderComponent(component, props = {}, slots = {}, input = {}) {
|
|
214
|
-
const context = this.createContext({
|
|
215
|
-
props,
|
|
216
|
-
slots,
|
|
217
|
-
request: input.request,
|
|
218
|
-
url: input.url,
|
|
219
|
-
params: input.params,
|
|
220
|
-
routePath: input.routePath || "/",
|
|
221
|
-
site: input.site,
|
|
222
|
-
styles: input.styles,
|
|
223
|
-
scripts: input.scripts,
|
|
224
|
-
headScripts: input.headScripts
|
|
225
|
-
});
|
|
226
|
-
if (typeof component === "function") {
|
|
227
|
-
return await component(context);
|
|
228
|
-
}
|
|
229
|
-
if (component && typeof component.default === "function") {
|
|
230
|
-
return await component.default(context);
|
|
231
|
-
}
|
|
232
|
-
return "";
|
|
233
|
-
}
|
|
234
|
-
};
|
|
235
|
-
|
|
236
|
-
export {
|
|
237
|
-
Aero
|
|
238
|
-
};
|
package/dist/chunk-F7MXQXLM.js
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
// src/utils/redirects.ts
|
|
2
|
-
function redirectsToRouteRules(redirects) {
|
|
3
|
-
const out = {};
|
|
4
|
-
for (const rule of redirects) {
|
|
5
|
-
const status = rule.status ?? 302;
|
|
6
|
-
out[rule.from] = {
|
|
7
|
-
redirect: status === 307 ? rule.to : { to: rule.to, statusCode: status }
|
|
8
|
-
};
|
|
9
|
-
}
|
|
10
|
-
return out;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export {
|
|
14
|
-
redirectsToRouteRules
|
|
15
|
-
};
|
package/dist/chunk-JAMYN2VX.js
DELETED
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
// src/utils/path.ts
|
|
2
|
-
function toPosix(value) {
|
|
3
|
-
return value.replace(/\\/g, "/");
|
|
4
|
-
}
|
|
5
|
-
function toPosixRelative(value, root) {
|
|
6
|
-
const valuePosix = toPosix(value);
|
|
7
|
-
const rootPosix = toPosix(root);
|
|
8
|
-
if (valuePosix.startsWith(rootPosix + "/")) {
|
|
9
|
-
return valuePosix.slice(rootPosix.length + 1);
|
|
10
|
-
}
|
|
11
|
-
return valuePosix;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
// src/utils/route-pattern.ts
|
|
15
|
-
var PARAM_SEGMENT_REGEX = /^\[([^.\]\[]+)\]$/;
|
|
16
|
-
function parseRoutePattern(pattern) {
|
|
17
|
-
const rawSegments = pattern.split("/").filter(Boolean);
|
|
18
|
-
const segments = rawSegments.map((seg) => {
|
|
19
|
-
const paramMatch = seg.match(PARAM_SEGMENT_REGEX);
|
|
20
|
-
if (paramMatch) {
|
|
21
|
-
return { type: "param", name: paramMatch[1] };
|
|
22
|
-
}
|
|
23
|
-
return { type: "static", value: seg };
|
|
24
|
-
});
|
|
25
|
-
return { segments };
|
|
26
|
-
}
|
|
27
|
-
function isDynamicRoutePattern(pattern) {
|
|
28
|
-
const { segments } = parseRoutePattern(pattern);
|
|
29
|
-
return segments.some((s) => s.type === "param");
|
|
30
|
-
}
|
|
31
|
-
function matchRoutePattern(pattern, pageName) {
|
|
32
|
-
const { segments } = parseRoutePattern(pattern);
|
|
33
|
-
const requestedSegments = pageName.split("/").filter(Boolean);
|
|
34
|
-
if (segments.length !== requestedSegments.length) return null;
|
|
35
|
-
const params = {};
|
|
36
|
-
for (let i = 0; i < segments.length; i++) {
|
|
37
|
-
const seg = segments[i];
|
|
38
|
-
const requestSeg = requestedSegments[i];
|
|
39
|
-
if (seg.type === "param") {
|
|
40
|
-
params[seg.name] = decodeURIComponent(requestSeg);
|
|
41
|
-
} else if (seg.value !== requestSeg) {
|
|
42
|
-
return null;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
return params;
|
|
46
|
-
}
|
|
47
|
-
function expandRoutePattern(pattern, params) {
|
|
48
|
-
const { segments } = parseRoutePattern(pattern);
|
|
49
|
-
const parts = [];
|
|
50
|
-
for (const seg of segments) {
|
|
51
|
-
if (seg.type === "param") {
|
|
52
|
-
if (!(seg.name in params)) {
|
|
53
|
-
throw new Error(
|
|
54
|
-
`[aero] getStaticPaths: missing param "${seg.name}" for pattern "${pattern}". Provided params: ${JSON.stringify(params)}`
|
|
55
|
-
);
|
|
56
|
-
}
|
|
57
|
-
parts.push(params[seg.name]);
|
|
58
|
-
} else {
|
|
59
|
-
parts.push(seg.value);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
return parts.join("/");
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// src/utils/routing.ts
|
|
66
|
-
function pagePathToKey(path) {
|
|
67
|
-
const withoutExt = toPosix(path).replace(/\.html$/i, "");
|
|
68
|
-
if (withoutExt.includes("pages/")) {
|
|
69
|
-
return withoutExt.split("pages/").pop();
|
|
70
|
-
}
|
|
71
|
-
const segments = withoutExt.split("/").filter(Boolean);
|
|
72
|
-
if (segments.length > 1) {
|
|
73
|
-
return segments.join("/");
|
|
74
|
-
}
|
|
75
|
-
return segments.pop() || path;
|
|
76
|
-
}
|
|
77
|
-
function resolvePageName(url) {
|
|
78
|
-
const [pathPart] = url.split("?");
|
|
79
|
-
let clean = pathPart || "/";
|
|
80
|
-
if (clean === "/" || clean === "") return "index";
|
|
81
|
-
if (clean.endsWith("/")) {
|
|
82
|
-
clean = clean + "index";
|
|
83
|
-
}
|
|
84
|
-
clean = clean.replace(/^\//, "");
|
|
85
|
-
clean = clean.replace(/\.html$/, "");
|
|
86
|
-
return clean || "index";
|
|
87
|
-
}
|
|
88
|
-
function resolveDynamicPage(pageName, pagesMap) {
|
|
89
|
-
for (const [key, mod] of Object.entries(pagesMap)) {
|
|
90
|
-
if (!key.includes("[") || !key.includes("]") || key.includes(".")) continue;
|
|
91
|
-
const params = matchRoutePattern(key, pageName);
|
|
92
|
-
if (params != null) {
|
|
93
|
-
return { module: mod, pageName: key, params };
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
return null;
|
|
97
|
-
}
|
|
98
|
-
function resolvePageTarget(component, pagesMap) {
|
|
99
|
-
if (typeof component !== "string") {
|
|
100
|
-
return component != null ? { module: component, pageName: "index", params: {} } : null;
|
|
101
|
-
}
|
|
102
|
-
const pageName = component;
|
|
103
|
-
let target = pagesMap[pageName];
|
|
104
|
-
if (!target) {
|
|
105
|
-
target = pagesMap[`${pageName}/index`];
|
|
106
|
-
}
|
|
107
|
-
if (!target && pageName === "index") {
|
|
108
|
-
target = pagesMap["home"];
|
|
109
|
-
}
|
|
110
|
-
if (!target) {
|
|
111
|
-
const dynamicMatch = resolveDynamicPage(pageName, pagesMap) ?? resolveDynamicPage(`${pageName}/index`, pagesMap);
|
|
112
|
-
if (dynamicMatch) return dynamicMatch;
|
|
113
|
-
}
|
|
114
|
-
if (!target && pageName.endsWith("/index")) {
|
|
115
|
-
const stripped = pageName.slice(0, -"/index".length);
|
|
116
|
-
target = pagesMap[stripped];
|
|
117
|
-
if (target) return { module: target, pageName: stripped, params: {} };
|
|
118
|
-
const dynamicMatch = resolveDynamicPage(stripped, pagesMap);
|
|
119
|
-
if (dynamicMatch) return dynamicMatch;
|
|
120
|
-
}
|
|
121
|
-
if (!target) return null;
|
|
122
|
-
return { module: target, pageName, params: {} };
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
export {
|
|
126
|
-
toPosix,
|
|
127
|
-
toPosixRelative,
|
|
128
|
-
isDynamicRoutePattern,
|
|
129
|
-
expandRoutePattern,
|
|
130
|
-
pagePathToKey,
|
|
131
|
-
resolvePageName,
|
|
132
|
-
resolvePageTarget
|
|
133
|
-
};
|