@andesine/pages 0.0.0-stage → 0.4.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 +99 -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,12 @@
|
|
|
1
|
+
---
|
|
2
|
+
import config from "virtual:andesine/config";
|
|
3
|
+
import Layout from "virtual:andesine/layout";
|
|
4
|
+
import { getNotFoundContext } from "../../runtime.js";
|
|
5
|
+
|
|
6
|
+
const page = await getNotFoundContext(config);
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
<Layout page={page}>
|
|
10
|
+
<p>This page does not exist, or it moved to a different address.</p>
|
|
11
|
+
<p><a href={page.site.href}>Go to the home page</a></p>
|
|
12
|
+
</Layout>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { t as textResponse } from "../../chunks/response-CtzaKMWH.js";
|
|
2
|
+
import { r as createRobots } from "../../chunks/files-BxqiQzFj.js";
|
|
3
|
+
import config from "virtual:andesine/config";
|
|
4
|
+
//#region src/astro/routes/robots.ts
|
|
5
|
+
const GET = () => textResponse(createRobots(config), "text/plain");
|
|
6
|
+
//#endregion
|
|
7
|
+
export { GET };
|
|
8
|
+
|
|
9
|
+
//# sourceMappingURL=robots.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"robots.js","names":[],"sources":["../../../src/astro/routes/robots.ts"],"sourcesContent":["import type { APIRoute } from \"astro\";\nimport config from \"virtual:andesine/config\";\nimport { createRobots } from \"../../output/files\";\nimport { textResponse } from \"../../output/response\";\n\nexport const GET: APIRoute = () => textResponse(createRobots(config), \"text/plain\");\n"],"mappings":";;;;AAKA,MAAa,YAAsB,aAAa,aAAa,MAAM,GAAG,YAAY"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { i as toSearchItems } from "../../chunks/limits-Ppc7BQPG.js";
|
|
2
|
+
import { i as toErrorResponse, n as json, r as readRequest, t as createPageResolver } from "../../chunks/request-DOuBHGQs.js";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import config from "virtual:andesine/config";
|
|
5
|
+
//#region src/search/endpoint.ts
|
|
6
|
+
const bodySchema = z.object({
|
|
7
|
+
source: z.string().min(1),
|
|
8
|
+
query: z.string().trim().min(1).max(500),
|
|
9
|
+
limit: z.number().int().min(1).max(20).default(8)
|
|
10
|
+
}).strict();
|
|
11
|
+
const handleSearch = async (request, config) => {
|
|
12
|
+
const result = await readRequest(request, config, {
|
|
13
|
+
schema: bodySchema,
|
|
14
|
+
maxSize: 4e3,
|
|
15
|
+
timeout: 15e3
|
|
16
|
+
});
|
|
17
|
+
if ("response" in result) return result.response;
|
|
18
|
+
const { body, source, client, signal } = result.request;
|
|
19
|
+
try {
|
|
20
|
+
const [resolve, { results }] = await Promise.all([createPageResolver(source, config.base), client.search.published({
|
|
21
|
+
query: body.query,
|
|
22
|
+
collectionID: source.collection,
|
|
23
|
+
channel: "published",
|
|
24
|
+
limit: body.limit
|
|
25
|
+
}, { signal })]);
|
|
26
|
+
const items = toSearchItems(results, resolve);
|
|
27
|
+
return json({ items });
|
|
28
|
+
} catch (error) {
|
|
29
|
+
return toErrorResponse(error, {
|
|
30
|
+
limited: "Too many searches. Try again soon.",
|
|
31
|
+
failed: "Search is not available now."
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
//#endregion
|
|
36
|
+
//#region src/astro/routes/search.ts
|
|
37
|
+
const prerender = false;
|
|
38
|
+
const POST = ({ request }) => handleSearch(request, config);
|
|
39
|
+
//#endregion
|
|
40
|
+
export { POST, prerender };
|
|
41
|
+
|
|
42
|
+
//# sourceMappingURL=search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.js","names":[],"sources":["../../../src/search/endpoint.ts","../../../src/astro/routes/search.ts"],"sourcesContent":["import { z } from \"zod\";\nimport type { PagesConfig } from \"../config\";\nimport { toSearchItems } from \"./items\";\nimport { createPageResolver, json, readRequest, toErrorResponse } from \"./request\";\n\nconst bodySchema = z\n .object({\n source: z.string().min(1),\n query: z.string().trim().min(1).max(500),\n limit: z.number().int().min(1).max(20).default(8)\n })\n .strict();\n\nconst handleSearch = async (request: Request, config: PagesConfig): Promise<Response> => {\n const result = await readRequest(request, config, {\n schema: bodySchema,\n maxSize: 4_000,\n timeout: 15_000\n });\n\n if (\"response\" in result) return result.response;\n\n const { body, source, client, signal } = result.request;\n\n try {\n const [resolve, { results }] = await Promise.all([\n createPageResolver(source, config.base),\n client.search.published(\n {\n query: body.query,\n collectionID: source.collection,\n channel: \"published\",\n limit: body.limit\n },\n { signal }\n )\n ]);\n const items = toSearchItems(results, resolve);\n\n return json({ items });\n } catch (error) {\n return toErrorResponse(error, {\n limited: \"Too many searches. Try again soon.\",\n failed: \"Search is not available now.\"\n });\n }\n};\n\nexport { handleSearch };\n","import type { APIRoute } from \"astro\";\nimport config from \"virtual:andesine/config\";\nimport { handleSearch } from \"../../search/endpoint\";\n\nexport const prerender = false;\n\nexport const POST: APIRoute = ({ request }) => handleSearch(request, config);\n"],"mappings":";;;;;AAKA,MAAM,aAAa,EAChB,OAAO;CACN,QAAQ,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC;CACxB,OAAO,EAAE,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,GAAG;CACvC,OAAO,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC;AAClD,CAAC,CAAC,CACD,OAAO;AAEV,MAAM,eAAe,OAAO,SAAkB,WAA2C;CACvF,MAAM,SAAS,MAAM,YAAY,SAAS,QAAQ;EAChD,QAAQ;EACR,SAAS;EACT,SAAS;CACX,CAAC;CAED,IAAI,cAAc,QAAQ,OAAO,OAAO;CAExC,MAAM,EAAE,MAAM,QAAQ,QAAQ,WAAW,OAAO;CAEhD,IAAI;EACF,MAAM,CAAC,SAAS,EAAE,aAAa,MAAM,QAAQ,IAAI,CAC/C,mBAAmB,QAAQ,OAAO,IAAI,GACtC,OAAO,OAAO,UACZ;GACE,OAAO,KAAK;GACZ,cAAc,OAAO;GACrB,SAAS;GACT,OAAO,KAAK;EACd,GACA,EAAE,OAAO,CACX,CACF,CAAC;EACD,MAAM,QAAQ,cAAc,SAAS,OAAO;EAE5C,OAAO,KAAK,EAAE,MAAM,CAAC;CACvB,SAAS,OAAO;EACd,OAAO,gBAAgB,OAAO;GAC5B,SAAS;GACT,QAAQ;EACV,CAAC;CACH;AACF;;;AC1CA,MAAa,YAAY;AAEzB,MAAa,QAAkB,EAAE,cAAc,aAAa,SAAS,MAAM"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { t as textResponse } from "../../chunks/response-CtzaKMWH.js";
|
|
2
|
+
import { t as loadCatalog } from "../../chunks/catalog-DU4BUrpw.js";
|
|
3
|
+
import { i as createSitemap } from "../../chunks/files-BxqiQzFj.js";
|
|
4
|
+
import config from "virtual:andesine/config";
|
|
5
|
+
//#region src/astro/routes/sitemap.ts
|
|
6
|
+
const GET = async () => {
|
|
7
|
+
return textResponse(createSitemap(config, await loadCatalog(config)), "application/xml");
|
|
8
|
+
};
|
|
9
|
+
//#endregion
|
|
10
|
+
export { GET };
|
|
11
|
+
|
|
12
|
+
//# sourceMappingURL=sitemap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sitemap.js","names":[],"sources":["../../../src/astro/routes/sitemap.ts"],"sourcesContent":["import type { APIRoute } from \"astro\";\nimport config from \"virtual:andesine/config\";\nimport { loadCatalog } from \"../../output/catalog\";\nimport { createSitemap } from \"../../output/files\";\nimport { textResponse } from \"../../output/response\";\n\nexport const GET: APIRoute = async () => {\n return textResponse(createSitemap(config, await loadCatalog(config)), \"application/xml\");\n};\n"],"mappings":";;;;;AAMA,MAAa,MAAgB,YAAY;CACvC,OAAO,aAAa,cAAc,QAAQ,MAAM,YAAY,MAAM,CAAC,GAAG,iBAAiB;AACzF"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { t as textResponse } from "../../chunks/response-CtzaKMWH.js";
|
|
2
|
+
import { t as loadCatalog } from "../../chunks/catalog-DU4BUrpw.js";
|
|
3
|
+
import { r as loadSkill } from "../../chunks/skill-CBTGUHQH.js";
|
|
4
|
+
import config, { skill } from "virtual:andesine/config";
|
|
5
|
+
//#region src/astro/routes/skill.ts
|
|
6
|
+
const GET = async () => {
|
|
7
|
+
const { content } = await loadSkill(config, skill, () => loadCatalog(config));
|
|
8
|
+
return textResponse(content, "text/markdown");
|
|
9
|
+
};
|
|
10
|
+
//#endregion
|
|
11
|
+
export { GET };
|
|
12
|
+
|
|
13
|
+
//# sourceMappingURL=skill.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill.js","names":[],"sources":["../../../src/astro/routes/skill.ts"],"sourcesContent":["import type { APIRoute } from \"astro\";\nimport config, { skill } from \"virtual:andesine/config\";\nimport { loadCatalog } from \"../../output/catalog\";\nimport { textResponse } from \"../../output/response\";\nimport { loadSkill } from \"../../output/skill\";\n\nexport const GET: APIRoute = async () => {\n const { content } = await loadSkill(config, skill, () => loadCatalog(config));\n\n return textResponse(content, \"text/markdown\");\n};\n"],"mappings":";;;;;AAMA,MAAa,MAAgB,YAAY;CACvC,MAAM,EAAE,YAAY,MAAM,UAAU,QAAQ,aAAa,YAAY,MAAM,CAAC;CAE5E,OAAO,aAAa,SAAS,eAAe;AAC9C"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { t as textResponse } from "../../chunks/response-CtzaKMWH.js";
|
|
2
|
+
import { t as loadCatalog } from "../../chunks/catalog-DU4BUrpw.js";
|
|
3
|
+
import { a as toSkillName, i as readSkill, n as createSkillsIndex, r as loadSkill, t as createAgentSkillsIndex } from "../../chunks/skill-CBTGUHQH.js";
|
|
4
|
+
import config, { skill } from "virtual:andesine/config";
|
|
5
|
+
//#region src/astro/routes/skills.ts
|
|
6
|
+
const name = skill ? readSkill(skill).name : toSkillName(config.name);
|
|
7
|
+
const files = {
|
|
8
|
+
"agent-skills/index.json": async (loaded) => {
|
|
9
|
+
return textResponse(await createAgentSkillsIndex(config, loaded), "application/json");
|
|
10
|
+
},
|
|
11
|
+
[`agent-skills/${name}/SKILL.md`]: (loaded) => textResponse(loaded.content, "text/markdown"),
|
|
12
|
+
"skills/index.json": (loaded) => textResponse(createSkillsIndex(loaded), "application/json"),
|
|
13
|
+
[`skills/${name}/SKILL.md`]: (loaded) => textResponse(loaded.content, "text/markdown")
|
|
14
|
+
};
|
|
15
|
+
const getStaticPaths = () => Object.keys(files).map((path) => ({ params: { path } }));
|
|
16
|
+
const GET = async ({ params }) => {
|
|
17
|
+
const file = files[params.path ?? ""];
|
|
18
|
+
if (!file) return textResponse("Not found", "text/plain", { status: 404 });
|
|
19
|
+
return file(await loadSkill(config, skill, () => loadCatalog(config)));
|
|
20
|
+
};
|
|
21
|
+
//#endregion
|
|
22
|
+
export { GET, getStaticPaths };
|
|
23
|
+
|
|
24
|
+
//# sourceMappingURL=skills.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skills.js","names":[],"sources":["../../../src/astro/routes/skills.ts"],"sourcesContent":["import type { APIRoute } from \"astro\";\nimport config, { skill } from \"virtual:andesine/config\";\nimport { loadCatalog } from \"../../output/catalog\";\nimport { textResponse } from \"../../output/response\";\nimport {\n createAgentSkillsIndex,\n createSkillsIndex,\n loadSkill,\n readSkill,\n toSkillName,\n type Skill\n} from \"../../output/skill\";\n\nconst name = skill ? readSkill(skill).name : toSkillName(config.name);\n// The agentskills.io discovery index, and the index of the `skills` CLI, with their files.\nconst files: Record<string, (skill: Skill) => Response | Promise<Response>> = {\n \"agent-skills/index.json\": async (loaded) => {\n return textResponse(await createAgentSkillsIndex(config, loaded), \"application/json\");\n },\n [`agent-skills/${name}/SKILL.md`]: (loaded) => textResponse(loaded.content, \"text/markdown\"),\n \"skills/index.json\": (loaded) => textResponse(createSkillsIndex(loaded), \"application/json\"),\n [`skills/${name}/SKILL.md`]: (loaded) => textResponse(loaded.content, \"text/markdown\")\n};\n\nexport const getStaticPaths = () => Object.keys(files).map((path) => ({ params: { path } }));\n\nexport const GET: APIRoute = async ({ params }) => {\n const file = files[params.path ?? \"\"];\n\n if (!file) return textResponse(\"Not found\", \"text/plain\", { status: 404 });\n\n return file(await loadSkill(config, skill, () => loadCatalog(config)));\n};\n"],"mappings":";;;;;AAaA,MAAM,OAAO,QAAQ,UAAU,KAAK,CAAC,CAAC,OAAO,YAAY,OAAO,IAAI;AAEpE,MAAM,QAAwE;CAC5E,2BAA2B,OAAO,WAAW;EAC3C,OAAO,aAAa,MAAM,uBAAuB,QAAQ,MAAM,GAAG,kBAAkB;CACtF;EACC,gBAAgB,KAAK,cAAc,WAAW,aAAa,OAAO,SAAS,eAAe;CAC3F,sBAAsB,WAAW,aAAa,kBAAkB,MAAM,GAAG,kBAAkB;EAC1F,UAAU,KAAK,cAAc,WAAW,aAAa,OAAO,SAAS,eAAe;AACvF;AAEA,MAAa,uBAAuB,OAAO,KAAK,KAAK,CAAC,CAAC,KAAK,UAAU,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE;AAE3F,MAAa,MAAgB,OAAO,EAAE,aAAa;CACjD,MAAM,OAAO,MAAM,OAAO,QAAQ;CAElC,IAAI,CAAC,MAAM,OAAO,aAAa,aAAa,cAAc,EAAE,QAAQ,IAAI,CAAC;CAEzE,OAAO,KAAK,MAAM,UAAU,QAAQ,aAAa,YAAY,MAAM,CAAC,CAAC;AACvE"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { o as socialImageSize, r as getSocialPaths } from "../../chunks/site-DY-uZ0PP.js";
|
|
2
|
+
import config from "virtual:andesine/config";
|
|
3
|
+
import social from "virtual:andesine/social";
|
|
4
|
+
import { Resvg } from "@resvg/resvg-js";
|
|
5
|
+
import satori from "satori";
|
|
6
|
+
import { html } from "satori-html";
|
|
7
|
+
//#region src/social/render.ts
|
|
8
|
+
const entities = {
|
|
9
|
+
amp: "&",
|
|
10
|
+
lt: "<",
|
|
11
|
+
gt: ">",
|
|
12
|
+
quot: "\"",
|
|
13
|
+
apos: "'"
|
|
14
|
+
};
|
|
15
|
+
/** satori-html keeps entities as text, so card markup could not show `<` or `&`. */
|
|
16
|
+
const decodeEntities = (text) => {
|
|
17
|
+
return text.replace(/&(#x[\da-f]+|#\d+|\w+);/gi, (entity, name) => {
|
|
18
|
+
if (name[0] !== "#") return entities[name] ?? entity;
|
|
19
|
+
const isHex = name[1]?.toLowerCase() === "x";
|
|
20
|
+
return String.fromCodePoint(Number.parseInt(name.slice(isHex ? 2 : 1), isHex ? 16 : 10));
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Prepares satori-html output for Satori: decodes entities in text and attributes, and removes
|
|
25
|
+
* empty `children` arrays, which Satori counts as many children.
|
|
26
|
+
*/
|
|
27
|
+
const prepareTree = (node) => {
|
|
28
|
+
const props = Object.fromEntries(Object.entries(node.props).map(([name, value]) => {
|
|
29
|
+
return [name, typeof value === "string" && name !== "children" ? decodeEntities(value) : value];
|
|
30
|
+
}));
|
|
31
|
+
const { children } = node.props;
|
|
32
|
+
const prepare = (child) => {
|
|
33
|
+
return typeof child === "string" ? decodeEntities(child) : prepareTree(child);
|
|
34
|
+
};
|
|
35
|
+
if (Array.isArray(children)) return {
|
|
36
|
+
...node,
|
|
37
|
+
props: {
|
|
38
|
+
...props,
|
|
39
|
+
children: children.length ? children.map(prepare) : void 0
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
return {
|
|
43
|
+
...node,
|
|
44
|
+
props: children === void 0 ? props : {
|
|
45
|
+
...props,
|
|
46
|
+
children: prepare(children)
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
/** Decodes a base64 data URL. `atob` works in every runtime, unlike `Buffer`. */
|
|
51
|
+
const fromDataURL = (url) => {
|
|
52
|
+
const text = atob(url.slice(url.indexOf(",") + 1));
|
|
53
|
+
return Uint8Array.from(text, (character) => character.charCodeAt(0)).buffer;
|
|
54
|
+
};
|
|
55
|
+
const toFontData = (font) => {
|
|
56
|
+
return {
|
|
57
|
+
...font,
|
|
58
|
+
data: typeof font.data === "string" ? fromDataURL(font.data) : font.data
|
|
59
|
+
};
|
|
60
|
+
};
|
|
61
|
+
const renderSocialImage = async (card, data) => {
|
|
62
|
+
const markup = String(card.render(data)).trim().replace(/>\s+</g, "><");
|
|
63
|
+
const tree = prepareTree(html(markup));
|
|
64
|
+
const svg = await satori(tree, {
|
|
65
|
+
...socialImageSize,
|
|
66
|
+
fonts: (await card.fonts()).map(toFontData)
|
|
67
|
+
});
|
|
68
|
+
const png = new Resvg(svg, { fitTo: {
|
|
69
|
+
mode: "width",
|
|
70
|
+
value: socialImageSize.width
|
|
71
|
+
} }).render().asPng();
|
|
72
|
+
return new Uint8Array(png);
|
|
73
|
+
};
|
|
74
|
+
//#endregion
|
|
75
|
+
//#region src/astro/routes/social.ts
|
|
76
|
+
const getStaticPaths = () => getSocialPaths(config);
|
|
77
|
+
const GET = async ({ props }) => {
|
|
78
|
+
const image = await renderSocialImage(social.card, {
|
|
79
|
+
...props.data,
|
|
80
|
+
logo: social.logo,
|
|
81
|
+
showSiteName: !config.logo || config.logo.title,
|
|
82
|
+
logoFormat: config.logo?.format,
|
|
83
|
+
background: social.background,
|
|
84
|
+
brand: config.brand
|
|
85
|
+
});
|
|
86
|
+
return new Response(image, { headers: { "Content-Type": "image/png" } });
|
|
87
|
+
};
|
|
88
|
+
//#endregion
|
|
89
|
+
export { GET, getStaticPaths };
|
|
90
|
+
|
|
91
|
+
//# sourceMappingURL=social.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"social.js","names":[],"sources":["../../../src/social/render.ts","../../../src/astro/routes/social.ts"],"sourcesContent":["import { Resvg } from \"@resvg/resvg-js\";\nimport satori from \"satori\";\nimport { html } from \"satori-html\";\nimport { socialImageSize } from \"./size\";\nimport type { SocialCard, SocialCardData, SocialCardFont } from \"./types\";\n\ninterface MarkupNode {\n type: string;\n props: { children?: string | MarkupNode | Array<string | MarkupNode>; [name: string]: unknown };\n}\n\nconst entities: Record<string, string> = { amp: \"&\", lt: \"<\", gt: \">\", quot: '\"', apos: \"'\" };\n\n/** satori-html keeps entities as text, so card markup could not show `<` or `&`. */\nconst decodeEntities = (text: string): string => {\n return text.replace(/&(#x[\\da-f]+|#\\d+|\\w+);/gi, (entity, name: string) => {\n if (name[0] !== \"#\") return entities[name] ?? entity;\n\n const isHex = name[1]?.toLowerCase() === \"x\";\n\n return String.fromCodePoint(Number.parseInt(name.slice(isHex ? 2 : 1), isHex ? 16 : 10));\n });\n};\n/**\n * Prepares satori-html output for Satori: decodes entities in text and attributes, and removes\n * empty `children` arrays, which Satori counts as many children.\n */\nconst prepareTree = (node: MarkupNode): MarkupNode => {\n const props = Object.fromEntries(\n Object.entries(node.props).map(([name, value]) => {\n return [\n name,\n typeof value === \"string\" && name !== \"children\" ? decodeEntities(value) : value\n ];\n })\n );\n const { children } = node.props;\n const prepare = (child: string | MarkupNode): string | MarkupNode => {\n return typeof child === \"string\" ? decodeEntities(child) : prepareTree(child);\n };\n\n if (Array.isArray(children)) {\n return {\n ...node,\n props: { ...props, children: children.length ? children.map(prepare) : undefined }\n };\n }\n\n return {\n ...node,\n props: children === undefined ? props : { ...props, children: prepare(children) }\n };\n};\n/** Decodes a base64 data URL. `atob` works in every runtime, unlike `Buffer`. */\nconst fromDataURL = (url: string): ArrayBuffer => {\n const text = atob(url.slice(url.indexOf(\",\") + 1));\n\n return Uint8Array.from(text, (character) => character.charCodeAt(0)).buffer;\n};\nconst toFontData = (font: SocialCardFont) => {\n return { ...font, data: typeof font.data === \"string\" ? fromDataURL(font.data) : font.data };\n};\nconst renderSocialImage = async (\n card: SocialCard,\n data: SocialCardData\n): Promise<Uint8Array<ArrayBuffer>> => {\n // Whitespace between tags would become text nodes, which Satori lays out as children.\n const markup = String(card.render(data)).trim().replace(/>\\s+</g, \"><\");\n const tree = prepareTree(html(markup) as MarkupNode);\n const svg = await satori(tree as Parameters<typeof satori>[0], {\n ...socialImageSize,\n fonts: (await card.fonts()).map(toFontData)\n });\n\n const png = new Resvg(svg, { fitTo: { mode: \"width\", value: socialImageSize.width } })\n .render()\n .asPng();\n\n return new Uint8Array(png);\n};\n\nexport { renderSocialImage };\n","import type { APIRoute } from \"astro\";\nimport config from \"virtual:andesine/config\";\nimport social from \"virtual:andesine/social\";\nimport { getSocialPaths, type SocialPath } from \"../../site\";\nimport { renderSocialImage } from \"../../social/render\";\n\nexport const getStaticPaths = () => getSocialPaths(config);\n\nexport const GET: APIRoute = async ({ props }) => {\n const image = await renderSocialImage(social.card!, {\n ...(props as SocialPath[\"props\"]).data,\n logo: social.logo,\n showSiteName: !config.logo || config.logo.title,\n logoFormat: config.logo?.format,\n background: social.background,\n brand: config.brand\n });\n\n return new Response(image, { headers: { \"Content-Type\": \"image/png\" } });\n};\n"],"mappings":";;;;;;;AAWA,MAAM,WAAmC;CAAE,KAAK;CAAK,IAAI;CAAK,IAAI;CAAK,MAAM;CAAK,MAAM;AAAI;;AAG5F,MAAM,kBAAkB,SAAyB;CAC/C,OAAO,KAAK,QAAQ,8BAA8B,QAAQ,SAAiB;EACzE,IAAI,KAAK,OAAO,KAAK,OAAO,SAAS,SAAS;EAE9C,MAAM,QAAQ,KAAK,EAAE,EAAE,YAAY,MAAM;EAEzC,OAAO,OAAO,cAAc,OAAO,SAAS,KAAK,MAAM,QAAQ,IAAI,CAAC,GAAG,QAAQ,KAAK,EAAE,CAAC;CACzF,CAAC;AACH;;;;;AAKA,MAAM,eAAe,SAAiC;CACpD,MAAM,QAAQ,OAAO,YACnB,OAAO,QAAQ,KAAK,KAAK,CAAC,CAAC,KAAK,CAAC,MAAM,WAAW;EAChD,OAAO,CACL,MACA,OAAO,UAAU,YAAY,SAAS,aAAa,eAAe,KAAK,IAAI,KAC7E;CACF,CAAC,CACH;CACA,MAAM,EAAE,aAAa,KAAK;CAC1B,MAAM,WAAW,UAAoD;EACnE,OAAO,OAAO,UAAU,WAAW,eAAe,KAAK,IAAI,YAAY,KAAK;CAC9E;CAEA,IAAI,MAAM,QAAQ,QAAQ,GACxB,OAAO;EACL,GAAG;EACH,OAAO;GAAE,GAAG;GAAO,UAAU,SAAS,SAAS,SAAS,IAAI,OAAO,IAAI,KAAA;EAAU;CACnF;CAGF,OAAO;EACL,GAAG;EACH,OAAO,aAAa,KAAA,IAAY,QAAQ;GAAE,GAAG;GAAO,UAAU,QAAQ,QAAQ;EAAE;CAClF;AACF;;AAEA,MAAM,eAAe,QAA6B;CAChD,MAAM,OAAO,KAAK,IAAI,MAAM,IAAI,QAAQ,GAAG,IAAI,CAAC,CAAC;CAEjD,OAAO,WAAW,KAAK,OAAO,cAAc,UAAU,WAAW,CAAC,CAAC,CAAC,CAAC;AACvE;AACA,MAAM,cAAc,SAAyB;CAC3C,OAAO;EAAE,GAAG;EAAM,MAAM,OAAO,KAAK,SAAS,WAAW,YAAY,KAAK,IAAI,IAAI,KAAK;CAAK;AAC7F;AACA,MAAM,oBAAoB,OACxB,MACA,SACqC;CAErC,MAAM,SAAS,OAAO,KAAK,OAAO,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,QAAQ,UAAU,IAAI;CACtE,MAAM,OAAO,YAAY,KAAK,MAAM,CAAe;CACnD,MAAM,MAAM,MAAM,OAAO,MAAsC;EAC7D,GAAG;EACH,QAAQ,MAAM,KAAK,MAAM,EAAA,CAAG,IAAI,UAAU;CAC5C,CAAC;CAED,MAAM,MAAM,IAAI,MAAM,KAAK,EAAE,OAAO;EAAE,MAAM;EAAS,OAAO,gBAAgB;CAAM,EAAE,CAAC,CAAC,CACnF,OAAO,CAAC,CACR,MAAM;CAET,OAAO,IAAI,WAAW,GAAG;AAC3B;;;ACzEA,MAAa,uBAAuB,eAAe,MAAM;AAEzD,MAAa,MAAgB,OAAO,EAAE,YAAY;CAChD,MAAM,QAAQ,MAAM,kBAAkB,OAAO,MAAO;EAClD,GAAI,MAA8B;EAClC,MAAM,OAAO;EACb,cAAc,CAAC,OAAO,QAAQ,OAAO,KAAK;EAC1C,YAAY,OAAO,MAAM;EACzB,YAAY,OAAO;EACnB,OAAO,OAAO;CAChB,CAAC;CAED,OAAO,IAAI,SAAS,OAAO,EAAE,SAAS,EAAE,gBAAgB,YAAY,EAAE,CAAC;AACzE"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
---
|
|
2
|
+
import config, { highlight } from "virtual:andesine/config";
|
|
3
|
+
import Layout from "virtual:andesine/layout";
|
|
4
|
+
import { components } from "virtual:andesine/components";
|
|
5
|
+
import Content from "../content.astro";
|
|
6
|
+
import { getStaticPaths as getPaths, renderRoute } from "../../runtime.js";
|
|
7
|
+
|
|
8
|
+
export const getStaticPaths = () => getPaths(config);
|
|
9
|
+
|
|
10
|
+
const { route } = Astro.props;
|
|
11
|
+
|
|
12
|
+
if (route.type === "redirect") return Astro.redirect(route.target);
|
|
13
|
+
|
|
14
|
+
const {
|
|
15
|
+
Content: FileContent,
|
|
16
|
+
operation,
|
|
17
|
+
nodes,
|
|
18
|
+
summary,
|
|
19
|
+
aside,
|
|
20
|
+
iconCSS,
|
|
21
|
+
page
|
|
22
|
+
} = await renderRoute(route, highlight);
|
|
23
|
+
const Operation = components.Operation;
|
|
24
|
+
|
|
25
|
+
if (operation && !Operation) throw new Error("The template has no component for <Operation>.");
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
<Layout page={page}>
|
|
29
|
+
{iconCSS && <style is:inline set:html={iconCSS} />}
|
|
30
|
+
{summary && <Content slot="summary" nodes={summary.children} components={components} />}
|
|
31
|
+
{aside && <Content slot="aside" nodes={aside.children} components={components} />}
|
|
32
|
+
<div
|
|
33
|
+
data-pagefind-body={route.indexed || undefined}
|
|
34
|
+
data-pagefind-filter={route.indexed ? `source:${route.sourceID}` : undefined}
|
|
35
|
+
>
|
|
36
|
+
{
|
|
37
|
+
route.indexed && (
|
|
38
|
+
<span data-pagefind-meta="title" hidden>
|
|
39
|
+
{page.title}
|
|
40
|
+
</span>
|
|
41
|
+
)
|
|
42
|
+
}
|
|
43
|
+
{
|
|
44
|
+
FileContent ? (
|
|
45
|
+
<FileContent components={components} />
|
|
46
|
+
) : operation ? (
|
|
47
|
+
<Operation view={operation} />
|
|
48
|
+
) : (
|
|
49
|
+
<Content nodes={nodes.children} components={components} />
|
|
50
|
+
)
|
|
51
|
+
}
|
|
52
|
+
</div>
|
|
53
|
+
</Layout>
|
package/dist/astro.d.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { t as FileTreeItem } from "./chunks/mdx-components-CUUDTapN.js";
|
|
2
|
+
import { n as OperationParts, r as OperationView } from "./chunks/view-Dlf_VRI7.js";
|
|
3
|
+
//#region src/sources/openapi/embed.d.ts
|
|
4
|
+
interface OperationProps extends OperationParts {
|
|
5
|
+
/** Set on reference pages. */
|
|
6
|
+
view?: OperationView;
|
|
7
|
+
/** The ID of an OpenAPI source, for embeds. */
|
|
8
|
+
source?: string;
|
|
9
|
+
/** The operation ID, or `METHOD /path` without one, for embeds. */
|
|
10
|
+
id?: string;
|
|
11
|
+
/** Prefix of element IDs; needed when a page embeds the same operation twice. */
|
|
12
|
+
anchor?: string;
|
|
13
|
+
}
|
|
14
|
+
/** The view of an `<Operation>`: the given view on reference pages, or an embedded operation. */
|
|
15
|
+
declare const getOperationView: (props: OperationProps) => Promise<OperationView>;
|
|
16
|
+
//#endregion
|
|
17
|
+
//#region src/astro.d.ts
|
|
18
|
+
interface Slots {
|
|
19
|
+
has(name: string): boolean;
|
|
20
|
+
render(name: string, args?: unknown[]): Promise<string>;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Reads the tabs of a tabbed component: its labels, from the `values` prop that the Andesine MDX
|
|
24
|
+
* plugin and content renderer add, and its rendered panels.
|
|
25
|
+
*/
|
|
26
|
+
declare const renderTabs: (values: string, slots: Slots) => Promise<{
|
|
27
|
+
values: string[];
|
|
28
|
+
panels: string[];
|
|
29
|
+
}>;
|
|
30
|
+
/** Reads the `items` prop of a file tree: JSON from the Andesine MDX plugin, or nested items. */
|
|
31
|
+
declare const readFileTreeItems: (items: string | FileTreeItem[]) => FileTreeItem[];
|
|
32
|
+
//#endregion
|
|
33
|
+
export { type OperationProps, getOperationView, readFileTreeItems, renderTabs };
|
|
34
|
+
//# sourceMappingURL=astro.d.ts.map
|
package/dist/astro.js
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { i as createLinks, t as loadOpenAPIModel, u as toOperationTitle } from "./chunks/stored-CcEfvCQH.js";
|
|
2
|
+
import { n as toID, t as createOperationView } from "./chunks/view-C-9ZM1zK.js";
|
|
3
|
+
import config, { highlight } from "virtual:andesine/config";
|
|
4
|
+
//#region src/sources/openapi/embed.ts
|
|
5
|
+
const links = /* @__PURE__ */ new WeakMap();
|
|
6
|
+
/** The view of an `<Operation>`: the given view on reference pages, or an embedded operation. */
|
|
7
|
+
const getOperationView = async (props) => {
|
|
8
|
+
if (props.view) return props.view;
|
|
9
|
+
const source = config.sources.find((item) => item.id === props.source);
|
|
10
|
+
if (source?.type !== "openapi") throw new Error(`<Operation>: "${props.source}" is not an OpenAPI source. Set \`source\` to its ID.`);
|
|
11
|
+
const model = await loadOpenAPIModel(source);
|
|
12
|
+
const operation = model.operations.find((item) => item.id === props.id);
|
|
13
|
+
if (!operation) throw new Error(`<Operation>: "${props.id}" is not an operation of source "${source.id}".`);
|
|
14
|
+
if (!links.has(model)) links.set(model, createLinks(source, model, config.base).links);
|
|
15
|
+
return createOperationView(operation, model, {
|
|
16
|
+
highlight,
|
|
17
|
+
title: toOperationTitle(operation),
|
|
18
|
+
href: links.get(model).operations[operation.id],
|
|
19
|
+
anchor: props.anchor ?? `${toID(source.id)}-${toID(operation.id)}-`,
|
|
20
|
+
parts: {
|
|
21
|
+
description: props.description,
|
|
22
|
+
authentication: props.authentication,
|
|
23
|
+
parameters: props.parameters,
|
|
24
|
+
requestBody: props.requestBody,
|
|
25
|
+
responses: props.responses,
|
|
26
|
+
examples: props.examples
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
};
|
|
30
|
+
//#endregion
|
|
31
|
+
//#region src/astro.ts
|
|
32
|
+
/**
|
|
33
|
+
* Renders the panels of a tabbed component. MDX passes named slots `tab-0`, `tab-1`, and so on;
|
|
34
|
+
* Andesine content passes a default slot function that takes the panel index.
|
|
35
|
+
*/
|
|
36
|
+
const renderPanels = (slots, count) => {
|
|
37
|
+
return Promise.all(Array.from({ length: count }, async (_, index) => {
|
|
38
|
+
const html = slots.has(`tab-${index}`) ? await slots.render(`tab-${index}`) : await slots.render("default", [index]);
|
|
39
|
+
return String(html);
|
|
40
|
+
}));
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Reads the tabs of a tabbed component: its labels, from the `values` prop that the Andesine MDX
|
|
44
|
+
* plugin and content renderer add, and its rendered panels.
|
|
45
|
+
*/
|
|
46
|
+
const renderTabs = async (values, slots) => {
|
|
47
|
+
const labels = JSON.parse(values);
|
|
48
|
+
return {
|
|
49
|
+
values: labels,
|
|
50
|
+
panels: await renderPanels(slots, labels.length)
|
|
51
|
+
};
|
|
52
|
+
};
|
|
53
|
+
/** Reads the `items` prop of a file tree: JSON from the Andesine MDX plugin, or nested items. */
|
|
54
|
+
const readFileTreeItems = (items) => {
|
|
55
|
+
return typeof items === "string" ? JSON.parse(items) : items;
|
|
56
|
+
};
|
|
57
|
+
//#endregion
|
|
58
|
+
export { getOperationView, readFileTreeItems, renderTabs };
|
|
59
|
+
|
|
60
|
+
//# sourceMappingURL=astro.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"astro.js","names":[],"sources":["../src/sources/openapi/embed.ts","../src/astro.ts"],"sourcesContent":["import config, { highlight } from \"virtual:andesine/config\";\nimport { toOperationTitle } from \"./labels\";\nimport { createLinks } from \"./load\";\nimport type { ApiModel } from \"./model\";\nimport type { OpenAPILinks } from \"./markdown\";\nimport { loadOpenAPIModel } from \"./stored\";\nimport { createOperationView, toID, type OperationParts, type OperationView } from \"./view\";\n\ninterface OperationProps extends OperationParts {\n /** Set on reference pages. */\n view?: OperationView;\n /** The ID of an OpenAPI source, for embeds. */\n source?: string;\n /** The operation ID, or `METHOD /path` without one, for embeds. */\n id?: string;\n /** Prefix of element IDs; needed when a page embeds the same operation twice. */\n anchor?: string;\n}\n\n// Links by model, so a spec that loads again in development gets new links.\nconst links = new WeakMap<ApiModel, OpenAPILinks>();\n\n/** The view of an `<Operation>`: the given view on reference pages, or an embedded operation. */\nconst getOperationView = async (props: OperationProps): Promise<OperationView> => {\n if (props.view) return props.view;\n\n const source = config.sources.find((item) => item.id === props.source);\n\n if (source?.type !== \"openapi\") {\n throw new Error(\n `<Operation>: \"${props.source}\" is not an OpenAPI source. Set \\`source\\` to its ID.`\n );\n }\n\n const model = await loadOpenAPIModel(source);\n const operation = model.operations.find((item) => item.id === props.id);\n\n if (!operation) {\n throw new Error(`<Operation>: \"${props.id}\" is not an operation of source \"${source.id}\".`);\n }\n\n if (!links.has(model)) links.set(model, createLinks(source, model, config.base).links);\n\n return createOperationView(operation, model, {\n highlight,\n title: toOperationTitle(operation),\n href: links.get(model)!.operations[operation.id]!,\n anchor: props.anchor ?? `${toID(source.id)}-${toID(operation.id)}-`,\n parts: {\n description: props.description,\n authentication: props.authentication,\n parameters: props.parameters,\n requestBody: props.requestBody,\n responses: props.responses,\n examples: props.examples\n }\n });\n};\n\nexport { getOperationView };\nexport type { OperationProps };\n","import type { FileTreeItem } from \"./content/mdx-components\";\n\ninterface Slots {\n has(name: string): boolean;\n render(name: string, args?: unknown[]): Promise<string>;\n}\n\n/**\n * Renders the panels of a tabbed component. MDX passes named slots `tab-0`, `tab-1`, and so on;\n * Andesine content passes a default slot function that takes the panel index.\n */\nconst renderPanels = (slots: Slots, count: number): Promise<string[]> => {\n return Promise.all(\n Array.from({ length: count }, async (_, index) => {\n const html = slots.has(`tab-${index}`)\n ? await slots.render(`tab-${index}`)\n : await slots.render(\"default\", [index]);\n\n // Function slots return an `HTMLString` object; islands need a plain string.\n return String(html);\n })\n );\n};\n\n/**\n * Reads the tabs of a tabbed component: its labels, from the `values` prop that the Andesine MDX\n * plugin and content renderer add, and its rendered panels.\n */\nconst renderTabs = async (\n values: string,\n slots: Slots\n): Promise<{ values: string[]; panels: string[] }> => {\n const labels: string[] = JSON.parse(values);\n\n return { values: labels, panels: await renderPanels(slots, labels.length) };\n};\n/** Reads the `items` prop of a file tree: JSON from the Andesine MDX plugin, or nested items. */\nconst readFileTreeItems = (items: string | FileTreeItem[]): FileTreeItem[] => {\n return typeof items === \"string\" ? JSON.parse(items) : items;\n};\n\nexport { renderTabs, readFileTreeItems };\nexport { getOperationView } from \"./sources/openapi/embed\";\nexport type { OperationProps } from \"./sources/openapi/embed\";\n"],"mappings":";;;;AAoBA,MAAM,wBAAQ,IAAI,QAAgC;;AAGlD,MAAM,mBAAmB,OAAO,UAAkD;CAChF,IAAI,MAAM,MAAM,OAAO,MAAM;CAE7B,MAAM,SAAS,OAAO,QAAQ,MAAM,SAAS,KAAK,OAAO,MAAM,MAAM;CAErE,IAAI,QAAQ,SAAS,WACnB,MAAM,IAAI,MACR,iBAAiB,MAAM,OAAO,sDAChC;CAGF,MAAM,QAAQ,MAAM,iBAAiB,MAAM;CAC3C,MAAM,YAAY,MAAM,WAAW,MAAM,SAAS,KAAK,OAAO,MAAM,EAAE;CAEtE,IAAI,CAAC,WACH,MAAM,IAAI,MAAM,iBAAiB,MAAM,GAAG,mCAAmC,OAAO,GAAG,GAAG;CAG5F,IAAI,CAAC,MAAM,IAAI,KAAK,GAAG,MAAM,IAAI,OAAO,YAAY,QAAQ,OAAO,OAAO,IAAI,CAAC,CAAC,KAAK;CAErF,OAAO,oBAAoB,WAAW,OAAO;EAC3C;EACA,OAAO,iBAAiB,SAAS;EACjC,MAAM,MAAM,IAAI,KAAK,CAAC,CAAE,WAAW,UAAU;EAC7C,QAAQ,MAAM,UAAU,GAAG,KAAK,OAAO,EAAE,EAAE,GAAG,KAAK,UAAU,EAAE,EAAE;EACjE,OAAO;GACL,aAAa,MAAM;GACnB,gBAAgB,MAAM;GACtB,YAAY,MAAM;GAClB,aAAa,MAAM;GACnB,WAAW,MAAM;GACjB,UAAU,MAAM;EAClB;CACF,CAAC;AACH;;;;;;;AC9CA,MAAM,gBAAgB,OAAc,UAAqC;CACvE,OAAO,QAAQ,IACb,MAAM,KAAK,EAAE,QAAQ,MAAM,GAAG,OAAO,GAAG,UAAU;EAChD,MAAM,OAAO,MAAM,IAAI,OAAO,OAAO,IACjC,MAAM,MAAM,OAAO,OAAO,OAAO,IACjC,MAAM,MAAM,OAAO,WAAW,CAAC,KAAK,CAAC;EAGzC,OAAO,OAAO,IAAI;CACpB,CAAC,CACH;AACF;;;;;AAMA,MAAM,aAAa,OACjB,QACA,UACoD;CACpD,MAAM,SAAmB,KAAK,MAAM,MAAM;CAE1C,OAAO;EAAE,QAAQ;EAAQ,QAAQ,MAAM,aAAa,OAAO,OAAO,MAAM;CAAE;AAC5E;;AAEA,MAAM,qBAAqB,UAAmD;CAC5E,OAAO,OAAO,UAAU,WAAW,KAAK,MAAM,KAAK,IAAI;AACzD"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { n as toSegments, t as toHref } from "./paths-75QgA3Qs.js";
|
|
2
|
+
//#region src/sources/andesine/assets.ts
|
|
3
|
+
const assetPath = "_andesine/assets";
|
|
4
|
+
const assetFile = /^[a-f\d]{64}\.(png|jpeg|webp)$/;
|
|
5
|
+
const mimeTypes = {
|
|
6
|
+
png: "image/png",
|
|
7
|
+
jpeg: "image/jpeg",
|
|
8
|
+
webp: "image/webp"
|
|
9
|
+
};
|
|
10
|
+
const getAssetPrefix = (base) => {
|
|
11
|
+
return toHref(toSegments(base, "Site base"), assetPath.split("/"));
|
|
12
|
+
};
|
|
13
|
+
const getDeliveryURL = (asset, entryID) => {
|
|
14
|
+
const url = new URL(asset.url);
|
|
15
|
+
if (!(url.protocol === "https:" && !url.username && !url.password)) throw new Error(`Entry ${entryID}, asset ${asset.assetID}: expected a public HTTPS URL.`);
|
|
16
|
+
return url.href;
|
|
17
|
+
};
|
|
18
|
+
//#endregion
|
|
19
|
+
export { mimeTypes as a, getDeliveryURL as i, assetPath as n, getAssetPrefix as r, assetFile as t };
|
|
20
|
+
|
|
21
|
+
//# sourceMappingURL=assets-D6WJmZ05.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assets-D6WJmZ05.js","names":[],"sources":["../../src/sources/andesine/assets.ts"],"sourcesContent":["import type { PublishedAsset } from \"@andesine/sdk\";\nimport { toHref, toSegments } from \"../../routing\";\n\ninterface AssetStore {\n /** Returns the URL that pages use for an image. */\n resolve(asset: PublishedAsset, entryID: string): Promise<string>;\n}\n\nconst assetPath = \"_andesine/assets\";\nconst assetFile = /^[a-f\\d]{64}\\.(png|jpeg|webp)$/;\nconst mimeTypes = { png: \"image/png\", jpeg: \"image/jpeg\", webp: \"image/webp\" };\n\nconst getAssetPrefix = (base: string): string => {\n return toHref(toSegments(base, \"Site base\"), assetPath.split(\"/\"));\n};\nconst getDeliveryURL = (asset: PublishedAsset, entryID: string): string => {\n const url = new URL(asset.url);\n const isPublicHTTPS = url.protocol === \"https:\" && !url.username && !url.password;\n\n if (!isPublicHTTPS) {\n throw new Error(`Entry ${entryID}, asset ${asset.assetID}: expected a public HTTPS URL.`);\n }\n\n return url.href;\n};\nexport { assetPath, assetFile, mimeTypes, getAssetPrefix, getDeliveryURL };\nexport type { AssetStore };\n"],"mappings":";;AAQA,MAAM,YAAY;AAClB,MAAM,YAAY;AAClB,MAAM,YAAY;CAAE,KAAK;CAAa,MAAM;CAAc,MAAM;AAAa;AAE7E,MAAM,kBAAkB,SAAyB;CAC/C,OAAO,OAAO,WAAW,MAAM,WAAW,GAAG,UAAU,MAAM,GAAG,CAAC;AACnE;AACA,MAAM,kBAAkB,OAAuB,YAA4B;CACzE,MAAM,MAAM,IAAI,IAAI,MAAM,GAAG;CAG7B,IAAI,EAFkB,IAAI,aAAa,YAAY,CAAC,IAAI,YAAY,CAAC,IAAI,WAGvE,MAAM,IAAI,MAAM,SAAS,QAAQ,UAAU,MAAM,QAAQ,+BAA+B;CAG1F,OAAO,IAAI;AACb"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { o as flattenTree, r as createSections, t as loadStaticSources } from "./sources-Cm6NdIen.js";
|
|
2
|
+
//#region src/output/catalog.ts
|
|
3
|
+
/** Lists the public pages of all sources. Pages that are hidden from search are left out. */
|
|
4
|
+
const loadCatalog = async (config) => {
|
|
5
|
+
const sources = await loadStaticSources(config);
|
|
6
|
+
const isPublic = (page) => Boolean(page && !page.searchHidden);
|
|
7
|
+
return {
|
|
8
|
+
sections: createSections(config, sources).map((section) => {
|
|
9
|
+
const pages = [...flattenTree(section.navigation).map((node) => node.page), ...section.sources.flatMap((source) => source.pages)].filter(isPublic);
|
|
10
|
+
return {
|
|
11
|
+
label: section.label,
|
|
12
|
+
pages: [...new Set(pages)],
|
|
13
|
+
topics: section.navigation.flatMap((node) => {
|
|
14
|
+
const page = flattenTree([node]).map((item) => item.page).find(isPublic);
|
|
15
|
+
return page ? [{
|
|
16
|
+
label: node.label,
|
|
17
|
+
page
|
|
18
|
+
}] : [];
|
|
19
|
+
})
|
|
20
|
+
};
|
|
21
|
+
}),
|
|
22
|
+
pages: sources.flatMap((source) => source.pages).filter(isPublic)
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
//#endregion
|
|
26
|
+
export { loadCatalog as t };
|
|
27
|
+
|
|
28
|
+
//# sourceMappingURL=catalog-DU4BUrpw.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog-DU4BUrpw.js","names":[],"sources":["../../src/output/catalog.ts"],"sourcesContent":["import type { PagesConfig } from \"../config\";\nimport { createSections, flattenTree } from \"../navigation\";\nimport { loadStaticSources, type SourcePage } from \"../sources\";\n\ninterface CatalogTopic {\n label: string;\n /** The topic's landing page, or its first page. */\n page: SourcePage;\n}\n\ninterface CatalogSection {\n label: string;\n /** Pages in navigation order, followed by pages hidden from navigation. */\n pages: SourcePage[];\n /** The top-level navigation items. */\n topics: CatalogTopic[];\n}\n\ninterface Catalog {\n sections: CatalogSection[];\n pages: SourcePage[];\n}\n\n/** Lists the public pages of all sources. Pages that are hidden from search are left out. */\nconst loadCatalog = async (config: PagesConfig): Promise<Catalog> => {\n const sources = await loadStaticSources(config);\n const isPublic = (page?: SourcePage): page is SourcePage => Boolean(page && !page.searchHidden);\n\n return {\n sections: createSections(config, sources).map((section) => {\n const pages = [\n ...flattenTree(section.navigation).map((node) => node.page),\n ...section.sources.flatMap((source) => source.pages)\n ].filter(isPublic);\n\n return {\n label: section.label,\n pages: [...new Set(pages)],\n topics: section.navigation.flatMap((node) => {\n const page = flattenTree([node])\n .map((item) => item.page)\n .find(isPublic);\n\n return page ? [{ label: node.label, page }] : [];\n })\n };\n }),\n pages: sources.flatMap((source) => source.pages).filter(isPublic)\n };\n};\n\nexport { loadCatalog };\nexport type { Catalog, CatalogSection, CatalogTopic };\n"],"mappings":";;;AAwBA,MAAM,cAAc,OAAO,WAA0C;CACnE,MAAM,UAAU,MAAM,kBAAkB,MAAM;CAC9C,MAAM,YAAY,SAA0C,QAAQ,QAAQ,CAAC,KAAK,YAAY;CAE9F,OAAO;EACL,UAAU,eAAe,QAAQ,OAAO,CAAC,CAAC,KAAK,YAAY;GACzD,MAAM,QAAQ,CACZ,GAAG,YAAY,QAAQ,UAAU,CAAC,CAAC,KAAK,SAAS,KAAK,IAAI,GAC1D,GAAG,QAAQ,QAAQ,SAAS,WAAW,OAAO,KAAK,CACrD,CAAC,CAAC,OAAO,QAAQ;GAEjB,OAAO;IACL,OAAO,QAAQ;IACf,OAAO,CAAC,GAAG,IAAI,IAAI,KAAK,CAAC;IACzB,QAAQ,QAAQ,WAAW,SAAS,SAAS;KAC3C,MAAM,OAAO,YAAY,CAAC,IAAI,CAAC,CAAC,CAC7B,KAAK,SAAS,KAAK,IAAI,CAAC,CACxB,KAAK,QAAQ;KAEhB,OAAO,OAAO,CAAC;MAAE,OAAO,KAAK;MAAO;KAAK,CAAC,IAAI,CAAC;IACjD,CAAC;GACH;EACF,CAAC;EACD,OAAO,QAAQ,SAAS,WAAW,OAAO,KAAK,CAAC,CAAC,OAAO,QAAQ;CAClE;AACF"}
|