@aerobuilt/core 0.3.1 → 0.3.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.
|
@@ -26,6 +26,65 @@ 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
|
+
*/
|
|
38
|
+
/** Prefix for data attributes (e.g. `data-each` → ATTR_PREFIX + ATTR_EACH). */
|
|
39
|
+
const ATTR_PREFIX = "data-";
|
|
40
|
+
/** Attribute for spreading props onto a component: `data-props` or `data-props="{ ... }"`. */
|
|
41
|
+
const ATTR_PROPS = "props";
|
|
42
|
+
/** Attribute for iteration: `data-each="{ item in items }"`. */
|
|
43
|
+
const ATTR_EACH = "each";
|
|
44
|
+
const ATTR_IF = "if";
|
|
45
|
+
const ATTR_ELSE_IF = "else-if";
|
|
46
|
+
const ATTR_ELSE = "else";
|
|
47
|
+
/** Slot name (on `<slot>` or content). */
|
|
48
|
+
const ATTR_NAME = "name";
|
|
49
|
+
const ATTR_SLOT = "slot";
|
|
50
|
+
/** Script runs at build time; extracted and becomes render function body. */
|
|
51
|
+
const ATTR_IS_BUILD = "is:build";
|
|
52
|
+
/** Script left in template in place; not extracted. */
|
|
53
|
+
const ATTR_IS_INLINE = "is:inline";
|
|
54
|
+
/** Script hoisted to head; extracted. */
|
|
55
|
+
const ATTR_IS_BLOCKING = "is:blocking";
|
|
56
|
+
/** Script/style receives data from template: `pass:data="{ config }"` or `pass:data="{ ...theme }"`. */
|
|
57
|
+
const ATTR_PASS_DATA = "pass:data";
|
|
58
|
+
/** Script external source (HTML attribute). */
|
|
59
|
+
const ATTR_SRC = "src";
|
|
60
|
+
const TAG_SLOT = "slot";
|
|
61
|
+
/** Default slot name when no name is given. */
|
|
62
|
+
const SLOT_NAME_DEFAULT = "default";
|
|
63
|
+
/** Matches `item in items` for data-each (captures: loop variable, iterable expression). */
|
|
64
|
+
const EACH_REGEX = /^(\w+)\s+in\s+(.+)$/;
|
|
65
|
+
/** Matches tag names ending with `-component` or `-layout`. */
|
|
66
|
+
const COMPONENT_SUFFIX_REGEX = /-(component|layout)$/;
|
|
67
|
+
/** Self-closing tag: `<tag ... />`. */
|
|
68
|
+
const SELF_CLOSING_TAG_REGEX = /<([a-z0-9-]+)([^>]*?)\/>/gi;
|
|
69
|
+
const SELF_CLOSING_TAIL_REGEX = /\/>$/;
|
|
70
|
+
/** HTML void elements that have no closing tag. */
|
|
71
|
+
const VOID_TAGS = new Set([
|
|
72
|
+
"area",
|
|
73
|
+
"base",
|
|
74
|
+
"br",
|
|
75
|
+
"col",
|
|
76
|
+
"embed",
|
|
77
|
+
"hr",
|
|
78
|
+
"img",
|
|
79
|
+
"input",
|
|
80
|
+
"link",
|
|
81
|
+
"meta",
|
|
82
|
+
"param",
|
|
83
|
+
"source",
|
|
84
|
+
"track",
|
|
85
|
+
"wbr"
|
|
86
|
+
]);
|
|
87
|
+
|
|
29
88
|
//#endregion
|
|
30
89
|
//#region src/compiler/build-script-analysis.ts
|
|
31
90
|
/**
|
|
@@ -190,4 +249,4 @@ function analyzeBuildScriptForEditor(script) {
|
|
|
190
249
|
}
|
|
191
250
|
|
|
192
251
|
//#endregion
|
|
193
|
-
export { compileInterpolationFromSegments as a,
|
|
252
|
+
export { DEFAULT_DIRECTIVE_PREFIXES as C, tokenizeCurlyInterpolation as E, VOID_TAGS as S, compileInterpolationFromSegments as T, EACH_REGEX as _, ATTR_ELSE_IF as a, SLOT_NAME_DEFAULT as b, ATTR_IS_BUILD as c, ATTR_PASS_DATA as d, ATTR_PREFIX as f, COMPONENT_SUFFIX_REGEX as g, ATTR_SRC as h, ATTR_ELSE as i, ATTR_IS_INLINE as l, ATTR_SLOT as m, analyzeBuildScriptForEditor as n, ATTR_IF as o, ATTR_PROPS as p, ATTR_EACH as r, ATTR_IS_BLOCKING as s, analyzeBuildScript as t, ATTR_NAME as u, SELF_CLOSING_TAG_REGEX as v, isDirectiveAttr as w, TAG_SLOT as x, SELF_CLOSING_TAIL_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.
|
|
@@ -71,4 +74,4 @@ interface BuildScriptAnalysisForEditorResult {
|
|
|
71
74
|
*/
|
|
72
75
|
declare function analyzeBuildScriptForEditor(script: string): BuildScriptAnalysisForEditorResult;
|
|
73
76
|
//#endregion
|
|
74
|
-
export { type BuildScriptAnalysisForEditorResult, type BuildScriptImportForEditor, DEFAULT_DIRECTIVE_PREFIXES, type DirectiveAttrConfig, type InterpolationSegment, type LiteralSegment, type Segment, type TokenizeOptions, analyzeBuildScriptForEditor, compileInterpolationFromSegments, isDirectiveAttr, tokenizeCurlyInterpolation };
|
|
77
|
+
export { type BuildScriptAnalysisForEditorResult, type BuildScriptImportForEditor, COMPONENT_SUFFIX_REGEX, DEFAULT_DIRECTIVE_PREFIXES, type DirectiveAttrConfig, type InterpolationSegment, type LiteralSegment, type Segment, type TokenizeOptions, analyzeBuildScriptForEditor, compileInterpolationFromSegments, isDirectiveAttr, tokenizeCurlyInterpolation };
|
package/dist/entry-editor.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { C as DEFAULT_DIRECTIVE_PREFIXES, E as tokenizeCurlyInterpolation, T as compileInterpolationFromSegments, g as COMPONENT_SUFFIX_REGEX, n as analyzeBuildScriptForEditor, w as isDirectiveAttr } from "./build-script-analysis-Bll0Ujh4.mjs";
|
|
2
2
|
|
|
3
|
-
export { DEFAULT_DIRECTIVE_PREFIXES, analyzeBuildScriptForEditor, compileInterpolationFromSegments, isDirectiveAttr, tokenizeCurlyInterpolation };
|
|
3
|
+
export { COMPONENT_SUFFIX_REGEX, DEFAULT_DIRECTIVE_PREFIXES, analyzeBuildScriptForEditor, compileInterpolationFromSegments, 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 { E as tokenizeCurlyInterpolation, S as VOID_TAGS, T as compileInterpolationFromSegments, _ as EACH_REGEX, a as ATTR_ELSE_IF, b as SLOT_NAME_DEFAULT, c as ATTR_IS_BUILD, d as ATTR_PASS_DATA, f as ATTR_PREFIX, g as COMPONENT_SUFFIX_REGEX, h as ATTR_SRC, i as ATTR_ELSE, l as ATTR_IS_INLINE, m as ATTR_SLOT, o as ATTR_IF, p as ATTR_PROPS, r as ATTR_EACH, s as ATTR_IS_BLOCKING, t as analyzeBuildScript, u as ATTR_NAME, v as SELF_CLOSING_TAG_REGEX, w as isDirectiveAttr, x as TAG_SLOT, y as SELF_CLOSING_TAIL_REGEX } from "../build-script-analysis-Bll0Ujh4.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";
|
|
@@ -117,65 +117,6 @@ function resolveDirs(dirs) {
|
|
|
117
117
|
};
|
|
118
118
|
}
|
|
119
119
|
|
|
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
120
|
//#endregion
|
|
180
121
|
//#region src/compiler/parser.ts
|
|
181
122
|
/** Serialize element attributes to a string, excluding given names (case-insensitive). Values are XML-escaped. */
|
|
@@ -1085,6 +1026,109 @@ function compile(parsed, options) {
|
|
|
1085
1026
|
});
|
|
1086
1027
|
return importsCode + "\n" + renderFn;
|
|
1087
1028
|
}
|
|
1029
|
+
/**
|
|
1030
|
+
* Compile an HTML template source into a JavaScript module string. Single entry for parse + compile.
|
|
1031
|
+
* When optional `parsed` is provided (e.g. after registering client scripts in the plugin), it is used to avoid parsing twice.
|
|
1032
|
+
*
|
|
1033
|
+
* @param htmlSource - Raw HTML template string.
|
|
1034
|
+
* @param options - CompileOptions (root, resolvePath, importer, optional script overrides).
|
|
1035
|
+
* @param parsed - Optional pre-parsed result; when provided, used instead of parsing htmlSource again.
|
|
1036
|
+
* @returns Module source (async render function + optional getStaticPaths).
|
|
1037
|
+
*/
|
|
1038
|
+
function compileTemplate(htmlSource, options, parsed) {
|
|
1039
|
+
const p = parsed ?? parse(htmlSource);
|
|
1040
|
+
return compile(p, {
|
|
1041
|
+
...options,
|
|
1042
|
+
clientScripts: options.clientScripts ?? p.clientScripts,
|
|
1043
|
+
inlineScripts: options.inlineScripts ?? p.inlineScripts,
|
|
1044
|
+
blockingScripts: options.blockingScripts ?? p.blockingScripts
|
|
1045
|
+
});
|
|
1046
|
+
}
|
|
1047
|
+
|
|
1048
|
+
//#endregion
|
|
1049
|
+
//#region src/vite/rewrite.ts
|
|
1050
|
+
/** Route path to output file path (e.g. '' → index.html, about → about/index.html). */
|
|
1051
|
+
function toOutputFile(routePath) {
|
|
1052
|
+
if (routePath === "") return "index.html";
|
|
1053
|
+
if (routePath === "404") return "404.html";
|
|
1054
|
+
return toPosix(path$1.join(routePath, "index.html"));
|
|
1055
|
+
}
|
|
1056
|
+
/** Relative path from fromDir to targetPath, always starting with ./ when non-empty. */
|
|
1057
|
+
function normalizeRelativeLink(fromDir, targetPath) {
|
|
1058
|
+
const rel = path$1.posix.relative(fromDir, targetPath);
|
|
1059
|
+
if (!rel) return "./";
|
|
1060
|
+
if (rel.startsWith(".")) return rel;
|
|
1061
|
+
return `./${rel}`;
|
|
1062
|
+
}
|
|
1063
|
+
/** Relative path to a route (directory index); appends trailing slash for non-root routes. */
|
|
1064
|
+
function normalizeRelativeRouteLink(fromDir, routePath) {
|
|
1065
|
+
const targetDir = routePath === "" ? "" : routePath;
|
|
1066
|
+
const rel = path$1.posix.relative(fromDir, targetDir);
|
|
1067
|
+
let res = !rel ? "./" : rel.startsWith(".") ? rel : `./${rel}`;
|
|
1068
|
+
if (routePath !== "" && routePath !== "404" && !res.endsWith("/")) res += "/";
|
|
1069
|
+
return res;
|
|
1070
|
+
}
|
|
1071
|
+
function normalizeRoutePathFromHref(value) {
|
|
1072
|
+
if (value === "/") return "";
|
|
1073
|
+
return value.replace(/^\/+/, "").replace(/\/+$/, "");
|
|
1074
|
+
}
|
|
1075
|
+
function isSkippableUrl$1(value) {
|
|
1076
|
+
if (!value) return true;
|
|
1077
|
+
return SKIP_PROTOCOL_REGEX.test(value);
|
|
1078
|
+
}
|
|
1079
|
+
const ASSET_IMAGE_EXT = /\.(jpg|jpeg|png|gif|webp|svg|ico)(\?|$)/i;
|
|
1080
|
+
/** Rewrite one absolute URL to dist-relative using manifest and route set; leaves API and external URLs unchanged. */
|
|
1081
|
+
function rewriteAbsoluteUrl(value, fromDir, manifest, routeSet, apiPrefix = DEFAULT_API_PREFIX) {
|
|
1082
|
+
if (value.startsWith(apiPrefix)) return value;
|
|
1083
|
+
const noQuery = value.split(/[?#]/)[0] || value;
|
|
1084
|
+
const suffix = value.slice(noQuery.length);
|
|
1085
|
+
const manifestKey = noQuery.replace(/^\//, "");
|
|
1086
|
+
let manifestEntry = manifest[noQuery] ?? manifest[manifestKey];
|
|
1087
|
+
if (!manifestEntry && noQuery.startsWith("assets/")) {
|
|
1088
|
+
const entry = Object.values(manifest).find((e) => e?.file === noQuery || e?.file === manifestKey);
|
|
1089
|
+
if (entry) manifestEntry = entry;
|
|
1090
|
+
}
|
|
1091
|
+
if (manifestEntry?.file) return normalizeRelativeLink(fromDir, manifestEntry.assets?.find((a) => ASSET_IMAGE_EXT.test(a)) ?? manifestEntry.file) + suffix;
|
|
1092
|
+
if (noQuery.startsWith("/assets/")) return normalizeRelativeLink(fromDir, noQuery.replace(/^\//, "")) + suffix;
|
|
1093
|
+
const route = normalizeRoutePathFromHref(noQuery);
|
|
1094
|
+
if (routeSet.has(route) || route === "") return (route === "404" ? normalizeRelativeLink(fromDir, toOutputFile(route)) : normalizeRelativeRouteLink(fromDir, route)) + suffix;
|
|
1095
|
+
return normalizeRelativeLink(fromDir, noQuery.replace(/^\//, "")) + suffix;
|
|
1096
|
+
}
|
|
1097
|
+
/** Rewrite script src (virtual client → hashed asset) and LINK_ATTRS in rendered HTML; add doctype. */
|
|
1098
|
+
function rewriteRenderedHtml(html, outputFile, manifest, routeSet, apiPrefix = DEFAULT_API_PREFIX) {
|
|
1099
|
+
const fromDir = path$1.posix.dirname(outputFile);
|
|
1100
|
+
const { document } = parseHTML(html);
|
|
1101
|
+
for (const script of Array.from(document.querySelectorAll("script[src]"))) {
|
|
1102
|
+
const src = script.getAttribute("src") || "";
|
|
1103
|
+
if (src.startsWith(CLIENT_SCRIPT_PREFIX)) {
|
|
1104
|
+
const newSrc = rewriteAbsoluteUrl(src, fromDir, manifest, routeSet, apiPrefix);
|
|
1105
|
+
script.setAttribute("src", newSrc);
|
|
1106
|
+
script.setAttribute("type", "module");
|
|
1107
|
+
script.removeAttribute("defer");
|
|
1108
|
+
continue;
|
|
1109
|
+
}
|
|
1110
|
+
if (script.getAttribute("type") === "module") script.removeAttribute("defer");
|
|
1111
|
+
}
|
|
1112
|
+
for (const el of Array.from(document.querySelectorAll("*"))) for (const attrName of LINK_ATTRS) {
|
|
1113
|
+
if (!el.hasAttribute(attrName)) continue;
|
|
1114
|
+
const current = (el.getAttribute(attrName) || "").trim();
|
|
1115
|
+
if (!current || isSkippableUrl$1(current)) continue;
|
|
1116
|
+
if (!current.startsWith("/")) continue;
|
|
1117
|
+
el.setAttribute(attrName, rewriteAbsoluteUrl(current, fromDir, manifest, routeSet, apiPrefix));
|
|
1118
|
+
}
|
|
1119
|
+
const htmlTag = document.documentElement;
|
|
1120
|
+
if (htmlTag) return addDoctype(htmlTag.outerHTML);
|
|
1121
|
+
return addDoctype(document.toString());
|
|
1122
|
+
}
|
|
1123
|
+
/** Prepend `<!doctype html>` if missing. */
|
|
1124
|
+
function addDoctype(html) {
|
|
1125
|
+
return /^\s*<!doctype\s+html/i.test(html) ? html : `<!doctype html>\n${html}`;
|
|
1126
|
+
}
|
|
1127
|
+
function readManifest(distDir) {
|
|
1128
|
+
const manifestPath = path$1.join(distDir, ".vite", "manifest.json");
|
|
1129
|
+
if (!fs.existsSync(manifestPath)) return {};
|
|
1130
|
+
return JSON.parse(fs.readFileSync(manifestPath, "utf-8"));
|
|
1131
|
+
}
|
|
1088
1132
|
|
|
1089
1133
|
//#endregion
|
|
1090
1134
|
//#region src/vite/build.ts
|
|
@@ -1132,12 +1176,6 @@ function toRouteFromPageName(pageName) {
|
|
|
1132
1176
|
if (pageName.endsWith("/index")) return pageName.slice(0, -6);
|
|
1133
1177
|
return pageName;
|
|
1134
1178
|
}
|
|
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
1179
|
/**
|
|
1142
1180
|
* Generate sitemap.xml from route paths. Only called when site URL is set.
|
|
1143
1181
|
* Excludes 404. Writes to distDir/sitemap.xml.
|
|
@@ -1152,34 +1190,15 @@ function writeSitemap(routePaths, site, distDir) {
|
|
|
1152
1190
|
function escapeXml(s) {
|
|
1153
1191
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
1154
1192
|
}
|
|
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(/\/+$/, "");
|
|
1193
|
+
/** Root-relative path for manifest key (posix). */
|
|
1194
|
+
function toManifestKey(root, filePath) {
|
|
1195
|
+
return toPosixRelative(filePath, root);
|
|
1173
1196
|
}
|
|
1174
1197
|
/** True if URL is empty or matches SKIP_PROTOCOL_REGEX (external, hash, etc.). */
|
|
1175
1198
|
function isSkippableUrl(value) {
|
|
1176
1199
|
if (!value) return true;
|
|
1177
1200
|
return SKIP_PROTOCOL_REGEX.test(value);
|
|
1178
1201
|
}
|
|
1179
|
-
/** Root-relative path for manifest key (posix). */
|
|
1180
|
-
function toManifestKey(root, filePath) {
|
|
1181
|
-
return toPosixRelative(filePath, root);
|
|
1182
|
-
}
|
|
1183
1202
|
/** Resolve script/link src or href to absolute path; returns null for external/skippable or unresolvable. */
|
|
1184
1203
|
function resolveTemplateAssetPath(rawValue, templateFile, root, resolvePath) {
|
|
1185
1204
|
if (!rawValue || isSkippableUrl(rawValue)) return null;
|
|
@@ -1299,60 +1318,6 @@ function walkFiles(dir) {
|
|
|
1299
1318
|
}
|
|
1300
1319
|
return files;
|
|
1301
1320
|
}
|
|
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
1321
|
/**
|
|
1357
1322
|
* Render all static pages into outDir: discover pages, expand dynamic routes via getStaticPaths, run Vite in middleware mode, rewrite URLs, optionally minify.
|
|
1358
1323
|
*
|
|
@@ -1665,19 +1630,20 @@ function createAeroVirtualsPlugin(state) {
|
|
|
1665
1630
|
if (!state.config || !state.aliasResult) return null;
|
|
1666
1631
|
this.addWatchFile(filePath);
|
|
1667
1632
|
try {
|
|
1668
|
-
const
|
|
1633
|
+
const code = readFileSync(filePath, "utf-8");
|
|
1634
|
+
const parsed = parse(code);
|
|
1669
1635
|
const baseName = toPosixRelative(filePath, state.config.root).replace(/\.html$/i, "");
|
|
1670
1636
|
registerClientScriptsToMap(parsed, baseName, state.clientScripts);
|
|
1671
1637
|
for (let i = 0; i < parsed.clientScripts.length; i++) parsed.clientScripts[i].content = getClientScriptVirtualUrl(baseName, i, parsed.clientScripts.length);
|
|
1672
1638
|
return {
|
|
1673
|
-
code:
|
|
1639
|
+
code: compileTemplate(code, {
|
|
1674
1640
|
root: state.config.root,
|
|
1675
1641
|
clientScripts: parsed.clientScripts,
|
|
1676
1642
|
blockingScripts: parsed.blockingScripts,
|
|
1677
1643
|
inlineScripts: parsed.inlineScripts,
|
|
1678
1644
|
resolvePath: state.aliasResult.resolve,
|
|
1679
1645
|
importer: filePath
|
|
1680
|
-
}),
|
|
1646
|
+
}, parsed),
|
|
1681
1647
|
map: null
|
|
1682
1648
|
};
|
|
1683
1649
|
} catch {
|
|
@@ -1714,14 +1680,14 @@ function createAeroTransformPlugin(state) {
|
|
|
1714
1680
|
for (let i = 0; i < parsed.clientScripts.length; i++) parsed.clientScripts[i].content = getClientScriptVirtualUrl(baseName, i, parsed.clientScripts.length);
|
|
1715
1681
|
}
|
|
1716
1682
|
return {
|
|
1717
|
-
code:
|
|
1683
|
+
code: compileTemplate(code, {
|
|
1718
1684
|
root: state.config.root,
|
|
1719
1685
|
clientScripts: parsed.clientScripts,
|
|
1720
1686
|
blockingScripts: parsed.blockingScripts,
|
|
1721
1687
|
inlineScripts: parsed.inlineScripts,
|
|
1722
1688
|
resolvePath: state.aliasResult.resolve,
|
|
1723
1689
|
importer: id
|
|
1724
|
-
}),
|
|
1690
|
+
}, parsed),
|
|
1725
1691
|
map: null
|
|
1726
1692
|
};
|
|
1727
1693
|
} catch (err) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aerobuilt/core",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Jamie Wilson",
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
"sharp": "^0.34.5",
|
|
61
61
|
"svgo": "^4.0.0",
|
|
62
62
|
"vite-plugin-image-optimizer": "^2.0.3",
|
|
63
|
-
"@aerobuilt/interpolation": "0.3.
|
|
63
|
+
"@aerobuilt/interpolation": "0.3.2"
|
|
64
64
|
},
|
|
65
65
|
"peerDependencies": {
|
|
66
66
|
"vite": "^8.0.0-0"
|