@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.
Files changed (110) hide show
  1. package/CHANGELOG.md +99 -0
  2. package/LICENSE +21 -0
  3. package/README.md +92 -2
  4. package/dist/answers.d.ts +6 -0
  5. package/dist/astro/content.astro +118 -0
  6. package/dist/astro/middleware.js +39 -0
  7. package/dist/astro/middleware.js.map +1 -0
  8. package/dist/astro/routes/answers.js +129 -0
  9. package/dist/astro/routes/answers.js.map +1 -0
  10. package/dist/astro/routes/entry-pages.js +22 -0
  11. package/dist/astro/routes/entry-pages.js.map +1 -0
  12. package/dist/astro/routes/llms-full.js +12 -0
  13. package/dist/astro/routes/llms-full.js.map +1 -0
  14. package/dist/astro/routes/llms.js +12 -0
  15. package/dist/astro/routes/llms.js.map +1 -0
  16. package/dist/astro/routes/markdown-alias.js +14 -0
  17. package/dist/astro/routes/markdown-alias.js.map +1 -0
  18. package/dist/astro/routes/markdown.js +12 -0
  19. package/dist/astro/routes/markdown.js.map +1 -0
  20. package/dist/astro/routes/not-found.astro +12 -0
  21. package/dist/astro/routes/robots.js +9 -0
  22. package/dist/astro/routes/robots.js.map +1 -0
  23. package/dist/astro/routes/search.js +42 -0
  24. package/dist/astro/routes/search.js.map +1 -0
  25. package/dist/astro/routes/sitemap.js +12 -0
  26. package/dist/astro/routes/sitemap.js.map +1 -0
  27. package/dist/astro/routes/skill.js +13 -0
  28. package/dist/astro/routes/skill.js.map +1 -0
  29. package/dist/astro/routes/skills.js +24 -0
  30. package/dist/astro/routes/skills.js.map +1 -0
  31. package/dist/astro/routes/social.js +91 -0
  32. package/dist/astro/routes/social.js.map +1 -0
  33. package/dist/astro/routes/static.astro +53 -0
  34. package/dist/astro/routes/well-known-llms.js +2 -0
  35. package/dist/astro.d.ts +34 -0
  36. package/dist/astro.js +60 -0
  37. package/dist/astro.js.map +1 -0
  38. package/dist/chunks/assets-D6WJmZ05.js +21 -0
  39. package/dist/chunks/assets-D6WJmZ05.js.map +1 -0
  40. package/dist/chunks/catalog-DU4BUrpw.js +28 -0
  41. package/dist/chunks/catalog-DU4BUrpw.js.map +1 -0
  42. package/dist/chunks/config-CuH5JSI4.js +184 -0
  43. package/dist/chunks/config-CuH5JSI4.js.map +1 -0
  44. package/dist/chunks/files-BxqiQzFj.js +62 -0
  45. package/dist/chunks/files-BxqiQzFj.js.map +1 -0
  46. package/dist/chunks/hash-D4piIIQ6.js +11 -0
  47. package/dist/chunks/hash-D4piIIQ6.js.map +1 -0
  48. package/dist/chunks/index-D8wL2B5s.d.ts +571 -0
  49. package/dist/chunks/index-vsu3hISM.d.ts +62 -0
  50. package/dist/chunks/limits-Ppc7BQPG.js +45 -0
  51. package/dist/chunks/limits-Ppc7BQPG.js.map +1 -0
  52. package/dist/chunks/markdown-DKJSQxR2.js +42 -0
  53. package/dist/chunks/markdown-DKJSQxR2.js.map +1 -0
  54. package/dist/chunks/mdx-components-CUUDTapN.d.ts +9 -0
  55. package/dist/chunks/normalize-DG5nxOLm.js +361 -0
  56. package/dist/chunks/normalize-DG5nxOLm.js.map +1 -0
  57. package/dist/chunks/paths-75QgA3Qs.js +16 -0
  58. package/dist/chunks/paths-75QgA3Qs.js.map +1 -0
  59. package/dist/chunks/prepare-lnuw_ycM.js +219 -0
  60. package/dist/chunks/prepare-lnuw_ycM.js.map +1 -0
  61. package/dist/chunks/read-DCv1lmcM.js +57 -0
  62. package/dist/chunks/read-DCv1lmcM.js.map +1 -0
  63. package/dist/chunks/request-DOuBHGQs.js +92 -0
  64. package/dist/chunks/request-DOuBHGQs.js.map +1 -0
  65. package/dist/chunks/response-CtzaKMWH.js +15 -0
  66. package/dist/chunks/response-CtzaKMWH.js.map +1 -0
  67. package/dist/chunks/site-DY-uZ0PP.js +419 -0
  68. package/dist/chunks/site-DY-uZ0PP.js.map +1 -0
  69. package/dist/chunks/skill-CBTGUHQH.js +85 -0
  70. package/dist/chunks/skill-CBTGUHQH.js.map +1 -0
  71. package/dist/chunks/sources-Cm6NdIen.js +236 -0
  72. package/dist/chunks/sources-Cm6NdIen.js.map +1 -0
  73. package/dist/chunks/stored-CabomV-C.js +354 -0
  74. package/dist/chunks/stored-CabomV-C.js.map +1 -0
  75. package/dist/chunks/stored-CcEfvCQH.js +475 -0
  76. package/dist/chunks/stored-CcEfvCQH.js.map +1 -0
  77. package/dist/chunks/types-DBzuXfSe.d.ts +53 -0
  78. package/dist/chunks/view-C-9ZM1zK.js +745 -0
  79. package/dist/chunks/view-C-9ZM1zK.js.map +1 -0
  80. package/dist/chunks/view-Dlf_VRI7.d.ts +151 -0
  81. package/dist/client.d.ts +73 -0
  82. package/dist/client.js +295 -0
  83. package/dist/client.js.map +1 -0
  84. package/dist/collections.d.ts +7 -0
  85. package/dist/collections.js +215 -0
  86. package/dist/collections.js.map +1 -0
  87. package/dist/entry-pages.d.ts +10 -0
  88. package/dist/index.d.ts +5 -0
  89. package/dist/index.js +38 -0
  90. package/dist/index.js.map +1 -0
  91. package/dist/integration.d.ts +16 -0
  92. package/dist/integration.js +435 -0
  93. package/dist/integration.js.map +1 -0
  94. package/dist/llms-full.d.ts +5 -0
  95. package/dist/llms.d.ts +5 -0
  96. package/dist/markdown-alias.d.ts +7 -0
  97. package/dist/markdown.d.ts +7 -0
  98. package/dist/middleware.d.ts +8 -0
  99. package/dist/robots.d.ts +5 -0
  100. package/dist/runtime.d.ts +81 -0
  101. package/dist/runtime.js +56 -0
  102. package/dist/runtime.js.map +1 -0
  103. package/dist/scripts/restore-navigation.js +1 -0
  104. package/dist/search.d.ts +6 -0
  105. package/dist/sitemap.d.ts +5 -0
  106. package/dist/skill.d.ts +5 -0
  107. package/dist/skills.d.ts +10 -0
  108. package/dist/social.d.ts +7 -0
  109. package/dist/well-known-llms.d.ts +2 -0
  110. 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>
@@ -0,0 +1,2 @@
1
+ import { GET } from "./llms.js";
2
+ export { GET };
@@ -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"}