@andesine/pages 0.0.0-stage → 0.6.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/CHANGELOG.md +103 -0
- package/LICENSE +21 -0
- package/README.md +92 -2
- package/dist/answers.d.ts +6 -0
- package/dist/astro/content.astro +118 -0
- package/dist/astro/middleware.js +39 -0
- package/dist/astro/middleware.js.map +1 -0
- package/dist/astro/routes/answers.js +129 -0
- package/dist/astro/routes/answers.js.map +1 -0
- package/dist/astro/routes/entry-pages.js +22 -0
- package/dist/astro/routes/entry-pages.js.map +1 -0
- package/dist/astro/routes/llms-full.js +12 -0
- package/dist/astro/routes/llms-full.js.map +1 -0
- package/dist/astro/routes/llms.js +12 -0
- package/dist/astro/routes/llms.js.map +1 -0
- package/dist/astro/routes/markdown-alias.js +14 -0
- package/dist/astro/routes/markdown-alias.js.map +1 -0
- package/dist/astro/routes/markdown.js +12 -0
- package/dist/astro/routes/markdown.js.map +1 -0
- package/dist/astro/routes/not-found.astro +12 -0
- package/dist/astro/routes/robots.js +9 -0
- package/dist/astro/routes/robots.js.map +1 -0
- package/dist/astro/routes/search.js +42 -0
- package/dist/astro/routes/search.js.map +1 -0
- package/dist/astro/routes/sitemap.js +12 -0
- package/dist/astro/routes/sitemap.js.map +1 -0
- package/dist/astro/routes/skill.js +13 -0
- package/dist/astro/routes/skill.js.map +1 -0
- package/dist/astro/routes/skills.js +24 -0
- package/dist/astro/routes/skills.js.map +1 -0
- package/dist/astro/routes/social.js +91 -0
- package/dist/astro/routes/social.js.map +1 -0
- package/dist/astro/routes/static.astro +53 -0
- package/dist/astro/routes/well-known-llms.js +2 -0
- package/dist/astro.d.ts +34 -0
- package/dist/astro.js +60 -0
- package/dist/astro.js.map +1 -0
- package/dist/chunks/assets-D6WJmZ05.js +21 -0
- package/dist/chunks/assets-D6WJmZ05.js.map +1 -0
- package/dist/chunks/catalog-DU4BUrpw.js +28 -0
- package/dist/chunks/catalog-DU4BUrpw.js.map +1 -0
- package/dist/chunks/config-CuH5JSI4.js +184 -0
- package/dist/chunks/config-CuH5JSI4.js.map +1 -0
- package/dist/chunks/files-BxqiQzFj.js +62 -0
- package/dist/chunks/files-BxqiQzFj.js.map +1 -0
- package/dist/chunks/hash-D4piIIQ6.js +11 -0
- package/dist/chunks/hash-D4piIIQ6.js.map +1 -0
- package/dist/chunks/index-D8wL2B5s.d.ts +571 -0
- package/dist/chunks/index-vsu3hISM.d.ts +62 -0
- package/dist/chunks/limits-Ppc7BQPG.js +45 -0
- package/dist/chunks/limits-Ppc7BQPG.js.map +1 -0
- package/dist/chunks/markdown-DKJSQxR2.js +42 -0
- package/dist/chunks/markdown-DKJSQxR2.js.map +1 -0
- package/dist/chunks/mdx-components-CUUDTapN.d.ts +9 -0
- package/dist/chunks/normalize-DG5nxOLm.js +361 -0
- package/dist/chunks/normalize-DG5nxOLm.js.map +1 -0
- package/dist/chunks/paths-75QgA3Qs.js +16 -0
- package/dist/chunks/paths-75QgA3Qs.js.map +1 -0
- package/dist/chunks/prepare-lnuw_ycM.js +219 -0
- package/dist/chunks/prepare-lnuw_ycM.js.map +1 -0
- package/dist/chunks/read-DCv1lmcM.js +57 -0
- package/dist/chunks/read-DCv1lmcM.js.map +1 -0
- package/dist/chunks/request-DOuBHGQs.js +92 -0
- package/dist/chunks/request-DOuBHGQs.js.map +1 -0
- package/dist/chunks/response-CtzaKMWH.js +15 -0
- package/dist/chunks/response-CtzaKMWH.js.map +1 -0
- package/dist/chunks/site-DY-uZ0PP.js +419 -0
- package/dist/chunks/site-DY-uZ0PP.js.map +1 -0
- package/dist/chunks/skill-CBTGUHQH.js +85 -0
- package/dist/chunks/skill-CBTGUHQH.js.map +1 -0
- package/dist/chunks/sources-Cm6NdIen.js +236 -0
- package/dist/chunks/sources-Cm6NdIen.js.map +1 -0
- package/dist/chunks/stored-CabomV-C.js +354 -0
- package/dist/chunks/stored-CabomV-C.js.map +1 -0
- package/dist/chunks/stored-CcEfvCQH.js +475 -0
- package/dist/chunks/stored-CcEfvCQH.js.map +1 -0
- package/dist/chunks/types-DBzuXfSe.d.ts +53 -0
- package/dist/chunks/view-C-9ZM1zK.js +745 -0
- package/dist/chunks/view-C-9ZM1zK.js.map +1 -0
- package/dist/chunks/view-Dlf_VRI7.d.ts +151 -0
- package/dist/client.d.ts +73 -0
- package/dist/client.js +295 -0
- package/dist/client.js.map +1 -0
- package/dist/collections.d.ts +7 -0
- package/dist/collections.js +215 -0
- package/dist/collections.js.map +1 -0
- package/dist/entry-pages.d.ts +10 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +38 -0
- package/dist/index.js.map +1 -0
- package/dist/integration.d.ts +16 -0
- package/dist/integration.js +435 -0
- package/dist/integration.js.map +1 -0
- package/dist/llms-full.d.ts +5 -0
- package/dist/llms.d.ts +5 -0
- package/dist/markdown-alias.d.ts +7 -0
- package/dist/markdown.d.ts +7 -0
- package/dist/middleware.d.ts +8 -0
- package/dist/robots.d.ts +5 -0
- package/dist/runtime.d.ts +81 -0
- package/dist/runtime.js +56 -0
- package/dist/runtime.js.map +1 -0
- package/dist/scripts/restore-navigation.js +1 -0
- package/dist/search.d.ts +6 -0
- package/dist/sitemap.d.ts +5 -0
- package/dist/skill.d.ts +5 -0
- package/dist/skills.d.ts +10 -0
- package/dist/social.d.ts +7 -0
- package/dist/well-known-llms.d.ts +2 -0
- package/package.json +103 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/social/html.ts"],"sourcesContent":["type MarkupValue = Markup | string | number | boolean | null | undefined | MarkupValue[];\n\nconst entities: Record<string, string> = { \"&\": \"&\", \"<\": \"<\", \">\": \">\", '\"': \""\" };\n\n/** Card markup from the `html` template tag, whose values are already escaped. */\nclass Markup {\n constructor(readonly value: string) {}\n\n toString(): string {\n return this.value;\n }\n}\n\nconst toMarkup = (value: MarkupValue): string => {\n const isEmpty = value === null || value === undefined || typeof value === \"boolean\";\n\n if (value instanceof Markup) return value.value;\n if (Array.isArray(value)) return value.map(toMarkup).join(\"\");\n if (isEmpty) return \"\";\n\n return String(value).replace(/[&<>\"]/g, (character) => entities[character]!);\n};\n/**\n * A template tag for social card markup. It escapes values, joins arrays, and leaves out\n * `false`, `null`, and `undefined`, so `${condition && html`…`}` adds optional parts.\n */\nconst html = (strings: TemplateStringsArray, ...values: MarkupValue[]): Markup => {\n return new Markup(\n strings.reduce((result, part, index) => {\n return result + part + (index < values.length ? toMarkup(values[index]!) : \"\");\n }, \"\")\n );\n};\n\nexport { html, Markup };\nexport type { MarkupValue };\n"],"mappings":";;AAEA,MAAM,WAAmC;CAAE,KAAK;CAAS,KAAK;CAAQ,KAAK;CAAQ,MAAK;AAAS;;AAGjG,IAAM,SAAN,MAAa;CACU;CAArB,YAAY,OAAwB;EAAf,KAAA,QAAA;CAAgB;CAErC,WAAmB;EACjB,OAAO,KAAK;CACd;AACF;AAEA,MAAM,YAAY,UAA+B;CAC/C,MAAM,UAAU,UAAU,QAAQ,UAAU,KAAA,KAAa,OAAO,UAAU;CAE1E,IAAI,iBAAiB,QAAQ,OAAO,MAAM;CAC1C,IAAI,MAAM,QAAQ,KAAK,GAAG,OAAO,MAAM,IAAI,QAAQ,CAAC,CAAC,KAAK,EAAE;CAC5D,IAAI,SAAS,OAAO;CAEpB,OAAO,OAAO,KAAK,CAAC,CAAC,QAAQ,YAAY,cAAc,SAAS,UAAW;AAC7E;;;;;AAKA,MAAM,QAAQ,SAA+B,GAAG,WAAkC;CAChF,OAAO,IAAI,OACT,QAAQ,QAAQ,QAAQ,MAAM,UAAU;EACtC,OAAO,SAAS,QAAQ,QAAQ,OAAO,SAAS,SAAS,OAAO,MAAO,IAAI;CAC7E,GAAG,EAAE,CACP;AACF"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { AstroIntegration } from "astro";
|
|
2
|
+
//#region src/integration.d.ts
|
|
3
|
+
interface AndesineOptions {
|
|
4
|
+
/** Relative to the project root. */
|
|
5
|
+
config?: string;
|
|
6
|
+
/** Astro layout that renders each page. Relative to the project root. */
|
|
7
|
+
layout?: string;
|
|
8
|
+
/** Module that exports the `components` for page content. Relative to the project root. */
|
|
9
|
+
components?: string;
|
|
10
|
+
/** Module that exports the social card for generated page images. Relative to the project root. */
|
|
11
|
+
socialCard?: string;
|
|
12
|
+
}
|
|
13
|
+
declare const andesine: (options?: AndesineOptions) => AstroIntegration;
|
|
14
|
+
//#endregion
|
|
15
|
+
export { type AndesineOptions, andesine };
|
|
16
|
+
//# sourceMappingURL=integration.d.ts.map
|
|
@@ -0,0 +1,435 @@
|
|
|
1
|
+
import { n as parseConfig } from "./chunks/config-CuH5JSI4.js";
|
|
2
|
+
import { a as mimeTypes, n as assetPath, r as getAssetPrefix, t as assetFile } from "./chunks/assets-D6WJmZ05.js";
|
|
3
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
4
|
+
import { dirname, join, resolve } from "node:path";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
import { copyFile, mkdir, readFile } from "node:fs/promises";
|
|
7
|
+
import { runnerImport } from "vite";
|
|
8
|
+
import { createIndex } from "pagefind";
|
|
9
|
+
//#region src/content/mdx-components.ts
|
|
10
|
+
const stringAttribute = (name, value) => {
|
|
11
|
+
return {
|
|
12
|
+
type: "mdxJsxAttribute",
|
|
13
|
+
name,
|
|
14
|
+
value
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
const getAttribute = (node, name) => {
|
|
18
|
+
return node.attributes?.find((attribute) => attribute.name === name)?.value;
|
|
19
|
+
};
|
|
20
|
+
/** Reads `title="..."` from a code fence meta string. */
|
|
21
|
+
const getCodeTitle = (meta) => {
|
|
22
|
+
const match = meta?.match(/title=(?:"([^"]*)"|'([^']*)'|(\S+))/);
|
|
23
|
+
return match?.[1] ?? match?.[2] ?? match?.[3];
|
|
24
|
+
};
|
|
25
|
+
const withValues = (node, labels, children) => {
|
|
26
|
+
if (new Set(labels).size !== labels.length) throw new Error(`<${node.name}> needs a unique label for each tab: ${labels.join(", ")}.`);
|
|
27
|
+
return {
|
|
28
|
+
type: node.type,
|
|
29
|
+
name: node.name,
|
|
30
|
+
attributes: [...(node.attributes ?? []).filter((attribute) => attribute.name !== "values"), stringAttribute("values", JSON.stringify(labels))],
|
|
31
|
+
children
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
/** `<Tabs>` children `<Tab label="...">` become the named slots `tab-0`, `tab-1`, and so on. */
|
|
35
|
+
const prepareTabs = (node) => {
|
|
36
|
+
const labels = [];
|
|
37
|
+
const children = (node.children ?? []).map((child) => {
|
|
38
|
+
if (child.type !== "mdxJsxFlowElement" || child.name !== "Tab") return child;
|
|
39
|
+
const label = getAttribute(child, "label");
|
|
40
|
+
const index = labels.length;
|
|
41
|
+
if (typeof label !== "string" || !label.trim()) throw new Error(`<Tab> ${index + 1} needs a text label, e.g. <Tab label="npm">.`);
|
|
42
|
+
labels.push(label);
|
|
43
|
+
return {
|
|
44
|
+
type: child.type,
|
|
45
|
+
name: child.name,
|
|
46
|
+
attributes: [...child.attributes ?? [], stringAttribute("slot", `tab-${index}`)],
|
|
47
|
+
children: child.children
|
|
48
|
+
};
|
|
49
|
+
});
|
|
50
|
+
return withValues(node, labels, children);
|
|
51
|
+
};
|
|
52
|
+
/** `<CodeGroup>` code fences become tabs, labeled by their `title` or language. */
|
|
53
|
+
const prepareCodeGroup = (node) => {
|
|
54
|
+
const blocks = (node.children ?? []).filter((child) => child.type === "code");
|
|
55
|
+
const labels = blocks.map((block) => getCodeTitle(block.meta) ?? block.lang ?? "Code");
|
|
56
|
+
const children = blocks.map((block, index) => {
|
|
57
|
+
return {
|
|
58
|
+
type: "mdxJsxFlowElement",
|
|
59
|
+
name: "div",
|
|
60
|
+
attributes: [stringAttribute("slot", `tab-${index}`)],
|
|
61
|
+
children: [block]
|
|
62
|
+
};
|
|
63
|
+
});
|
|
64
|
+
return withValues(node, labels, children);
|
|
65
|
+
};
|
|
66
|
+
/** Returns the text of a node, with inline code. */
|
|
67
|
+
const getText = (node) => {
|
|
68
|
+
return node.type === "text" || node.type === "inlineCode" ? node.value ?? "" : (node.children ?? []).map(getText).join("");
|
|
69
|
+
};
|
|
70
|
+
const toFileTreeItems = (list) => {
|
|
71
|
+
return (list.children ?? []).map((item) => {
|
|
72
|
+
const label = item.children?.find((child) => child.type !== "list");
|
|
73
|
+
const nested = item.children?.find((child) => child.type === "list");
|
|
74
|
+
const name = label ? getText(label).trim() : "";
|
|
75
|
+
const folder = name.endsWith("/") || Boolean(nested);
|
|
76
|
+
return {
|
|
77
|
+
name: name.replace(/\/$/, ""),
|
|
78
|
+
type: folder ? "folder" : "file",
|
|
79
|
+
children: nested ? toFileTreeItems(nested) : []
|
|
80
|
+
};
|
|
81
|
+
});
|
|
82
|
+
};
|
|
83
|
+
/** `<FileTree>` gets its nested list as JSON `items`. Items that end with `/`, or have nested items, are folders. */
|
|
84
|
+
const prepareFileTree = (node) => {
|
|
85
|
+
const list = node.children?.find((child) => child.type === "list");
|
|
86
|
+
if (!list) throw new Error("<FileTree> needs a Markdown list of files and folders.");
|
|
87
|
+
return {
|
|
88
|
+
type: node.type,
|
|
89
|
+
name: node.name,
|
|
90
|
+
attributes: [stringAttribute("items", JSON.stringify(toFileTreeItems(list)))],
|
|
91
|
+
children: []
|
|
92
|
+
};
|
|
93
|
+
};
|
|
94
|
+
/** The web page shows only human content; agent content is in the Markdown outputs. */
|
|
95
|
+
const applyVisibility = (node, context) => {
|
|
96
|
+
const audience = getAttribute(node, "for");
|
|
97
|
+
if (audience !== "agents" && audience !== "humans") throw new Error("<Visibility> needs for=\"agents\" or for=\"humans\".");
|
|
98
|
+
context.replaceNode(node, audience === "humans" ? node.children ?? [] : []);
|
|
99
|
+
};
|
|
100
|
+
const handlers = {
|
|
101
|
+
Tabs: prepareTabs,
|
|
102
|
+
CodeGroup: prepareCodeGroup,
|
|
103
|
+
FileTree: prepareFileTree
|
|
104
|
+
};
|
|
105
|
+
/**
|
|
106
|
+
* Sätteri plugin that prepares the MDX components that need data from their children, and
|
|
107
|
+
* applies `<Visibility>`.
|
|
108
|
+
*/
|
|
109
|
+
const mdxComponents = {
|
|
110
|
+
name: "andesine-mdx-components",
|
|
111
|
+
mdxJsxFlowElement(node, context) {
|
|
112
|
+
if (node.name === "Visibility") return applyVisibility(node, context);
|
|
113
|
+
if (node.name) return handlers[node.name]?.(node);
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
//#endregion
|
|
117
|
+
//#region src/content/shiki-code-title.ts
|
|
118
|
+
/** Adds `data-title` from a code fence `title="..."` to the highlighted `<pre>`. */
|
|
119
|
+
const shikiCodeTitle = {
|
|
120
|
+
name: "andesine-code-title",
|
|
121
|
+
pre(node) {
|
|
122
|
+
const meta = this.options.meta;
|
|
123
|
+
const title = getCodeTitle(typeof meta === "string" ? meta : meta?.__raw);
|
|
124
|
+
if (title) node.properties["data-title"] = title;
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
//#endregion
|
|
128
|
+
//#region src/integration/assets.ts
|
|
129
|
+
const readFileList = async (directory) => {
|
|
130
|
+
const files = JSON.parse(await readFile(new URL("files.json", directory), "utf8"));
|
|
131
|
+
return Array.isArray(files) ? files.filter((file) => assetFile.test(String(file))) : [];
|
|
132
|
+
};
|
|
133
|
+
/** Copies the cached images of build-time Andesine sources into the build output. */
|
|
134
|
+
const copyAssets = async (cache, output, sourceIDs) => {
|
|
135
|
+
const destination = new URL(`${assetPath}/`, output);
|
|
136
|
+
if (!sourceIDs.length) return;
|
|
137
|
+
await mkdir(destination, { recursive: true });
|
|
138
|
+
for (const sourceID of sourceIDs) {
|
|
139
|
+
const directory = new URL(`andesine/${sourceID}/`, cache);
|
|
140
|
+
for (const file of await readFileList(directory)) await copyFile(new URL(file, directory), new URL(file, destination));
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
/** Serves the cached images in development. */
|
|
144
|
+
const serveAssets = (server, cache, base, sourceIDs) => {
|
|
145
|
+
const prefix = getAssetPrefix(base);
|
|
146
|
+
server.middlewares.use(async (request, response, next) => {
|
|
147
|
+
const path = new URL(request.url ?? "/", "http://localhost").pathname;
|
|
148
|
+
const file = path.slice(prefix.length);
|
|
149
|
+
if (!path.startsWith(prefix) || !assetFile.test(file)) return next();
|
|
150
|
+
for (const sourceID of sourceIDs) {
|
|
151
|
+
const bytes = await readFile(new URL(`andesine/${sourceID}/${file}`, cache)).catch(() => null);
|
|
152
|
+
if (!bytes) continue;
|
|
153
|
+
response.setHeader("Content-Type", mimeTypes[file.split(".").at(-1)]);
|
|
154
|
+
response.end(bytes);
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
next();
|
|
158
|
+
});
|
|
159
|
+
};
|
|
160
|
+
//#endregion
|
|
161
|
+
//#region src/integration/load-config.ts
|
|
162
|
+
const loadConfig = async (path) => {
|
|
163
|
+
if (!existsSync(path)) throw new Error(`Andesine Pages config not found: ${path}`);
|
|
164
|
+
const { module, dependencies } = await runnerImport(path);
|
|
165
|
+
return {
|
|
166
|
+
config: parseConfig(module.default, path),
|
|
167
|
+
dependencies
|
|
168
|
+
};
|
|
169
|
+
};
|
|
170
|
+
//#endregion
|
|
171
|
+
//#region src/search/pagefind.ts
|
|
172
|
+
const withIndex = async (task) => {
|
|
173
|
+
const { index, errors } = await createIndex();
|
|
174
|
+
if (!index) throw new Error(`Pagefind: ${errors.join(", ")}`);
|
|
175
|
+
try {
|
|
176
|
+
return await task(index);
|
|
177
|
+
} finally {
|
|
178
|
+
await index.deleteIndex();
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
const assertNoErrors = (result) => {
|
|
182
|
+
if (result.errors.length) throw new Error(`Pagefind: ${result.errors.join(", ")}`);
|
|
183
|
+
};
|
|
184
|
+
/**
|
|
185
|
+
* Indexes the built pages that have a `data-pagefind-body` element, and writes the index to
|
|
186
|
+
* `pagefind/` in the output directory.
|
|
187
|
+
*/
|
|
188
|
+
const writePagefindIndex = (directory) => {
|
|
189
|
+
return withIndex(async (index) => {
|
|
190
|
+
assertNoErrors(await index.addDirectory({ path: directory }));
|
|
191
|
+
assertNoErrors(await index.writeFiles({ outputPath: join(directory, "pagefind") }));
|
|
192
|
+
});
|
|
193
|
+
};
|
|
194
|
+
/** Creates index files in memory from records, for the development server. */
|
|
195
|
+
const createPagefindFiles = (records) => {
|
|
196
|
+
return withIndex(async (index) => {
|
|
197
|
+
for (const record of records) assertNoErrors(await index.addCustomRecord(record));
|
|
198
|
+
const result = await index.getFiles();
|
|
199
|
+
assertNoErrors(result);
|
|
200
|
+
return new Map(result.files.map((file) => [file.path, file.content]));
|
|
201
|
+
});
|
|
202
|
+
};
|
|
203
|
+
//#endregion
|
|
204
|
+
//#region src/integration/pagefind-dev.ts
|
|
205
|
+
const contentTypes = {
|
|
206
|
+
js: "text/javascript",
|
|
207
|
+
json: "application/json"
|
|
208
|
+
};
|
|
209
|
+
/**
|
|
210
|
+
* Serves a Pagefind index in development. It is built in memory from the source records on the
|
|
211
|
+
* first request, and again after a file changes.
|
|
212
|
+
*/
|
|
213
|
+
const servePagefind = (server, base, loadRecords) => {
|
|
214
|
+
const prefix = `${base}pagefind/`;
|
|
215
|
+
let files;
|
|
216
|
+
server.watcher.on("all", () => files = void 0);
|
|
217
|
+
server.middlewares.use(async (request, response, next) => {
|
|
218
|
+
const path = new URL(request.url ?? "/", "http://localhost").pathname;
|
|
219
|
+
if (!path.startsWith(prefix)) return next();
|
|
220
|
+
files ??= loadRecords().then(createPagefindFiles);
|
|
221
|
+
try {
|
|
222
|
+
const body = (await files).get(path.slice(prefix.length));
|
|
223
|
+
response.setHeader("Cache-Control", "no-store");
|
|
224
|
+
response.statusCode = body ? 200 : 404;
|
|
225
|
+
response.setHeader("Content-Type", contentTypes[path.split(".").at(-1)] ?? "application/octet-stream");
|
|
226
|
+
response.end(body);
|
|
227
|
+
} catch (error) {
|
|
228
|
+
files = void 0;
|
|
229
|
+
server.config.logger.error(`Pagefind development index failed: ${String(error)}`);
|
|
230
|
+
response.statusCode = 503;
|
|
231
|
+
response.end();
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
};
|
|
235
|
+
//#endregion
|
|
236
|
+
//#region src/integration/virtual-modules.ts
|
|
237
|
+
const createConfigModule = (options) => {
|
|
238
|
+
const { config, configPath } = options;
|
|
239
|
+
const imports = [];
|
|
240
|
+
const assignments = [];
|
|
241
|
+
const importAsset = (target, value) => {
|
|
242
|
+
if (!value || !/^\.\.?\//.test(value)) return;
|
|
243
|
+
const name = `asset${imports.length}`;
|
|
244
|
+
const path = resolve(dirname(configPath), value);
|
|
245
|
+
imports.push(`import ${name} from ${JSON.stringify(`${path}?url&no-inline`)};`);
|
|
246
|
+
assignments.push(`${target} = ${name};`);
|
|
247
|
+
};
|
|
248
|
+
importAsset("config.logo.src", config.logo?.src);
|
|
249
|
+
importAsset("config.favicon", config.favicon);
|
|
250
|
+
importAsset("config.social.image", config.social.image);
|
|
251
|
+
return [
|
|
252
|
+
...imports,
|
|
253
|
+
`const config = ${JSON.stringify(config)};`,
|
|
254
|
+
...assignments,
|
|
255
|
+
`export const highlight = ${JSON.stringify(options.highlight)};`,
|
|
256
|
+
config.agents.skill ? `export { default as skill } from ${JSON.stringify(`${resolve(dirname(configPath), config.agents.skill)}?raw`)};` : "export const skill = undefined;",
|
|
257
|
+
"export default config;"
|
|
258
|
+
].join("\n");
|
|
259
|
+
};
|
|
260
|
+
/** The template's social card, with the card images as data URLs. */
|
|
261
|
+
const createSocialModule = (options) => {
|
|
262
|
+
const { config, configPath } = options;
|
|
263
|
+
const toImport = (name, value) => {
|
|
264
|
+
if (!value || !/^\.\.?\//.test(value)) return `const ${name} = undefined;`;
|
|
265
|
+
const path = resolve(dirname(configPath), value);
|
|
266
|
+
return `import ${name} from ${JSON.stringify(`${path}?inline`)};`;
|
|
267
|
+
};
|
|
268
|
+
if (!config.social.generate) return "export default {};";
|
|
269
|
+
return [
|
|
270
|
+
`import card from ${JSON.stringify(options.socialCardPath)};`,
|
|
271
|
+
toImport("logo", config.logo?.src),
|
|
272
|
+
toImport("background", config.social.background),
|
|
273
|
+
"export default { card, logo, background };"
|
|
274
|
+
].join("\n");
|
|
275
|
+
};
|
|
276
|
+
const virtualModules = (options) => {
|
|
277
|
+
const modules = {
|
|
278
|
+
"virtual:andesine/config": () => createConfigModule(options),
|
|
279
|
+
"virtual:andesine/layout": () => {
|
|
280
|
+
return `export { default } from ${JSON.stringify(options.layoutPath)};`;
|
|
281
|
+
},
|
|
282
|
+
"virtual:andesine/components": () => {
|
|
283
|
+
return existsSync(options.componentsPath) ? `export { components } from ${JSON.stringify(options.componentsPath)};` : "export const components = {};";
|
|
284
|
+
},
|
|
285
|
+
"virtual:andesine/social": () => createSocialModule(options)
|
|
286
|
+
};
|
|
287
|
+
return {
|
|
288
|
+
name: "andesine-pages-virtual-modules",
|
|
289
|
+
resolveId(id) {
|
|
290
|
+
if (id in modules) return `\0${id}`;
|
|
291
|
+
},
|
|
292
|
+
load(id) {
|
|
293
|
+
if (id.startsWith("\0")) return modules[id.slice(1)]?.();
|
|
294
|
+
}
|
|
295
|
+
};
|
|
296
|
+
};
|
|
297
|
+
//#endregion
|
|
298
|
+
//#region src/integration.ts
|
|
299
|
+
const socialRenderers = ["satori", "@resvg/resvg-js"];
|
|
300
|
+
const pageLists = {
|
|
301
|
+
"/sitemap.xml": "sitemap",
|
|
302
|
+
"/llms.txt": "llms",
|
|
303
|
+
"/llms-full.txt": "llms-full",
|
|
304
|
+
"/.well-known/llms.txt": "well-known-llms",
|
|
305
|
+
"/skill.md": "skill",
|
|
306
|
+
"/.well-known/[...path]": "skills"
|
|
307
|
+
};
|
|
308
|
+
const getBuildSourceIDs = (config) => {
|
|
309
|
+
return config.sources.filter((source) => source.type === "andesine").map((source) => source.id);
|
|
310
|
+
};
|
|
311
|
+
const andesine = (options = {}) => {
|
|
312
|
+
let config;
|
|
313
|
+
let cache;
|
|
314
|
+
let output;
|
|
315
|
+
return {
|
|
316
|
+
name: "@andesine/pages",
|
|
317
|
+
hooks: {
|
|
318
|
+
"astro:config:setup": async ({ config: astroConfig, updateConfig, injectRoute, injectScript, addMiddleware, addWatchFile, logger }) => {
|
|
319
|
+
const root = fileURLToPath(astroConfig.root);
|
|
320
|
+
const configPath = resolve(root, options.config ?? "andesine.config.ts");
|
|
321
|
+
const layoutPath = resolve(root, options.layout ?? "src/layouts/page.astro");
|
|
322
|
+
const componentsPath = resolve(root, options.components ?? "src/components/content/index.ts");
|
|
323
|
+
const socialCardPath = resolve(root, options.socialCard ?? "src/components/social/card.ts");
|
|
324
|
+
const loaded = await loadConfig(configPath);
|
|
325
|
+
const { dependencies } = loaded;
|
|
326
|
+
const processor = astroConfig.markdown.processor;
|
|
327
|
+
const isCloudflare = astroConfig.adapter?.name === "@astrojs/cloudflare";
|
|
328
|
+
config = loaded.config;
|
|
329
|
+
config.social.generate &&= existsSync(socialCardPath);
|
|
330
|
+
[configPath, ...dependencies].forEach((path) => addWatchFile(path));
|
|
331
|
+
if (processor?.name === "satteri") processor.options.mdastPlugins = [...processor.options.mdastPlugins ?? [], mdxComponents];
|
|
332
|
+
else logger.warn("MDX content components need the Sätteri Markdown processor.");
|
|
333
|
+
updateConfig({
|
|
334
|
+
site: config.site,
|
|
335
|
+
base: config.base,
|
|
336
|
+
markdown: { shikiConfig: { transformers: [shikiCodeTitle] } },
|
|
337
|
+
vite: {
|
|
338
|
+
plugins: [virtualModules({
|
|
339
|
+
config,
|
|
340
|
+
configPath,
|
|
341
|
+
layoutPath,
|
|
342
|
+
componentsPath,
|
|
343
|
+
socialCardPath,
|
|
344
|
+
highlight: astroConfig.markdown.shikiConfig
|
|
345
|
+
})],
|
|
346
|
+
ssr: { noExternal: ["@andesine/pages"] },
|
|
347
|
+
environments: isCloudflare ? {} : {
|
|
348
|
+
ssr: { resolve: { external: socialRenderers } },
|
|
349
|
+
prerender: { resolve: { external: socialRenderers } }
|
|
350
|
+
},
|
|
351
|
+
optimizeDeps: { exclude: socialRenderers }
|
|
352
|
+
}
|
|
353
|
+
});
|
|
354
|
+
injectScript("head-inline", readFileSync(new URL("./scripts/restore-navigation.js", import.meta.url), "utf8"));
|
|
355
|
+
addMiddleware({
|
|
356
|
+
entrypoint: new URL("./astro/middleware.js", import.meta.url),
|
|
357
|
+
order: "pre"
|
|
358
|
+
});
|
|
359
|
+
injectRoute({
|
|
360
|
+
pattern: "/[...path]",
|
|
361
|
+
entrypoint: new URL("./astro/routes/static.astro", import.meta.url),
|
|
362
|
+
prerender: true
|
|
363
|
+
});
|
|
364
|
+
injectRoute({
|
|
365
|
+
pattern: "/[...path]/index.md",
|
|
366
|
+
entrypoint: new URL("./astro/routes/markdown.js", import.meta.url),
|
|
367
|
+
prerender: true
|
|
368
|
+
});
|
|
369
|
+
injectRoute({
|
|
370
|
+
pattern: "/[...path].md",
|
|
371
|
+
entrypoint: new URL("./astro/routes/markdown-alias.js", import.meta.url),
|
|
372
|
+
prerender: true
|
|
373
|
+
});
|
|
374
|
+
if (config.social.generate) injectRoute({
|
|
375
|
+
pattern: "/[...path]/social.png",
|
|
376
|
+
entrypoint: new URL("./astro/routes/social.js", import.meta.url),
|
|
377
|
+
prerender: true
|
|
378
|
+
});
|
|
379
|
+
for (const [pattern, name] of Object.entries(pageLists)) injectRoute({
|
|
380
|
+
pattern,
|
|
381
|
+
entrypoint: new URL(`./astro/routes/${name}.js`, import.meta.url),
|
|
382
|
+
prerender: true
|
|
383
|
+
});
|
|
384
|
+
injectRoute({
|
|
385
|
+
pattern: "/robots.txt",
|
|
386
|
+
entrypoint: new URL("./astro/routes/robots.js", import.meta.url),
|
|
387
|
+
prerender: true
|
|
388
|
+
});
|
|
389
|
+
injectRoute({
|
|
390
|
+
pattern: "/404",
|
|
391
|
+
entrypoint: new URL("./astro/routes/not-found.astro", import.meta.url),
|
|
392
|
+
prerender: true
|
|
393
|
+
});
|
|
394
|
+
const andesineSources = config.sources.filter((source) => source.type === "andesine");
|
|
395
|
+
if (andesineSources.some((source) => source.publicKey)) injectRoute({
|
|
396
|
+
pattern: "/_andesine/pages/[source].json",
|
|
397
|
+
entrypoint: new URL("./astro/routes/entry-pages.js", import.meta.url),
|
|
398
|
+
prerender: true
|
|
399
|
+
});
|
|
400
|
+
if (andesineSources.some((source) => !source.publicKey)) injectRoute({
|
|
401
|
+
pattern: "/_andesine/search",
|
|
402
|
+
entrypoint: new URL("./astro/routes/search.js", import.meta.url),
|
|
403
|
+
prerender: false
|
|
404
|
+
});
|
|
405
|
+
if (andesineSources.some((source) => source.answers && !source.publicKey)) injectRoute({
|
|
406
|
+
pattern: "/_andesine/answers",
|
|
407
|
+
entrypoint: new URL("./astro/routes/answers.js", import.meta.url),
|
|
408
|
+
prerender: false
|
|
409
|
+
});
|
|
410
|
+
},
|
|
411
|
+
"astro:config:done": ({ config: astroConfig, buildOutput }) => {
|
|
412
|
+
cache = astroConfig.cacheDir;
|
|
413
|
+
output = buildOutput === "server" ? astroConfig.build.client : astroConfig.outDir;
|
|
414
|
+
},
|
|
415
|
+
"astro:server:setup": ({ server }) => {
|
|
416
|
+
const runtime = fileURLToPath(new URL("./runtime.js", import.meta.url));
|
|
417
|
+
serveAssets(server, cache, config.base, getBuildSourceIDs(config));
|
|
418
|
+
servePagefind(server, config.base, async () => {
|
|
419
|
+
return (await server.ssrLoadModule(runtime)).getSearchRecords(config);
|
|
420
|
+
});
|
|
421
|
+
},
|
|
422
|
+
"astro:build:done": async ({ logger }) => {
|
|
423
|
+
await copyAssets(cache, output, getBuildSourceIDs(config));
|
|
424
|
+
if (config.sources.some((source) => source.type !== "andesine")) {
|
|
425
|
+
await writePagefindIndex(fileURLToPath(output));
|
|
426
|
+
logger.info("Wrote the local search index.");
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
};
|
|
431
|
+
};
|
|
432
|
+
//#endregion
|
|
433
|
+
export { andesine };
|
|
434
|
+
|
|
435
|
+
//# sourceMappingURL=integration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"integration.js","names":[],"sources":["../src/content/mdx-components.ts","../src/content/shiki-code-title.ts","../src/integration/assets.ts","../src/integration/load-config.ts","../src/search/pagefind.ts","../src/integration/pagefind-dev.ts","../src/integration/virtual-modules.ts","../src/integration.ts"],"sourcesContent":["interface MdastNode {\n type: string;\n name?: string | null;\n value?: string;\n lang?: string | null;\n meta?: string | null;\n attributes?: MdxAttribute[];\n children?: MdastNode[];\n}\n\ninterface FileTreeItem {\n name: string;\n type: \"file\" | \"folder\";\n children: FileTreeItem[];\n}\n\ninterface MdxAttribute {\n type: string;\n name: string;\n value?: unknown;\n}\n\ninterface VisitorContext {\n /** Swaps the node for the given nodes; an empty array removes it. */\n replaceNode(node: MdastNode, content: MdastNode[]): void;\n}\n\n/** Returns a node that replaces the visited node. */\ntype Handler = (node: MdastNode) => MdastNode;\n\nconst stringAttribute = (name: string, value: string): MdxAttribute => {\n return {\n type: \"mdxJsxAttribute\",\n name,\n value\n };\n};\nconst getAttribute = (node: MdastNode, name: string): unknown => {\n return node.attributes?.find((attribute) => attribute.name === name)?.value;\n};\n/** Reads `title=\"...\"` from a code fence meta string. */\nconst getCodeTitle = (meta?: string | null): string | undefined => {\n const match = meta?.match(/title=(?:\"([^\"]*)\"|'([^']*)'|(\\S+))/);\n\n return match?.[1] ?? match?.[2] ?? match?.[3];\n};\nconst withValues = (node: MdastNode, labels: string[], children: MdastNode[]): MdastNode => {\n if (new Set(labels).size !== labels.length) {\n throw new Error(`<${node.name}> needs a unique label for each tab: ${labels.join(\", \")}.`);\n }\n\n return {\n type: node.type,\n name: node.name,\n attributes: [\n ...(node.attributes ?? []).filter((attribute) => attribute.name !== \"values\"),\n stringAttribute(\"values\", JSON.stringify(labels))\n ],\n children\n };\n};\n/** `<Tabs>` children `<Tab label=\"...\">` become the named slots `tab-0`, `tab-1`, and so on. */\nconst prepareTabs: Handler = (node) => {\n const labels: string[] = [];\n const children = (node.children ?? []).map((child) => {\n if (child.type !== \"mdxJsxFlowElement\" || child.name !== \"Tab\") return child;\n\n const label = getAttribute(child, \"label\");\n const index = labels.length;\n\n if (typeof label !== \"string\" || !label.trim()) {\n throw new Error(`<Tab> ${index + 1} needs a text label, e.g. <Tab label=\"npm\">.`);\n }\n\n labels.push(label);\n\n return {\n type: child.type,\n name: child.name,\n attributes: [...(child.attributes ?? []), stringAttribute(\"slot\", `tab-${index}`)],\n children: child.children\n };\n });\n\n return withValues(node, labels, children);\n};\n/** `<CodeGroup>` code fences become tabs, labeled by their `title` or language. */\nconst prepareCodeGroup: Handler = (node) => {\n const blocks = (node.children ?? []).filter((child) => child.type === \"code\");\n const labels = blocks.map((block) => getCodeTitle(block.meta) ?? block.lang ?? \"Code\");\n const children = blocks.map((block, index) => {\n return {\n type: \"mdxJsxFlowElement\",\n name: \"div\",\n attributes: [stringAttribute(\"slot\", `tab-${index}`)],\n children: [block]\n };\n });\n\n return withValues(node, labels, children);\n};\n/** Returns the text of a node, with inline code. */\nconst getText = (node: MdastNode): string => {\n return node.type === \"text\" || node.type === \"inlineCode\"\n ? (node.value ?? \"\")\n : (node.children ?? []).map(getText).join(\"\");\n};\nconst toFileTreeItems = (list: MdastNode): FileTreeItem[] => {\n return (list.children ?? []).map((item) => {\n const label = item.children?.find((child) => child.type !== \"list\");\n const nested = item.children?.find((child) => child.type === \"list\");\n const name = label ? getText(label).trim() : \"\";\n const folder = name.endsWith(\"/\") || Boolean(nested);\n\n return {\n name: name.replace(/\\/$/, \"\"),\n type: folder ? \"folder\" : \"file\",\n children: nested ? toFileTreeItems(nested) : []\n };\n });\n};\n/** `<FileTree>` gets its nested list as JSON `items`. Items that end with `/`, or have nested items, are folders. */\nconst prepareFileTree: Handler = (node) => {\n const list = node.children?.find((child) => child.type === \"list\");\n\n if (!list) throw new Error(\"<FileTree> needs a Markdown list of files and folders.\");\n\n return {\n type: node.type,\n name: node.name,\n attributes: [stringAttribute(\"items\", JSON.stringify(toFileTreeItems(list)))],\n children: []\n };\n};\n/** The web page shows only human content; agent content is in the Markdown outputs. */\nconst applyVisibility = (node: MdastNode, context: VisitorContext): void => {\n const audience = getAttribute(node, \"for\");\n\n if (audience !== \"agents\" && audience !== \"humans\") {\n throw new Error('<Visibility> needs for=\"agents\" or for=\"humans\".');\n }\n\n context.replaceNode(node, audience === \"humans\" ? (node.children ?? []) : []);\n};\nconst handlers: Record<string, Handler> = {\n Tabs: prepareTabs,\n CodeGroup: prepareCodeGroup,\n FileTree: prepareFileTree\n};\n\n/**\n * Sätteri plugin that prepares the MDX components that need data from their children, and\n * applies `<Visibility>`.\n */\nconst mdxComponents = {\n name: \"andesine-mdx-components\",\n mdxJsxFlowElement(node: MdastNode, context: VisitorContext): MdastNode | void {\n if (node.name === \"Visibility\") return applyVisibility(node, context);\n if (node.name) return handlers[node.name]?.(node);\n }\n};\n\nexport { mdxComponents, getCodeTitle };\nexport type { FileTreeItem };\n","import { getCodeTitle } from \"./mdx-components\";\n\ninterface TransformerContext {\n /** Sätteri passes the fence meta as a string; other processors pass `{ __raw }`. */\n options: { meta?: string | { __raw?: string } };\n}\n\ninterface HastElement {\n properties: Record<string, unknown>;\n}\n\n/** Adds `data-title` from a code fence `title=\"...\"` to the highlighted `<pre>`. */\nconst shikiCodeTitle = {\n name: \"andesine-code-title\",\n pre(this: TransformerContext, node: HastElement): void {\n const meta = this.options.meta;\n const title = getCodeTitle(typeof meta === \"string\" ? meta : meta?.__raw);\n\n if (title) node.properties[\"data-title\"] = title;\n }\n};\n\nexport { shikiCodeTitle };\n","import { copyFile, mkdir, readFile } from \"node:fs/promises\";\nimport type { ViteDevServer } from \"vite\";\nimport { assetFile, assetPath, getAssetPrefix, mimeTypes } from \"../sources/andesine/assets\";\n\nconst readFileList = async (directory: URL): Promise<string[]> => {\n const files: unknown = JSON.parse(await readFile(new URL(\"files.json\", directory), \"utf8\"));\n\n return Array.isArray(files) ? files.filter((file) => assetFile.test(String(file))) : [];\n};\n/** Copies the cached images of build-time Andesine sources into the build output. */\nconst copyAssets = async (cache: URL, output: URL, sourceIDs: string[]): Promise<void> => {\n const destination = new URL(`${assetPath}/`, output);\n\n if (!sourceIDs.length) return;\n\n await mkdir(destination, { recursive: true });\n\n for (const sourceID of sourceIDs) {\n const directory = new URL(`andesine/${sourceID}/`, cache);\n\n for (const file of await readFileList(directory)) {\n await copyFile(new URL(file, directory), new URL(file, destination));\n }\n }\n};\n/** Serves the cached images in development. */\nconst serveAssets = (\n server: ViteDevServer,\n cache: URL,\n base: string,\n sourceIDs: string[]\n): void => {\n const prefix = getAssetPrefix(base);\n\n server.middlewares.use(async (request, response, next) => {\n const path = new URL(request.url ?? \"/\", \"http://localhost\").pathname;\n const file = path.slice(prefix.length);\n\n if (!path.startsWith(prefix) || !assetFile.test(file)) return next();\n\n for (const sourceID of sourceIDs) {\n const bytes = await readFile(new URL(`andesine/${sourceID}/${file}`, cache)).catch(\n () => null\n );\n\n if (!bytes) continue;\n\n response.setHeader(\n \"Content-Type\",\n mimeTypes[file.split(\".\").at(-1) as keyof typeof mimeTypes]\n );\n response.end(bytes);\n\n return;\n }\n\n next();\n });\n};\n\nexport { copyAssets, serveAssets };\n","import { existsSync } from \"node:fs\";\nimport { runnerImport } from \"vite\";\nimport { parseConfig, type PagesConfig } from \"../config\";\n\ninterface LoadedConfig {\n config: PagesConfig;\n /** Imported local files, for development reloads. */\n dependencies: string[];\n}\n\nconst loadConfig = async (path: string): Promise<LoadedConfig> => {\n if (!existsSync(path)) throw new Error(`Andesine Pages config not found: ${path}`);\n\n const { module, dependencies } = await runnerImport<{ default?: unknown }>(path);\n\n return { config: parseConfig(module.default, path), dependencies };\n};\n\nexport { loadConfig };\n","import { join } from \"node:path\";\nimport { createIndex, type CustomRecord, type PagefindIndex } from \"pagefind\";\n\nconst withIndex = async <T>(task: (index: PagefindIndex) => Promise<T>): Promise<T> => {\n const { index, errors } = await createIndex();\n\n if (!index) throw new Error(`Pagefind: ${errors.join(\", \")}`);\n\n try {\n return await task(index);\n } finally {\n await index.deleteIndex();\n }\n};\nconst assertNoErrors = (result: { errors: string[] }): void => {\n if (result.errors.length) throw new Error(`Pagefind: ${result.errors.join(\", \")}`);\n};\n/**\n * Indexes the built pages that have a `data-pagefind-body` element, and writes the index to\n * `pagefind/` in the output directory.\n */\nconst writePagefindIndex = (directory: string): Promise<void> => {\n return withIndex(async (index) => {\n assertNoErrors(await index.addDirectory({ path: directory }));\n assertNoErrors(await index.writeFiles({ outputPath: join(directory, \"pagefind\") }));\n });\n};\n/** Creates index files in memory from records, for the development server. */\nconst createPagefindFiles = (records: CustomRecord[]): Promise<Map<string, Uint8Array>> => {\n return withIndex(async (index) => {\n for (const record of records) assertNoErrors(await index.addCustomRecord(record));\n\n const result = await index.getFiles();\n\n assertNoErrors(result);\n\n return new Map(result.files.map((file) => [file.path, file.content]));\n });\n};\n\nexport { writePagefindIndex, createPagefindFiles };\n","import type { CustomRecord } from \"pagefind\";\nimport type { ViteDevServer } from \"vite\";\nimport { createPagefindFiles } from \"../search/pagefind\";\n\nconst contentTypes: Record<string, string> = { js: \"text/javascript\", json: \"application/json\" };\n\n/**\n * Serves a Pagefind index in development. It is built in memory from the source records on the\n * first request, and again after a file changes.\n */\nconst servePagefind = (\n server: ViteDevServer,\n base: string,\n loadRecords: () => Promise<CustomRecord[]>\n): void => {\n const prefix = `${base}pagefind/`;\n\n let files: Promise<Map<string, Uint8Array>> | undefined;\n\n server.watcher.on(\"all\", () => (files = undefined));\n server.middlewares.use(async (request, response, next) => {\n const path = new URL(request.url ?? \"/\", \"http://localhost\").pathname;\n\n if (!path.startsWith(prefix)) return next();\n\n files ??= loadRecords().then(createPagefindFiles);\n\n try {\n const body = (await files).get(path.slice(prefix.length));\n\n response.setHeader(\"Cache-Control\", \"no-store\");\n response.statusCode = body ? 200 : 404;\n response.setHeader(\n \"Content-Type\",\n contentTypes[path.split(\".\").at(-1)!] ?? \"application/octet-stream\"\n );\n response.end(body);\n } catch (error) {\n files = undefined;\n server.config.logger.error(`Pagefind development index failed: ${String(error)}`);\n response.statusCode = 503;\n response.end();\n }\n });\n};\n\nexport { servePagefind };\n","import { existsSync } from \"node:fs\";\nimport { dirname, resolve } from \"node:path\";\nimport type { Plugin } from \"vite\";\nimport type { PagesConfig } from \"../config\";\n\ninterface VirtualModulesOptions {\n config: PagesConfig;\n configPath: string;\n layoutPath: string;\n componentsPath: string;\n socialCardPath: string;\n /** Astro's Shiki config; functions, such as transformers, are left out. */\n highlight: object;\n}\n\nconst createConfigModule = (options: VirtualModulesOptions): string => {\n const { config, configPath } = options;\n const imports: string[] = [];\n const assignments: string[] = [];\n const importAsset = (target: string, value?: string): void => {\n if (!value || !/^\\.\\.?\\//.test(value)) return;\n\n const name = `asset${imports.length}`;\n const path = resolve(dirname(configPath), value);\n\n imports.push(`import ${name} from ${JSON.stringify(`${path}?url&no-inline`)};`);\n assignments.push(`${target} = ${name};`);\n };\n\n importAsset(\"config.logo.src\", config.logo?.src);\n importAsset(\"config.favicon\", config.favicon);\n importAsset(\"config.social.image\", config.social.image);\n\n return [\n ...imports,\n `const config = ${JSON.stringify(config)};`,\n ...assignments,\n `export const highlight = ${JSON.stringify(options.highlight)};`,\n config.agents.skill\n ? `export { default as skill } from ${JSON.stringify(`${resolve(dirname(configPath), config.agents.skill)}?raw`)};`\n : \"export const skill = undefined;\",\n \"export default config;\"\n ].join(\"\\n\");\n};\n/** The template's social card, with the card images as data URLs. */\nconst createSocialModule = (options: VirtualModulesOptions): string => {\n const { config, configPath } = options;\n // Only files next to the config can be inlined; the card leaves out other images.\n const toImport = (name: string, value?: string): string => {\n if (!value || !/^\\.\\.?\\//.test(value)) return `const ${name} = undefined;`;\n\n const path = resolve(dirname(configPath), value);\n\n return `import ${name} from ${JSON.stringify(`${path}?inline`)};`;\n };\n\n if (!config.social.generate) return \"export default {};\";\n\n return [\n `import card from ${JSON.stringify(options.socialCardPath)};`,\n toImport(\"logo\", config.logo?.src),\n toImport(\"background\", config.social.background),\n \"export default { card, logo, background };\"\n ].join(\"\\n\");\n};\nconst virtualModules = (options: VirtualModulesOptions): Plugin => {\n const modules: Record<string, () => string> = {\n \"virtual:andesine/config\": () => createConfigModule(options),\n \"virtual:andesine/layout\": () => {\n return `export { default } from ${JSON.stringify(options.layoutPath)};`;\n },\n \"virtual:andesine/components\": () => {\n return existsSync(options.componentsPath)\n ? `export { components } from ${JSON.stringify(options.componentsPath)};`\n : \"export const components = {};\";\n },\n \"virtual:andesine/social\": () => createSocialModule(options)\n };\n\n return {\n name: \"andesine-pages-virtual-modules\",\n resolveId(id) {\n if (id in modules) return `\\0${id}`;\n },\n load(id) {\n if (id.startsWith(\"\\0\")) return modules[id.slice(1)]?.();\n }\n };\n};\n\nexport { virtualModules };\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport type { AstroIntegration } from \"astro\";\nimport type { PagesConfig } from \"./config\";\nimport { mdxComponents } from \"./content/mdx-components\";\nimport { shikiCodeTitle } from \"./content/shiki-code-title\";\nimport { copyAssets, serveAssets } from \"./integration/assets\";\nimport { loadConfig } from \"./integration/load-config\";\nimport { servePagefind } from \"./integration/pagefind-dev\";\nimport { virtualModules } from \"./integration/virtual-modules\";\nimport { writePagefindIndex } from \"./search/pagefind\";\n\ninterface AndesineOptions {\n /** Relative to the project root. */\n config?: string;\n /** Astro layout that renders each page. Relative to the project root. */\n layout?: string;\n /** Module that exports the `components` for page content. Relative to the project root. */\n components?: string;\n /** Module that exports the social card for generated page images. Relative to the project root. */\n socialCard?: string;\n}\n\ninterface MarkdownProcessor {\n name: string;\n options: { mdastPlugins?: unknown[] };\n}\n\nconst socialRenderers = [\"satori\", \"@resvg/resvg-js\"];\nconst pageLists = {\n \"/sitemap.xml\": \"sitemap\",\n \"/llms.txt\": \"llms\",\n \"/llms-full.txt\": \"llms-full\",\n \"/.well-known/llms.txt\": \"well-known-llms\",\n \"/skill.md\": \"skill\",\n \"/.well-known/[...path]\": \"skills\"\n};\n\nconst getBuildSourceIDs = (config: PagesConfig): string[] => {\n return config.sources.filter((source) => source.type === \"andesine\").map((source) => source.id);\n};\nconst andesine = (options: AndesineOptions = {}): AstroIntegration => {\n let config: PagesConfig;\n let cache: URL;\n let output: URL;\n\n return {\n name: \"@andesine/pages\",\n hooks: {\n \"astro:config:setup\": async ({\n config: astroConfig,\n updateConfig,\n injectRoute,\n injectScript,\n addMiddleware,\n addWatchFile,\n logger\n }) => {\n const root = fileURLToPath(astroConfig.root);\n const configPath = resolve(root, options.config ?? \"andesine.config.ts\");\n const layoutPath = resolve(root, options.layout ?? \"src/layouts/page.astro\");\n const componentsPath = resolve(\n root,\n options.components ?? \"src/components/content/index.ts\"\n );\n const socialCardPath = resolve(root, options.socialCard ?? \"src/components/social/card.ts\");\n const loaded = await loadConfig(configPath);\n const { dependencies } = loaded;\n const processor = astroConfig.markdown.processor as MarkdownProcessor | undefined;\n const isCloudflare = astroConfig.adapter?.name === \"@astrojs/cloudflare\";\n\n config = loaded.config;\n // Without a social card, pages use the default image.\n config.social.generate &&= existsSync(socialCardPath);\n [configPath, ...dependencies].forEach((path) => addWatchFile(path));\n\n // Astro keeps processor options mutable, so integrations can add plugins.\n if (processor?.name === \"satteri\") {\n processor.options.mdastPlugins = [\n ...(processor.options.mdastPlugins ?? []),\n mdxComponents\n ];\n } else {\n logger.warn(\"MDX content components need the Sätteri Markdown processor.\");\n }\n\n updateConfig({\n site: config.site,\n base: config.base,\n markdown: { shikiConfig: { transformers: [shikiCodeTitle] } },\n vite: {\n plugins: [\n virtualModules({\n config,\n configPath,\n layoutPath,\n componentsPath,\n socialCardPath,\n highlight: astroConfig.markdown.shikiConfig\n })\n ],\n ssr: { noExternal: [\"@andesine/pages\"] },\n // The social image renderers load native and WebAssembly code, so they stay outside\n // the server bundles. The site installs them. Cloudflare does not allow externals.\n environments: isCloudflare\n ? {}\n : {\n ssr: { resolve: { external: socialRenderers } },\n prerender: { resolve: { external: socialRenderers } }\n },\n optimizeDeps: { exclude: socialRenderers }\n }\n });\n\n // Restores saved navigation tree groups before the first paint; see the script's source.\n injectScript(\n \"head-inline\",\n readFileSync(new URL(\"./scripts/restore-navigation.js\", import.meta.url), \"utf8\")\n );\n\n addMiddleware({\n entrypoint: new URL(\"./astro/middleware.js\", import.meta.url),\n order: \"pre\"\n });\n\n injectRoute({\n pattern: \"/[...path]\",\n entrypoint: new URL(\"./astro/routes/static.astro\", import.meta.url),\n prerender: true\n });\n injectRoute({\n pattern: \"/[...path]/index.md\",\n entrypoint: new URL(\"./astro/routes/markdown.js\", import.meta.url),\n prerender: true\n });\n injectRoute({\n pattern: \"/[...path].md\",\n entrypoint: new URL(\"./astro/routes/markdown-alias.js\", import.meta.url),\n prerender: true\n });\n\n if (config.social.generate) {\n injectRoute({\n pattern: \"/[...path]/social.png\",\n entrypoint: new URL(\"./astro/routes/social.js\", import.meta.url),\n prerender: true\n });\n }\n\n for (const [pattern, name] of Object.entries(pageLists)) {\n injectRoute({\n pattern,\n entrypoint: new URL(`./astro/routes/${name}.js`, import.meta.url),\n prerender: true\n });\n }\n\n injectRoute({\n pattern: \"/robots.txt\",\n entrypoint: new URL(\"./astro/routes/robots.js\", import.meta.url),\n prerender: true\n });\n injectRoute({\n pattern: \"/404\",\n entrypoint: new URL(\"./astro/routes/not-found.astro\", import.meta.url),\n prerender: true\n });\n\n // Sources with a publishable key are searched from the browser; the others keep their\n // secret key on the server, so they need server routes.\n const andesineSources = config.sources.filter((source) => source.type === \"andesine\");\n\n if (andesineSources.some((source) => source.publicKey)) {\n injectRoute({\n pattern: \"/_andesine/pages/[source].json\",\n entrypoint: new URL(\"./astro/routes/entry-pages.js\", import.meta.url),\n prerender: true\n });\n }\n\n if (andesineSources.some((source) => !source.publicKey)) {\n injectRoute({\n pattern: \"/_andesine/search\",\n entrypoint: new URL(\"./astro/routes/search.js\", import.meta.url),\n prerender: false\n });\n }\n\n if (andesineSources.some((source) => source.answers && !source.publicKey)) {\n injectRoute({\n pattern: \"/_andesine/answers\",\n entrypoint: new URL(\"./astro/routes/answers.js\", import.meta.url),\n prerender: false\n });\n }\n },\n \"astro:config:done\": ({ config: astroConfig, buildOutput }) => {\n cache = astroConfig.cacheDir;\n output = buildOutput === \"server\" ? astroConfig.build.client : astroConfig.outDir;\n },\n \"astro:server:setup\": ({ server }) => {\n const runtime = fileURLToPath(new URL(\"./runtime.js\", import.meta.url));\n\n serveAssets(server, cache, config.base, getBuildSourceIDs(config));\n servePagefind(server, config.base, async () => {\n return (await server.ssrLoadModule(runtime)).getSearchRecords(config);\n });\n },\n \"astro:build:done\": async ({ logger }) => {\n await copyAssets(cache, output, getBuildSourceIDs(config));\n\n if (config.sources.some((source) => source.type !== \"andesine\")) {\n await writePagefindIndex(fileURLToPath(output));\n logger.info(\"Wrote the local search index.\");\n }\n }\n }\n };\n};\n\nexport { andesine };\nexport type { AndesineOptions };\n"],"mappings":"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"}
|
package/dist/llms.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { t as MarkdownPath } from "./chunks/index-vsu3hISM.js";
|
|
2
|
+
import { APIRoute } from "astro";
|
|
3
|
+
//#region src/astro/routes/markdown-alias.d.ts
|
|
4
|
+
export declare const getStaticPaths: () => Promise<MarkdownPath[]>;
|
|
5
|
+
export declare const GET: APIRoute;
|
|
6
|
+
//#endregion
|
|
7
|
+
//# sourceMappingURL=markdown-alias.d.ts.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { t as MarkdownPath } from "./chunks/index-vsu3hISM.js";
|
|
2
|
+
import { APIRoute } from "astro";
|
|
3
|
+
//#region src/astro/routes/markdown.d.ts
|
|
4
|
+
export declare const getStaticPaths: () => Promise<MarkdownPath[]>;
|
|
5
|
+
export declare const GET: APIRoute;
|
|
6
|
+
//#endregion
|
|
7
|
+
//# sourceMappingURL=markdown.d.ts.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
//#region src/astro/middleware.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Serves a page's Markdown to requests that prefer it. Hosts serve built pages as files, so this
|
|
4
|
+
* works in development only; a host can add the same rule for `Accept: text/markdown`.
|
|
5
|
+
*/
|
|
6
|
+
export declare const onRequest: import("astro").MiddlewareHandler;
|
|
7
|
+
//#endregion
|
|
8
|
+
//# sourceMappingURL=middleware.d.ts.map
|