blume 2.2.2 → 2.2.4

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 (145) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/THIRD-PARTY-NOTICES.md +51 -0
  3. package/dist/cli/{chunk-kmswjxj9.js → chunk-0b1a8xqz.js} +3 -3
  4. package/dist/cli/{chunk-rtvgmg2j.js → chunk-0qx6vwwf.js} +2 -2
  5. package/dist/cli/{chunk-qcyxkj44.js → chunk-3ps63r91.js} +43 -17
  6. package/dist/cli/chunk-3ps63r91.js.map +15 -0
  7. package/dist/cli/{chunk-b680sv30.js → chunk-402xaaxn.js} +10 -8
  8. package/dist/cli/chunk-402xaaxn.js.map +13 -0
  9. package/dist/cli/{chunk-k45sq16q.js → chunk-49xa4yf2.js} +39 -23
  10. package/dist/cli/{chunk-k45sq16q.js.map → chunk-49xa4yf2.js.map} +3 -3
  11. package/dist/cli/{chunk-j4nfgn2j.js → chunk-51wr1wre.js} +1 -1
  12. package/dist/cli/{chunk-9jqmq5hv.js → chunk-531qbwn1.js} +6 -6
  13. package/dist/cli/{chunk-r5nm9w0c.js → chunk-5bp65pv4.js} +107 -37
  14. package/dist/cli/{chunk-r5nm9w0c.js.map → chunk-5bp65pv4.js.map} +11 -10
  15. package/dist/cli/{chunk-yg8ckc3g.js → chunk-6nvcjzts.js} +2 -2
  16. package/dist/cli/{chunk-x7bh6d9j.js → chunk-6v5w8vzd.js} +4 -4
  17. package/dist/cli/{chunk-f260jdrn.js → chunk-8cshtem6.js} +5 -5
  18. package/dist/cli/{chunk-ydqzkhjn.js → chunk-8h5ceyk0.js} +6 -6
  19. package/dist/cli/{chunk-e1n41w9m.js → chunk-8v90n67z.js} +3 -3
  20. package/dist/cli/{chunk-etckvbrh.js → chunk-98me5yas.js} +14 -14
  21. package/dist/cli/{chunk-hktq4j5r.js → chunk-9k7gg4ga.js} +16 -10
  22. package/dist/cli/{chunk-hktq4j5r.js.map → chunk-9k7gg4ga.js.map} +5 -5
  23. package/dist/cli/{chunk-34wap3ed.js → chunk-9qmc57zw.js} +3 -3
  24. package/dist/cli/{chunk-beb0z983.js → chunk-a1xmzxk2.js} +16 -16
  25. package/dist/cli/{chunk-gwy55cx3.js → chunk-ajw85dgf.js} +2 -2
  26. package/dist/cli/{chunk-69rjf786.js → chunk-ansqj08e.js} +5 -5
  27. package/dist/cli/{chunk-q1wwrxzw.js → chunk-b0vwhmdf.js} +3 -3
  28. package/dist/cli/chunk-b0vwhmdf.js.map +10 -0
  29. package/dist/cli/{chunk-nqna8dzp.js → chunk-b5gztt4j.js} +17 -17
  30. package/dist/cli/{chunk-fnxgtjeq.js → chunk-bc4jz2m4.js} +1 -1
  31. package/dist/cli/{chunk-aafhwx74.js → chunk-d4h1y312.js} +1 -1
  32. package/dist/cli/{chunk-080mfch6.js → chunk-et7zwqkg.js} +15 -15
  33. package/dist/cli/{chunk-487b95qy.js → chunk-f29q3j13.js} +41 -25
  34. package/dist/cli/{chunk-487b95qy.js.map → chunk-f29q3j13.js.map} +3 -3
  35. package/dist/cli/{chunk-c5bjxq8v.js → chunk-f72388jn.js} +2 -2
  36. package/dist/cli/{chunk-t2h8pwy1.js → chunk-g0hpwbyx.js} +4 -4
  37. package/dist/cli/{chunk-40vk8kgf.js → chunk-j102xmnk.js} +7 -7
  38. package/dist/cli/{chunk-ppa6mg4d.js → chunk-m54bz9ng.js} +6 -6
  39. package/dist/cli/{chunk-h0qwdbem.js → chunk-mt6njy68.js} +2 -2
  40. package/dist/cli/{chunk-2ssh60qh.js → chunk-n091sgam.js} +6 -6
  41. package/dist/cli/{chunk-1ch3ct3r.js → chunk-p33bf2nb.js} +14 -14
  42. package/dist/cli/{chunk-4zxh25hc.js → chunk-saxq5jjr.js} +2 -2
  43. package/dist/cli/{chunk-x60e15st.js → chunk-sbt1s5j2.js} +17 -17
  44. package/dist/cli/{chunk-gxhcf2hs.js → chunk-tckd6qwv.js} +2 -2
  45. package/dist/cli/{chunk-p834rkcn.js → chunk-tf4134kk.js} +5 -5
  46. package/dist/cli/{chunk-zxd5jrgx.js → chunk-vxdjss7f.js} +76 -34
  47. package/dist/cli/{chunk-zxd5jrgx.js.map → chunk-vxdjss7f.js.map} +4 -4
  48. package/dist/cli/{chunk-9h8mh2tk.js → chunk-x2pgg22t.js} +1 -1
  49. package/dist/cli/{chunk-hn3g2b89.js → chunk-xhrwrzrh.js} +9 -9
  50. package/dist/cli/index.js +18 -18
  51. package/dist/types/ai/ask-context.d.ts +8 -0
  52. package/dist/types/ai/link-text.d.ts +5 -0
  53. package/dist/types/ai/relative-links.d.ts +26 -6
  54. package/dist/types/core/config-input.d.ts +41 -1
  55. package/dist/types/core/data.d.ts +14 -0
  56. package/dist/types/core/last-modified.d.ts +33 -18
  57. package/dist/types/core/links.d.ts +16 -0
  58. package/dist/types/core/schema.d.ts +17 -1
  59. package/dist/types/core/types.d.ts +10 -0
  60. package/dist/types/deploy/sitemap.d.ts +9 -0
  61. package/dist/types/search/documents.d.ts +3 -1
  62. package/dist/types/search/fold.d.ts +33 -0
  63. package/dist/types/search/orama-index.d.ts +4 -4
  64. package/dist/types/seo/jsonld.d.ts +33 -0
  65. package/docs/configuration/search.mdx +2 -2
  66. package/docs/configuration/theming.mdx +13 -1
  67. package/docs/content/frontmatter.mdx +1 -1
  68. package/docs/content/i18n.mdx +1 -1
  69. package/docs/content/sources/remote-mdx.mdx +1 -1
  70. package/docs/discoverability/open-graph.mdx +16 -1
  71. package/docs/discoverability/sitemap-and-robots.mdx +12 -0
  72. package/docs/discoverability/structured-data.mdx +44 -0
  73. package/package.json +4 -3
  74. package/skills/blume-migrate/references/docus.md +1 -2
  75. package/skills/blume-migrate/references/docusaurus.md +1 -1
  76. package/skills/blume-migrate/references/vitepress.md +2 -2
  77. package/skills/blume-migrate/references/vuepress.md +1 -1
  78. package/src/ai/ask-context.ts +52 -14
  79. package/src/ai/ask-data.ts +4 -1
  80. package/src/ai/ask-tools.ts +17 -5
  81. package/src/ai/link-text.ts +6 -0
  82. package/src/ai/llms.ts +1 -7
  83. package/src/ai/markdown.ts +8 -4
  84. package/src/ai/relative-links.ts +155 -48
  85. package/src/ai/site-skill.ts +1 -4
  86. package/src/astro/generate.ts +7 -0
  87. package/src/astro/templates.ts +36 -20
  88. package/src/components/layout/Header.astro +18 -10
  89. package/src/components/layout/PageActions.astro +1 -0
  90. package/src/components/layout/PageLayout.astro +31 -13
  91. package/src/components/layout/ReferenceLayout.astro +6 -1
  92. package/src/components/layout/RootLayout.astro +13 -1
  93. package/src/components/layout/head-scripts.ts +5 -1
  94. package/src/components/layout/locale-redirect.ts +38 -19
  95. package/src/components/layout/search/types.ts +12 -4
  96. package/src/core/config-input.ts +40 -1
  97. package/src/core/config.ts +5 -2
  98. package/src/core/data.ts +14 -0
  99. package/src/core/last-modified.ts +80 -34
  100. package/src/core/links.ts +43 -2
  101. package/src/core/manifest.ts +2 -0
  102. package/src/core/project-graph.ts +83 -43
  103. package/src/core/schema.ts +48 -9
  104. package/src/core/types.ts +10 -0
  105. package/src/deploy/sitemap.ts +127 -49
  106. package/src/search/documents.ts +34 -11
  107. package/src/search/fold.ts +175 -0
  108. package/src/search/orama-index.ts +40 -49
  109. package/src/seo/jsonld.ts +100 -23
  110. package/src/theme/chrome-icons.ts +2 -1
  111. package/src/theme/entry.ts +4 -1
  112. package/dist/cli/chunk-b680sv30.js.map +0 -13
  113. package/dist/cli/chunk-q1wwrxzw.js.map +0 -10
  114. package/dist/cli/chunk-qcyxkj44.js.map +0 -14
  115. /package/dist/cli/{chunk-kmswjxj9.js.map → chunk-0b1a8xqz.js.map} +0 -0
  116. /package/dist/cli/{chunk-rtvgmg2j.js.map → chunk-0qx6vwwf.js.map} +0 -0
  117. /package/dist/cli/{chunk-j4nfgn2j.js.map → chunk-51wr1wre.js.map} +0 -0
  118. /package/dist/cli/{chunk-9jqmq5hv.js.map → chunk-531qbwn1.js.map} +0 -0
  119. /package/dist/cli/{chunk-yg8ckc3g.js.map → chunk-6nvcjzts.js.map} +0 -0
  120. /package/dist/cli/{chunk-x7bh6d9j.js.map → chunk-6v5w8vzd.js.map} +0 -0
  121. /package/dist/cli/{chunk-f260jdrn.js.map → chunk-8cshtem6.js.map} +0 -0
  122. /package/dist/cli/{chunk-ydqzkhjn.js.map → chunk-8h5ceyk0.js.map} +0 -0
  123. /package/dist/cli/{chunk-e1n41w9m.js.map → chunk-8v90n67z.js.map} +0 -0
  124. /package/dist/cli/{chunk-etckvbrh.js.map → chunk-98me5yas.js.map} +0 -0
  125. /package/dist/cli/{chunk-34wap3ed.js.map → chunk-9qmc57zw.js.map} +0 -0
  126. /package/dist/cli/{chunk-beb0z983.js.map → chunk-a1xmzxk2.js.map} +0 -0
  127. /package/dist/cli/{chunk-gwy55cx3.js.map → chunk-ajw85dgf.js.map} +0 -0
  128. /package/dist/cli/{chunk-69rjf786.js.map → chunk-ansqj08e.js.map} +0 -0
  129. /package/dist/cli/{chunk-nqna8dzp.js.map → chunk-b5gztt4j.js.map} +0 -0
  130. /package/dist/cli/{chunk-fnxgtjeq.js.map → chunk-bc4jz2m4.js.map} +0 -0
  131. /package/dist/cli/{chunk-aafhwx74.js.map → chunk-d4h1y312.js.map} +0 -0
  132. /package/dist/cli/{chunk-080mfch6.js.map → chunk-et7zwqkg.js.map} +0 -0
  133. /package/dist/cli/{chunk-c5bjxq8v.js.map → chunk-f72388jn.js.map} +0 -0
  134. /package/dist/cli/{chunk-t2h8pwy1.js.map → chunk-g0hpwbyx.js.map} +0 -0
  135. /package/dist/cli/{chunk-40vk8kgf.js.map → chunk-j102xmnk.js.map} +0 -0
  136. /package/dist/cli/{chunk-ppa6mg4d.js.map → chunk-m54bz9ng.js.map} +0 -0
  137. /package/dist/cli/{chunk-h0qwdbem.js.map → chunk-mt6njy68.js.map} +0 -0
  138. /package/dist/cli/{chunk-2ssh60qh.js.map → chunk-n091sgam.js.map} +0 -0
  139. /package/dist/cli/{chunk-1ch3ct3r.js.map → chunk-p33bf2nb.js.map} +0 -0
  140. /package/dist/cli/{chunk-4zxh25hc.js.map → chunk-saxq5jjr.js.map} +0 -0
  141. /package/dist/cli/{chunk-x60e15st.js.map → chunk-sbt1s5j2.js.map} +0 -0
  142. /package/dist/cli/{chunk-gxhcf2hs.js.map → chunk-tckd6qwv.js.map} +0 -0
  143. /package/dist/cli/{chunk-p834rkcn.js.map → chunk-tf4134kk.js.map} +0 -0
  144. /package/dist/cli/{chunk-9h8mh2tk.js.map → chunk-x2pgg22t.js.map} +0 -0
  145. /package/dist/cli/{chunk-hn3g2b89.js.map → chunk-xhrwrzrh.js.map} +0 -0
@@ -5,13 +5,13 @@ import {
5
5
  import {
6
6
  ComponentOverridesError,
7
7
  analyzeComponentOverrides
8
- } from "./chunk-j4nfgn2j.js";
8
+ } from "./chunk-51wr1wre.js";
9
9
  import {
10
10
  findConfigFile,
11
11
  findComponentsFile,
12
12
  ConfigValidationError,
13
13
  loadConfig
14
- } from "./chunk-r5nm9w0c.js";
14
+ } from "./chunk-5bp65pv4.js";
15
15
 
16
16
  // src/upgrade/upgrade.ts
17
17
  import { existsSync } from "node:fs";
@@ -199,4 +199,4 @@ When \`${options.runner} blume doctor\` reports no errors, run \`${options.runne
199
199
  export { UPGRADE_GUIDE_URL, UPGRADE_GUIDE_FILE, manualBumpAdvice, bumpBlumeDependency, isOutsideBlumeProject, removedBuildFlags, flagList, removedBuildFlagsAdvice, collectUpgradeFindings, upgradePrompt };
200
200
 
201
201
  //# debugId=1E503C224ED252A564756E2164756E21
202
- //# sourceMappingURL=chunk-34wap3ed.js.map
202
+ //# sourceMappingURL=chunk-9qmc57zw.js.map
@@ -2,36 +2,36 @@
2
2
  import {
3
3
  ensureGitignore
4
4
  } from "./chunk-yzhm0j9q.js";
5
- import"./chunk-r5nm9w0c.js";
5
+ import"./chunk-5bp65pv4.js";
6
6
  import {
7
7
  commandMeta,
8
8
  logger,
9
9
  reportDiagnostics
10
10
  } from "./index.js";
11
- import"./chunk-zxd5jrgx.js";
11
+ import"./chunk-vxdjss7f.js";
12
12
  import {
13
13
  astroBuildDiagnostics
14
- } from "./chunk-4zxh25hc.js";
14
+ } from "./chunk-saxq5jjr.js";
15
15
  import {
16
16
  refuseIfDevRunning
17
- } from "./chunk-h0qwdbem.js";
17
+ } from "./chunk-mt6njy68.js";
18
18
  import"./chunk-zccbjcj0.js";
19
- import"./chunk-k45sq16q.js";
19
+ import"./chunk-49xa4yf2.js";
20
20
  import {
21
21
  refuseIfEjected
22
- } from "./chunk-e1n41w9m.js";
23
- import"./chunk-hktq4j5r.js";
24
- import"./chunk-b680sv30.js";
25
- import"./chunk-rtvgmg2j.js";
26
- import"./chunk-j4nfgn2j.js";
22
+ } from "./chunk-8v90n67z.js";
23
+ import"./chunk-9k7gg4ga.js";
24
+ import"./chunk-402xaaxn.js";
25
+ import"./chunk-0qx6vwwf.js";
26
+ import"./chunk-51wr1wre.js";
27
27
  import"./chunk-jq5n4avg.js";
28
- import"./chunk-487b95qy.js";
29
- import"./chunk-9h8mh2tk.js";
28
+ import"./chunk-f29q3j13.js";
29
+ import"./chunk-x2pgg22t.js";
30
30
  import {
31
31
  prepareProject
32
- } from "./chunk-t2h8pwy1.js";
33
- import"./chunk-gwy55cx3.js";
34
- import"./chunk-q1wwrxzw.js";
32
+ } from "./chunk-g0hpwbyx.js";
33
+ import"./chunk-ajw85dgf.js";
34
+ import"./chunk-b0vwhmdf.js";
35
35
 
36
36
  // src/cli/commands/check.ts
37
37
  import { existsSync } from "node:fs";
@@ -102,4 +102,4 @@ export {
102
102
  };
103
103
 
104
104
  //# debugId=2169D092EE0AE81964756E2164756E21
105
- //# sourceMappingURL=chunk-beb0z983.js.map
105
+ //# sourceMappingURL=chunk-a1xmzxk2.js.map
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  needsPlaygroundProxy,
4
4
  resolveAskBackend
5
- } from "./chunk-r5nm9w0c.js";
5
+ } from "./chunk-5bp65pv4.js";
6
6
 
7
7
  // src/core/server-features.ts
8
8
  var serverFeatures = (config) => {
@@ -101,4 +101,4 @@ var checkRequiredSecrets = (config) => {
101
101
  export { serverFeatures, checkRequiredSecrets };
102
102
 
103
103
  //# debugId=D62D6223654FF46464756E2164756E21
104
- //# sourceMappingURL=chunk-gwy55cx3.js.map
104
+ //# sourceMappingURL=chunk-ajw85dgf.js.map
@@ -8,7 +8,7 @@ import {
8
8
  deployPlatform,
9
9
  resolveProjectContext,
10
10
  loadConfig
11
- } from "./chunk-r5nm9w0c.js";
11
+ } from "./chunk-5bp65pv4.js";
12
12
  import {
13
13
  normalizeBasePath,
14
14
  stripBasePath
@@ -23,13 +23,13 @@ import {
23
23
  trailingSlashAnswer,
24
24
  answerRequestsFirst,
25
25
  refuseIfEjected
26
- } from "./chunk-e1n41w9m.js";
26
+ } from "./chunk-8v90n67z.js";
27
27
  import {
28
28
  deployOutputDir
29
- } from "./chunk-k45sq16q.js";
29
+ } from "./chunk-49xa4yf2.js";
30
30
  import {
31
31
  parsePort
32
- } from "./chunk-fnxgtjeq.js";
32
+ } from "./chunk-bc4jz2m4.js";
33
33
 
34
34
  // src/cli/commands/preview.ts
35
35
  import { existsSync } from "node:fs";
@@ -143,4 +143,4 @@ export {
143
143
  };
144
144
 
145
145
  //# debugId=A1D72D1423B1BFEC64756E2164756E21
146
- //# sourceMappingURL=chunk-69rjf786.js.map
146
+ //# sourceMappingURL=chunk-ansqj08e.js.map
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  asciiSlugify
4
- } from "./chunk-r5nm9w0c.js";
4
+ } from "./chunk-5bp65pv4.js";
5
5
 
6
6
  // src/ai/site-skill.ts
7
7
  var NAME_MAX = 64;
@@ -15,5 +15,5 @@ var siteSkillName = (project) => {
15
15
 
16
16
  export { SKILL_MD_PATH, siteSkillName };
17
17
 
18
- //# debugId=CA3AF8894895500A64756E2164756E21
19
- //# sourceMappingURL=chunk-q1wwrxzw.js.map
18
+ //# debugId=61191DC8DC62ECF564756E2164756E21
19
+ //# sourceMappingURL=chunk-b0vwhmdf.js.map
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/ai/site-skill.ts"],
4
+ "sourcesContent": [
5
+ "import { hasGeneratedChangelog } from \"../astro/pages.ts\";\nimport {\n mountBasePath,\n normalizeBasePath,\n withBasePath,\n} from \"../core/base-path.ts\";\nimport { CHANGELOG_INDEX_ROUTE } from \"../core/changelog-index.ts\";\nimport { discoverPagesSync } from \"../core/custom-pages.ts\";\nimport { isHiddenPage } from \"../core/hidden-pages.ts\";\nimport { metaDescription } from \"../core/manifest.ts\";\nimport type { BlumeProject } from \"../core/project-graph.ts\";\nimport { absoluteUrl } from \"../core/site-url.ts\";\nimport type { NavNode, PageRecord } from \"../core/types.ts\";\nimport { resolveReferences } from \"../openapi/references.ts\";\nimport { docsPhrase } from \"./ai-catalog.ts\";\nimport { API_PAGES_PATH } from \"./api/paths.ts\";\nimport { linkText } from \"./link-text.ts\";\nimport { asciiSlugify } from \"./mcp/discovery.ts\";\nimport {\n SKILL_DESCRIPTION_MAX,\n generatesSiteSkill,\n skillMdArtifact,\n} from \"./skills.ts\";\nimport type { SkillArtifact } from \"./skills.ts\";\n\n/**\n * The site's own agent skill (`agents.skillMd`): a `SKILL.md` in the Agent\n * Skills format, built from what the build already knows — the site's title\n * and description, how to read any page as Markdown, llms.txt and the MCP\n * server, the API references, and a map of the docs with each page's one-line\n * description. No model writes it, so it costs nothing and is current with\n * every build: a guide to the docs rather than a summary of the product. A\n * hand-written skill of the same name in `agents.skills` replaces it.\n */\n\n/** The most pages the map lists; llms.txt holds the rest. */\nexport const MAX_SKILL_PAGES = 200;\n\n/** The Agent Skills spec caps a skill name at 64 characters. */\nconst NAME_MAX = 64;\n\n/** Where the site skill is served besides the discovery index. */\nexport const SKILL_MD_PATH = \"/skill.md\";\n\n/**\n * The site skill's name: the title as a skill name (lowercase alphanumerics\n * and single hyphens), else the site's host, for a title with no Latin\n * letters in it.\n */\nexport const siteSkillName = (project: BlumeProject): string => {\n const { site } = project.config.deployment.options;\n const fromTitle = asciiSlugify(project.config.title);\n const name =\n fromTitle || asciiSlugify(site ? new URL(site).hostname : \"\") || \"docs\";\n return name.slice(0, NAME_MAX).replace(/-+$/u, \"\");\n};\n\n/**\n * Current-version, default-locale pages worth listing: not API operations,\n * and not changelog entries, which the changelog index covers in one line.\n */\nconst mappedPages = (project: BlumeProject): PageRecord[] => {\n const defaultLocale = project.config.i18n?.defaultLocale;\n return project.graph.pages.filter(\n (page) =>\n !(\n page.meta.ai.exclude ||\n page.meta.draft ||\n isHiddenPage(page, project.graph) ||\n page.meta.seo.noindex ||\n page.version !== \"\" ||\n page.source.name === \"openapi\" ||\n page.contentType === \"changelog\"\n ) &&\n (defaultLocale === undefined || page.locale === defaultLocale)\n );\n};\n\n/** Renders the page map, listing each page once, up to the cap. */\nclass PageMap {\n readonly #byRoute: Map<string, PageRecord>;\n readonly #listed = new Set<string>();\n readonly #url: (route: string) => string;\n\n constructor(pages: PageRecord[], url: (route: string) => string) {\n this.#byRoute = new Map(pages.map((page) => [page.route, page]));\n this.#url = url;\n }\n\n /** How many listable pages the cap left out. */\n get omitted(): number {\n return this.#byRoute.size - this.#listed.size;\n }\n\n /** The Markdown link line for a route, or nothing when it isn't listed. */\n line(route: string): string[] {\n const page = this.#byRoute.get(route);\n if (\n !page ||\n this.#listed.has(route) ||\n this.#listed.size >= MAX_SKILL_PAGES\n ) {\n return [];\n }\n this.#listed.add(route);\n // As `llms.txt` lists it: the page's meta description.\n const description = metaDescription(page);\n const summary = description ? `: ${description}` : \"\";\n return [`- [${linkText(page.title)}](${this.#url(route)})${summary}`];\n }\n\n /** One navigation level: its loose pages, then each group under a heading. */\n level(nodes: NavNode[], depth: number): string[] {\n const list: string[] = [];\n const groups: string[] = [];\n for (const node of nodes) {\n if (node.kind === \"page\") {\n list.push(...this.line(node.route));\n continue;\n }\n const blocks = [\n ...(node.route ? this.line(node.route) : []),\n ...this.level(node.children, depth + 1),\n ];\n if (blocks.length > 0) {\n groups.push(\n \"\",\n `${\"#\".repeat(Math.min(depth, 6))} ${node.label}`,\n \"\",\n ...blocks\n );\n }\n }\n return [...list, ...groups];\n }\n\n /** Pages the navigation doesn't reach, in route order. */\n rest(): string[] {\n return [...this.#byRoute.keys()]\n .toSorted((a, b) => a.localeCompare(b))\n .flatMap((route) => this.line(route));\n }\n}\n\n/** The \"Reading the docs\" bullets: every agent surface the site serves. */\nconst surfaceLines = (\n project: BlumeProject,\n url: (path: string) => string\n): string[] => {\n const { agents } = project.config;\n const lines = [\n `- Any page as Markdown: add \\`.md\\` to its URL (the home page is ${url(\"/index.md\")}). Every page link below already points at the Markdown.`,\n ];\n if (agents.llmsTxt.enabled) {\n lines.push(\n `- [llms.txt](${url(\"/llms.txt\")}): every page with a one-line summary.`,\n `- [llms-full.txt](${url(\"/llms-full.txt\")}): every page in one file, for when you need all of it.`\n );\n }\n if (agents.mcp.enabled) {\n lines.push(\n `- MCP server at ${url(agents.mcp.route)}, with \\`search_docs\\`, \\`get_page\\`, \\`list_pages\\`, and \\`get_navigation\\`. Connect it to search the docs instead of guessing URLs.`\n );\n }\n if (agents.api) {\n lines.push(\n `- [JSON API](${url(API_PAGES_PATH)}): the page index, with each page as JSON and Markdown.`\n );\n }\n const userPages = project.context.pagesRoot\n ? discoverPagesSync(project.context.pagesRoot)\n : [];\n if (hasGeneratedChangelog(project, userPages)) {\n lines.push(\n `- [Changelog](${url(`${CHANGELOG_INDEX_ROUTE}.md`)}): release notes, newest first.`\n );\n }\n return lines;\n};\n\n/** The \"API reference\" bullets, one per rendered reference. */\nconst referenceLines = (\n project: BlumeProject,\n url: (path: string) => string\n): string[] =>\n resolveReferences(project.config).map((reference) => {\n // Scalar renders its own page with no Markdown mirror; Blume-rendered\n // references are pages like any other, one per operation.\n const route =\n reference.kind === \"scalar\"\n ? reference.route\n : withBasePath(reference.basePath, reference.route);\n const pages =\n reference.kind === \"scalar\"\n ? \"\"\n : \", with a page per operation (add `.md` for its Markdown)\";\n return `- [${linkText(reference.label)}](${url(route)})${pages}.`;\n });\n\n/** The skill's frontmatter `description`: what it's for and when to use it. */\nconst skillDescription = (project: BlumeProject): string => {\n const { description, title } = project.config;\n const summary = description ? ` ${description.trim()}` : \"\";\n return `Read ${docsPhrase(title, \"docs\")} instead of answering from memory.${summary} Use when a task involves ${title}: how it works, how to set it up or configure it, or its API.`.slice(\n 0,\n SKILL_DESCRIPTION_MAX\n );\n};\n\n/** The site skill's `SKILL.md`. */\nconst skillMarkdown = (project: BlumeProject, name: string): string => {\n const { config } = project;\n const { site = \"\" } = config.deployment.options;\n const base = normalizeBasePath(config.deployment.options.base);\n // Mounted and encoded like llms.txt's links.\n const url = (path: string): string =>\n encodeURI(absoluteUrl(site, mountBasePath(base, path)));\n const markdownUrl = (route: string): string =>\n url(route === \"/\" ? \"/index.md\" : `${route}.md`);\n\n const map = new PageMap(mappedPages(project), markdownUrl);\n const pages = [\n ...map.level(project.graph.navigation.sidebar, 3),\n ...map.rest(),\n ];\n const { omitted } = map;\n if (omitted > 0) {\n pages.push(\n \"\",\n config.agents.llmsTxt.enabled\n ? `…and ${omitted} more. [llms.txt](${url(\"/llms.txt\")}) lists every page.`\n : `…and ${omitted} more.`\n );\n }\n const references = referenceLines(project, url);\n\n return [\n \"---\",\n `name: ${name}`,\n `description: ${JSON.stringify(skillDescription(project))}`,\n \"---\",\n \"\",\n `# ${config.title}`,\n \"\",\n ...(config.description ? [config.description.trim(), \"\"] : []),\n `This skill points you at ${docsPhrase(config.title, \"docs\")}, at ${url(\"/\")}. When a task involves ${config.title}, read the relevant page before relying on what you remember: the docs are the source of truth, and they change.`,\n \"\",\n \"## Reading the docs\",\n \"\",\n ...surfaceLines(project, url),\n ...(references.length > 0\n ? [\"\", \"## API reference\", \"\", ...references]\n : []),\n ...(pages.length > 0 ? [\"\", \"## Pages\", \"\", ...pages] : []),\n \"\",\n ]\n .join(\"\\n\")\n .replaceAll(/\\n{3,}/gu, \"\\n\\n\");\n};\n\n/**\n * The generated site skill, or `null` when `agents.skillMd` is off or there\n * is no `deployment.site` to make its links absolute.\n */\nexport const buildSiteSkill = (project: BlumeProject): SkillArtifact | null => {\n if (!generatesSiteSkill(project.config)) {\n return null;\n }\n const name = siteSkillName(project);\n return skillMdArtifact(\n name,\n skillDescription(project),\n skillMarkdown(project, name)\n );\n};\n"
6
+ ],
7
+ "mappings": ";;;;;;AAuCA,IAAM,WAAW;AAGV,IAAM,gBAAgB;AAOtB,IAAM,gBAAgB,CAAC,YAAkC;AAAA,EAC9D,QAAQ,SAAS,QAAQ,OAAO,WAAW;AAAA,EAC3C,MAAM,YAAY,aAAa,QAAQ,OAAO,KAAK;AAAA,EACnD,MAAM,OACJ,aAAa,aAAa,OAAO,IAAI,IAAI,IAAI,EAAE,WAAW,EAAE,KAAK;AAAA,EACnE,OAAO,KAAK,MAAM,GAAG,QAAQ,EAAE,QAAQ,QAAQ,EAAE;AAAA;",
8
+ "debugId": "61191DC8DC62ECF564756E2164756E21",
9
+ "names": []
10
+ }
@@ -7,51 +7,51 @@ import {
7
7
  } from "./index.js";
8
8
  import {
9
9
  deployPlatform
10
- } from "./chunk-r5nm9w0c.js";
11
- import"./chunk-zxd5jrgx.js";
10
+ } from "./chunk-5bp65pv4.js";
11
+ import"./chunk-vxdjss7f.js";
12
12
  import"./chunk-zccbjcj0.js";
13
13
  import {
14
14
  refuseIfEjected
15
- } from "./chunk-e1n41w9m.js";
15
+ } from "./chunk-8v90n67z.js";
16
16
  import {
17
17
  publishBuildProject,
18
18
  ogCacheDir,
19
19
  pruneCardCache,
20
20
  cardCacheTally
21
- } from "./chunk-hktq4j5r.js";
22
- import"./chunk-b680sv30.js";
21
+ } from "./chunk-9k7gg4ga.js";
22
+ import"./chunk-402xaaxn.js";
23
23
  import {
24
24
  deployOutputDir,
25
25
  deployStaticDir,
26
26
  surfaceAdapterOutput
27
- } from "./chunk-k45sq16q.js";
28
- import"./chunk-487b95qy.js";
27
+ } from "./chunk-49xa4yf2.js";
28
+ import"./chunk-f29q3j13.js";
29
29
  import {
30
30
  ensureGitignore
31
31
  } from "./chunk-yzhm0j9q.js";
32
- import"./chunk-j4nfgn2j.js";
32
+ import"./chunk-51wr1wre.js";
33
33
  import {
34
34
  removedBuildFlags,
35
35
  flagList,
36
36
  removedBuildFlagsAdvice
37
- } from "./chunk-34wap3ed.js";
37
+ } from "./chunk-9qmc57zw.js";
38
38
  import {
39
39
  astroBuildDiagnostics,
40
40
  buildFailureLocator
41
- } from "./chunk-4zxh25hc.js";
41
+ } from "./chunk-saxq5jjr.js";
42
42
  import {
43
43
  refuseIfDevRunning
44
- } from "./chunk-h0qwdbem.js";
45
- import"./chunk-rtvgmg2j.js";
44
+ } from "./chunk-mt6njy68.js";
45
+ import"./chunk-0qx6vwwf.js";
46
46
  import"./chunk-jq5n4avg.js";
47
- import"./chunk-9h8mh2tk.js";
47
+ import"./chunk-x2pgg22t.js";
48
48
  import {
49
49
  prepareProject
50
- } from "./chunk-t2h8pwy1.js";
50
+ } from "./chunk-g0hpwbyx.js";
51
51
  import {
52
52
  serverFeatures
53
- } from "./chunk-gwy55cx3.js";
54
- import"./chunk-q1wwrxzw.js";
53
+ } from "./chunk-ajw85dgf.js";
54
+ import"./chunk-b0vwhmdf.js";
55
55
 
56
56
  // src/cli/commands/build.ts
57
57
  import { existsSync } from "node:fs";
@@ -276,4 +276,4 @@ export {
276
276
  };
277
277
 
278
278
  //# debugId=43360653920765D464756E2164756E21
279
- //# sourceMappingURL=chunk-nqna8dzp.js.map
279
+ //# sourceMappingURL=chunk-b5gztt4j.js.map
@@ -62,4 +62,4 @@ var parseTimeoutSeconds = (value, fallback) => {
62
62
  export { parsePort, parseIgnoreFlag, parseTimeoutSeconds };
63
63
 
64
64
  //# debugId=1CED8804CB94605564756E2164756E21
65
- //# sourceMappingURL=chunk-fnxgtjeq.js.map
65
+ //# sourceMappingURL=chunk-bc4jz2m4.js.map
@@ -1035,4 +1035,4 @@ var launchInstalledAgent = async (bin, prompt, platform = process.platform) => {
1035
1035
  export { finding, checkSelected, checkTerms, unknownCheckTerms, formatReport, reportJson, formatCatalog, AGENTS, writeAgentReport, fixPrompt, launchAgent, launchInstalledAgent };
1036
1036
 
1037
1037
  //# debugId=367C2A1AC5492B0664756E2164756E21
1038
- //# sourceMappingURL=chunk-aafhwx74.js.map
1038
+ //# sourceMappingURL=chunk-d4h1y312.js.map
@@ -3,7 +3,7 @@ import {
3
3
  resolveRuntimeDir,
4
4
  resolveProjectContext,
5
5
  loadConfig
6
- } from "./chunk-r5nm9w0c.js";
6
+ } from "./chunk-5bp65pv4.js";
7
7
  import"./chunk-zccbjcj0.js";
8
8
  import {
9
9
  commandMeta,
@@ -11,24 +11,24 @@ import {
11
11
  } from "./index.js";
12
12
  import {
13
13
  readDevLock
14
- } from "./chunk-h0qwdbem.js";
15
- import"./chunk-k45sq16q.js";
14
+ } from "./chunk-mt6njy68.js";
15
+ import"./chunk-49xa4yf2.js";
16
16
  import {
17
17
  refuseIfEjected
18
- } from "./chunk-e1n41w9m.js";
19
- import"./chunk-hktq4j5r.js";
20
- import"./chunk-zxd5jrgx.js";
21
- import"./chunk-b680sv30.js";
22
- import"./chunk-rtvgmg2j.js";
23
- import"./chunk-j4nfgn2j.js";
18
+ } from "./chunk-8v90n67z.js";
19
+ import"./chunk-9k7gg4ga.js";
20
+ import"./chunk-vxdjss7f.js";
21
+ import"./chunk-402xaaxn.js";
22
+ import"./chunk-0qx6vwwf.js";
23
+ import"./chunk-51wr1wre.js";
24
24
  import"./chunk-jq5n4avg.js";
25
- import"./chunk-487b95qy.js";
26
- import"./chunk-9h8mh2tk.js";
25
+ import"./chunk-f29q3j13.js";
26
+ import"./chunk-x2pgg22t.js";
27
27
  import {
28
28
  prepareProject
29
- } from "./chunk-t2h8pwy1.js";
30
- import"./chunk-gwy55cx3.js";
31
- import"./chunk-q1wwrxzw.js";
29
+ } from "./chunk-g0hpwbyx.js";
30
+ import"./chunk-ajw85dgf.js";
31
+ import"./chunk-b0vwhmdf.js";
32
32
 
33
33
  // src/cli/commands/sync.ts
34
34
  import { rm } from "node:fs/promises";
@@ -74,4 +74,4 @@ export {
74
74
  };
75
75
 
76
76
  //# debugId=67B7B6A961A6206764756E2164756E21
77
- //# sourceMappingURL=chunk-080mfch6.js.map
77
+ //# sourceMappingURL=chunk-et7zwqkg.js.map
@@ -30,10 +30,10 @@ import {
30
30
  SIGNATURES_DIRECTORY_PATH,
31
31
  buildSignaturesDirectory,
32
32
  deployPlatform
33
- } from "./chunk-r5nm9w0c.js";
33
+ } from "./chunk-5bp65pv4.js";
34
34
  import {
35
35
  SKILL_MD_PATH
36
- } from "./chunk-q1wwrxzw.js";
36
+ } from "./chunk-b0vwhmdf.js";
37
37
 
38
38
  // src/deploy/generated-files.ts
39
39
  import { join } from "pathe";
@@ -202,12 +202,29 @@ var canonicalElsewhere = (canonical, served) => {
202
202
  return normalizePath(path) !== normalizePath(served);
203
203
  };
204
204
  var URLS_PER_FILE = 50000;
205
- var renderUrlset = (urls) => `<?xml version="1.0" encoding="UTF-8"?>
206
- <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
205
+ var renderUrlset = (urls, alternatesEnabled) => `<?xml version="1.0" encoding="UTF-8"?>
206
+ <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"${alternatesEnabled ? ' xmlns:xhtml="http://www.w3.org/1999/xhtml"' : ""}>
207
207
  ${urls.join(`
208
208
  `)}
209
209
  </urlset>
210
210
  `;
211
+ var indexablePages = (project) => {
212
+ const deployBase = normalizeBasePath(project.config.deployment.options.base);
213
+ const noindexVersions = new Set((project.config.versions?.archived ?? []).flatMap((version) => version.noindex ? [version.id] : []));
214
+ return project.graph.pages.filter((page) => !page.meta.draft && !isHiddenPage(page, project.graph) && !page.meta.seo.noindex && !noindexVersions.has(page.version) && !ERROR_ROUTES.has(page.route) && !canonicalElsewhere(page.meta.seo.canonical, mountBasePath(deployBase, page.route)));
215
+ };
216
+ var listedPages = (project) => {
217
+ const latestVersions = new Set((project.config.versions?.archived ?? []).flatMap((version) => version.canonical === "latest" ? [version.id] : []));
218
+ const currentKeys = new Set(project.graph.pages.flatMap((page) => page.version === "" ? [`${page.versionKey}\x00${page.locale}`] : []));
219
+ return indexablePages(project).filter((page) => !(latestVersions.has(page.version) && !page.meta.seo.canonical && currentKeys.has(`${page.versionKey}\x00${page.locale}`)));
220
+ };
221
+ var hreflangAlternates = (project) => {
222
+ const indexable = new Set(indexablePages(project).map((page) => page.route));
223
+ return new Map(project.manifest.routes.map((route) => [
224
+ route.path,
225
+ route.fallback || indexable.has(route.path) ? route.alternates.filter((alternate) => indexable.has(alternate.path)) : []
226
+ ]));
227
+ };
211
228
  var buildSitemapFiles = (project) => {
212
229
  const { site } = project.config.deployment.options;
213
230
  if (!(site && project.config.seo.sitemap)) {
@@ -215,32 +232,29 @@ var buildSitemapFiles = (project) => {
215
232
  }
216
233
  const base = siteRoot(site);
217
234
  const deployBase = normalizeBasePath(project.config.deployment.options.base);
218
- const { versions } = project.config;
219
- const archivedById = new Map((versions?.archived ?? []).map((version) => [version.id, version]));
220
- const currentKeys = versions ? new Set(project.graph.pages.flatMap((page) => page.version === "" ? [`${page.versionKey}\x00${page.locale}`] : [])) : null;
221
- const archivedExcluded = (page) => {
222
- if (!page.version) {
223
- return false;
235
+ const alternatesEnabled = project.config.seo.sitemap !== true && project.config.seo.sitemap.alternates;
236
+ const hreflang = alternatesEnabled ? hreflangAlternates(project) : null;
237
+ const alternateTags = (route) => {
238
+ const alternates = hreflang?.get(route) ?? [];
239
+ if (alternates.length < 2) {
240
+ return "";
224
241
  }
225
- const archived = archivedById.get(page.version);
226
- return Boolean(archived?.noindex || archived?.canonical === "latest" && !page.meta.seo.canonical && currentKeys?.has(`${page.versionKey}\x00${page.locale}`));
242
+ const defaultPage = alternates.find((entry) => entry.locale === project.config.i18n?.defaultLocale);
243
+ const links = defaultPage ? [...alternates, { ...defaultPage, locale: "x-default" }] : alternates;
244
+ return links.map((entry) => `<xhtml:link rel="alternate" hreflang="${escapeXml(entry.locale)}" href="${escapeXml(encodeURI(`${base}${mountBasePath(deployBase, entry.path)}`))}"/>`).join("");
227
245
  };
228
246
  const seen = new Set;
229
247
  const urls = [];
230
- const pushUrl = (route, lastModified) => {
248
+ const pushUrl = (route, lastModified, alternates = "") => {
231
249
  const loc = escapeXml(encodeURI(`${base}${route}`));
232
250
  if (seen.has(loc)) {
233
251
  return;
234
252
  }
235
253
  seen.add(loc);
236
- urls.push(` <url><loc>${loc}</loc>${lastmodTag(lastModified)}</url>`);
254
+ urls.push(` <url><loc>${loc}</loc>${lastmodTag(lastModified)}${alternates}</url>`);
237
255
  };
238
- for (const page of project.graph.pages) {
239
- const served = mountBasePath(deployBase, page.route);
240
- if (page.meta.draft || isHiddenPage(page, project.graph) || page.meta.seo.noindex || ERROR_ROUTES.has(page.route) || archivedExcluded(page) || canonicalElsewhere(page.meta.seo.canonical, served)) {
241
- continue;
242
- }
243
- pushUrl(served, page.lastModified);
256
+ for (const page of listedPages(project)) {
257
+ pushUrl(mountBasePath(deployBase, page.route), page.lastModified, alternateTags(page.route));
244
258
  }
245
259
  const userPages = project.context.pagesRoot ? discoverPagesSync(project.context.pagesRoot) : [];
246
260
  const extraRoutes = customStaticRoutes(userPages).filter((route) => !ERROR_ROUTES.has(route));
@@ -252,7 +266,9 @@ var buildSitemapFiles = (project) => {
252
266
  }
253
267
  urls.sort();
254
268
  if (urls.length <= URLS_PER_FILE) {
255
- return [{ name: "sitemap.xml", xml: renderUrlset(urls) }];
269
+ return [
270
+ { name: "sitemap.xml", xml: renderUrlset(urls, alternatesEnabled) }
271
+ ];
256
272
  }
257
273
  const chunks = [];
258
274
  const references = [];
@@ -260,7 +276,7 @@ var buildSitemapFiles = (project) => {
260
276
  const name = `sitemap-${chunks.length + 1}.xml`;
261
277
  chunks.push({
262
278
  name,
263
- xml: renderUrlset(urls.slice(start, start + URLS_PER_FILE))
279
+ xml: renderUrlset(urls.slice(start, start + URLS_PER_FILE), alternatesEnabled)
264
280
  });
265
281
  const loc = escapeXml(encodeURI(`${base}${mountBasePath(deployBase, `/${name}`)}`));
266
282
  references.push(` <sitemap><loc>${loc}</loc></sitemap>`);
@@ -323,7 +339,7 @@ var generatedFilePaths = (project) => {
323
339
  };
324
340
  var servedFiles = (project) => staticFileResolver(join(project.context.root, "public"), generatedFilePaths(project));
325
341
 
326
- export { generatedFilePaths, servedFiles };
342
+ export { hreflangAlternates, generatedFilePaths, servedFiles };
327
343
 
328
- //# debugId=AFE0F5252B96AD6064756E2164756E21
329
- //# sourceMappingURL=chunk-487b95qy.js.map
344
+ //# debugId=3DB9B0C9F36E00AB64756E2164756E21
345
+ //# sourceMappingURL=chunk-f29q3j13.js.map
@@ -5,9 +5,9 @@
5
5
  "import { join } from \"pathe\";\n\nimport { buildAgentReadability } from \"../ai/agent-readability.ts\";\nimport {\n AI_CATALOG_PATH,\n ARD_MANIFEST_PATH,\n buildAiCatalog,\n} from \"../ai/ai-catalog.ts\";\nimport { API_CATALOG_PATH, buildApiCatalog } from \"../ai/api-catalog.ts\";\nimport {\n API_NAVIGATION_PATH,\n API_PAGES_PATH,\n OPENAPI_PATH,\n} from \"../ai/api/paths.ts\";\nimport { SKILL_MD_PATH } from \"../ai/site-skill.ts\";\nimport { AGENT_SKILLS_INDEX_PATH, servesSkillsIndex } from \"../ai/skills.ts\";\nimport type { SkillArtifact } from \"../ai/skills.ts\";\nimport {\n buildSignaturesDirectory,\n SIGNATURES_DIRECTORY_PATH,\n} from \"../ai/web-bot-auth.ts\";\nimport type { BlumeProject } from \"../core/project-graph.ts\";\nimport type { ResolvedConfig } from \"../core/schema.ts\";\nimport { staticFileResolver } from \"../core/static-files.ts\";\nimport { buildRobots } from \"./robots.ts\";\nimport { buildRssFeeds } from \"./rss.ts\";\nimport { buildSitemapFiles } from \"./sitemap.ts\";\n\n/** A generated `.well-known` discovery document: `null` content when it's off. */\nexport interface WellKnownFile {\n content: string | null;\n label: string;\n path: string;\n}\n\n/**\n * The generated `.well-known` discovery documents — the Web Bot Auth signature\n * directory, the RFC 9727 API catalog, and the AI catalog under both the\n * ai-catalog spec's well-known URI and the ARD v0.91 one (see\n * `ai/ai-catalog.ts`) — each with `null` content when its feature is off.\n */\nexport const wellKnownFiles = (\n config: ResolvedConfig,\n skills: readonly SkillArtifact[]\n): WellKnownFile[] => {\n const aiCatalog = buildAiCatalog(config, skills);\n return [\n {\n content: buildSignaturesDirectory(config),\n label: \"Web Bot Auth\",\n path: SIGNATURES_DIRECTORY_PATH,\n },\n {\n content: buildApiCatalog(config),\n label: \"RFC 9727\",\n path: API_CATALOG_PATH,\n },\n { content: aiCatalog, label: \"AI Catalog\", path: AI_CATALOG_PATH },\n { content: aiCatalog, label: \"ARD manifest\", path: ARD_MANIFEST_PATH },\n ];\n};\n\n/**\n * The files a build serves beside its pages that don't come from `public/`,\n * as base-less root-relative paths: what `publishBuildArtifacts` writes once\n * Astro is done (llms.txt, the sitemap, robots.txt, `agent-readability.json`,\n * the `.well-known` discovery documents, the Agent Skills index, `skill.md`)\n * and the generated endpoints at fixed paths (the RSS feeds, the JSON docs\n * API and its OpenAPI description, the MCP discovery documents). Each is\n * listed under the gate its writer reads, so a feature the config switches\n * off drops its file here too: `blume validate` accepts a link to\n * `/llms.txt` exactly when the build writes one.\n *\n * Read from the config alone, before a build: the skill archives a build\n * publishes beside the index, and the platform files (`_redirects`,\n * `_headers`, `vercel.json`), aren't listed. A page's Markdown copy\n * (`/guide.md`) is its route's, and resolves through the page.\n */\nexport const generatedFilePaths = (project: BlumeProject): string[] => {\n const { config } = project;\n const paths: string[] = [];\n if (config.agents.llmsTxt.enabled) {\n paths.push(\"/llms.txt\", \"/llms-full.txt\");\n }\n paths.push(\n ...(buildSitemapFiles(project) ?? []).map((file) => `/${file.name}`)\n );\n if (buildRobots(project)) {\n paths.push(\"/robots.txt\");\n }\n if (buildAgentReadability(project)) {\n paths.push(\"/agent-readability.json\");\n }\n paths.push(\n ...wellKnownFiles(config, []).flatMap((file) =>\n file.content ? [file.path] : []\n )\n );\n if (servesSkillsIndex(config)) {\n paths.push(AGENT_SKILLS_INDEX_PATH);\n if (config.agents.skillMd) {\n paths.push(SKILL_MD_PATH);\n }\n }\n paths.push(...buildRssFeeds(project).map((feed) => feed.path));\n if (config.agents.api) {\n paths.push(OPENAPI_PATH, API_PAGES_PATH, API_NAVIGATION_PATH);\n }\n if (config.agents.mcp.enabled) {\n paths.push(\"/.well-known/mcp.json\", \"/.well-known/mcp/server-card.json\");\n }\n return paths;\n};\n\n/**\n * Whether a base-less path is a file the project's site serves beside its\n * pages: one in `public/` (`/spec.pdf`, a folder's `index.html`) or one the\n * build generates (`/llms.txt`). What `generateRuntime` and `blume doctor`\n * check navigation entries against, beside the routes, as `blume validate`\n * checks links.\n */\nexport const servedFiles = (\n project: BlumeProject\n): ((path: string) => boolean) =>\n staticFileResolver(\n join(project.context.root, \"public\"),\n generatedFilePaths(project)\n );\n",
6
6
  "import { mountBasePath, normalizeBasePath } from \"../core/base-path.ts\";\nimport { repoUrl } from \"../core/github.ts\";\nimport type { BlumeProject } from \"../core/project-graph.ts\";\nimport type { ContentSignalPolicy, ContentSignals } from \"../core/schema.ts\";\nimport { absoluteUrl } from \"../core/site-url.ts\";\nimport { deployPlatform } from \"../deploy/platforms/index.ts\";\nimport { buildRssFeeds } from \"../deploy/rss.ts\";\nimport { AI_CATALOG_PATH, hasAiCatalog } from \"./ai-catalog.ts\";\nimport { hasApiCatalog } from \"./api-catalog.ts\";\nimport { API_PAGES_PATH, API_SEARCH_PATH, OPENAPI_PATH } from \"./api/paths.ts\";\nimport { servesSkillsIndex } from \"./skills.ts\";\n\n/** Token map for the machine-readable content-usage echo. */\nconst USAGE_TOKENS: [keyof ContentSignalPolicy, string][] = [\n [\"search\", \"search\"],\n [\"aiInput\", \"ai-input\"],\n [\"aiTrain\", \"ai-train\"],\n];\n\n/**\n * The configured usage preferences as a `{ token: allowed }` object, or null\n * when the declaration is disabled (`contentSignals: false`). Mirrors the\n * robots.txt `Content-Signal` line so an agent that reads the manifest instead\n * of robots.txt sees the same policy.\n */\nconst usagePolicy = (\n signals: ContentSignals\n): Record<string, boolean> | null => {\n if (!signals) {\n return null;\n }\n return Object.fromEntries(\n USAGE_TOKENS.map(([key, token]) => [token, signals[key]] as const)\n );\n};\n\n/**\n * The advertised assistant URL. An external endpoint is not served under\n * `deployment.base`, so a root-relative one absolutizes against the site\n * origin alone; the built-in route gets site and base via `abs`.\n */\nconst askApiUrl = (\n endpoint: string | undefined,\n site: string | null,\n abs: (path: string) => string\n): string => {\n if (!endpoint) {\n return abs(\"/api/ask\");\n }\n return site && endpoint.startsWith(\"/\")\n ? absoluteUrl(site, endpoint)\n : endpoint;\n};\n\n/** The `.well-known` discovery URLs a site can publish. */\ninterface WellKnownArtifacts {\n httpMessageSignaturesDirectory?: string;\n aiCatalog?: string;\n apiCatalog?: string;\n agentSkills?: string;\n}\n\n/** The JSON docs API's entry points; `search` exists on server output only. */\ninterface ApiArtifact {\n openapi: string;\n pages: string;\n search?: string;\n}\n\n/** The agent-facing artifact index the manifest publishes. */\ninterface AgentArtifacts extends WellKnownArtifacts {\n markdown: { contentNegotiation?: string; pattern: string };\n api?: ApiArtifact;\n llmsFullTxt?: string;\n llmsTxt?: string;\n mcp?: { discovery: string; url: string };\n askApi?: string;\n sitemap?: string;\n feeds?: string[];\n}\n\n/** The published `agent-readability.json` document. */\nexport interface AgentReadabilityManifest {\n artifacts: AgentArtifacts;\n description?: string;\n generator?: string;\n name: string;\n site: string | null;\n contentUsage?: Record<string, boolean>;\n repository?: string;\n}\n\n/**\n * The raw-Markdown mirror pattern. `Accept: text/markdown` negotiation is\n * advertised only where the deployed site actually honors it — a server build\n * on a platform that declares `negotiatesMarkdown` (Vercel, whose routing\n * config gets the rewrite rules; Cloudflare, whose deploy bundle gets a\n * wrapper Worker — see `deploy/platforms/*`). Static builds and other\n * adapters serve prerendered pages from a static layer with no request-time\n * hook, so agents there should fetch the `.md` pattern directly.\n */\nconst markdownArtifact = (\n config: BlumeProject[\"config\"],\n abs: (path: string) => string\n): AgentArtifacts[\"markdown\"] => {\n const negotiates =\n config.deployment.options.output === \"server\" &&\n deployPlatform(config.deployment).negotiatesMarkdown;\n return negotiates\n ? { contentNegotiation: \"text/markdown\", pattern: abs(\"/{route}.md\") }\n : { pattern: abs(\"/{route}.md\") };\n};\n\n/** The JSON docs API's entry points, or null when the API is off. */\nconst apiArtifact = (\n config: BlumeProject[\"config\"],\n abs: (path: string) => string\n): ApiArtifact | null => {\n if (!config.agents.api) {\n return null;\n }\n const api: ApiArtifact = {\n openapi: abs(OPENAPI_PATH),\n pages: abs(API_PAGES_PATH),\n };\n if (config.deployment.options.output === \"server\") {\n api.search = abs(API_SEARCH_PATH);\n }\n return api;\n};\n\n/** The `.well-known` discovery artifacts the site publishes, if any. */\nconst wellKnownArtifacts = (\n config: BlumeProject[\"config\"],\n abs: (path: string) => string\n): WellKnownArtifacts => {\n const artifacts: WellKnownArtifacts = {};\n if (config.agents.webBotAuth.keys.length > 0) {\n artifacts.httpMessageSignaturesDirectory = abs(\n \"/.well-known/http-message-signatures-directory\"\n );\n }\n if (hasAiCatalog(config)) {\n artifacts.aiCatalog = abs(AI_CATALOG_PATH);\n }\n if (hasApiCatalog(config)) {\n artifacts.apiCatalog = abs(\"/.well-known/api-catalog\");\n }\n if (servesSkillsIndex(config)) {\n artifacts.agentSkills = abs(\"/.well-known/agent-skills/index.json\");\n }\n return artifacts;\n};\n\n/**\n * Build `agent-readability.json`: a root manifest that indexes the project's\n * agent-facing surface — llms.txt, the raw-Markdown mirrors, the JSON docs\n * API and its OpenAPI description, the MCP server, the assistant, sitemap, and feeds\n * — so agents can discover and cite the docs without\n * scraping HTML. URLs are absolute when a `site` is configured and root-relative\n * (still under `deployment.base`) otherwise. Returns null when the manifest is\n * disabled.\n */\nexport const buildAgentReadability = (\n project: BlumeProject\n): AgentReadabilityManifest | null => {\n const { config } = project;\n if (!config.agents.agentReadability) {\n return null;\n }\n\n const site = config.deployment.options.site ?? null;\n // Every artifact is served under `deployment.base` — with or without a\n // `site`; concatenate rather than `new URL()` so the subpath is preserved.\n const deployBase = normalizeBasePath(config.deployment.options.base);\n const abs = (path: string): string => {\n const based = mountBasePath(deployBase, path);\n return site ? absoluteUrl(site, based) : based;\n };\n\n const artifacts: AgentArtifacts = {\n markdown: markdownArtifact(config, abs),\n };\n const api = apiArtifact(config, abs);\n if (api) {\n artifacts.api = api;\n }\n if (config.agents.llmsTxt.enabled) {\n artifacts.llmsFullTxt = abs(\"/llms-full.txt\");\n artifacts.llmsTxt = abs(\"/llms.txt\");\n }\n if (config.agents.mcp.enabled) {\n artifacts.mcp = {\n discovery: abs(\"/.well-known/mcp.json\"),\n url: abs(config.agents.mcp.route),\n };\n }\n if (config.ai.assistant?.enabled) {\n artifacts.askApi = askApiUrl(config.ai.assistant.endpoint, site, abs);\n }\n Object.assign(artifacts, wellKnownArtifacts(config, abs));\n if (site && config.seo.sitemap) {\n artifacts.sitemap = abs(\"/sitemap.xml\");\n }\n const feeds =\n site && config.seo.rss.enabled\n ? buildRssFeeds(project).map((feed) => abs(feed.path))\n : [];\n if (feeds.length > 0) {\n artifacts.feeds = feeds;\n }\n\n const version = project.manifest?.blumeVersion;\n const manifest: AgentReadabilityManifest = {\n artifacts,\n description: config.description,\n generator: version ? `blume@${version}` : undefined,\n name: config.agents.mcp.name ?? config.title,\n site,\n };\n\n const usage = usagePolicy(config.agents.contentSignals);\n if (usage) {\n manifest.contentUsage = usage;\n }\n if (config.github) {\n manifest.repository = repoUrl(config.github);\n }\n\n return manifest;\n};\n",
7
7
  "import { mountBasePath, normalizeBasePath } from \"../core/base-path.ts\";\nimport type { BlumeProject } from \"../core/project-graph.ts\";\nimport type { ContentSignalPolicy, ContentSignals } from \"../core/schema.ts\";\nimport { absoluteUrl } from \"../core/site-url.ts\";\n\n/**\n * Ordered mapping from config field to its `Content-Signal` token. The order\n * fixes the emitted sequence (`search`, then `ai-input`, then `ai-train`).\n */\nconst SIGNAL_TOKENS: [keyof ContentSignalPolicy, string][] = [\n [\"search\", \"search\"],\n [\"aiInput\", \"ai-input\"],\n [\"aiTrain\", \"ai-train\"],\n];\n\n/**\n * The `Content-Signal:` line declaring how crawlers may reuse the site, or null\n * when the declaration is disabled (`contentSignals: false`). Otherwise every\n * signal is emitted with its resolved yes/no value.\n */\nconst contentSignalLine = (signals: ContentSignals): string | null => {\n if (!signals) {\n return null;\n }\n const tokens = SIGNAL_TOKENS.map(\n ([key, token]) => `${token}=${signals[key] ? \"yes\" : \"no\"}`\n );\n return `Content-Signal: ${tokens.join(\", \")}`;\n};\n\n/**\n * Build a robots.txt that allows all crawlers, declares any configured\n * `Content-Signal` usage preferences, and points to the sitemap when one is\n * available (a `site` is set and the sitemap is enabled). Returns null when\n * robots generation is disabled.\n */\nexport const buildRobots = (project: BlumeProject): string | null => {\n const { config } = project;\n if (!config.seo.robots) {\n return null;\n }\n\n const lines = [\"User-agent: *\"];\n const signal = contentSignalLine(config.agents.contentSignals);\n if (signal) {\n lines.push(signal);\n }\n lines.push(\"Allow: /\");\n\n const { site } = config.deployment.options;\n if (site && config.seo.sitemap) {\n const sitemapPath = mountBasePath(\n normalizeBasePath(config.deployment.options.base),\n \"/sitemap.xml\"\n );\n lines.push(\"\", `Sitemap: ${absoluteUrl(site, sitemapPath)}`);\n }\n return `${lines.join(\"\\n\")}\\n`;\n};\n",
8
- "// html-escaper's five-entity table is XML-safe (`'` → the numeric `&#39;`).\nimport { escape as escapeXml } from \"html-escaper\";\n\nimport {\n customStaticRoutes,\n discoverPagesSync,\n hasGeneratedChangelog,\n} from \"../astro/pages.ts\";\nimport {\n mountBasePath,\n normalizeBasePath,\n normalizePath,\n} from \"../core/base-path.ts\";\nimport { isHiddenPage } from \"../core/hidden-pages.ts\";\nimport type { BlumeProject } from \"../core/project-graph.ts\";\nimport { siteRoot } from \"../core/site-url.ts\";\n\n/**\n * Astro's reserved error routes. A user-authored override (`pages/404.astro`,\n * `pages/500.astro`, or a `404.md` content page — see `writeNotFoundPage` in\n * `astro/generate.ts`) is neither dynamic nor private, so it would otherwise\n * be emitted — but error pages aren't crawlable destinations and must stay out\n * of the sitemap.\n */\nconst ERROR_ROUTES = new Set([\"/404\", \"/500\"]);\n\n/** A `<lastmod>` element (W3C date) when the page has a valid modified date. */\nconst lastmodTag = (value: string | undefined): string => {\n if (!value) {\n return \"\";\n }\n const date = new Date(value);\n return Number.isNaN(date.getTime())\n ? \"\"\n : `<lastmod>${date.toISOString().slice(0, 10)}</lastmod>`;\n};\n\n/**\n * Whether a page's own `seo.canonical` names another URL. The sitemap lists\n * canonical URLs only, so such a page stays out — `blume audit` reports a\n * listed one as NON_CANONICAL_IN_SITEMAP and expects it unlisted. Compared by\n * decoded path, as the audit does: `served` is the page's path with the\n * deployment base mounted, which the canonical carries too.\n */\nconst canonicalElsewhere = (\n canonical: string | undefined,\n served: string\n): boolean => {\n if (!canonical) {\n return false;\n }\n const { pathname } = new URL(canonical);\n let path = pathname;\n try {\n path = decodeURI(pathname);\n } catch {\n // A malformed escape stays as written; it can't match the served path.\n }\n return normalizePath(path) !== normalizePath(served);\n};\n\n/** One emitted sitemap artifact: its dist-root filename and XML body. */\nexport interface SitemapFile {\n name: string;\n xml: string;\n}\n\n/** The build log line for an emitted sitemap set: one file, or an index. */\nexport const describeSitemapFiles = (files: readonly SitemapFile[]): string =>\n files.length === 1\n ? \"Generated sitemap.xml\"\n : `Generated sitemap.xml (index of ${files.length - 1} sitemap files)`;\n\n/**\n * The sitemaps.org cap on `<url>` entries in a single file. Beyond it,\n * `sitemap.xml` becomes a sitemap index pointing at numbered chunk files —\n * search engines reject an oversized urlset outright.\n */\nconst URLS_PER_FILE = 50_000;\n\nconst renderUrlset = (\n urls: string[]\n): string => `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\n${urls.join(\"\\n\")}\n</urlset>\n`;\n\n/**\n * Build the sitemap files from the route manifest plus the routes the manifest\n * can't see: custom `.astro` pages (most importantly a custom landing `/`) and\n * the generated `/changelog` index. Returns null when the sitemap is disabled\n * or no `site` is configured (absolute URLs are required for a valid sitemap).\n * Drafts, hidden, and `noindex` pages are excluded, and so is a page whose\n * `seo.canonical` points elsewhere.\n *\n * Sites within the per-file URL cap get the single classic `sitemap.xml`;\n * larger sites get `sitemap.xml` as a sitemap index over numbered\n * `sitemap-N.xml` chunks, all served from the same directory robots.txt\n * already points at.\n */\nexport const buildSitemapFiles = (\n project: BlumeProject\n): SitemapFile[] | null => {\n const { site } = project.config.deployment.options;\n if (!(site && project.config.seo.sitemap)) {\n return null;\n }\n\n const base = siteRoot(site);\n // Routes carry `basePath`; a `deployment.base` subdirectory is mounted on\n // top of every one, even a route whose first segment matches it: under base\n // `/guides`, `guides/setup.md` is served at `/guides/guides/setup`.\n const deployBase = normalizeBasePath(project.config.deployment.options.base);\n\n // Archived-version pages leave the sitemap when the version is noindexed,\n // or when their canonical points at a still-existing latest equivalent —\n // listing a URL whose canonical says \"index the other page\" invites the\n // noindexed-page-in-sitemap incoherence Docusaurus is known for. A page\n // that exists only in an archived version stays listed (self-canonical),\n // and a page's own `seo.canonical` wins over the version's default, as it\n // does in the page head (see `canonicalElsewhere`).\n const { versions } = project.config;\n const archivedById = new Map(\n (versions?.archived ?? []).map((version) => [version.id, version])\n );\n const currentKeys = versions\n ? new Set(\n project.graph.pages.flatMap((page) =>\n page.version === \"\" ? [`${page.versionKey}\\u0000${page.locale}`] : []\n )\n )\n : null;\n const archivedExcluded = (page: (typeof project.graph.pages)[number]) => {\n if (!page.version) {\n return false;\n }\n // A non-empty version always names a configured archived entry — that is\n // the only way detection assigns one.\n const archived = archivedById.get(page.version);\n return Boolean(\n archived?.noindex ||\n (archived?.canonical === \"latest\" &&\n !page.meta.seo.canonical &&\n currentKeys?.has(`${page.versionKey}\\u0000${page.locale}`))\n );\n };\n\n const seen = new Set<string>();\n const urls: string[] = [];\n const pushUrl = (route: string, lastModified?: string): void => {\n // `<loc>` must be a well-formed, XML-escaped URL: percent-encode the path,\n // then escape XML metacharacters (notably `&`) so a route like\n // `/Tips & Tricks` doesn't produce invalid XML that gets the whole sitemap\n // rejected.\n const loc = escapeXml(encodeURI(`${base}${route}`));\n if (seen.has(loc)) {\n return;\n }\n seen.add(loc);\n urls.push(` <url><loc>${loc}</loc>${lastmodTag(lastModified)}</url>`);\n };\n for (const page of project.graph.pages) {\n const served = mountBasePath(deployBase, page.route);\n if (\n page.meta.draft ||\n isHiddenPage(page, project.graph) ||\n page.meta.seo.noindex ||\n ERROR_ROUTES.has(page.route) ||\n archivedExcluded(page) ||\n canonicalElsewhere(page.meta.seo.canonical, served)\n ) {\n continue;\n }\n pushUrl(served, page.lastModified);\n }\n // Custom `.astro` pages and the generated changelog index mount outside\n // `basePath` (they're injected at their pattern — see `blumeIntegration`), so\n // only the deployment base layers onto their URLs.\n const userPages = project.context.pagesRoot\n ? discoverPagesSync(project.context.pagesRoot)\n : [];\n const extraRoutes = customStaticRoutes(userPages).filter(\n (route) => !ERROR_ROUTES.has(route)\n );\n if (hasGeneratedChangelog(project, userPages)) {\n extraRoutes.push(\"/changelog\");\n }\n for (const route of extraRoutes) {\n pushUrl(mountBasePath(deployBase, route));\n }\n urls.sort();\n\n if (urls.length <= URLS_PER_FILE) {\n return [{ name: \"sitemap.xml\", xml: renderUrlset(urls) }];\n }\n\n const chunks: SitemapFile[] = [];\n const references: string[] = [];\n for (let start = 0; start < urls.length; start += URLS_PER_FILE) {\n const name = `sitemap-${chunks.length + 1}.xml`;\n chunks.push({\n name,\n xml: renderUrlset(urls.slice(start, start + URLS_PER_FILE)),\n });\n // Chunks sit next to sitemap.xml, so their URLs layer the same deployment\n // base robots.txt uses for the index.\n const loc = escapeXml(\n encodeURI(`${base}${mountBasePath(deployBase, `/${name}`)}`)\n );\n references.push(` <sitemap><loc>${loc}</loc></sitemap>`);\n }\n const index = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<sitemapindex xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\n${references.join(\"\\n\")}\n</sitemapindex>\n`;\n return [{ name: \"sitemap.xml\", xml: index }, ...chunks];\n};\n"
8
+ "// html-escaper's five-entity table is XML-safe (`'` → the numeric `&#39;`).\nimport { escape as escapeXml } from \"html-escaper\";\n\nimport {\n customStaticRoutes,\n discoverPagesSync,\n hasGeneratedChangelog,\n} from \"../astro/pages.ts\";\nimport {\n mountBasePath,\n normalizeBasePath,\n normalizePath,\n} from \"../core/base-path.ts\";\nimport { isHiddenPage } from \"../core/hidden-pages.ts\";\nimport type { BlumeProject } from \"../core/project-graph.ts\";\nimport { siteRoot } from \"../core/site-url.ts\";\nimport type { RouteAlternate } from \"../core/types.ts\";\n\n/**\n * Astro's reserved error routes. A user-authored override (`pages/404.astro`,\n * `pages/500.astro`, or a `404.md` content page — see `writeNotFoundPage` in\n * `astro/generate.ts`) is neither dynamic nor private, so it would otherwise\n * be emitted — but error pages aren't crawlable destinations and must stay out\n * of the sitemap.\n */\nconst ERROR_ROUTES = new Set([\"/404\", \"/500\"]);\n\n/** A `<lastmod>` element (W3C date) when the page has a valid modified date. */\nconst lastmodTag = (value: string | undefined): string => {\n if (!value) {\n return \"\";\n }\n const date = new Date(value);\n return Number.isNaN(date.getTime())\n ? \"\"\n : `<lastmod>${date.toISOString().slice(0, 10)}</lastmod>`;\n};\n\n/**\n * Whether a page's own `seo.canonical` names another URL. The sitemap lists\n * canonical URLs only, so such a page stays out — `blume audit` reports a\n * listed one as NON_CANONICAL_IN_SITEMAP and expects it unlisted. Compared by\n * decoded path, as the audit does: `served` is the page's path with the\n * deployment base mounted, which the canonical carries too.\n */\nconst canonicalElsewhere = (\n canonical: string | undefined,\n served: string\n): boolean => {\n if (!canonical) {\n return false;\n }\n const { pathname } = new URL(canonical);\n let path = pathname;\n try {\n path = decodeURI(pathname);\n } catch {\n // A malformed escape stays as written; it can't match the served path.\n }\n return normalizePath(path) !== normalizePath(served);\n};\n\n/** One emitted sitemap artifact: its dist-root filename and XML body. */\nexport interface SitemapFile {\n name: string;\n xml: string;\n}\n\n/** The build log line for an emitted sitemap set: one file, or an index. */\nexport const describeSitemapFiles = (files: readonly SitemapFile[]): string =>\n files.length === 1\n ? \"Generated sitemap.xml\"\n : `Generated sitemap.xml (index of ${files.length - 1} sitemap files)`;\n\n/**\n * The sitemaps.org cap on `<url>` entries in a single file. Beyond it,\n * `sitemap.xml` becomes a sitemap index pointing at numbered chunk files —\n * search engines reject an oversized urlset outright.\n */\nconst URLS_PER_FILE = 50_000;\n\nconst renderUrlset = (\n urls: string[],\n alternatesEnabled: boolean\n): string => `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\"${alternatesEnabled ? ' xmlns:xhtml=\"http://www.w3.org/1999/xhtml\"' : \"\"}>\n${urls.join(\"\\n\")}\n</urlset>\n`;\n\n/**\n * The content pages crawlers may index under their own URL: drafts, hidden,\n * `noindex` (the page's or its archived version's), and error pages can't, nor\n * can a page whose own `seo.canonical` names another URL.\n */\nconst indexablePages = (\n project: BlumeProject\n): BlumeProject[\"graph\"][\"pages\"] => {\n const deployBase = normalizeBasePath(project.config.deployment.options.base);\n // A non-empty version always names a configured archived entry — that is\n // the only way detection assigns one.\n const noindexVersions = new Set(\n (project.config.versions?.archived ?? []).flatMap((version) =>\n version.noindex ? [version.id] : []\n )\n );\n return project.graph.pages.filter(\n (page) =>\n !page.meta.draft &&\n !isHiddenPage(page, project.graph) &&\n !page.meta.seo.noindex &&\n !noindexVersions.has(page.version) &&\n !ERROR_ROUTES.has(page.route) &&\n !canonicalElsewhere(\n page.meta.seo.canonical,\n mountBasePath(deployBase, page.route)\n )\n );\n};\n\n/**\n * The content pages the sitemap lists: the indexable ones, less archived-version\n * pages whose canonical points at a still-existing latest equivalent —\n * listing a URL whose canonical says \"index the other page\" invites the\n * noindexed-page-in-sitemap incoherence Docusaurus is known for. A page that\n * exists only in an archived version stays listed (self-canonical), and a\n * page's own `seo.canonical` wins over the version's default, as it does in\n * the page head (see `canonicalElsewhere`).\n */\nconst listedPages = (project: BlumeProject): BlumeProject[\"graph\"][\"pages\"] => {\n const latestVersions = new Set(\n (project.config.versions?.archived ?? []).flatMap((version) =>\n version.canonical === \"latest\" ? [version.id] : []\n )\n );\n const currentKeys = new Set(\n project.graph.pages.flatMap((page) =>\n page.version === \"\" ? [`${page.versionKey}\\u0000${page.locale}`] : []\n )\n );\n return indexablePages(project).filter(\n (page) =>\n !(\n latestVersions.has(page.version) &&\n !page.meta.seo.canonical &&\n currentKeys.has(`${page.versionKey}\\u0000${page.locale}`)\n )\n );\n};\n\n/**\n * Each route's hreflang set, keyed by route: its indexable translations. The\n * page head links it, and so does the sitemap under `seo.sitemap.alternates`,\n * so the two never disagree, and neither points crawlers at a page they're\n * told not to index. A page that can't be indexed joins no set — except an\n * i18n fallback copy, which links the translations it stands in for.\n */\nexport const hreflangAlternates = (\n project: BlumeProject\n): Map<string, RouteAlternate[]> => {\n const indexable = new Set(indexablePages(project).map((page) => page.route));\n return new Map(\n project.manifest.routes.map((route) => [\n route.path,\n route.fallback || indexable.has(route.path)\n ? route.alternates.filter((alternate) => indexable.has(alternate.path))\n : [],\n ])\n );\n};\n\n/**\n * Build the sitemap files from the route manifest plus the routes the manifest\n * can't see: custom `.astro` pages (most importantly a custom landing `/`) and\n * the generated `/changelog` index. Returns null when the sitemap is disabled\n * or no `site` is configured (absolute URLs are required for a valid sitemap).\n * Drafts, hidden, and `noindex` pages are excluded, and so is a page whose\n * `seo.canonical` points elsewhere.\n *\n * Sites within the per-file URL cap get the single classic `sitemap.xml`;\n * larger sites get `sitemap.xml` as a sitemap index over numbered\n * `sitemap-N.xml` chunks, all served from the same directory robots.txt\n * already points at.\n */\nexport const buildSitemapFiles = (\n project: BlumeProject\n): SitemapFile[] | null => {\n const { site } = project.config.deployment.options;\n if (!(site && project.config.seo.sitemap)) {\n return null;\n }\n\n const base = siteRoot(site);\n // Routes carry `basePath`; a `deployment.base` subdirectory is mounted on\n // top of every one, even a route whose first segment matches it: under base\n // `/guides`, `guides/setup.md` is served at `/guides/guides/setup`.\n const deployBase = normalizeBasePath(project.config.deployment.options.base);\n const alternatesEnabled =\n project.config.seo.sitemap !== true &&\n project.config.seo.sitemap.alternates;\n const hreflang = alternatesEnabled ? hreflangAlternates(project) : null;\n // A page's translations as `xhtml:link`s, plus `x-default` at the default\n // locale's — the same set the page head links, for pages in 2+ locales.\n const alternateTags = (route: string): string => {\n const alternates = hreflang?.get(route) ?? [];\n if (alternates.length < 2) {\n return \"\";\n }\n const defaultPage = alternates.find(\n (entry) => entry.locale === project.config.i18n?.defaultLocale\n );\n const links = defaultPage\n ? [...alternates, { ...defaultPage, locale: \"x-default\" }]\n : alternates;\n return links\n .map(\n (entry) =>\n `<xhtml:link rel=\"alternate\" hreflang=\"${escapeXml(entry.locale)}\" href=\"${escapeXml(encodeURI(`${base}${mountBasePath(deployBase, entry.path)}`))}\"/>`\n )\n .join(\"\");\n };\n\n const seen = new Set<string>();\n const urls: string[] = [];\n const pushUrl = (\n route: string,\n lastModified?: string,\n alternates = \"\"\n ): void => {\n // `<loc>` must be a well-formed, XML-escaped URL: percent-encode the path,\n // then escape XML metacharacters (notably `&`) so a route like\n // `/Tips & Tricks` doesn't produce invalid XML that gets the whole sitemap\n // rejected.\n const loc = escapeXml(encodeURI(`${base}${route}`));\n if (seen.has(loc)) {\n return;\n }\n seen.add(loc);\n urls.push(\n ` <url><loc>${loc}</loc>${lastmodTag(lastModified)}${alternates}</url>`\n );\n };\n for (const page of listedPages(project)) {\n pushUrl(\n mountBasePath(deployBase, page.route),\n page.lastModified,\n alternateTags(page.route)\n );\n }\n // Custom `.astro` pages and the generated changelog index mount outside\n // `basePath` (they're injected at their pattern — see `blumeIntegration`), so\n // only the deployment base layers onto their URLs.\n const userPages = project.context.pagesRoot\n ? discoverPagesSync(project.context.pagesRoot)\n : [];\n const extraRoutes = customStaticRoutes(userPages).filter(\n (route) => !ERROR_ROUTES.has(route)\n );\n if (hasGeneratedChangelog(project, userPages)) {\n extraRoutes.push(\"/changelog\");\n }\n for (const route of extraRoutes) {\n pushUrl(mountBasePath(deployBase, route));\n }\n urls.sort();\n\n if (urls.length <= URLS_PER_FILE) {\n return [\n { name: \"sitemap.xml\", xml: renderUrlset(urls, alternatesEnabled) },\n ];\n }\n\n const chunks: SitemapFile[] = [];\n const references: string[] = [];\n for (let start = 0; start < urls.length; start += URLS_PER_FILE) {\n const name = `sitemap-${chunks.length + 1}.xml`;\n chunks.push({\n name,\n xml: renderUrlset(\n urls.slice(start, start + URLS_PER_FILE),\n alternatesEnabled\n ),\n });\n // Chunks sit next to sitemap.xml, so their URLs layer the same deployment\n // base robots.txt uses for the index.\n const loc = escapeXml(\n encodeURI(`${base}${mountBasePath(deployBase, `/${name}`)}`)\n );\n references.push(` <sitemap><loc>${loc}</loc></sitemap>`);\n }\n const index = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<sitemapindex xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\n${references.join(\"\\n\")}\n</sitemapindex>\n`;\n return [{ name: \"sitemap.xml\", xml: index }, ...chunks];\n};\n"
9
9
  ],
10
- "mappings": "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",
11
- "debugId": "AFE0F5252B96AD6064756E2164756E21",
10
+ "mappings": "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",
11
+ "debugId": "3DB9B0C9F36E00AB64756E2164756E21",
12
12
  "names": []
13
13
  }
@@ -7,7 +7,7 @@ import {
7
7
  packageSrc,
8
8
  registry,
9
9
  findItem
10
- } from "./chunk-9h8mh2tk.js";
10
+ } from "./chunk-x2pgg22t.js";
11
11
 
12
12
  // src/cli/commands/add.ts
13
13
  import { existsSync } from "node:fs";
@@ -96,4 +96,4 @@ export {
96
96
  };
97
97
 
98
98
  //# debugId=B640E77C94BA0A0364756E2164756E21
99
- //# sourceMappingURL=chunk-c5bjxq8v.js.map
99
+ //# sourceMappingURL=chunk-f72388jn.js.map
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  packageDirFrom,
4
4
  generateRuntime
5
- } from "./chunk-hktq4j5r.js";
5
+ } from "./chunk-9k7gg4ga.js";
6
6
  import {
7
7
  loadEnvFiles,
8
8
  reportInternalError,
@@ -13,11 +13,11 @@ import {
13
13
  } from "./index.js";
14
14
  import {
15
15
  scanProject
16
- } from "./chunk-zxd5jrgx.js";
16
+ } from "./chunk-vxdjss7f.js";
17
17
  import {
18
18
  serverFeatures,
19
19
  checkRequiredSecrets
20
- } from "./chunk-gwy55cx3.js";
20
+ } from "./chunk-ajw85dgf.js";
21
21
 
22
22
  // src/cli/yarn-pnp.ts
23
23
  import { existsSync } from "node:fs";
@@ -121,4 +121,4 @@ var prepareProject = async (options) => {
121
121
  export { prepareProject };
122
122
 
123
123
  //# debugId=0B8AEED1A551B5FA64756E2164756E21
124
- //# sourceMappingURL=chunk-t2h8pwy1.js.map
124
+ //# sourceMappingURL=chunk-g0hpwbyx.js.map