@anubhav-choubey/web-for-agents 0.1.0 → 0.2.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/README.md +74 -515
- package/dist/bin.js +4 -4
- package/dist/chunk-CGIIB6AF.js +127 -0
- package/dist/{chunk-AZG5MLNG.js → chunk-F7PN5R25.js} +2 -0
- package/dist/chunk-LCVPXUFN.js +245 -0
- package/dist/{chunk-IF32TPGR.js → chunk-P6JSPAA2.js} +169 -124
- package/dist/{chunk-5TNG4QMP.js → chunk-PGZH33B5.js} +20 -2
- package/dist/chunk-PHTV5NAY.js +44 -0
- package/dist/{chunk-ZYMNO5AO.js → chunk-PSNLS4GL.js} +93 -57
- package/dist/{chunk-HONWT6GK.js → chunk-SMFRAZAA.js} +66 -34
- package/dist/cli.js +4 -4
- package/dist/{happyDom-XVDHYJDM.js → happyDom-WTYQ5UAC.js} +3 -3
- package/dist/index.js +41 -235
- package/dist/overlay.js +7 -32
- package/dist/{renderChild-Y2RFSYY4.js → renderChild-H6TR4SGV.js} +27 -4
- package/dist/vite.d.ts +88 -2
- package/dist/vite.js +628 -146
- package/package.json +1 -1
- package/dist/chunk-CKXHTGGT.js +0 -25
- package/dist/chunk-LCVI2PRP.js +0 -13
package/dist/vite.js
CHANGED
|
@@ -1,19 +1,27 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
EMPTY_OBJECT_SCHEMA,
|
|
3
|
+
schemaFromForm
|
|
4
|
+
} from "./chunk-LCVPXUFN.js";
|
|
4
5
|
import {
|
|
5
|
-
|
|
6
|
-
|
|
6
|
+
AI_BOTS,
|
|
7
|
+
scanHtml
|
|
8
|
+
} from "./chunk-CGIIB6AF.js";
|
|
9
|
+
import {
|
|
10
|
+
AGENT_MAP_VERSION,
|
|
11
|
+
isValidActionName,
|
|
12
|
+
metaLengthWarnings
|
|
13
|
+
} from "./chunk-PHTV5NAY.js";
|
|
7
14
|
import {
|
|
8
15
|
DEFAULT_CONTENT_SELECTOR,
|
|
9
16
|
DEFAULT_SHORTCUT,
|
|
10
17
|
buildPageMarkdown,
|
|
11
18
|
escapeLinkTarget,
|
|
12
19
|
escapeMarkdownInline,
|
|
20
|
+
markupActions,
|
|
13
21
|
parseShortcut,
|
|
14
22
|
readPageMeta,
|
|
15
23
|
selectContentRegion
|
|
16
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-PSNLS4GL.js";
|
|
17
25
|
import {
|
|
18
26
|
compareStrings
|
|
19
27
|
} from "./chunk-AAIYCJD3.js";
|
|
@@ -25,13 +33,15 @@ import {
|
|
|
25
33
|
TEMP_BASE_ATTR,
|
|
26
34
|
prepareShell,
|
|
27
35
|
readyCheck
|
|
28
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-SMFRAZAA.js";
|
|
29
37
|
import {
|
|
30
38
|
AGENT_GLOBAL,
|
|
31
39
|
AGENT_MAP_PATH,
|
|
32
40
|
CONTENT_ATTR,
|
|
41
|
+
HEAD_OWNED_ATTR,
|
|
33
42
|
LLMS_FULL_TXT_PATH,
|
|
34
43
|
LLMS_TXT_PATH,
|
|
44
|
+
MARKDOWN_LINK_KEY,
|
|
35
45
|
MARKDOWN_MIME,
|
|
36
46
|
PRERENDERED_ATTR,
|
|
37
47
|
ROBOTS_PATH,
|
|
@@ -42,19 +52,23 @@ import {
|
|
|
42
52
|
normalizeRoute,
|
|
43
53
|
publicUrl,
|
|
44
54
|
trimTrailingSlash
|
|
45
|
-
} from "./chunk-
|
|
55
|
+
} from "./chunk-F7PN5R25.js";
|
|
46
56
|
import {
|
|
47
57
|
POLL_MS,
|
|
48
58
|
RenderError,
|
|
49
59
|
SERIALIZE_EXPR,
|
|
60
|
+
SNAPSHOT_GRACE_MS,
|
|
61
|
+
TimeoutError,
|
|
62
|
+
assertNoPageErrors,
|
|
50
63
|
blockedHint,
|
|
51
64
|
createDeadline,
|
|
52
65
|
createOriginPolicy,
|
|
53
66
|
readyTimeoutMessage,
|
|
54
67
|
runInPage,
|
|
68
|
+
snapshotWarning,
|
|
55
69
|
waitForReady,
|
|
56
70
|
withoutBlockedLoads
|
|
57
|
-
} from "./chunk-
|
|
71
|
+
} from "./chunk-PGZH33B5.js";
|
|
58
72
|
import {
|
|
59
73
|
LOG_PREFIX,
|
|
60
74
|
errorMessage,
|
|
@@ -77,9 +91,18 @@ function segments(route) {
|
|
|
77
91
|
function decodeSegments(route) {
|
|
78
92
|
return segments(normalizeRoute(route)).map((s) => decodeURIComponent(s));
|
|
79
93
|
}
|
|
80
|
-
function
|
|
94
|
+
function encodePathSegment(segment) {
|
|
95
|
+
return encodeURIComponent(segment).replace(/%(24|26|2B|2C|3B|3D|3A|40)/g, (m) => decodeURIComponent(m));
|
|
96
|
+
}
|
|
97
|
+
function routeOfHtmlFile(file) {
|
|
98
|
+
const segs = file.slice(0, -".html".length).split("/");
|
|
99
|
+
if (segs[segs.length - 1] === "index") segs.pop();
|
|
100
|
+
return "/" + segs.map(encodePathSegment).join("/");
|
|
101
|
+
}
|
|
102
|
+
function routeHtmlFile(route, layout = "directory") {
|
|
81
103
|
const segs = decodeSegments(route);
|
|
82
|
-
|
|
104
|
+
if (segs.length === 0) return "index.html";
|
|
105
|
+
return segs.join("/") + (layout === "flat" ? ".html" : "/index.html");
|
|
83
106
|
}
|
|
84
107
|
function routeMdFile(route) {
|
|
85
108
|
return markdownPathFor(route).slice(1).split("/").map((s) => decodeURIComponent(s)).join("/");
|
|
@@ -108,7 +131,7 @@ function isSafeRoute(route) {
|
|
|
108
131
|
var MAX_NAME_BYTES = 255;
|
|
109
132
|
var MAX_SEGMENT_BYTES = MAX_NAME_BYTES - ".md".length;
|
|
110
133
|
var MAX_ROUTE_BYTES = 1024;
|
|
111
|
-
function isRouteTooLong(route) {
|
|
134
|
+
function isRouteTooLong(route, layout = "directory") {
|
|
112
135
|
let segs;
|
|
113
136
|
try {
|
|
114
137
|
segs = decodeSegments(route);
|
|
@@ -116,9 +139,10 @@ function isRouteTooLong(route) {
|
|
|
116
139
|
return false;
|
|
117
140
|
}
|
|
118
141
|
let total = 0;
|
|
119
|
-
|
|
142
|
+
const leafMax = layout === "flat" ? MAX_NAME_BYTES - ".html".length : MAX_SEGMENT_BYTES;
|
|
143
|
+
for (const [i, s] of segs.entries()) {
|
|
120
144
|
const n = Buffer.byteLength(s, "utf8");
|
|
121
|
-
if (n > MAX_SEGMENT_BYTES) return true;
|
|
145
|
+
if (n > (i === segs.length - 1 ? leafMax : MAX_SEGMENT_BYTES)) return true;
|
|
122
146
|
total += n + 1;
|
|
123
147
|
}
|
|
124
148
|
return total > MAX_ROUTE_BYTES;
|
|
@@ -136,16 +160,16 @@ function linkToRoute(href, origin, base) {
|
|
|
136
160
|
if (u.protocol !== "http:" && u.protocol !== "https:") return null;
|
|
137
161
|
if (u.origin !== new URL(origin).origin) return null;
|
|
138
162
|
const b = trimTrailingSlash(base);
|
|
139
|
-
let
|
|
163
|
+
let path6 = u.pathname;
|
|
140
164
|
if (b !== "") {
|
|
141
|
-
if (
|
|
142
|
-
|
|
165
|
+
if (path6 !== b && !path6.startsWith(b + "/")) return null;
|
|
166
|
+
path6 = path6.slice(b.length);
|
|
143
167
|
}
|
|
144
|
-
if (
|
|
145
|
-
|
|
146
|
-
const last =
|
|
168
|
+
if (path6 === "") path6 = "/";
|
|
169
|
+
path6 = path6.replace(/\/index\.html$/, "") || "/";
|
|
170
|
+
const last = path6.split("/").pop();
|
|
147
171
|
if (/\.[a-z0-9]+$/i.test(last)) return null;
|
|
148
|
-
const route = normalizeRoute(
|
|
172
|
+
const route = normalizeRoute(path6);
|
|
149
173
|
return isSafeRoute(route) ? route : null;
|
|
150
174
|
}
|
|
151
175
|
|
|
@@ -231,6 +255,21 @@ function outputFileName(fileName) {
|
|
|
231
255
|
}
|
|
232
256
|
return rel;
|
|
233
257
|
}
|
|
258
|
+
function symlinkOnPath(outDir, rel) {
|
|
259
|
+
let p = outDir;
|
|
260
|
+
const parts = rel.split("/");
|
|
261
|
+
for (let i = 0; i < parts.length; i++) {
|
|
262
|
+
p = path.join(p, parts[i]);
|
|
263
|
+
let st;
|
|
264
|
+
try {
|
|
265
|
+
st = fs.lstatSync(p);
|
|
266
|
+
} catch {
|
|
267
|
+
return null;
|
|
268
|
+
}
|
|
269
|
+
if (st.isSymbolicLink()) return parts.slice(0, i + 1).join("/");
|
|
270
|
+
}
|
|
271
|
+
return null;
|
|
272
|
+
}
|
|
234
273
|
var short = (s, max) => s.length <= max ? s : s.slice(0, max - 1) + "\u2026";
|
|
235
274
|
function createFileStager(opts) {
|
|
236
275
|
const files = /* @__PURE__ */ new Map();
|
|
@@ -247,6 +286,14 @@ function createFileStager(opts) {
|
|
|
247
286
|
stage(fileName, source) {
|
|
248
287
|
const file = outputFileName(fileName);
|
|
249
288
|
if (inPublicDir(file)) return { file, status: "skipped" };
|
|
289
|
+
const link = symlinkOnPath(opts.outDir, file);
|
|
290
|
+
if (link !== null) {
|
|
291
|
+
if (!warned.has("link:" + file)) {
|
|
292
|
+
warned.add("link:" + file);
|
|
293
|
+
opts.warn(`${LOG_PREFIX} ${link} is a symbolic link; not writing ${file} through it`);
|
|
294
|
+
}
|
|
295
|
+
return { file, status: "skipped" };
|
|
296
|
+
}
|
|
250
297
|
const status = files.has(file) ? "replaced" : "staged";
|
|
251
298
|
files.set(file, source);
|
|
252
299
|
return { file, status };
|
|
@@ -299,34 +346,6 @@ function createFileStager(opts) {
|
|
|
299
346
|
};
|
|
300
347
|
}
|
|
301
348
|
|
|
302
|
-
// src/vite/llms.ts
|
|
303
|
-
function header(site) {
|
|
304
|
-
const blocks = [`# ${escapeMarkdownInline(site.title)}`];
|
|
305
|
-
const desc = escapeMarkdownInline(site.description);
|
|
306
|
-
if (desc) blocks.push(`> ${desc}`);
|
|
307
|
-
return blocks;
|
|
308
|
-
}
|
|
309
|
-
function buildLlmsTxt(site, pages, sections = []) {
|
|
310
|
-
const blocks = header(site);
|
|
311
|
-
const lines = [...pages].sort(byRoute).map((p) => {
|
|
312
|
-
const title = escapeMarkdownInline(p.title);
|
|
313
|
-
const desc = escapeMarkdownInline(p.description);
|
|
314
|
-
return `- [${title}](${escapeLinkTarget(p.mdUrl ?? p.url)})${desc ? `: ${desc}` : ""}`;
|
|
315
|
-
});
|
|
316
|
-
blocks.push(["## Pages", ...lines.length ? ["", ...lines] : []].join("\n"));
|
|
317
|
-
for (const s of sections) {
|
|
318
|
-
blocks.push([`## ${s.heading}`, ...s.lines.length ? ["", ...s.lines] : []].join("\n"));
|
|
319
|
-
}
|
|
320
|
-
return blocks.join("\n\n") + "\n";
|
|
321
|
-
}
|
|
322
|
-
function buildLlmsFullTxt(site, pages) {
|
|
323
|
-
const head = header(site).join("\n\n");
|
|
324
|
-
const blocks = [...pages].sort(byRoute).filter((p) => p.markdown !== void 0).map((p) => `Source: ${p.url}
|
|
325
|
-
|
|
326
|
-
${p.markdown.trim()}`);
|
|
327
|
-
return [head, blocks.join("\n\n---\n\n")].filter(Boolean).join("\n\n") + "\n";
|
|
328
|
-
}
|
|
329
|
-
|
|
330
349
|
// src/vite/prerender/happyDomProcess.ts
|
|
331
350
|
import { fork } from "child_process";
|
|
332
351
|
import { createHash } from "crypto";
|
|
@@ -352,7 +371,7 @@ function nodeModulesRoot(file) {
|
|
|
352
371
|
}
|
|
353
372
|
var sourceEntry;
|
|
354
373
|
async function childEntryFile() {
|
|
355
|
-
const { CHILD_ENTRY } = await import("./renderChild-
|
|
374
|
+
const { CHILD_ENTRY } = await import("./renderChild-H6TR4SGV.js");
|
|
356
375
|
const file = fileURLToPath(CHILD_ENTRY);
|
|
357
376
|
if (!file.endsWith(".ts")) return file;
|
|
358
377
|
return sourceEntry ??= bundleFromSource(file);
|
|
@@ -732,8 +751,18 @@ function resolvePrerender(input) {
|
|
|
732
751
|
concurrency: posInt("concurrency", input.concurrency, usesBrowser ? 4 : 8),
|
|
733
752
|
maxRoutes: posInt("maxRoutes", input.maxRoutes, 500),
|
|
734
753
|
allowOrigins,
|
|
735
|
-
isolation: resolveIsolation(input.isolation, bad)
|
|
754
|
+
isolation: resolveIsolation(input.isolation, bad),
|
|
755
|
+
fileLayout: input.fileLayout ?? "directory",
|
|
756
|
+
onTimeout: input.onTimeout ?? "fail"
|
|
736
757
|
};
|
|
758
|
+
if (out.fileLayout !== "directory" && out.fileLayout !== "flat") bad("fileLayout", '"directory" or "flat"');
|
|
759
|
+
if (out.onTimeout !== "fail" && out.onTimeout !== "snapshot") bad("onTimeout", '"fail" or "snapshot"');
|
|
760
|
+
if (input.readySelector !== void 0) {
|
|
761
|
+
if (typeof input.readySelector !== "string" || input.readySelector.trim() === "") {
|
|
762
|
+
bad("readySelector", "a non-empty string");
|
|
763
|
+
}
|
|
764
|
+
out.readySelector = input.readySelector;
|
|
765
|
+
}
|
|
737
766
|
if (input.executablePath !== void 0) out.executablePath = input.executablePath;
|
|
738
767
|
if (input.idleMs !== void 0) {
|
|
739
768
|
if (typeof input.idleMs !== "number" || !Number.isInteger(input.idleMs) || input.idleMs < 0) {
|
|
@@ -751,6 +780,21 @@ function agentOutputs(r) {
|
|
|
751
780
|
if (r.agentMap) out.push(r.agentMap.fileName);
|
|
752
781
|
return out;
|
|
753
782
|
}
|
|
783
|
+
function resolveMarkdown(input) {
|
|
784
|
+
if (input !== void 0 && (typeof input !== "object" || input === null)) {
|
|
785
|
+
throw new Error(withPrefix("markdown must be false or { contentSelector, transform }"));
|
|
786
|
+
}
|
|
787
|
+
const sel = input?.contentSelector;
|
|
788
|
+
if (sel !== void 0 && (typeof sel !== "string" || sel === "")) {
|
|
789
|
+
throw new Error(`${LOG_PREFIX} markdown.contentSelector must be a non-empty string`);
|
|
790
|
+
}
|
|
791
|
+
const out = { contentSelector: sel ?? DEFAULT_CONTENT_SELECTOR };
|
|
792
|
+
if (input?.transform !== void 0) {
|
|
793
|
+
if (typeof input.transform !== "function") throw new Error(withPrefix("markdown.transform must be a function"));
|
|
794
|
+
out.transform = input.transform;
|
|
795
|
+
}
|
|
796
|
+
return out;
|
|
797
|
+
}
|
|
754
798
|
var AGENT_MAP_FILE = /^[A-Za-z0-9_.-]+\.json$/;
|
|
755
799
|
function resolveAgentMap(input) {
|
|
756
800
|
if (input === false) return false;
|
|
@@ -814,8 +858,8 @@ function resolveOptions(input) {
|
|
|
814
858
|
throw new Error(`${LOG_PREFIX} robots.ai.overrides.${bot} must be "allow" or "block"`);
|
|
815
859
|
}
|
|
816
860
|
}
|
|
817
|
-
for (const
|
|
818
|
-
if (/[\r\n]/.test(
|
|
861
|
+
for (const path6 of input.robots.disallow ?? []) {
|
|
862
|
+
if (/[\r\n]/.test(path6)) {
|
|
819
863
|
throw new Error(`${LOG_PREFIX} robots.disallow paths must not contain line breaks`);
|
|
820
864
|
}
|
|
821
865
|
}
|
|
@@ -836,13 +880,7 @@ function resolveOptions(input) {
|
|
|
836
880
|
warnings.push(withPrefix(`${names} ${verb} disabled because prerender is false`));
|
|
837
881
|
}
|
|
838
882
|
} else {
|
|
839
|
-
if (input.markdown !== false)
|
|
840
|
-
const sel = input.markdown?.contentSelector;
|
|
841
|
-
if (sel !== void 0 && (typeof sel !== "string" || sel === "")) {
|
|
842
|
-
throw new Error(`${LOG_PREFIX} markdown.contentSelector must be a non-empty string`);
|
|
843
|
-
}
|
|
844
|
-
markdown = { contentSelector: sel ?? DEFAULT_CONTENT_SELECTOR };
|
|
845
|
-
}
|
|
883
|
+
if (input.markdown !== false) markdown = resolveMarkdown(input.markdown);
|
|
846
884
|
if (input.llms !== false) llms = { ...input.llms };
|
|
847
885
|
agentMap = requestedAgentMap;
|
|
848
886
|
}
|
|
@@ -984,9 +1022,9 @@ function finalizeDocument(document, opts) {
|
|
|
984
1022
|
if (!u.startsWith(origin)) return u;
|
|
985
1023
|
const rest = u.slice(origin.length);
|
|
986
1024
|
if (rest !== "" && !/^[/?#]/.test(rest)) return u;
|
|
987
|
-
const
|
|
988
|
-
if (opts.fullBase) return trimTrailingSlash(opts.fullBase) + "/" +
|
|
989
|
-
return opts.relativeBase ? "." +
|
|
1025
|
+
const path6 = rest.startsWith("/") ? rest : "/" + rest;
|
|
1026
|
+
if (opts.fullBase) return trimTrailingSlash(opts.fullBase) + "/" + path6.slice(1);
|
|
1027
|
+
return opts.relativeBase ? "." + path6 : path6;
|
|
990
1028
|
}, attrs);
|
|
991
1029
|
}
|
|
992
1030
|
if (opts.relativeBase) {
|
|
@@ -1050,7 +1088,7 @@ async function crawlRoutes(opts, render) {
|
|
|
1050
1088
|
const seeds = [];
|
|
1051
1089
|
for (const s of [...new Set(opts.seeds.map(normalizeRoute))].sort()) {
|
|
1052
1090
|
if (!isSafeRoute(s)) continue;
|
|
1053
|
-
if (isRouteTooLong(s)) seedTooLong.push(s);
|
|
1091
|
+
if (isRouteTooLong(s, opts.fileLayout)) seedTooLong.push(s);
|
|
1054
1092
|
else if (!skip(s)) seeds.push(s);
|
|
1055
1093
|
}
|
|
1056
1094
|
const attempt = async (route, renderer) => {
|
|
@@ -1104,7 +1142,7 @@ async function crawlRoutes(opts, render) {
|
|
|
1104
1142
|
const tooLong2 = [];
|
|
1105
1143
|
const candidate = (r) => {
|
|
1106
1144
|
if (r === null || isExcluded(r, opts.exclude)) return false;
|
|
1107
|
-
if (isRouteTooLong(r)) {
|
|
1145
|
+
if (isRouteTooLong(r, opts.fileLayout)) {
|
|
1108
1146
|
tooLong2.push(r);
|
|
1109
1147
|
return false;
|
|
1110
1148
|
}
|
|
@@ -1286,7 +1324,7 @@ async function createChromeRenderer(channel, opts = {}, load = () => import("pla
|
|
|
1286
1324
|
}
|
|
1287
1325
|
const allowed = createOriginPolicy(opts.allowOrigins);
|
|
1288
1326
|
const idleMs = opts.idleMs ?? IDLE_MS;
|
|
1289
|
-
const check = readyCheck(idleMs);
|
|
1327
|
+
const check = readyCheck(idleMs, opts.readySelector);
|
|
1290
1328
|
let gone = false;
|
|
1291
1329
|
browser.on?.("disconnected", () => {
|
|
1292
1330
|
gone = true;
|
|
@@ -1303,8 +1341,9 @@ async function createChromeRenderer(channel, opts = {}, load = () => import("pla
|
|
|
1303
1341
|
return e;
|
|
1304
1342
|
};
|
|
1305
1343
|
const renderPage = async (url, timeoutMs, inPage) => {
|
|
1306
|
-
|
|
1307
|
-
|
|
1344
|
+
let deadline = createDeadline(timeoutMs);
|
|
1345
|
+
let timeoutText = readyTimeoutMessage(timeoutMs);
|
|
1346
|
+
let budgetMs = timeoutMs;
|
|
1308
1347
|
const origin = new URL(url).origin;
|
|
1309
1348
|
const blocked = [];
|
|
1310
1349
|
const opening = browser.newPage({ serviceWorkers: "block" }).then(async (p) => {
|
|
@@ -1345,22 +1384,35 @@ async function createChromeRenderer(channel, opts = {}, load = () => import("pla
|
|
|
1345
1384
|
page.on("pageerror", (e) => pageErrors.push(e.message));
|
|
1346
1385
|
let html;
|
|
1347
1386
|
let finalPath;
|
|
1387
|
+
let timedOut = false;
|
|
1348
1388
|
try {
|
|
1349
1389
|
await deadline.race(
|
|
1350
1390
|
page.goto(url, { waitUntil: "load", timeout: deadline.remaining() + 1e3 }),
|
|
1351
1391
|
timeoutText
|
|
1352
1392
|
);
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1393
|
+
try {
|
|
1394
|
+
await deadline.race(
|
|
1395
|
+
waitForReady(
|
|
1396
|
+
async () => {
|
|
1397
|
+
const r = await page.evaluate(check);
|
|
1398
|
+
return { ready: r.ready, errors: withoutBlockedLoads([...pageErrors, ...r.errors], blocked) };
|
|
1399
|
+
},
|
|
1400
|
+
timeoutMs,
|
|
1401
|
+
Math.min(POLL_MS, idleMs)
|
|
1402
|
+
),
|
|
1403
|
+
timeoutText
|
|
1404
|
+
);
|
|
1405
|
+
} catch (e) {
|
|
1406
|
+
if (!(opts.onTimeout === "snapshot" && e instanceof TimeoutError)) throw e;
|
|
1407
|
+
timedOut = true;
|
|
1408
|
+
deadline = createDeadline(SNAPSHOT_GRACE_MS);
|
|
1409
|
+
budgetMs = SNAPSHOT_GRACE_MS;
|
|
1410
|
+
timeoutText = readyTimeoutMessage(SNAPSHOT_GRACE_MS);
|
|
1411
|
+
await assertNoPageErrors(async () => {
|
|
1412
|
+
const r = await deadline.race(page.evaluate(check), timeoutText);
|
|
1413
|
+
return withoutBlockedLoads([...pageErrors, ...r.errors], blocked);
|
|
1414
|
+
});
|
|
1415
|
+
}
|
|
1364
1416
|
html = await deadline.race(page.evaluate(SERIALIZE_EXPR), timeoutText);
|
|
1365
1417
|
finalPath = new URL(page.url()).pathname;
|
|
1366
1418
|
} catch (e) {
|
|
@@ -1371,9 +1423,9 @@ async function createChromeRenderer(channel, opts = {}, load = () => import("pla
|
|
|
1371
1423
|
inPage,
|
|
1372
1424
|
(expr) => page.evaluate(expr),
|
|
1373
1425
|
deadline,
|
|
1374
|
-
|
|
1426
|
+
budgetMs
|
|
1375
1427
|
);
|
|
1376
|
-
return { html, finalPath, inPage: results };
|
|
1428
|
+
return { html, finalPath, inPage: results, ...timedOut ? { warnings: [snapshotWarning(timeoutMs)] } : {} };
|
|
1377
1429
|
} finally {
|
|
1378
1430
|
await settleWithin(page.close(), opts.pageCloseMs ?? PAGE_CLOSE_MS);
|
|
1379
1431
|
}
|
|
@@ -1397,6 +1449,10 @@ async function createChromeRenderer(channel, opts = {}, load = () => import("pla
|
|
|
1397
1449
|
// src/vite/prerender/renderers.ts
|
|
1398
1450
|
function createRendererPool(opts) {
|
|
1399
1451
|
const made = /* @__PURE__ */ new Map();
|
|
1452
|
+
const readiness = {
|
|
1453
|
+
...opts.readySelector !== void 0 ? { readySelector: opts.readySelector } : {},
|
|
1454
|
+
...opts.onTimeout !== void 0 ? { onTimeout: opts.onTimeout } : {}
|
|
1455
|
+
};
|
|
1400
1456
|
return {
|
|
1401
1457
|
get(name) {
|
|
1402
1458
|
let r = made.get(name);
|
|
@@ -1406,6 +1462,7 @@ function createRendererPool(opts) {
|
|
|
1406
1462
|
{
|
|
1407
1463
|
allowOrigins: opts.allowOrigins ?? [],
|
|
1408
1464
|
...opts.idleMs !== void 0 ? { idleMs: opts.idleMs } : {},
|
|
1465
|
+
...readiness,
|
|
1409
1466
|
...opts.syncResources ? { syncResources: opts.syncResources } : {}
|
|
1410
1467
|
},
|
|
1411
1468
|
{ codeGeneration: opts.codeGeneration === true }
|
|
@@ -1413,7 +1470,8 @@ function createRendererPool(opts) {
|
|
|
1413
1470
|
) : createChromeRenderer(name, {
|
|
1414
1471
|
...opts.executablePath !== void 0 ? { executablePath: opts.executablePath } : {},
|
|
1415
1472
|
allowOrigins: opts.allowOrigins ?? [],
|
|
1416
|
-
...opts.idleMs !== void 0 ? { idleMs: opts.idleMs } : {}
|
|
1473
|
+
...opts.idleMs !== void 0 ? { idleMs: opts.idleMs } : {},
|
|
1474
|
+
...readiness
|
|
1417
1475
|
});
|
|
1418
1476
|
made.set(name, r);
|
|
1419
1477
|
}
|
|
@@ -1433,7 +1491,25 @@ import { createServer } from "http";
|
|
|
1433
1491
|
import { realpathSync as realpathSync2 } from "fs";
|
|
1434
1492
|
import { readFile, realpath, stat } from "fs/promises";
|
|
1435
1493
|
import { extname, resolve, sep } from "path";
|
|
1436
|
-
|
|
1494
|
+
var viteParseAst;
|
|
1495
|
+
var VITE_MISSING = "prerendering needs the vite package, which is not installed: npm i -D vite. To add agent files to HTML you prerendered yourself, use web-for-agents generate, which does not need vite.";
|
|
1496
|
+
function isPackageNotFound(e, pkg) {
|
|
1497
|
+
const code = e?.code;
|
|
1498
|
+
if (code !== "ERR_MODULE_NOT_FOUND" && code !== "MODULE_NOT_FOUND") return false;
|
|
1499
|
+
return new RegExp(`(Cannot find (package|module) ['"]${pkg}['"])`).test(errorMessage(e));
|
|
1500
|
+
}
|
|
1501
|
+
async function loadViteParser(importVite = () => import("vite")) {
|
|
1502
|
+
if (viteParseAst) return viteParseAst;
|
|
1503
|
+
let mod;
|
|
1504
|
+
try {
|
|
1505
|
+
mod = await importVite();
|
|
1506
|
+
} catch (e) {
|
|
1507
|
+
if (isPackageNotFound(e, "vite")) throw new Error(withPrefix(VITE_MISSING), { cause: e });
|
|
1508
|
+
throw e;
|
|
1509
|
+
}
|
|
1510
|
+
viteParseAst = mod.parseAst;
|
|
1511
|
+
return viteParseAst;
|
|
1512
|
+
}
|
|
1437
1513
|
var TYPES = {
|
|
1438
1514
|
".html": "text/html; charset=utf-8",
|
|
1439
1515
|
".js": "text/javascript; charset=utf-8",
|
|
@@ -1458,6 +1534,8 @@ function fixImportMeta(code) {
|
|
|
1458
1534
|
}
|
|
1459
1535
|
function parenthesizeRegExps(code) {
|
|
1460
1536
|
if (!code.includes("/")) return code;
|
|
1537
|
+
const parseAst = viteParseAst;
|
|
1538
|
+
if (!parseAst) throw new Error(withPrefix("internal: loadViteParser() must run before parenthesizeRegExps"));
|
|
1461
1539
|
let ast;
|
|
1462
1540
|
try {
|
|
1463
1541
|
ast = parseAst(code, { sourceType: "module" });
|
|
@@ -1576,7 +1654,8 @@ function startStaticServer(opts) {
|
|
|
1576
1654
|
send(500, "text/plain; charset=utf-8", "Internal error");
|
|
1577
1655
|
}
|
|
1578
1656
|
});
|
|
1579
|
-
|
|
1657
|
+
const ready = compat ? loadViteParser() : Promise.resolve();
|
|
1658
|
+
return ready.then(() => new Promise((resolveP, reject) => {
|
|
1580
1659
|
server.once("error", reject);
|
|
1581
1660
|
server.listen(0, "127.0.0.1", () => {
|
|
1582
1661
|
const { port } = server.address();
|
|
@@ -1590,7 +1669,7 @@ function startStaticServer(opts) {
|
|
|
1590
1669
|
})
|
|
1591
1670
|
});
|
|
1592
1671
|
});
|
|
1593
|
-
});
|
|
1672
|
+
}));
|
|
1594
1673
|
}
|
|
1595
1674
|
|
|
1596
1675
|
// src/vite/prerender/index.ts
|
|
@@ -1626,6 +1705,8 @@ async function prerenderSite(input) {
|
|
|
1626
1705
|
...pr.executablePath !== void 0 ? { executablePath: pr.executablePath } : {},
|
|
1627
1706
|
allowOrigins: pr.allowOrigins,
|
|
1628
1707
|
...pr.idleMs !== void 0 ? { idleMs: pr.idleMs } : {},
|
|
1708
|
+
...pr.readySelector !== void 0 ? { readySelector: pr.readySelector } : {},
|
|
1709
|
+
onTimeout: pr.onTimeout,
|
|
1629
1710
|
codeGeneration: pr.isolation.codeGeneration,
|
|
1630
1711
|
syncResources
|
|
1631
1712
|
});
|
|
@@ -1647,7 +1728,8 @@ async function prerenderSite(input) {
|
|
|
1647
1728
|
contentSelector: markdown ? markdown.contentSelector : DEFAULT_CONTENT_SELECTOR,
|
|
1648
1729
|
...markdown ? { markdownUrl: (route) => publicMdUrl(options.siteUrl, route) } : {},
|
|
1649
1730
|
inPage,
|
|
1650
|
-
skipRoute: input.skipRoute
|
|
1731
|
+
skipRoute: input.skipRoute,
|
|
1732
|
+
fileLayout: pr.fileLayout
|
|
1651
1733
|
},
|
|
1652
1734
|
async (url, renderer, timeoutMs, scripts) => (await pool.get(renderer)).render(url, timeoutMs, scripts)
|
|
1653
1735
|
).catch((e) => {
|
|
@@ -1777,7 +1859,35 @@ function buildSitemap(siteUrl, routes) {
|
|
|
1777
1859
|
return '<?xml version="1.0" encoding="UTF-8"?>\n<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n' + urls + "\n</urlset>\n";
|
|
1778
1860
|
}
|
|
1779
1861
|
|
|
1780
|
-
// src/vite/
|
|
1862
|
+
// src/vite/llms.ts
|
|
1863
|
+
function header(site) {
|
|
1864
|
+
const blocks = [`# ${escapeMarkdownInline(site.title)}`];
|
|
1865
|
+
const desc = escapeMarkdownInline(site.description);
|
|
1866
|
+
if (desc) blocks.push(`> ${desc}`);
|
|
1867
|
+
return blocks;
|
|
1868
|
+
}
|
|
1869
|
+
function buildLlmsTxt(site, pages, sections = []) {
|
|
1870
|
+
const blocks = header(site);
|
|
1871
|
+
const lines = [...pages].sort(byRoute).map((p) => {
|
|
1872
|
+
const title = escapeMarkdownInline(p.title);
|
|
1873
|
+
const desc = escapeMarkdownInline(p.description);
|
|
1874
|
+
return `- [${title}](${escapeLinkTarget(p.mdUrl ?? p.url)})${desc ? `: ${desc}` : ""}`;
|
|
1875
|
+
});
|
|
1876
|
+
blocks.push(["## Pages", ...lines.length ? ["", ...lines] : []].join("\n"));
|
|
1877
|
+
for (const s of sections) {
|
|
1878
|
+
blocks.push([`## ${s.heading}`, ...s.lines.length ? ["", ...s.lines] : []].join("\n"));
|
|
1879
|
+
}
|
|
1880
|
+
return blocks.join("\n\n") + "\n";
|
|
1881
|
+
}
|
|
1882
|
+
function buildLlmsFullTxt(site, pages) {
|
|
1883
|
+
const head = header(site).join("\n\n");
|
|
1884
|
+
const blocks = [...pages].sort(byRoute).filter((p) => p.markdown !== void 0).map((p) => `Source: ${p.url}
|
|
1885
|
+
|
|
1886
|
+
${p.markdown.trim()}`);
|
|
1887
|
+
return [head, blocks.join("\n\n---\n\n")].filter(Boolean).join("\n\n") + "\n";
|
|
1888
|
+
}
|
|
1889
|
+
|
|
1890
|
+
// src/vite/siteFiles.ts
|
|
1781
1891
|
var SPA_FALLBACK_FILE = "200.html";
|
|
1782
1892
|
var fileOf = (urlPath) => urlPath.slice(1);
|
|
1783
1893
|
function prefixed(e, context) {
|
|
@@ -1792,6 +1902,105 @@ async function callHook(ext, hook, fn) {
|
|
|
1792
1902
|
throw prefixed(e, `extension "${ext.name}" ${hook} failed`);
|
|
1793
1903
|
}
|
|
1794
1904
|
}
|
|
1905
|
+
function dropFileCollisions(pages, filesOf, taken, warn) {
|
|
1906
|
+
const kept = [];
|
|
1907
|
+
for (const page of pages) {
|
|
1908
|
+
const files = filesOf(page);
|
|
1909
|
+
const clash = files.find((f) => taken.has(f));
|
|
1910
|
+
if (clash !== void 0) {
|
|
1911
|
+
warn(
|
|
1912
|
+
`${LOG_PREFIX} skipped ${shortRoute(page.route)}: its file ${clash} is already the file of ${taken.get(clash)}`
|
|
1913
|
+
);
|
|
1914
|
+
continue;
|
|
1915
|
+
}
|
|
1916
|
+
for (const f of files) taken.set(f, shortRoute(page.route));
|
|
1917
|
+
kept.push(page);
|
|
1918
|
+
}
|
|
1919
|
+
return kept;
|
|
1920
|
+
}
|
|
1921
|
+
async function pageMarkdown(markdown, page) {
|
|
1922
|
+
const md = buildPageMarkdown(page.info.title, page.info.contentHtml, page.url);
|
|
1923
|
+
if (!markdown.transform) return md;
|
|
1924
|
+
let out;
|
|
1925
|
+
try {
|
|
1926
|
+
out = await markdown.transform({
|
|
1927
|
+
route: page.route,
|
|
1928
|
+
url: page.url,
|
|
1929
|
+
title: page.info.title,
|
|
1930
|
+
...page.info.description !== void 0 ? { description: page.info.description } : {},
|
|
1931
|
+
markdown: md,
|
|
1932
|
+
html: page.html
|
|
1933
|
+
});
|
|
1934
|
+
} catch (e) {
|
|
1935
|
+
throw prefixed(e, `markdown.transform failed for ${shortRoute(page.route)}`);
|
|
1936
|
+
}
|
|
1937
|
+
if (out === void 0) return md;
|
|
1938
|
+
if (typeof out !== "string") {
|
|
1939
|
+
throw new Error(withPrefix(`markdown.transform must return a string or undefined (got ${typeof out} for ${shortRoute(page.route)})`));
|
|
1940
|
+
}
|
|
1941
|
+
return out;
|
|
1942
|
+
}
|
|
1943
|
+
function pageLengthWarnings(listed) {
|
|
1944
|
+
return metaLengthWarnings(
|
|
1945
|
+
listed.map((p) => {
|
|
1946
|
+
const out = { route: p.route };
|
|
1947
|
+
if (p.info.titleFromDocument) out.title = p.info.title;
|
|
1948
|
+
if (p.info.description !== void 0) out.description = p.info.description;
|
|
1949
|
+
return out;
|
|
1950
|
+
})
|
|
1951
|
+
);
|
|
1952
|
+
}
|
|
1953
|
+
async function stageSiteFiles(opts, stager, { pages: allPages, listed, mdByRoute }) {
|
|
1954
|
+
const { siteUrl, markdown, llms, extensions, logger } = opts;
|
|
1955
|
+
for (const ext of extensions) {
|
|
1956
|
+
if (!ext.onRoute) continue;
|
|
1957
|
+
for (const page of listed) {
|
|
1958
|
+
await callHook(ext, `onRoute(${page.route})`, () => ext.onRoute(page.route, page.inPage[ext.name]));
|
|
1959
|
+
}
|
|
1960
|
+
}
|
|
1961
|
+
const rootPage = allPages.find((p) => p.route === "/");
|
|
1962
|
+
const rootTitle = rootPage?.info.titleFromDocument ? rootPage.info.title : void 0;
|
|
1963
|
+
const site = {
|
|
1964
|
+
url: siteUrl,
|
|
1965
|
+
title: (llms ? llms.title : void 0) ?? rootTitle ?? new URL(siteUrl).hostname
|
|
1966
|
+
};
|
|
1967
|
+
const description = (llms ? llms.description : void 0) ?? rootPage?.info.description;
|
|
1968
|
+
if (description !== void 0) site.description = description;
|
|
1969
|
+
const pages = listed.map((p) => {
|
|
1970
|
+
const out = { route: p.route, title: p.info.title, url: publicUrl(siteUrl, p.route) };
|
|
1971
|
+
if (p.info.description !== void 0) out.description = p.info.description;
|
|
1972
|
+
if (markdown) out.mdUrl = publicMdUrl(siteUrl, p.route);
|
|
1973
|
+
return out;
|
|
1974
|
+
});
|
|
1975
|
+
if (llms) {
|
|
1976
|
+
const sections = [];
|
|
1977
|
+
for (const ext of extensions) {
|
|
1978
|
+
if (ext.llmsSections) sections.push(...await callHook(ext, "llmsSections", () => ext.llmsSections()));
|
|
1979
|
+
}
|
|
1980
|
+
const llmsPages = pages.map((p) => {
|
|
1981
|
+
const md = mdByRoute.get(p.route);
|
|
1982
|
+
return md !== void 0 ? { ...p, markdown: md } : { ...p };
|
|
1983
|
+
});
|
|
1984
|
+
stager.stage(fileOf(LLMS_TXT_PATH), buildLlmsTxt(site, llmsPages, sections));
|
|
1985
|
+
if (markdown) stager.stage(fileOf(LLMS_FULL_TXT_PATH), buildLlmsFullTxt(site, llmsPages));
|
|
1986
|
+
}
|
|
1987
|
+
for (const ext of extensions) {
|
|
1988
|
+
if (!ext.finalize) continue;
|
|
1989
|
+
const ctx = {
|
|
1990
|
+
site,
|
|
1991
|
+
pages,
|
|
1992
|
+
emitFile: (fileName, source) => {
|
|
1993
|
+
const { file, status } = stager.stage(fileName, source);
|
|
1994
|
+
if (status === "replaced") logger.warn(`${LOG_PREFIX} extension "${ext.name}" overwrote ${file}`);
|
|
1995
|
+
},
|
|
1996
|
+
warn: (msg) => logger.warn(withPrefix(msg))
|
|
1997
|
+
};
|
|
1998
|
+
if (llms) ctx.llmsUrl = publicUrl(siteUrl, LLMS_TXT_PATH);
|
|
1999
|
+
await callHook(ext, "finalize", () => ext.finalize(ctx));
|
|
2000
|
+
}
|
|
2001
|
+
}
|
|
2002
|
+
|
|
2003
|
+
// src/vite/buildPlugin.ts
|
|
1795
2004
|
function isClientEnv(env) {
|
|
1796
2005
|
if (!env) return true;
|
|
1797
2006
|
if (env.config?.consumer) return env.config.consumer === "client";
|
|
@@ -1814,6 +2023,7 @@ function createBuildPlugin(resolved, extensions) {
|
|
|
1814
2023
|
const shell = fs2.readFileSync(shellFile, "utf8");
|
|
1815
2024
|
stager.stage(SPA_FALLBACK_FILE, shell);
|
|
1816
2025
|
const pr = resolved.prerender;
|
|
2026
|
+
const layout = pr === false ? "directory" : pr.fileLayout;
|
|
1817
2027
|
if (pr !== false && mayUseHappyDom(pr) && !hasPermissionModel() && !warnedPermission) {
|
|
1818
2028
|
warnedPermission = true;
|
|
1819
2029
|
logger.warn(NO_PERMISSION_MODEL_WARNING);
|
|
@@ -1825,71 +2035,35 @@ function createBuildPlugin(resolved, extensions) {
|
|
|
1825
2035
|
base,
|
|
1826
2036
|
shell,
|
|
1827
2037
|
options: resolved,
|
|
1828
|
-
skipRoute: (route) => stager.inPublicDir(routeHtmlFile(route)),
|
|
2038
|
+
skipRoute: (route) => stager.inPublicDir(routeHtmlFile(route, layout)),
|
|
1829
2039
|
extensions
|
|
1830
2040
|
});
|
|
1831
2041
|
} catch (e) {
|
|
1832
2042
|
throw prefixed(e, "prerender failed");
|
|
1833
2043
|
}
|
|
2044
|
+
const filesOf = (route) => [routeHtmlFile(route, layout), ...markdown ? [routeMdFile(route)] : []];
|
|
2045
|
+
const pages = dropFileCollisions(
|
|
2046
|
+
result.pages,
|
|
2047
|
+
(p) => filesOf(p.route),
|
|
2048
|
+
/* @__PURE__ */ new Map([[SPA_FALLBACK_FILE, `the SPA fallback (${SPA_FALLBACK_FILE})`]]),
|
|
2049
|
+
(m) => logger.warn(m)
|
|
2050
|
+
);
|
|
2051
|
+
result = { ...result, pages };
|
|
1834
2052
|
const mdByRoute = /* @__PURE__ */ new Map();
|
|
1835
|
-
|
|
1836
|
-
stager.stage(
|
|
1837
|
-
|
|
1838
|
-
const md = buildPageMarkdown(page.info.title, page.info.contentHtml, publicUrl(siteUrl, page.route));
|
|
1839
|
-
mdByRoute.set(page.route, md);
|
|
1840
|
-
stager.stage(routeMdFile(page.route), md);
|
|
2053
|
+
const stageNew = (file, source) => {
|
|
2054
|
+
if (stager.stage(file, source).status === "replaced") {
|
|
2055
|
+
throw new Error(`${LOG_PREFIX} internal error: ${file} was generated twice; nothing was written`);
|
|
1841
2056
|
}
|
|
1842
|
-
}
|
|
1843
|
-
return { result, listed: result.pages.filter((p) => p.listed), mdByRoute };
|
|
1844
|
-
};
|
|
1845
|
-
const runExtensions = async (stager, { result, listed, mdByRoute }) => {
|
|
1846
|
-
const { siteUrl, markdown, llms } = resolved;
|
|
1847
|
-
for (const ext of extensions) {
|
|
1848
|
-
if (!ext.onRoute) continue;
|
|
1849
|
-
for (const page of listed) {
|
|
1850
|
-
await callHook(ext, `onRoute(${page.route})`, () => ext.onRoute(page.route, page.inPage[ext.name]));
|
|
1851
|
-
}
|
|
1852
|
-
}
|
|
1853
|
-
const rootPage = result.pages.find((p) => p.route === "/");
|
|
1854
|
-
const rootTitle = rootPage?.info.titleFromDocument ? rootPage.info.title : void 0;
|
|
1855
|
-
const site = {
|
|
1856
|
-
url: siteUrl,
|
|
1857
|
-
title: (llms ? llms.title : void 0) ?? rootTitle ?? new URL(siteUrl).hostname
|
|
1858
2057
|
};
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
return out;
|
|
1866
|
-
});
|
|
1867
|
-
if (llms) {
|
|
1868
|
-
const sections = [];
|
|
1869
|
-
for (const ext of extensions) {
|
|
1870
|
-
if (ext.llmsSections) sections.push(...await callHook(ext, "llmsSections", () => ext.llmsSections()));
|
|
2058
|
+
for (const page of pages) {
|
|
2059
|
+
stageNew(routeHtmlFile(page.route, layout), page.html);
|
|
2060
|
+
if (markdown) {
|
|
2061
|
+
const md = await pageMarkdown(markdown, { ...page, url: publicUrl(siteUrl, page.route) });
|
|
2062
|
+
mdByRoute.set(page.route, md);
|
|
2063
|
+
stageNew(routeMdFile(page.route), md);
|
|
1871
2064
|
}
|
|
1872
|
-
const llmsPages = pages.map((p) => {
|
|
1873
|
-
const md = mdByRoute.get(p.route);
|
|
1874
|
-
return md !== void 0 ? { ...p, markdown: md } : { ...p };
|
|
1875
|
-
});
|
|
1876
|
-
stager.stage(fileOf(LLMS_TXT_PATH), buildLlmsTxt(site, llmsPages, sections));
|
|
1877
|
-
if (markdown) stager.stage(fileOf(LLMS_FULL_TXT_PATH), buildLlmsFullTxt(site, llmsPages));
|
|
1878
|
-
}
|
|
1879
|
-
for (const ext of extensions) {
|
|
1880
|
-
if (!ext.finalize) continue;
|
|
1881
|
-
const ctx = {
|
|
1882
|
-
site,
|
|
1883
|
-
pages,
|
|
1884
|
-
emitFile: (fileName, source) => {
|
|
1885
|
-
const { file, status } = stager.stage(fileName, source);
|
|
1886
|
-
if (status === "replaced") logger.warn(`${LOG_PREFIX} extension "${ext.name}" overwrote ${file}`);
|
|
1887
|
-
},
|
|
1888
|
-
warn: (msg) => logger.warn(withPrefix(msg))
|
|
1889
|
-
};
|
|
1890
|
-
if (llms) ctx.llmsUrl = publicUrl(siteUrl, LLMS_TXT_PATH);
|
|
1891
|
-
await callHook(ext, "finalize", () => ext.finalize(ctx));
|
|
1892
2065
|
}
|
|
2066
|
+
return { result, listed: pages.filter((p) => p.listed), mdByRoute };
|
|
1893
2067
|
};
|
|
1894
2068
|
const runPipeline = async () => {
|
|
1895
2069
|
const { siteUrl, markdown } = resolved;
|
|
@@ -1899,12 +2073,21 @@ function createBuildPlugin(resolved, extensions) {
|
|
|
1899
2073
|
const sitemapRoutes = rendered ? [
|
|
1900
2074
|
.../* @__PURE__ */ new Set([
|
|
1901
2075
|
...rendered.listed.map((p) => p.route),
|
|
1902
|
-
...resolved.routes.filter(
|
|
2076
|
+
...resolved.routes.filter(
|
|
2077
|
+
(r) => stager.inPublicDir(routeHtmlFile(r, pr === false ? "directory" : pr.fileLayout))
|
|
2078
|
+
)
|
|
1903
2079
|
])
|
|
1904
2080
|
].sort() : resolved.routes;
|
|
1905
2081
|
if (resolved.sitemap) stager.stage(fileOf(SITEMAP_PATH), buildSitemap(siteUrl, sitemapRoutes));
|
|
1906
2082
|
stager.stage(fileOf(ROBOTS_PATH), buildRobots(resolved));
|
|
1907
|
-
if (rendered)
|
|
2083
|
+
if (rendered) {
|
|
2084
|
+
const { siteUrl: url, markdown: md, llms } = resolved;
|
|
2085
|
+
await stageSiteFiles({ siteUrl: url, markdown: md, llms, extensions, logger }, stager, {
|
|
2086
|
+
pages: rendered.result.pages,
|
|
2087
|
+
listed: rendered.listed,
|
|
2088
|
+
mdByRoute: rendered.mdByRoute
|
|
2089
|
+
});
|
|
2090
|
+
}
|
|
1908
2091
|
stager.flush();
|
|
1909
2092
|
if (pr === false || !rendered) return;
|
|
1910
2093
|
const { result, listed } = rendered;
|
|
@@ -1934,6 +2117,7 @@ function createBuildPlugin(resolved, extensions) {
|
|
|
1934
2117
|
`${LOG_PREFIX} no [${CONTENT_ATTR}] or "${markdown.contentSelector}" element on ${result.bodyFallbackRoutes.join(", ")}; content was taken from <body> minus header, nav, footer, aside`
|
|
1935
2118
|
);
|
|
1936
2119
|
}
|
|
2120
|
+
for (const w of pageLengthWarnings(listed)) logger.warn(w);
|
|
1937
2121
|
logger.info(
|
|
1938
2122
|
`${LOG_PREFIX} prerendered ${result.pages.length} routes (${listed.length} listed in llms.txt and the sitemap; the sitemap also keeps configured routes served from publicDir)`
|
|
1939
2123
|
);
|
|
@@ -1979,17 +2163,314 @@ function createBuildPlugin(resolved, extensions) {
|
|
|
1979
2163
|
};
|
|
1980
2164
|
}
|
|
1981
2165
|
|
|
2166
|
+
// src/vite/generate.ts
|
|
2167
|
+
import fs3 from "fs";
|
|
2168
|
+
import path4 from "path";
|
|
2169
|
+
|
|
2170
|
+
// src/vite/generateActions.ts
|
|
2171
|
+
function staticActions(document) {
|
|
2172
|
+
const out = /* @__PURE__ */ new Map();
|
|
2173
|
+
for (const a of markupActions(document)) {
|
|
2174
|
+
if (!isValidActionName(a.name) || out.has(a.name)) continue;
|
|
2175
|
+
out.set(a.name, {
|
|
2176
|
+
name: a.name,
|
|
2177
|
+
description: a.description?.trim() || a.name,
|
|
2178
|
+
inputSchema: a.kind === "form" ? schemaFromForm(a.element) : { ...EMPTY_OBJECT_SCHEMA, properties: {} },
|
|
2179
|
+
destructive: a.destructive,
|
|
2180
|
+
readOnly: false,
|
|
2181
|
+
kind: a.kind
|
|
2182
|
+
});
|
|
2183
|
+
}
|
|
2184
|
+
return [...out.values()].sort((a, b) => compareStrings(a.name, b.name));
|
|
2185
|
+
}
|
|
2186
|
+
|
|
2187
|
+
// src/vite/generateHtml.ts
|
|
2188
|
+
function detectCharset(bytes) {
|
|
2189
|
+
if (bytes[0] === 239 && bytes[1] === 187 && bytes[2] === 191) return "utf-8";
|
|
2190
|
+
if (bytes[0] === 254 && bytes[1] === 255) return "utf-16be";
|
|
2191
|
+
if (bytes[0] === 255 && bytes[1] === 254) return "utf-16le";
|
|
2192
|
+
const head = Buffer.from(bytes.subarray(0, 1024)).toString("latin1");
|
|
2193
|
+
const m = /<meta\b[^>]*?charset\s*=\s*["']?\s*([A-Za-z0-9_:.-]+)/i.exec(head);
|
|
2194
|
+
if (m) {
|
|
2195
|
+
try {
|
|
2196
|
+
const enc = new TextDecoder(m[1]).encoding;
|
|
2197
|
+
return enc.startsWith("utf-16") ? "utf-8" : enc;
|
|
2198
|
+
} catch {
|
|
2199
|
+
}
|
|
2200
|
+
}
|
|
2201
|
+
return "utf-8";
|
|
2202
|
+
}
|
|
2203
|
+
function decodeHtml(bytes) {
|
|
2204
|
+
const charset = detectCharset(bytes);
|
|
2205
|
+
return { charset, text: new TextDecoder(charset).decode(bytes) };
|
|
2206
|
+
}
|
|
2207
|
+
var HEAD_RAW_TEXT = /* @__PURE__ */ new Set(["script", "style", "template", "textarea", "title", "noscript"]);
|
|
2208
|
+
var escapeAttr = (href) => href.replace(/&/g, "&").replace(/"/g, """).replace(/[^\x20-\x7e]/gu, (c) => `&#x${c.codePointAt(0).toString(16)};`);
|
|
2209
|
+
function isMarkdownAlternate(attrs) {
|
|
2210
|
+
const get = (n) => attrs.find((a) => a.name === n)?.value ?? "";
|
|
2211
|
+
const rel = get("rel").toLowerCase().split(/\s+/);
|
|
2212
|
+
return rel.includes("alternate") && get("type").split(";")[0].trim().toLowerCase() === MARKDOWN_MIME;
|
|
2213
|
+
}
|
|
2214
|
+
var ourLink = (attr) => `<link rel="alternate" type="${MARKDOWN_MIME}" href="${attr}" ${HEAD_OWNED_ATTR}="${MARKDOWN_LINK_KEY}">`;
|
|
2215
|
+
function setMarkdownLink(bytes, charset, href) {
|
|
2216
|
+
if (charset.startsWith("utf-16")) return null;
|
|
2217
|
+
const buf = Buffer.from(bytes);
|
|
2218
|
+
const view = buf.toString("latin1");
|
|
2219
|
+
const attr = escapeAttr(href);
|
|
2220
|
+
let headOpenEnd = -1;
|
|
2221
|
+
let headClose = -1;
|
|
2222
|
+
let bodyOpen = -1;
|
|
2223
|
+
let preamble = 0;
|
|
2224
|
+
let marked;
|
|
2225
|
+
for (const t of scanHtml(view, HEAD_RAW_TEXT)) {
|
|
2226
|
+
if (t.type === "comment") {
|
|
2227
|
+
if (headOpenEnd === -1 && /^<!doctype/i.test(view.slice(t.start, t.start + 9))) preamble = t.end;
|
|
2228
|
+
continue;
|
|
2229
|
+
}
|
|
2230
|
+
if (t.type !== "tag") continue;
|
|
2231
|
+
if (t.closing) {
|
|
2232
|
+
if (t.name === "head") {
|
|
2233
|
+
headClose = t.start;
|
|
2234
|
+
break;
|
|
2235
|
+
}
|
|
2236
|
+
continue;
|
|
2237
|
+
}
|
|
2238
|
+
if (t.name === "html" && headOpenEnd === -1) preamble = Math.max(preamble, t.end);
|
|
2239
|
+
if (t.name === "head" && headOpenEnd === -1) headOpenEnd = t.end;
|
|
2240
|
+
else if (t.name === "body") {
|
|
2241
|
+
bodyOpen = t.start;
|
|
2242
|
+
break;
|
|
2243
|
+
} else if (t.name === "link" && isMarkdownAlternate(t.attrs)) {
|
|
2244
|
+
const owner = t.attrs.find((a) => a.name === HEAD_OWNED_ATTR)?.value;
|
|
2245
|
+
if (owner !== MARKDOWN_LINK_KEY) return { bytes: buf, action: "kept" };
|
|
2246
|
+
marked ??= t;
|
|
2247
|
+
}
|
|
2248
|
+
}
|
|
2249
|
+
const splice = (start, end, text, action) => ({
|
|
2250
|
+
bytes: Buffer.concat([buf.subarray(0, start), Buffer.from(text, "latin1"), buf.subarray(end)]),
|
|
2251
|
+
action
|
|
2252
|
+
});
|
|
2253
|
+
if (marked) {
|
|
2254
|
+
const h = marked.attrs.find((a) => a.name === "href");
|
|
2255
|
+
if (h && h.valueStart !== -1) {
|
|
2256
|
+
if (h.value === attr) return { bytes: buf, action: "unchanged" };
|
|
2257
|
+
return splice(h.valueStart, h.valueEnd, h.quote ? attr : `"${attr}"`, "updated");
|
|
2258
|
+
}
|
|
2259
|
+
return splice(marked.start, marked.end, ourLink(attr), "updated");
|
|
2260
|
+
}
|
|
2261
|
+
const at = headClose !== -1 ? headClose : headOpenEnd !== -1 ? headOpenEnd : bodyOpen !== -1 ? bodyOpen : preamble;
|
|
2262
|
+
return splice(at, at, ourLink(attr), "inserted");
|
|
2263
|
+
}
|
|
2264
|
+
|
|
2265
|
+
// src/vite/generate.ts
|
|
2266
|
+
var SKIP_DIRS = /* @__PURE__ */ new Set(["assets", "node_modules"]);
|
|
2267
|
+
var SKIP_FILES = /* @__PURE__ */ new Set([SPA_FALLBACK_FILE, "404.html"]);
|
|
2268
|
+
function htmlFiles(outDir, warn) {
|
|
2269
|
+
const out = [];
|
|
2270
|
+
const walk = (dir, rel) => {
|
|
2271
|
+
for (const e of fs3.readdirSync(dir, { withFileTypes: true })) {
|
|
2272
|
+
if (e.name.startsWith(".")) continue;
|
|
2273
|
+
const r = rel ? `${rel}/${e.name}` : e.name;
|
|
2274
|
+
if (e.isSymbolicLink()) {
|
|
2275
|
+
if (e.name.endsWith(".html") || fs3.statSync(path4.join(dir, e.name), { throwIfNoEntry: false })?.isDirectory()) {
|
|
2276
|
+
warn(`${LOG_PREFIX} ${r} is a symbolic link; skipped`);
|
|
2277
|
+
}
|
|
2278
|
+
} else if (e.isDirectory()) {
|
|
2279
|
+
if (!(rel === "" && SKIP_DIRS.has(e.name))) walk(path4.join(dir, e.name), r);
|
|
2280
|
+
} else if (e.isFile() && e.name.endsWith(".html") && !SKIP_FILES.has(e.name)) {
|
|
2281
|
+
out.push(r);
|
|
2282
|
+
}
|
|
2283
|
+
}
|
|
2284
|
+
};
|
|
2285
|
+
walk(outDir, "");
|
|
2286
|
+
return out.sort(compareStrings);
|
|
2287
|
+
}
|
|
2288
|
+
var GENERATE_OPTION_KEYS = [
|
|
2289
|
+
"outDir",
|
|
2290
|
+
"siteUrl",
|
|
2291
|
+
"robots",
|
|
2292
|
+
"exclude",
|
|
2293
|
+
"sitemap",
|
|
2294
|
+
"markdown",
|
|
2295
|
+
"llms",
|
|
2296
|
+
"agentMap",
|
|
2297
|
+
"linkMarkdown",
|
|
2298
|
+
"overwrite",
|
|
2299
|
+
"logger"
|
|
2300
|
+
];
|
|
2301
|
+
async function generateAgentFiles(options) {
|
|
2302
|
+
if (!options || typeof options.outDir !== "string" || options.outDir === "") {
|
|
2303
|
+
throw new Error(withPrefix("outDir is required"));
|
|
2304
|
+
}
|
|
2305
|
+
for (const key of ["linkMarkdown", "overwrite"]) {
|
|
2306
|
+
if (options[key] !== void 0 && typeof options[key] !== "boolean") throw new Error(withPrefix(`${key} must be a boolean`));
|
|
2307
|
+
}
|
|
2308
|
+
const resolved = resolveOptions({
|
|
2309
|
+
siteUrl: options.siteUrl,
|
|
2310
|
+
robots: options.robots,
|
|
2311
|
+
...options.exclude !== void 0 ? { exclude: options.exclude } : {},
|
|
2312
|
+
...options.sitemap !== void 0 ? { sitemap: options.sitemap } : {},
|
|
2313
|
+
...options.markdown !== void 0 ? { markdown: options.markdown } : {},
|
|
2314
|
+
...options.llms !== void 0 ? { llms: options.llms } : {},
|
|
2315
|
+
...options.agentMap !== void 0 ? { agentMap: options.agentMap } : {},
|
|
2316
|
+
overlay: false
|
|
2317
|
+
});
|
|
2318
|
+
const { siteUrl, markdown } = resolved;
|
|
2319
|
+
const outDir = path4.resolve(options.outDir);
|
|
2320
|
+
if (!fs3.existsSync(outDir) || !fs3.statSync(outDir).isDirectory()) {
|
|
2321
|
+
throw new Error(`${LOG_PREFIX} ${outDir} is not a directory`);
|
|
2322
|
+
}
|
|
2323
|
+
const linkMarkdown = options.linkMarkdown ?? true;
|
|
2324
|
+
const base = options.logger ?? console;
|
|
2325
|
+
const warnings = [];
|
|
2326
|
+
const logger = {
|
|
2327
|
+
warn(msg) {
|
|
2328
|
+
warnings.push(msg);
|
|
2329
|
+
base.warn(msg);
|
|
2330
|
+
}
|
|
2331
|
+
};
|
|
2332
|
+
for (const w of resolved.warnings) logger.warn(w);
|
|
2333
|
+
const unknown = Object.keys(options).filter((k) => !GENERATE_OPTION_KEYS.includes(k));
|
|
2334
|
+
if (unknown.length > 0) {
|
|
2335
|
+
logger.warn(`${LOG_PREFIX} unknown option${unknown.length === 1 ? "" : "s"} ignored: ${unknown.join(", ")}`);
|
|
2336
|
+
}
|
|
2337
|
+
const fileByRoute = /* @__PURE__ */ new Map();
|
|
2338
|
+
for (const file of htmlFiles(outDir, (m) => logger.warn(m))) {
|
|
2339
|
+
const route = routeOfHtmlFile(file);
|
|
2340
|
+
if (!isSafeRoute(route)) {
|
|
2341
|
+
logger.warn(`${LOG_PREFIX} ${file} cannot be a page URL (its name has a backslash or similar); skipped`);
|
|
2342
|
+
continue;
|
|
2343
|
+
}
|
|
2344
|
+
if (route !== "/" && isExcluded(route, resolved.exclude)) continue;
|
|
2345
|
+
const other = fileByRoute.get(route);
|
|
2346
|
+
if (other !== void 0) {
|
|
2347
|
+
logger.warn(`${LOG_PREFIX} ${file} and ${other} are both ${shortRoute(route)}; using ${other}`);
|
|
2348
|
+
continue;
|
|
2349
|
+
}
|
|
2350
|
+
fileByRoute.set(route, file);
|
|
2351
|
+
}
|
|
2352
|
+
if (fileByRoute.size === 0) throw new Error(`${LOG_PREFIX} no .html pages found in ${outDir}`);
|
|
2353
|
+
const files = [...fileByRoute.values()];
|
|
2354
|
+
const flat = files.some((f) => f !== "index.html" && !f.endsWith("/index.html"));
|
|
2355
|
+
const dir = files.some((f) => f.endsWith("/index.html"));
|
|
2356
|
+
const fileLayout = flat && dir ? "mixed" : flat ? "flat" : "directory";
|
|
2357
|
+
const stager = createFileStager({ outDir, publicDir: "", warn: (m) => logger.warn(m) });
|
|
2358
|
+
const written = /* @__PURE__ */ new Set();
|
|
2359
|
+
const kept = [];
|
|
2360
|
+
const protectedFiles = /* @__PURE__ */ new Set([fileOf(ROBOTS_PATH), fileOf(SITEMAP_PATH), fileOf(LLMS_TXT_PATH), fileOf(LLMS_FULL_TXT_PATH)]);
|
|
2361
|
+
if (resolved.agentMap) protectedFiles.add(resolved.agentMap.fileName);
|
|
2362
|
+
const differs = (target, source) => fs3.existsSync(target) && !fs3.readFileSync(target).equals(typeof source === "string" ? Buffer.from(source) : source);
|
|
2363
|
+
const guarded = {
|
|
2364
|
+
...stager,
|
|
2365
|
+
stage(fileName, source) {
|
|
2366
|
+
const file = fileName.replace(/^\/+/, "");
|
|
2367
|
+
const target = path4.join(outDir, file);
|
|
2368
|
+
if (!options.overwrite && protectedFiles.has(file) && differs(target, source)) {
|
|
2369
|
+
if (!kept.includes(file)) {
|
|
2370
|
+
kept.push(file);
|
|
2371
|
+
logger.warn(`${LOG_PREFIX} ${file} already exists with different content; kept it (use overwrite to replace it)`);
|
|
2372
|
+
}
|
|
2373
|
+
return { file, status: "skipped" };
|
|
2374
|
+
}
|
|
2375
|
+
const r = stager.stage(fileName, source);
|
|
2376
|
+
if (r.status !== "skipped") written.add(r.file);
|
|
2377
|
+
return r;
|
|
2378
|
+
}
|
|
2379
|
+
};
|
|
2380
|
+
const pages = [];
|
|
2381
|
+
const result = [];
|
|
2382
|
+
const mdByRoute = /* @__PURE__ */ new Map();
|
|
2383
|
+
const bodyFallback = [];
|
|
2384
|
+
const utf16 = [];
|
|
2385
|
+
const ownLinks = [];
|
|
2386
|
+
const routes = dropFileCollisions(
|
|
2387
|
+
[...fileByRoute].map(([route, file]) => ({ route, file })).sort(byRoute),
|
|
2388
|
+
(p) => markdown ? [routeMdFile(p.route)] : [],
|
|
2389
|
+
/* @__PURE__ */ new Map(),
|
|
2390
|
+
(m) => logger.warn(m)
|
|
2391
|
+
);
|
|
2392
|
+
for (const { route, file } of routes) {
|
|
2393
|
+
const bytes = fs3.readFileSync(path4.join(outDir, file));
|
|
2394
|
+
const { charset, text: html } = decodeHtml(bytes);
|
|
2395
|
+
const url = publicUrl(siteUrl, route);
|
|
2396
|
+
const { document, dispose } = parseHtml(html);
|
|
2397
|
+
let page;
|
|
2398
|
+
try {
|
|
2399
|
+
const actions = resolved.agentMap ? staticActions(document) : [];
|
|
2400
|
+
const info = analyzeDocument(document, {
|
|
2401
|
+
pageUrl: url,
|
|
2402
|
+
contentSelector: markdown ? markdown.contentSelector : "main",
|
|
2403
|
+
route
|
|
2404
|
+
});
|
|
2405
|
+
const inPage = { "agent-map": { actions } };
|
|
2406
|
+
page = { route, info, listed: !info.noindex, inPage };
|
|
2407
|
+
} catch (e) {
|
|
2408
|
+
throw prefixed(e, `reading ${file} failed`);
|
|
2409
|
+
} finally {
|
|
2410
|
+
dispose();
|
|
2411
|
+
}
|
|
2412
|
+
pages.push(page);
|
|
2413
|
+
result.push({ route, file, listed: page.listed });
|
|
2414
|
+
if (!markdown) continue;
|
|
2415
|
+
if (page.info.contentSource === "body") bodyFallback.push(route);
|
|
2416
|
+
const md = await pageMarkdown(markdown, { route, url, info: page.info, html });
|
|
2417
|
+
mdByRoute.set(route, md);
|
|
2418
|
+
const mdFile = routeMdFile(route);
|
|
2419
|
+
if (differs(path4.join(outDir, mdFile), md)) {
|
|
2420
|
+
logger.warn(`${LOG_PREFIX} ${mdFile} already exists with different content; replacing it with the markdown of ${shortRoute(route)}`);
|
|
2421
|
+
}
|
|
2422
|
+
guarded.stage(mdFile, md);
|
|
2423
|
+
if (linkMarkdown) {
|
|
2424
|
+
const edit = setMarkdownLink(bytes, charset, publicMdUrl(siteUrl, route));
|
|
2425
|
+
if (edit === null) utf16.push(file);
|
|
2426
|
+
else if (edit.action === "kept") ownLinks.push(shortRoute(route));
|
|
2427
|
+
else if (edit.action !== "unchanged") guarded.stage(file, edit.bytes);
|
|
2428
|
+
}
|
|
2429
|
+
}
|
|
2430
|
+
const listed = pages.filter((p) => p.listed);
|
|
2431
|
+
if (resolved.sitemap) guarded.stage(fileOf(SITEMAP_PATH), buildSitemap(siteUrl, listed.map((p) => p.route)));
|
|
2432
|
+
guarded.stage(fileOf(ROBOTS_PATH), buildRobots(resolved));
|
|
2433
|
+
const extensions = resolved.agentMap ? [agentMapExtension({ siteUrl, fileName: resolved.agentMap.fileName })] : [];
|
|
2434
|
+
await stageSiteFiles({ siteUrl, markdown, llms: resolved.llms, extensions, logger }, guarded, {
|
|
2435
|
+
pages,
|
|
2436
|
+
listed,
|
|
2437
|
+
mdByRoute
|
|
2438
|
+
});
|
|
2439
|
+
stager.flush();
|
|
2440
|
+
if (markdown && bodyFallback.length > 0) {
|
|
2441
|
+
logger.warn(
|
|
2442
|
+
`${LOG_PREFIX} no [${CONTENT_ATTR}] or "${markdown.contentSelector}" element on ${bodyFallback.join(", ")}; content was taken from <body> minus header, nav, footer, aside`
|
|
2443
|
+
);
|
|
2444
|
+
}
|
|
2445
|
+
if (ownLinks.length > 0) {
|
|
2446
|
+
base.info(`${LOG_PREFIX} kept the page's own markdown link on ${ownLinks.join(", ")}`);
|
|
2447
|
+
}
|
|
2448
|
+
if (utf16.length > 0) {
|
|
2449
|
+
logger.warn(`${LOG_PREFIX} ${utf16.join(", ")} ${utf16.length === 1 ? "is" : "are"} UTF-16; the markdown link was not added`);
|
|
2450
|
+
}
|
|
2451
|
+
for (const w of pageLengthWarnings(listed)) logger.warn(w);
|
|
2452
|
+
base.info(`${LOG_PREFIX} generated agent files for ${pages.length} pages (${listed.length} listed) in ${outDir}`);
|
|
2453
|
+
return {
|
|
2454
|
+
outDir,
|
|
2455
|
+
fileLayout,
|
|
2456
|
+
pages: result.sort(byRoute),
|
|
2457
|
+
written: [...written].sort(compareStrings),
|
|
2458
|
+
kept: kept.sort(compareStrings),
|
|
2459
|
+
warnings
|
|
2460
|
+
};
|
|
2461
|
+
}
|
|
2462
|
+
|
|
1982
2463
|
// src/vite/overlay.ts
|
|
1983
2464
|
import { existsSync as existsSync2 } from "fs";
|
|
1984
2465
|
import { createRequire as createRequire2 } from "module";
|
|
1985
|
-
import
|
|
2466
|
+
import path5 from "path";
|
|
1986
2467
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
1987
2468
|
var OVERLAY_VIRTUAL_ID = "virtual:web-for-agents/overlay";
|
|
1988
2469
|
var RESOLVED_ID = "\0" + OVERLAY_VIRTUAL_ID;
|
|
1989
2470
|
var PACKAGE_NAME = "@anubhav-choubey/web-for-agents";
|
|
1990
2471
|
var OVERLAY_DEPS = ["turndown", "turndown-plugin-gfm"];
|
|
1991
2472
|
function overlayDepsFor(root) {
|
|
1992
|
-
const req = createRequire2(
|
|
2473
|
+
const req = createRequire2(path5.join(root, "noop.js"));
|
|
1993
2474
|
return OVERLAY_DEPS.map((dep) => {
|
|
1994
2475
|
try {
|
|
1995
2476
|
req.resolve(dep);
|
|
@@ -2014,7 +2495,7 @@ function overlayPlugin(o, siteUrl) {
|
|
|
2014
2495
|
name: "web-for-agents:overlay",
|
|
2015
2496
|
apply: (_config, env) => env.command === "serve" && !process.env.VITEST,
|
|
2016
2497
|
config(config) {
|
|
2017
|
-
return { optimizeDeps: { include: overlayDepsFor(
|
|
2498
|
+
return { optimizeDeps: { include: overlayDepsFor(path5.resolve(config.root ?? process.cwd())) } };
|
|
2018
2499
|
},
|
|
2019
2500
|
configResolved(config) {
|
|
2020
2501
|
base = config.base;
|
|
@@ -2045,5 +2526,6 @@ function webForAgents(options) {
|
|
|
2045
2526
|
}
|
|
2046
2527
|
export {
|
|
2047
2528
|
AI_BOTS,
|
|
2529
|
+
generateAgentFiles,
|
|
2048
2530
|
webForAgents
|
|
2049
2531
|
};
|