@aerobuilt/core 0.3.1 → 0.3.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.
|
@@ -26,6 +26,67 @@ function isDirectiveAttr(attrName, config = defaultConfig) {
|
|
|
26
26
|
return prefixes.some((p) => attrName.startsWith(p));
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
//#endregion
|
|
30
|
+
//#region src/compiler/constants.ts
|
|
31
|
+
/**
|
|
32
|
+
* Shared constants for the Aero compiler (parser, codegen, helpers).
|
|
33
|
+
*
|
|
34
|
+
* @remarks
|
|
35
|
+
* Attribute names are used with optional `data-` prefix (e.g. `data-each`). Script taxonomy uses
|
|
36
|
+
* `is:build`, `is:inline`, `is:blocking`; default scripts are treated as client (virtual module).
|
|
37
|
+
* When changing script taxonomy (is:build, is:inline, etc.), update all consumers per
|
|
38
|
+
* _reference/script-taxonomy-sync.md.
|
|
39
|
+
*/
|
|
40
|
+
/** Prefix for data attributes (e.g. `data-each` → ATTR_PREFIX + ATTR_EACH). */
|
|
41
|
+
const ATTR_PREFIX = "data-";
|
|
42
|
+
/** Attribute for spreading props onto a component: `data-props` or `data-props="{ ... }"`. */
|
|
43
|
+
const ATTR_PROPS = "props";
|
|
44
|
+
/** Attribute for iteration: `data-each="{ item in items }"`. */
|
|
45
|
+
const ATTR_EACH = "each";
|
|
46
|
+
const ATTR_IF = "if";
|
|
47
|
+
const ATTR_ELSE_IF = "else-if";
|
|
48
|
+
const ATTR_ELSE = "else";
|
|
49
|
+
/** Slot name (on `<slot>` or content). */
|
|
50
|
+
const ATTR_NAME = "name";
|
|
51
|
+
const ATTR_SLOT = "slot";
|
|
52
|
+
/** Script runs at build time; extracted and becomes render function body. */
|
|
53
|
+
const ATTR_IS_BUILD = "is:build";
|
|
54
|
+
/** Script left in template in place; not extracted. */
|
|
55
|
+
const ATTR_IS_INLINE = "is:inline";
|
|
56
|
+
/** Script hoisted to head; extracted. */
|
|
57
|
+
const ATTR_IS_BLOCKING = "is:blocking";
|
|
58
|
+
/** Script/style receives data from template: `pass:data="{ config }"` or `pass:data="{ ...theme }"`. */
|
|
59
|
+
const ATTR_PASS_DATA = "pass:data";
|
|
60
|
+
/** Script external source (HTML attribute). */
|
|
61
|
+
const ATTR_SRC = "src";
|
|
62
|
+
const TAG_SLOT = "slot";
|
|
63
|
+
/** Default slot name when no name is given. */
|
|
64
|
+
const SLOT_NAME_DEFAULT = "default";
|
|
65
|
+
/** Matches `item in items` for data-each (captures: loop variable, iterable expression). */
|
|
66
|
+
const EACH_REGEX = /^(\w+)\s+in\s+(.+)$/;
|
|
67
|
+
/** Matches tag names ending with `-component` or `-layout`. */
|
|
68
|
+
const COMPONENT_SUFFIX_REGEX = /-(component|layout)$/;
|
|
69
|
+
/** Self-closing tag: `<tag ... />`. */
|
|
70
|
+
const SELF_CLOSING_TAG_REGEX = /<([a-z0-9-]+)([^>]*?)\/>/gi;
|
|
71
|
+
const SELF_CLOSING_TAIL_REGEX = /\/>$/;
|
|
72
|
+
/** HTML void elements that have no closing tag. */
|
|
73
|
+
const VOID_TAGS = new Set([
|
|
74
|
+
"area",
|
|
75
|
+
"base",
|
|
76
|
+
"br",
|
|
77
|
+
"col",
|
|
78
|
+
"embed",
|
|
79
|
+
"hr",
|
|
80
|
+
"img",
|
|
81
|
+
"input",
|
|
82
|
+
"link",
|
|
83
|
+
"meta",
|
|
84
|
+
"param",
|
|
85
|
+
"source",
|
|
86
|
+
"track",
|
|
87
|
+
"wbr"
|
|
88
|
+
]);
|
|
89
|
+
|
|
29
90
|
//#endregion
|
|
30
91
|
//#region src/compiler/build-script-analysis.ts
|
|
31
92
|
/**
|
|
@@ -128,6 +189,92 @@ function analyzeBuildScript(script) {
|
|
|
128
189
|
};
|
|
129
190
|
}
|
|
130
191
|
/**
|
|
192
|
+
* Extract the props type name from a build script that uses `Aero.props as TypeName`
|
|
193
|
+
* or `const { ... } = Aero.props as TypeName`.
|
|
194
|
+
*
|
|
195
|
+
* @param script - Raw build script content (JS or TS).
|
|
196
|
+
* @returns The type name and whether it was from destructuring, or null if not found.
|
|
197
|
+
*/
|
|
198
|
+
function getPropsTypeFromBuildScript(script) {
|
|
199
|
+
if (!script.trim()) return null;
|
|
200
|
+
const result = parseSync(BUILD_SCRIPT_FILENAME, script, {
|
|
201
|
+
sourceType: "module",
|
|
202
|
+
range: true,
|
|
203
|
+
lang: "ts"
|
|
204
|
+
});
|
|
205
|
+
if (result.errors.length > 0) return null;
|
|
206
|
+
const body = result.program.body;
|
|
207
|
+
if (!body) return null;
|
|
208
|
+
for (const stmt of body) {
|
|
209
|
+
const found = findPropsTypeInNode(stmt);
|
|
210
|
+
if (found) return found;
|
|
211
|
+
}
|
|
212
|
+
return null;
|
|
213
|
+
}
|
|
214
|
+
function findPropsTypeInNode(node) {
|
|
215
|
+
if (!node || typeof node !== "object") return null;
|
|
216
|
+
const n = node;
|
|
217
|
+
if (n.type === "TSAsExpression") {
|
|
218
|
+
const expr = n.expression;
|
|
219
|
+
const typeAnnotation = n.typeAnnotation;
|
|
220
|
+
if (isAeroProps(expr)) {
|
|
221
|
+
const typeName = getTypeNameFromAnnotation(typeAnnotation);
|
|
222
|
+
if (typeName) return {
|
|
223
|
+
typeName,
|
|
224
|
+
isFromDestructuring: false
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
return null;
|
|
228
|
+
}
|
|
229
|
+
if (n.type === "VariableDeclaration") {
|
|
230
|
+
const declarations = n.declarations;
|
|
231
|
+
for (const decl of declarations ?? []) {
|
|
232
|
+
const d = decl;
|
|
233
|
+
const init = d.init;
|
|
234
|
+
const id = d.id;
|
|
235
|
+
const isDestructuring = id && typeof id === "object" && id.type === "ObjectPattern";
|
|
236
|
+
const found = findPropsTypeInNode(init);
|
|
237
|
+
if (found) return {
|
|
238
|
+
...found,
|
|
239
|
+
isFromDestructuring: !!isDestructuring
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
return null;
|
|
243
|
+
}
|
|
244
|
+
for (const key of [
|
|
245
|
+
"init",
|
|
246
|
+
"expression",
|
|
247
|
+
"argument",
|
|
248
|
+
"body",
|
|
249
|
+
"consequent",
|
|
250
|
+
"alternate"
|
|
251
|
+
]) {
|
|
252
|
+
const child = n[key];
|
|
253
|
+
if (Array.isArray(child)) for (const c of child) {
|
|
254
|
+
const found = findPropsTypeInNode(c);
|
|
255
|
+
if (found) return found;
|
|
256
|
+
}
|
|
257
|
+
else if (child) {
|
|
258
|
+
const found = findPropsTypeInNode(child);
|
|
259
|
+
if (found) return found;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
return null;
|
|
263
|
+
}
|
|
264
|
+
function isAeroProps(expr) {
|
|
265
|
+
if (expr?.type !== "MemberExpression") return false;
|
|
266
|
+
const obj = expr.object;
|
|
267
|
+
const prop = expr.property;
|
|
268
|
+
const objName = obj?.type === "Identifier" ? obj.name : obj?.name;
|
|
269
|
+
const propName = prop?.type === "Identifier" ? prop.name : prop?.name;
|
|
270
|
+
return objName === "Aero" && propName === "props";
|
|
271
|
+
}
|
|
272
|
+
function getTypeNameFromAnnotation(annotation) {
|
|
273
|
+
if (!annotation) return null;
|
|
274
|
+
if (annotation.type === "TSTypeReference") return annotation.typeName?.name;
|
|
275
|
+
return null;
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
131
278
|
* Analyze build script for editor use: same as analyzeBuildScript but returns imports with
|
|
132
279
|
* source ranges (full statement and per-binding) so the extension can map to vscode.Range.
|
|
133
280
|
*
|
|
@@ -190,4 +337,4 @@ function analyzeBuildScriptForEditor(script) {
|
|
|
190
337
|
}
|
|
191
338
|
|
|
192
339
|
//#endregion
|
|
193
|
-
export { compileInterpolationFromSegments as
|
|
340
|
+
export { VOID_TAGS as C, tokenizeCurlyInterpolation as D, compileInterpolationFromSegments as E, TAG_SLOT as S, isDirectiveAttr as T, COMPONENT_SUFFIX_REGEX as _, ATTR_ELSE as a, SELF_CLOSING_TAIL_REGEX as b, ATTR_IS_BLOCKING as c, ATTR_NAME as d, ATTR_PASS_DATA as f, ATTR_SRC as g, ATTR_SLOT as h, ATTR_EACH as i, ATTR_IS_BUILD as l, ATTR_PROPS as m, analyzeBuildScriptForEditor as n, ATTR_ELSE_IF as o, ATTR_PREFIX as p, getPropsTypeFromBuildScript as r, ATTR_IF as s, analyzeBuildScript as t, ATTR_IS_INLINE as u, EACH_REGEX as v, DEFAULT_DIRECTIVE_PREFIXES as w, SLOT_NAME_DEFAULT as x, SELF_CLOSING_TAG_REGEX as y };
|
package/dist/entry-editor.d.mts
CHANGED
|
@@ -3,8 +3,7 @@ import { InterpolationSegment, LiteralSegment, Segment, TokenizeOptions, compile
|
|
|
3
3
|
//#region src/compiler/directive-attributes.d.ts
|
|
4
4
|
/**
|
|
5
5
|
* Classifier for directive attributes (Alpine.js, HTMX, Vue, etc.) that should
|
|
6
|
-
* skip { } interpolation in the compiler.
|
|
7
|
-
* declarative list for clearer semantics and easier extension.
|
|
6
|
+
* skip { } interpolation in the compiler.
|
|
8
7
|
*
|
|
9
8
|
* @packageDocumentation
|
|
10
9
|
*/
|
|
@@ -30,6 +29,10 @@ declare const DEFAULT_DIRECTIVE_PREFIXES: string[];
|
|
|
30
29
|
*/
|
|
31
30
|
declare function isDirectiveAttr(attrName: string, config?: DirectiveAttrConfig): boolean;
|
|
32
31
|
//#endregion
|
|
32
|
+
//#region src/compiler/constants.d.ts
|
|
33
|
+
/** Matches tag names ending with `-component` or `-layout`. */
|
|
34
|
+
declare const COMPONENT_SUFFIX_REGEX: RegExp;
|
|
35
|
+
//#endregion
|
|
33
36
|
//#region src/compiler/build-script-analysis.d.ts
|
|
34
37
|
/**
|
|
35
38
|
* AST-based analysis of Aero build scripts: extract imports and getStaticPaths export.
|
|
@@ -62,6 +65,19 @@ interface BuildScriptImportForEditor extends BuildScriptImport {
|
|
|
62
65
|
interface BuildScriptAnalysisForEditorResult {
|
|
63
66
|
imports: BuildScriptImportForEditor[];
|
|
64
67
|
}
|
|
68
|
+
/** Result of getPropsTypeFromBuildScript: the type name used in `Aero.props as TypeName`. */
|
|
69
|
+
interface PropsTypeResult {
|
|
70
|
+
typeName: string;
|
|
71
|
+
isFromDestructuring: boolean;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Extract the props type name from a build script that uses `Aero.props as TypeName`
|
|
75
|
+
* or `const { ... } = Aero.props as TypeName`.
|
|
76
|
+
*
|
|
77
|
+
* @param script - Raw build script content (JS or TS).
|
|
78
|
+
* @returns The type name and whether it was from destructuring, or null if not found.
|
|
79
|
+
*/
|
|
80
|
+
declare function getPropsTypeFromBuildScript(script: string): PropsTypeResult | null;
|
|
65
81
|
/**
|
|
66
82
|
* Analyze build script for editor use: same as analyzeBuildScript but returns imports with
|
|
67
83
|
* source ranges (full statement and per-binding) so the extension can map to vscode.Range.
|
|
@@ -71,4 +87,4 @@ interface BuildScriptAnalysisForEditorResult {
|
|
|
71
87
|
*/
|
|
72
88
|
declare function analyzeBuildScriptForEditor(script: string): BuildScriptAnalysisForEditorResult;
|
|
73
89
|
//#endregion
|
|
74
|
-
export { type BuildScriptAnalysisForEditorResult, type BuildScriptImportForEditor, DEFAULT_DIRECTIVE_PREFIXES, type DirectiveAttrConfig, type InterpolationSegment, type LiteralSegment, type Segment, type TokenizeOptions, analyzeBuildScriptForEditor, compileInterpolationFromSegments, isDirectiveAttr, tokenizeCurlyInterpolation };
|
|
90
|
+
export { type BuildScriptAnalysisForEditorResult, type BuildScriptImportForEditor, COMPONENT_SUFFIX_REGEX, DEFAULT_DIRECTIVE_PREFIXES, type DirectiveAttrConfig, type InterpolationSegment, type LiteralSegment, type PropsTypeResult, type Segment, type TokenizeOptions, analyzeBuildScriptForEditor, compileInterpolationFromSegments, getPropsTypeFromBuildScript, isDirectiveAttr, tokenizeCurlyInterpolation };
|
package/dist/entry-editor.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { D as tokenizeCurlyInterpolation, E as compileInterpolationFromSegments, T as isDirectiveAttr, _ as COMPONENT_SUFFIX_REGEX, n as analyzeBuildScriptForEditor, r as getPropsTypeFromBuildScript, w as DEFAULT_DIRECTIVE_PREFIXES } from "./build-script-analysis-1t1wROdQ.mjs";
|
|
2
2
|
|
|
3
|
-
export { DEFAULT_DIRECTIVE_PREFIXES, analyzeBuildScriptForEditor, compileInterpolationFromSegments, isDirectiveAttr, tokenizeCurlyInterpolation };
|
|
3
|
+
export { COMPONENT_SUFFIX_REGEX, DEFAULT_DIRECTIVE_PREFIXES, analyzeBuildScriptForEditor, compileInterpolationFromSegments, getPropsTypeFromBuildScript, isDirectiveAttr, tokenizeCurlyInterpolation };
|
package/dist/vite/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { a as isDynamicRoutePattern, i as expandRoutePattern, n as resolvePageName, o as toPosix, s as toPosixRelative, t as pagePathToKey } from "../routing-Bai79LCq.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { C as VOID_TAGS, D as tokenizeCurlyInterpolation, E as compileInterpolationFromSegments, S as TAG_SLOT, T as isDirectiveAttr, _ as COMPONENT_SUFFIX_REGEX, a as ATTR_ELSE, b as SELF_CLOSING_TAIL_REGEX, c as ATTR_IS_BLOCKING, d as ATTR_NAME, f as ATTR_PASS_DATA, g as ATTR_SRC, h as ATTR_SLOT, i as ATTR_EACH, l as ATTR_IS_BUILD, m as ATTR_PROPS, o as ATTR_ELSE_IF, p as ATTR_PREFIX, s as ATTR_IF, t as analyzeBuildScript, u as ATTR_IS_INLINE, v as EACH_REGEX, x as SLOT_NAME_DEFAULT, y as SELF_CLOSING_TAG_REGEX } from "../build-script-analysis-1t1wROdQ.mjs";
|
|
3
3
|
import { loadTsconfigAliases, mergeWithDefaultAliases } from "../utils/aliases.mjs";
|
|
4
4
|
import { redirectsToRouteRules } from "../utils/redirects.mjs";
|
|
5
5
|
import { createRequire } from "node:module";
|
|
@@ -7,6 +7,7 @@ import { ViteImageOptimizer } from "vite-plugin-image-optimizer";
|
|
|
7
7
|
import { nitro } from "nitro/vite";
|
|
8
8
|
import { parseHTML } from "linkedom";
|
|
9
9
|
import path from "path";
|
|
10
|
+
import { transformSync } from "oxc-transform";
|
|
10
11
|
import path$1 from "node:path";
|
|
11
12
|
import { minify } from "html-minifier-next";
|
|
12
13
|
import fs, { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
@@ -64,17 +65,18 @@ function extractKeyFromEntry(entry) {
|
|
|
64
65
|
/** Virtual URL prefix for extracted client scripts (e.g. `/@aero/client/client/pages/home.js`). Root-relative; no filesystem path. */
|
|
65
66
|
const CLIENT_SCRIPT_PREFIX = "/@aero/client/";
|
|
66
67
|
/**
|
|
67
|
-
* Virtual URL for one client script.
|
|
68
|
+
* Virtual URL for one client script.
|
|
69
|
+
* Single script uses `.ts`, multiple use `.0.ts`, `.1.ts`, etc.
|
|
68
70
|
* Use this in the Vite transform and static build so URL generation is consistent.
|
|
69
71
|
*/
|
|
70
72
|
function getClientScriptVirtualUrl(baseName, index, total) {
|
|
71
|
-
const suffix = total === 1 ? ".
|
|
73
|
+
const suffix = total === 1 ? ".ts" : `.${index}.ts`;
|
|
72
74
|
return CLIENT_SCRIPT_PREFIX + baseName + suffix;
|
|
73
75
|
}
|
|
74
76
|
/** Virtual module ID requested by the app; resolved to `RESOLVED_*` so `load()` can re-export from the real runtime instance. */
|
|
75
|
-
const RUNTIME_INSTANCE_MODULE_ID = "virtual:aero/runtime-instance";
|
|
77
|
+
const RUNTIME_INSTANCE_MODULE_ID = "virtual:aero/runtime-instance.ts";
|
|
76
78
|
/** Resolved ID (with `\0` prefix) so Vite treats it as an internal module. */
|
|
77
|
-
const RESOLVED_RUNTIME_INSTANCE_MODULE_ID = "\0virtual:aero/runtime-instance";
|
|
79
|
+
const RESOLVED_RUNTIME_INSTANCE_MODULE_ID = "\0virtual:aero/runtime-instance.ts";
|
|
78
80
|
/** Prefix for virtual empty-CSS modules used when Vite requests .html?html-proxy&inline-css (Aero .html are JS, not HTML with styles). */
|
|
79
81
|
const AERO_EMPTY_INLINE_CSS_PREFIX = "\0aero:empty-inline-css:";
|
|
80
82
|
/** Prefix for virtual HTML template modules. Resolving .html to this id returns compiled JS so vite:build-html never sees raw/compiled HTML. */
|
|
@@ -117,65 +119,6 @@ function resolveDirs(dirs) {
|
|
|
117
119
|
};
|
|
118
120
|
}
|
|
119
121
|
|
|
120
|
-
//#endregion
|
|
121
|
-
//#region src/compiler/constants.ts
|
|
122
|
-
/**
|
|
123
|
-
* Shared constants for the Aero compiler (parser, codegen, helpers).
|
|
124
|
-
*
|
|
125
|
-
* @remarks
|
|
126
|
-
* Attribute names are used with optional `data-` prefix (e.g. `data-each`). Script taxonomy uses
|
|
127
|
-
* `is:build`, `is:inline`, `is:blocking`; default scripts are treated as client (virtual module).
|
|
128
|
-
*/
|
|
129
|
-
/** Prefix for data attributes (e.g. `data-each` → ATTR_PREFIX + ATTR_EACH). */
|
|
130
|
-
const ATTR_PREFIX = "data-";
|
|
131
|
-
/** Attribute for spreading props onto a component: `data-props` or `data-props="{ ... }"`. */
|
|
132
|
-
const ATTR_PROPS = "props";
|
|
133
|
-
/** Attribute for iteration: `data-each="{ item in items }"`. */
|
|
134
|
-
const ATTR_EACH = "each";
|
|
135
|
-
const ATTR_IF = "if";
|
|
136
|
-
const ATTR_ELSE_IF = "else-if";
|
|
137
|
-
const ATTR_ELSE = "else";
|
|
138
|
-
/** Slot name (on `<slot>` or content). */
|
|
139
|
-
const ATTR_NAME = "name";
|
|
140
|
-
const ATTR_SLOT = "slot";
|
|
141
|
-
/** Script runs at build time; extracted and becomes render function body. */
|
|
142
|
-
const ATTR_IS_BUILD = "is:build";
|
|
143
|
-
/** Script left in template in place; not extracted. */
|
|
144
|
-
const ATTR_IS_INLINE = "is:inline";
|
|
145
|
-
/** Script hoisted to head; extracted. */
|
|
146
|
-
const ATTR_IS_BLOCKING = "is:blocking";
|
|
147
|
-
/** Script/style receives data from template: `pass:data="{ config }"` or `pass:data="{ ...theme }"`. */
|
|
148
|
-
const ATTR_PASS_DATA = "pass:data";
|
|
149
|
-
/** Script external source (HTML attribute). */
|
|
150
|
-
const ATTR_SRC = "src";
|
|
151
|
-
const TAG_SLOT = "slot";
|
|
152
|
-
/** Default slot name when no name is given. */
|
|
153
|
-
const SLOT_NAME_DEFAULT = "default";
|
|
154
|
-
/** Matches `item in items` for data-each (captures: loop variable, iterable expression). */
|
|
155
|
-
const EACH_REGEX = /^(\w+)\s+in\s+(.+)$/;
|
|
156
|
-
/** Matches tag names ending with `-component` or `-layout`. */
|
|
157
|
-
const COMPONENT_SUFFIX_REGEX = /-(component|layout)$/;
|
|
158
|
-
/** Self-closing tag: `<tag ... />`. */
|
|
159
|
-
const SELF_CLOSING_TAG_REGEX = /<([a-z0-9-]+)([^>]*?)\/>/gi;
|
|
160
|
-
const SELF_CLOSING_TAIL_REGEX = /\/>$/;
|
|
161
|
-
/** HTML void elements that have no closing tag. */
|
|
162
|
-
const VOID_TAGS = new Set([
|
|
163
|
-
"area",
|
|
164
|
-
"base",
|
|
165
|
-
"br",
|
|
166
|
-
"col",
|
|
167
|
-
"embed",
|
|
168
|
-
"hr",
|
|
169
|
-
"img",
|
|
170
|
-
"input",
|
|
171
|
-
"link",
|
|
172
|
-
"meta",
|
|
173
|
-
"param",
|
|
174
|
-
"source",
|
|
175
|
-
"track",
|
|
176
|
-
"wbr"
|
|
177
|
-
]);
|
|
178
|
-
|
|
179
122
|
//#endregion
|
|
180
123
|
//#region src/compiler/parser.ts
|
|
181
124
|
/** Serialize element attributes to a string, excluding given names (case-insensitive). Values are XML-escaped. */
|
|
@@ -627,6 +570,11 @@ var Resolver = class {
|
|
|
627
570
|
|
|
628
571
|
//#endregion
|
|
629
572
|
//#region src/compiler/codegen.ts
|
|
573
|
+
/** Strip TypeScript syntax from a script string, returning plain JavaScript. */
|
|
574
|
+
function stripTypes(code, filename = "script.ts") {
|
|
575
|
+
if (!code.trim()) return code;
|
|
576
|
+
return transformSync(filename, code, { typescript: { onlyRemoveTypeImports: true } }).code.replace(/(?:^|\n)\s*export\s*\{\s*\}\s*;?/g, "");
|
|
577
|
+
}
|
|
630
578
|
/** Internal lowerer: walks DOM nodes and builds IR; used by compile(). */
|
|
631
579
|
var Lowerer = class {
|
|
632
580
|
resolver;
|
|
@@ -1012,7 +960,7 @@ function compile(parsed, options) {
|
|
|
1012
960
|
const lowerer = new Lowerer(resolver);
|
|
1013
961
|
let script = parsed.buildScript ? parsed.buildScript.content : "";
|
|
1014
962
|
const analysis = analyzeBuildScript(script);
|
|
1015
|
-
script = analysis.scriptWithoutImportsAndGetStaticPaths;
|
|
963
|
+
script = stripTypes(analysis.scriptWithoutImportsAndGetStaticPaths);
|
|
1016
964
|
const getStaticPathsFn = analysis.getStaticPathsFn;
|
|
1017
965
|
const importsLines = [];
|
|
1018
966
|
const quote = "\"";
|
|
@@ -1067,15 +1015,18 @@ function compile(parsed, options) {
|
|
|
1067
1015
|
} else if (isHead) headScripts.push(tagExpr);
|
|
1068
1016
|
else rootScripts.push(`scripts?.add(${tagExpr});`);
|
|
1069
1017
|
}
|
|
1070
|
-
if (options.blockingScripts) for (const blockingScript of options.blockingScripts)
|
|
1071
|
-
const
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1018
|
+
if (options.blockingScripts) for (const blockingScript of options.blockingScripts) {
|
|
1019
|
+
const strippedContent = stripTypes(blockingScript.content, "blocking.ts");
|
|
1020
|
+
if (blockingScript.passDataExpr) {
|
|
1021
|
+
const jsMapExpr = `Object.entries(${validateSingleBracedExpression(blockingScript.passDataExpr, {
|
|
1022
|
+
directive: "pass:data",
|
|
1023
|
+
tagName: "script"
|
|
1024
|
+
})}).map(([k, v]) => "\\nconst " + k + " = " + JSON.stringify(v) + ";").join("")`;
|
|
1025
|
+
headScripts.push(`\`<script${blockingScript.attrs ? " " + blockingScript.attrs : ""}>\${${jsMapExpr}}${strippedContent.replace(/`/g, "\\`")}<\/script>\``);
|
|
1026
|
+
} else {
|
|
1027
|
+
const escapedContent = strippedContent.replace(/`/g, "\\`").replace(/\$\{/g, "\\${");
|
|
1028
|
+
headScripts.push(`\`<script${blockingScript.attrs ? " " + blockingScript.attrs : ""}>${escapedContent}<\/script>\``);
|
|
1029
|
+
}
|
|
1079
1030
|
}
|
|
1080
1031
|
const renderFn = emitRenderFunction(script, bodyCode, {
|
|
1081
1032
|
getStaticPathsFn: getStaticPathsFn || void 0,
|
|
@@ -1085,6 +1036,109 @@ function compile(parsed, options) {
|
|
|
1085
1036
|
});
|
|
1086
1037
|
return importsCode + "\n" + renderFn;
|
|
1087
1038
|
}
|
|
1039
|
+
/**
|
|
1040
|
+
* Compile an HTML template source into a JavaScript module string. Single entry for parse + compile.
|
|
1041
|
+
* When optional `parsed` is provided (e.g. after registering client scripts in the plugin), it is used to avoid parsing twice.
|
|
1042
|
+
*
|
|
1043
|
+
* @param htmlSource - Raw HTML template string.
|
|
1044
|
+
* @param options - CompileOptions (root, resolvePath, importer, optional script overrides).
|
|
1045
|
+
* @param parsed - Optional pre-parsed result; when provided, used instead of parsing htmlSource again.
|
|
1046
|
+
* @returns Module source (async render function + optional getStaticPaths).
|
|
1047
|
+
*/
|
|
1048
|
+
function compileTemplate(htmlSource, options, parsed) {
|
|
1049
|
+
const p = parsed ?? parse(htmlSource);
|
|
1050
|
+
return compile(p, {
|
|
1051
|
+
...options,
|
|
1052
|
+
clientScripts: options.clientScripts ?? p.clientScripts,
|
|
1053
|
+
inlineScripts: options.inlineScripts ?? p.inlineScripts,
|
|
1054
|
+
blockingScripts: options.blockingScripts ?? p.blockingScripts
|
|
1055
|
+
});
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
//#endregion
|
|
1059
|
+
//#region src/vite/rewrite.ts
|
|
1060
|
+
/** Route path to output file path (e.g. '' → index.html, about → about/index.html). */
|
|
1061
|
+
function toOutputFile(routePath) {
|
|
1062
|
+
if (routePath === "") return "index.html";
|
|
1063
|
+
if (routePath === "404") return "404.html";
|
|
1064
|
+
return toPosix(path$1.join(routePath, "index.html"));
|
|
1065
|
+
}
|
|
1066
|
+
/** Relative path from fromDir to targetPath, always starting with ./ when non-empty. */
|
|
1067
|
+
function normalizeRelativeLink(fromDir, targetPath) {
|
|
1068
|
+
const rel = path$1.posix.relative(fromDir, targetPath);
|
|
1069
|
+
if (!rel) return "./";
|
|
1070
|
+
if (rel.startsWith(".")) return rel;
|
|
1071
|
+
return `./${rel}`;
|
|
1072
|
+
}
|
|
1073
|
+
/** Relative path to a route (directory index); appends trailing slash for non-root routes. */
|
|
1074
|
+
function normalizeRelativeRouteLink(fromDir, routePath) {
|
|
1075
|
+
const targetDir = routePath === "" ? "" : routePath;
|
|
1076
|
+
const rel = path$1.posix.relative(fromDir, targetDir);
|
|
1077
|
+
let res = !rel ? "./" : rel.startsWith(".") ? rel : `./${rel}`;
|
|
1078
|
+
if (routePath !== "" && routePath !== "404" && !res.endsWith("/")) res += "/";
|
|
1079
|
+
return res;
|
|
1080
|
+
}
|
|
1081
|
+
function normalizeRoutePathFromHref(value) {
|
|
1082
|
+
if (value === "/") return "";
|
|
1083
|
+
return value.replace(/^\/+/, "").replace(/\/+$/, "");
|
|
1084
|
+
}
|
|
1085
|
+
function isSkippableUrl$1(value) {
|
|
1086
|
+
if (!value) return true;
|
|
1087
|
+
return SKIP_PROTOCOL_REGEX.test(value);
|
|
1088
|
+
}
|
|
1089
|
+
const ASSET_IMAGE_EXT = /\.(jpg|jpeg|png|gif|webp|svg|ico)(\?|$)/i;
|
|
1090
|
+
/** Rewrite one absolute URL to dist-relative using manifest and route set; leaves API and external URLs unchanged. */
|
|
1091
|
+
function rewriteAbsoluteUrl(value, fromDir, manifest, routeSet, apiPrefix = DEFAULT_API_PREFIX) {
|
|
1092
|
+
if (value.startsWith(apiPrefix)) return value;
|
|
1093
|
+
const noQuery = value.split(/[?#]/)[0] || value;
|
|
1094
|
+
const suffix = value.slice(noQuery.length);
|
|
1095
|
+
const manifestKey = noQuery.replace(/^\//, "");
|
|
1096
|
+
let manifestEntry = manifest[noQuery] ?? manifest[manifestKey];
|
|
1097
|
+
if (!manifestEntry && noQuery.startsWith("assets/")) {
|
|
1098
|
+
const entry = Object.values(manifest).find((e) => e?.file === noQuery || e?.file === manifestKey);
|
|
1099
|
+
if (entry) manifestEntry = entry;
|
|
1100
|
+
}
|
|
1101
|
+
if (manifestEntry?.file) return normalizeRelativeLink(fromDir, manifestEntry.assets?.find((a) => ASSET_IMAGE_EXT.test(a)) ?? manifestEntry.file) + suffix;
|
|
1102
|
+
if (noQuery.startsWith("/assets/")) return normalizeRelativeLink(fromDir, noQuery.replace(/^\//, "")) + suffix;
|
|
1103
|
+
const route = normalizeRoutePathFromHref(noQuery);
|
|
1104
|
+
if (routeSet.has(route) || route === "") return (route === "404" ? normalizeRelativeLink(fromDir, toOutputFile(route)) : normalizeRelativeRouteLink(fromDir, route)) + suffix;
|
|
1105
|
+
return normalizeRelativeLink(fromDir, noQuery.replace(/^\//, "")) + suffix;
|
|
1106
|
+
}
|
|
1107
|
+
/** Rewrite script src (virtual client → hashed asset) and LINK_ATTRS in rendered HTML; add doctype. */
|
|
1108
|
+
function rewriteRenderedHtml(html, outputFile, manifest, routeSet, apiPrefix = DEFAULT_API_PREFIX) {
|
|
1109
|
+
const fromDir = path$1.posix.dirname(outputFile);
|
|
1110
|
+
const { document } = parseHTML(html);
|
|
1111
|
+
for (const script of Array.from(document.querySelectorAll("script[src]"))) {
|
|
1112
|
+
const src = script.getAttribute("src") || "";
|
|
1113
|
+
if (src.startsWith(CLIENT_SCRIPT_PREFIX)) {
|
|
1114
|
+
const newSrc = rewriteAbsoluteUrl(src, fromDir, manifest, routeSet, apiPrefix);
|
|
1115
|
+
script.setAttribute("src", newSrc);
|
|
1116
|
+
script.setAttribute("type", "module");
|
|
1117
|
+
script.removeAttribute("defer");
|
|
1118
|
+
continue;
|
|
1119
|
+
}
|
|
1120
|
+
if (script.getAttribute("type") === "module") script.removeAttribute("defer");
|
|
1121
|
+
}
|
|
1122
|
+
for (const el of Array.from(document.querySelectorAll("*"))) for (const attrName of LINK_ATTRS) {
|
|
1123
|
+
if (!el.hasAttribute(attrName)) continue;
|
|
1124
|
+
const current = (el.getAttribute(attrName) || "").trim();
|
|
1125
|
+
if (!current || isSkippableUrl$1(current)) continue;
|
|
1126
|
+
if (!current.startsWith("/")) continue;
|
|
1127
|
+
el.setAttribute(attrName, rewriteAbsoluteUrl(current, fromDir, manifest, routeSet, apiPrefix));
|
|
1128
|
+
}
|
|
1129
|
+
const htmlTag = document.documentElement;
|
|
1130
|
+
if (htmlTag) return addDoctype(htmlTag.outerHTML);
|
|
1131
|
+
return addDoctype(document.toString());
|
|
1132
|
+
}
|
|
1133
|
+
/** Prepend `<!doctype html>` if missing. */
|
|
1134
|
+
function addDoctype(html) {
|
|
1135
|
+
return /^\s*<!doctype\s+html/i.test(html) ? html : `<!doctype html>\n${html}`;
|
|
1136
|
+
}
|
|
1137
|
+
function readManifest(distDir) {
|
|
1138
|
+
const manifestPath = path$1.join(distDir, ".vite", "manifest.json");
|
|
1139
|
+
if (!fs.existsSync(manifestPath)) return {};
|
|
1140
|
+
return JSON.parse(fs.readFileSync(manifestPath, "utf-8"));
|
|
1141
|
+
}
|
|
1088
1142
|
|
|
1089
1143
|
//#endregion
|
|
1090
1144
|
//#region src/vite/build.ts
|
|
@@ -1132,12 +1186,6 @@ function toRouteFromPageName(pageName) {
|
|
|
1132
1186
|
if (pageName.endsWith("/index")) return pageName.slice(0, -6);
|
|
1133
1187
|
return pageName;
|
|
1134
1188
|
}
|
|
1135
|
-
/** Route path to output file path (e.g. '' → index.html, about → about/index.html). */
|
|
1136
|
-
function toOutputFile(routePath) {
|
|
1137
|
-
if (routePath === "") return "index.html";
|
|
1138
|
-
if (routePath === "404") return "404.html";
|
|
1139
|
-
return toPosix(path$1.join(routePath, "index.html"));
|
|
1140
|
-
}
|
|
1141
1189
|
/**
|
|
1142
1190
|
* Generate sitemap.xml from route paths. Only called when site URL is set.
|
|
1143
1191
|
* Excludes 404. Writes to distDir/sitemap.xml.
|
|
@@ -1152,34 +1200,15 @@ function writeSitemap(routePaths, site, distDir) {
|
|
|
1152
1200
|
function escapeXml(s) {
|
|
1153
1201
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
1154
1202
|
}
|
|
1155
|
-
/**
|
|
1156
|
-
function
|
|
1157
|
-
|
|
1158
|
-
if (!rel) return "./";
|
|
1159
|
-
if (rel.startsWith(".")) return rel;
|
|
1160
|
-
return `./${rel}`;
|
|
1161
|
-
}
|
|
1162
|
-
/** Relative path to a route (directory index); appends trailing slash for non-root routes. */
|
|
1163
|
-
function normalizeRelativeRouteLink(fromDir, routePath) {
|
|
1164
|
-
const targetDir = routePath === "" ? "" : routePath;
|
|
1165
|
-
const rel = path$1.posix.relative(fromDir, targetDir);
|
|
1166
|
-
let res = !rel ? "./" : rel.startsWith(".") ? rel : `./${rel}`;
|
|
1167
|
-
if (routePath !== "" && routePath !== "404" && !res.endsWith("/")) res += "/";
|
|
1168
|
-
return res;
|
|
1169
|
-
}
|
|
1170
|
-
function normalizeRoutePathFromHref(value) {
|
|
1171
|
-
if (value === "/") return "";
|
|
1172
|
-
return value.replace(/^\/+/, "").replace(/\/+$/, "");
|
|
1203
|
+
/** Root-relative path for manifest key (posix). */
|
|
1204
|
+
function toManifestKey(root, filePath) {
|
|
1205
|
+
return toPosixRelative(filePath, root);
|
|
1173
1206
|
}
|
|
1174
1207
|
/** True if URL is empty or matches SKIP_PROTOCOL_REGEX (external, hash, etc.). */
|
|
1175
1208
|
function isSkippableUrl(value) {
|
|
1176
1209
|
if (!value) return true;
|
|
1177
1210
|
return SKIP_PROTOCOL_REGEX.test(value);
|
|
1178
1211
|
}
|
|
1179
|
-
/** Root-relative path for manifest key (posix). */
|
|
1180
|
-
function toManifestKey(root, filePath) {
|
|
1181
|
-
return toPosixRelative(filePath, root);
|
|
1182
|
-
}
|
|
1183
1212
|
/** Resolve script/link src or href to absolute path; returns null for external/skippable or unresolvable. */
|
|
1184
1213
|
function resolveTemplateAssetPath(rawValue, templateFile, root, resolvePath) {
|
|
1185
1214
|
if (!rawValue || isSkippableUrl(rawValue)) return null;
|
|
@@ -1299,60 +1328,6 @@ function walkFiles(dir) {
|
|
|
1299
1328
|
}
|
|
1300
1329
|
return files;
|
|
1301
1330
|
}
|
|
1302
|
-
/** Prepend `<!doctype html>` if missing. */
|
|
1303
|
-
function addDoctype(html) {
|
|
1304
|
-
return /^\s*<!doctype\s+html/i.test(html) ? html : `<!doctype html>\n${html}`;
|
|
1305
|
-
}
|
|
1306
|
-
/** Image extensions: when a manifest entry's .file is a .js chunk but .assets lists the real image, use it. */
|
|
1307
|
-
const ASSET_IMAGE_EXT = /\.(jpg|jpeg|png|gif|webp|svg|ico)(\?|$)/i;
|
|
1308
|
-
/** Rewrite one absolute URL to dist-relative using manifest and route set; leaves API and external URLs unchanged. */
|
|
1309
|
-
function rewriteAbsoluteUrl(value, fromDir, manifest, routeSet, apiPrefix = DEFAULT_API_PREFIX) {
|
|
1310
|
-
if (value.startsWith(apiPrefix)) return value;
|
|
1311
|
-
const noQuery = value.split(/[?#]/)[0] || value;
|
|
1312
|
-
const suffix = value.slice(noQuery.length);
|
|
1313
|
-
const manifestKey = noQuery.replace(/^\//, "");
|
|
1314
|
-
let manifestEntry = manifest[noQuery] ?? manifest[manifestKey];
|
|
1315
|
-
if (!manifestEntry && noQuery.startsWith("assets/")) {
|
|
1316
|
-
const entry = Object.values(manifest).find((e) => e?.file === noQuery || e?.file === manifestKey);
|
|
1317
|
-
if (entry) manifestEntry = entry;
|
|
1318
|
-
}
|
|
1319
|
-
if (manifestEntry?.file) return normalizeRelativeLink(fromDir, manifestEntry.assets?.find((a) => ASSET_IMAGE_EXT.test(a)) ?? manifestEntry.file) + suffix;
|
|
1320
|
-
if (noQuery.startsWith("/assets/")) return normalizeRelativeLink(fromDir, noQuery.replace(/^\//, "")) + suffix;
|
|
1321
|
-
const route = normalizeRoutePathFromHref(noQuery);
|
|
1322
|
-
if (routeSet.has(route) || route === "") return (route === "404" ? normalizeRelativeLink(fromDir, toOutputFile(route)) : normalizeRelativeRouteLink(fromDir, route)) + suffix;
|
|
1323
|
-
return normalizeRelativeLink(fromDir, noQuery.replace(/^\//, "")) + suffix;
|
|
1324
|
-
}
|
|
1325
|
-
/** Rewrite script src (virtual client → hashed asset) and LINK_ATTRS in rendered HTML; add doctype. */
|
|
1326
|
-
function rewriteRenderedHtml(html, outputFile, manifest, routeSet, apiPrefix = DEFAULT_API_PREFIX) {
|
|
1327
|
-
const fromDir = path$1.posix.dirname(outputFile);
|
|
1328
|
-
const { document } = parseHTML(html);
|
|
1329
|
-
for (const script of Array.from(document.querySelectorAll("script[src]"))) {
|
|
1330
|
-
const src = script.getAttribute("src") || "";
|
|
1331
|
-
if (src.startsWith(CLIENT_SCRIPT_PREFIX)) {
|
|
1332
|
-
const newSrc = rewriteAbsoluteUrl(src, fromDir, manifest, routeSet, apiPrefix);
|
|
1333
|
-
script.setAttribute("src", newSrc);
|
|
1334
|
-
script.setAttribute("type", "module");
|
|
1335
|
-
script.removeAttribute("defer");
|
|
1336
|
-
continue;
|
|
1337
|
-
}
|
|
1338
|
-
if (script.getAttribute("type") === "module") script.removeAttribute("defer");
|
|
1339
|
-
}
|
|
1340
|
-
for (const el of Array.from(document.querySelectorAll("*"))) for (const attrName of LINK_ATTRS) {
|
|
1341
|
-
if (!el.hasAttribute(attrName)) continue;
|
|
1342
|
-
const current = (el.getAttribute(attrName) || "").trim();
|
|
1343
|
-
if (!current || isSkippableUrl(current)) continue;
|
|
1344
|
-
if (!current.startsWith("/")) continue;
|
|
1345
|
-
el.setAttribute(attrName, rewriteAbsoluteUrl(current, fromDir, manifest, routeSet, apiPrefix));
|
|
1346
|
-
}
|
|
1347
|
-
const htmlTag = document.documentElement;
|
|
1348
|
-
if (htmlTag) return addDoctype(htmlTag.outerHTML);
|
|
1349
|
-
return addDoctype(document.toString());
|
|
1350
|
-
}
|
|
1351
|
-
function readManifest(distDir) {
|
|
1352
|
-
const manifestPath = path$1.join(distDir, ".vite", "manifest.json");
|
|
1353
|
-
if (!fs.existsSync(manifestPath)) return {};
|
|
1354
|
-
return JSON.parse(fs.readFileSync(manifestPath, "utf-8"));
|
|
1355
|
-
}
|
|
1356
1331
|
/**
|
|
1357
1332
|
* Render all static pages into outDir: discover pages, expand dynamic routes via getStaticPaths, run Vite in middleware mode, rewrite URLs, optionally minify.
|
|
1358
1333
|
*
|
|
@@ -1591,7 +1566,7 @@ function clientGlobPrefix(clientDir) {
|
|
|
1591
1566
|
* Ensures template resolution works for custom dirs (e.g. dirs.client === 'frontend').
|
|
1592
1567
|
* runtimeImportPath: path that resolves to @aerobuilt/core/runtime from the generated file (e.g. relative to .aero/ for SSR).
|
|
1593
1568
|
*/
|
|
1594
|
-
function getRuntimeInstanceVirtualSource(clientDir, runtimeImportPath = "
|
|
1569
|
+
function getRuntimeInstanceVirtualSource(clientDir, runtimeImportPath = "aerobuilt/runtime") {
|
|
1595
1570
|
const prefix = clientGlobPrefix(clientDir);
|
|
1596
1571
|
const componentsPattern = `${prefix}/components/**/*.html`;
|
|
1597
1572
|
const layoutsPattern = `${prefix}/layouts/*.html`;
|
|
@@ -1637,7 +1612,10 @@ function createAeroVirtualsPlugin(state) {
|
|
|
1637
1612
|
discoverClientScriptContentMap(state.config.root, state.dirs.client).forEach((entry, url) => state.clientScripts.set(url, entry));
|
|
1638
1613
|
},
|
|
1639
1614
|
async resolveId(id, importer) {
|
|
1640
|
-
if (id === RUNTIME_INSTANCE_MODULE_ID)
|
|
1615
|
+
if (id === RUNTIME_INSTANCE_MODULE_ID) {
|
|
1616
|
+
if (state.config?.command === "build" && state.generatedRuntimeInstancePath) return state.generatedRuntimeInstancePath;
|
|
1617
|
+
return RESOLVED_RUNTIME_INSTANCE_MODULE_ID;
|
|
1618
|
+
}
|
|
1641
1619
|
if (id.startsWith(CLIENT_SCRIPT_PREFIX)) return "\0" + id;
|
|
1642
1620
|
if (id.startsWith("\0" + CLIENT_SCRIPT_PREFIX)) return id;
|
|
1643
1621
|
if (id.startsWith(AERO_HTML_VIRTUAL_PREFIX)) return id;
|
|
@@ -1665,19 +1643,20 @@ function createAeroVirtualsPlugin(state) {
|
|
|
1665
1643
|
if (!state.config || !state.aliasResult) return null;
|
|
1666
1644
|
this.addWatchFile(filePath);
|
|
1667
1645
|
try {
|
|
1668
|
-
const
|
|
1646
|
+
const code = readFileSync(filePath, "utf-8");
|
|
1647
|
+
const parsed = parse(code);
|
|
1669
1648
|
const baseName = toPosixRelative(filePath, state.config.root).replace(/\.html$/i, "");
|
|
1670
1649
|
registerClientScriptsToMap(parsed, baseName, state.clientScripts);
|
|
1671
1650
|
for (let i = 0; i < parsed.clientScripts.length; i++) parsed.clientScripts[i].content = getClientScriptVirtualUrl(baseName, i, parsed.clientScripts.length);
|
|
1672
1651
|
return {
|
|
1673
|
-
code:
|
|
1652
|
+
code: compileTemplate(code, {
|
|
1674
1653
|
root: state.config.root,
|
|
1675
1654
|
clientScripts: parsed.clientScripts,
|
|
1676
1655
|
blockingScripts: parsed.blockingScripts,
|
|
1677
1656
|
inlineScripts: parsed.inlineScripts,
|
|
1678
1657
|
resolvePath: state.aliasResult.resolve,
|
|
1679
1658
|
importer: filePath
|
|
1680
|
-
}),
|
|
1659
|
+
}, parsed),
|
|
1681
1660
|
map: null
|
|
1682
1661
|
};
|
|
1683
1662
|
} catch {
|
|
@@ -1714,14 +1693,14 @@ function createAeroTransformPlugin(state) {
|
|
|
1714
1693
|
for (let i = 0; i < parsed.clientScripts.length; i++) parsed.clientScripts[i].content = getClientScriptVirtualUrl(baseName, i, parsed.clientScripts.length);
|
|
1715
1694
|
}
|
|
1716
1695
|
return {
|
|
1717
|
-
code:
|
|
1696
|
+
code: compileTemplate(code, {
|
|
1718
1697
|
root: state.config.root,
|
|
1719
1698
|
clientScripts: parsed.clientScripts,
|
|
1720
1699
|
blockingScripts: parsed.blockingScripts,
|
|
1721
1700
|
inlineScripts: parsed.inlineScripts,
|
|
1722
1701
|
resolvePath: state.aliasResult.resolve,
|
|
1723
1702
|
importer: id
|
|
1724
|
-
}),
|
|
1703
|
+
}, parsed),
|
|
1725
1704
|
map: null
|
|
1726
1705
|
};
|
|
1727
1706
|
} catch (err) {
|
package/env.d.ts
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ambient type declarations for Aero templates.
|
|
3
|
+
*
|
|
4
|
+
* Include in your project by adding `"types": ["@aerobuilt/core/env"]` to tsconfig.json,
|
|
5
|
+
* or via a triple-slash directive: `/// <reference types="@aerobuilt/core/env" />`
|
|
6
|
+
*
|
|
7
|
+
* These declarations type the globals available inside `<script is:build>` blocks.
|
|
8
|
+
*
|
|
9
|
+
* Single source of truth: the language server generates its preamble from this file.
|
|
10
|
+
* When changing globals (Aero, renderComponent, *.html, aero:content), run:
|
|
11
|
+
* pnpm --dir packages/language-server exec npm run prebuild
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* The `Aero` context object available in build scripts. Provides access to
|
|
16
|
+
* component props, request data, and rendering utilities.
|
|
17
|
+
*
|
|
18
|
+
* Use `Aero.props` (capital A). The lowercase `aero` is not defined at runtime.
|
|
19
|
+
*/
|
|
20
|
+
declare const Aero: {
|
|
21
|
+
/** Props passed to the current component or page. */
|
|
22
|
+
props: Record<string, any>
|
|
23
|
+
/** Named slot content (key to HTML string). */
|
|
24
|
+
slots: Record<string, string>
|
|
25
|
+
/** The incoming request (available during SSR). */
|
|
26
|
+
request: Request
|
|
27
|
+
/** The request URL. */
|
|
28
|
+
url: URL
|
|
29
|
+
/** Dynamic route parameters (e.g. `{ id: '42' }` for `/posts/[id]`). */
|
|
30
|
+
params: Record<string, string>
|
|
31
|
+
/** Canonical site URL from `aero.config` (e.g. `'https://example.com'`). */
|
|
32
|
+
site?: string
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Render a child component and return its HTML.
|
|
37
|
+
*
|
|
38
|
+
* @param component - The imported component (default import from an `.html` file).
|
|
39
|
+
* @param props - Props to pass to the component.
|
|
40
|
+
* @param slots - Named slot content.
|
|
41
|
+
* @returns The rendered HTML string.
|
|
42
|
+
*/
|
|
43
|
+
declare function renderComponent(
|
|
44
|
+
component: any,
|
|
45
|
+
props?: Record<string, any>,
|
|
46
|
+
slots?: Record<string, string>,
|
|
47
|
+
): Promise<string>
|
|
48
|
+
|
|
49
|
+
/** Allows importing `.html` component files in build scripts. */
|
|
50
|
+
declare module '*.html' {
|
|
51
|
+
const component: string
|
|
52
|
+
export default component
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** Content collections: getCollection, render. Used by the language server for IntelliSense. */
|
|
56
|
+
declare module 'aero:content' {
|
|
57
|
+
interface CollectionEntry {
|
|
58
|
+
id: string
|
|
59
|
+
data: Record<string, any>
|
|
60
|
+
body?: string
|
|
61
|
+
}
|
|
62
|
+
export function getCollection(name: string): Promise<CollectionEntry[]>
|
|
63
|
+
export function render(
|
|
64
|
+
entry: CollectionEntry | Record<string, any>,
|
|
65
|
+
): Promise<{ html: string }>
|
|
66
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aerobuilt/core",
|
|
3
|
-
"version": "0.3.
|
|
4
|
-
"
|
|
3
|
+
"version": "0.3.3",
|
|
4
|
+
"private": false,
|
|
5
|
+
"homepage": "https://github.com/aerobuilt/aero",
|
|
5
6
|
"license": "MIT",
|
|
6
7
|
"author": "Jamie Wilson",
|
|
7
8
|
"repository": {
|
|
@@ -9,12 +10,12 @@
|
|
|
9
10
|
"url": "https://github.com/aerobuilt/aero.git",
|
|
10
11
|
"directory": "packages/core"
|
|
11
12
|
},
|
|
12
|
-
"homepage": "https://github.com/aerobuilt/aero",
|
|
13
|
-
"private": false,
|
|
14
|
-
"types": "./dist/entry-dev.d.mts",
|
|
15
13
|
"files": [
|
|
16
|
-
"dist"
|
|
14
|
+
"dist",
|
|
15
|
+
"env.d.ts"
|
|
17
16
|
],
|
|
17
|
+
"type": "module",
|
|
18
|
+
"types": "./dist/entry-dev.d.mts",
|
|
18
19
|
"exports": {
|
|
19
20
|
".": {
|
|
20
21
|
"types": "./dist/entry-dev.d.mts",
|
|
@@ -48,19 +49,27 @@
|
|
|
48
49
|
"./editor": {
|
|
49
50
|
"types": "./dist/entry-editor.d.mts",
|
|
50
51
|
"default": "./dist/entry-editor.mjs"
|
|
51
|
-
}
|
|
52
|
+
},
|
|
53
|
+
"./env": "./env.d.ts"
|
|
52
54
|
},
|
|
53
55
|
"dependencies": {
|
|
54
56
|
"get-tsconfig": "^4.13.6",
|
|
55
|
-
"oxc-resolver": "^11.19.0",
|
|
56
57
|
"html-minifier-next": "^5.1.1",
|
|
57
58
|
"linkedom": "^0.18.12",
|
|
58
59
|
"nitro": "^3.0.1-alpha.2",
|
|
59
60
|
"oxc-parser": "^0.115.0",
|
|
61
|
+
"oxc-resolver": "^11.19.0",
|
|
62
|
+
"oxc-transform": "^0.116.0",
|
|
60
63
|
"sharp": "^0.34.5",
|
|
61
64
|
"svgo": "^4.0.0",
|
|
62
65
|
"vite-plugin-image-optimizer": "^2.0.3",
|
|
63
|
-
"@aerobuilt/interpolation": "0.3.
|
|
66
|
+
"@aerobuilt/interpolation": "0.3.3"
|
|
67
|
+
},
|
|
68
|
+
"devDependencies": {
|
|
69
|
+
"@types/node": "^25.3.0",
|
|
70
|
+
"tsdown": "^0.21.0-beta.2",
|
|
71
|
+
"typescript": "^5.9.3",
|
|
72
|
+
"vitest": "^4.0.18"
|
|
64
73
|
},
|
|
65
74
|
"peerDependencies": {
|
|
66
75
|
"vite": "^8.0.0-0"
|
|
@@ -70,12 +79,6 @@
|
|
|
70
79
|
"optional": true
|
|
71
80
|
}
|
|
72
81
|
},
|
|
73
|
-
"devDependencies": {
|
|
74
|
-
"@types/node": "^25.3.0",
|
|
75
|
-
"tsdown": "^0.21.0-beta.2",
|
|
76
|
-
"typescript": "^5.9.3",
|
|
77
|
-
"vitest": "^4.0.18"
|
|
78
|
-
},
|
|
79
82
|
"scripts": {
|
|
80
83
|
"build": "tsdown",
|
|
81
84
|
"typecheck": "tsc --noEmit",
|