@kirchdev/duxt 0.3.4 → 0.3.5-dev-main.43-3310f4b

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 (219) hide show
  1. package/README.md +24 -9
  2. package/app/app.vue +17 -11
  3. package/app/assets/css/duxt.css +47 -6
  4. package/app/components/DuxtAnnouncements.vue +117 -0
  5. package/app/components/DuxtBrunoEntries.vue +62 -0
  6. package/app/components/DuxtCodeBlock.vue +18 -34
  7. package/app/components/DuxtCodeToolbar.vue +14 -0
  8. package/app/components/DuxtCopyButton.vue +33 -0
  9. package/app/components/DuxtCopyPage.vue +32 -30
  10. package/app/components/DuxtFooter.vue +39 -8
  11. package/app/components/DuxtHeader.vue +107 -48
  12. package/app/components/DuxtLandingProse.vue +1 -1
  13. package/app/components/DuxtLinkLabel.vue +36 -0
  14. package/app/components/DuxtLiveWindow.vue +8 -8
  15. package/app/components/DuxtLocale.vue +10 -1
  16. package/app/components/DuxtNavigation.vue +2 -2
  17. package/app/components/DuxtOpenApiClient.vue +285 -90
  18. package/app/components/DuxtOpenApiMedia.vue +30 -18
  19. package/app/components/DuxtOpenApiSchema.vue +10 -7
  20. package/app/components/DuxtPageFeedback.vue +7 -0
  21. package/app/components/DuxtPageInfo.vue +15 -12
  22. package/app/components/DuxtPageNav.vue +41 -27
  23. package/app/components/DuxtPreviewSkeleton.vue +4 -4
  24. package/app/components/DuxtProgress.vue +2 -14
  25. package/app/components/DuxtSearch.vue +230 -90
  26. package/app/components/DuxtSearchInput.vue +70 -0
  27. package/app/components/DuxtSections.vue +11 -1
  28. package/app/components/DuxtSegmented.vue +64 -0
  29. package/app/components/DuxtShortcuts.vue +16 -11
  30. package/app/components/DuxtShortcutsTrigger.vue +49 -0
  31. package/app/components/DuxtSkipLink.vue +1 -1
  32. package/app/components/DuxtToc.vue +16 -10
  33. package/app/components/DuxtTranslationBanner.vue +1 -1
  34. package/app/components/DuxtVersion.vue +53 -12
  35. package/app/components/DuxtVersionBanner.vue +5 -5
  36. package/app/components/content/AccordionItem.vue +2 -2
  37. package/app/components/content/BrunoOverview.vue +260 -0
  38. package/app/components/content/BrunoRequest.vue +141 -0
  39. package/app/components/content/BrunoRequests.vue +104 -0
  40. package/app/components/content/Callout.vue +5 -5
  41. package/app/components/content/ChangelogReleases.vue +161 -40
  42. package/app/components/content/CodeGroup.vue +41 -37
  43. package/app/components/content/Field.vue +1 -1
  44. package/app/components/content/FileTree.vue +1 -1
  45. package/app/components/content/OpenApiOperation.vue +4 -4
  46. package/app/components/content/OpenApiOperations.vue +1 -1
  47. package/app/components/content/OpenApiOverview.vue +1 -1
  48. package/app/components/content/PackageManagers.vue +42 -58
  49. package/app/components/content/PageCards.vue +7 -4
  50. package/app/components/content/Preview.vue +15 -39
  51. package/app/components/content/ProseImg.vue +596 -49
  52. package/app/components/content/Since.vue +1 -1
  53. package/app/components/content/Steps.vue +6 -4
  54. package/app/components/content/TabGroup.vue +13 -12
  55. package/app/components/ui/breadcrumb/BreadcrumbSeparator.vue +1 -1
  56. package/app/components/ui/command/CommandShortcut.vue +1 -1
  57. package/app/components/ui/dialog/DialogContent.vue +2 -2
  58. package/app/components/ui/dialog/DialogHeader.vue +1 -1
  59. package/app/components/ui/dialog/DialogScrollContent.vue +1 -1
  60. package/app/components/ui/dropdown-menu/DropdownMenuCheckboxItem.vue +2 -2
  61. package/app/components/ui/dropdown-menu/DropdownMenuItem.vue +1 -1
  62. package/app/components/ui/dropdown-menu/DropdownMenuLabel.vue +1 -1
  63. package/app/components/ui/dropdown-menu/DropdownMenuRadioItem.vue +2 -2
  64. package/app/components/ui/dropdown-menu/DropdownMenuShortcut.vue +1 -1
  65. package/app/components/ui/dropdown-menu/DropdownMenuSubTrigger.vue +2 -2
  66. package/app/components/ui/navigation-menu/NavigationMenuContent.vue +1 -1
  67. package/app/components/ui/navigation-menu/NavigationMenuTrigger.vue +1 -1
  68. package/app/components/ui/navigation-menu/NavigationMenuViewport.vue +1 -1
  69. package/app/components/ui/scroll-area/ScrollBar.vue +1 -1
  70. package/app/components/ui/select/SelectItem.vue +2 -2
  71. package/app/components/ui/sheet/SheetContent.vue +29 -3
  72. package/app/components/ui/sidebar/Sidebar.vue +28 -4
  73. package/app/components/ui/sidebar/SidebarGroupAction.vue +1 -1
  74. package/app/components/ui/sidebar/SidebarInset.vue +1 -1
  75. package/app/components/ui/sidebar/SidebarMenuAction.vue +1 -1
  76. package/app/components/ui/sidebar/SidebarMenuBadge.vue +1 -1
  77. package/app/components/ui/sidebar/SidebarMenuSub.vue +1 -1
  78. package/app/components/ui/sidebar/SidebarMenuSubButton.vue +1 -1
  79. package/app/components/ui/sidebar/SidebarProvider.vue +7 -16
  80. package/app/components/ui/sidebar/index.ts +10 -2
  81. package/app/components/ui/sidebar/utils.ts +0 -1
  82. package/app/components/ui/sonner/Sonner.vue +18 -0
  83. package/app/components/ui/tabs/TabsList.vue +13 -3
  84. package/app/components/ui/tabs/TabsTrigger.vue +24 -3
  85. package/app/components/ui/tooltip/TooltipContent.vue +2 -2
  86. package/app/composables/useActiveHeading.ts +3 -25
  87. package/app/composables/useDuxtAnalytics.ts +50 -0
  88. package/app/composables/useDuxtAnimatedHeight.ts +8 -38
  89. package/app/composables/useDuxtAnnouncements.ts +153 -0
  90. package/app/composables/useDuxtCopy.ts +51 -0
  91. package/app/composables/useDuxtDirection.ts +23 -0
  92. package/app/composables/useDuxtNavigation.ts +28 -8
  93. package/app/composables/useDuxtPath.ts +3 -5
  94. package/app/composables/useDuxtSearch.ts +87 -35
  95. package/app/composables/useDuxtSection.ts +15 -1
  96. package/app/composables/useDuxtSectionRow.ts +6 -5
  97. package/app/composables/useDuxtShortcuts.ts +319 -20
  98. package/app/composables/useDuxtVersion.ts +57 -6
  99. package/app/composables/useDuxtViewportMeasure.ts +37 -0
  100. package/app/composables/useFuzzySearch.ts +9 -4
  101. package/app/composables/useRecentPages.ts +14 -17
  102. package/app/error.vue +112 -74
  103. package/app/layouts/changelog.vue +9 -1
  104. package/app/layouts/default.vue +9 -0
  105. package/app/layouts/docs.vue +9 -1
  106. package/app/layouts/reference.vue +9 -1
  107. package/app/middleware/duxt-section-layout.global.ts +1 -3
  108. package/app/pages/[...slug].vue +146 -35
  109. package/app/pages/index.vue +15 -23
  110. package/app/types/duxt.d.ts +312 -4
  111. package/app/utils/analytics.ts +91 -0
  112. package/app/utils/announcements.ts +205 -0
  113. package/app/utils/changelog.ts +0 -28
  114. package/app/utils/code-highlight.ts +3 -1
  115. package/app/utils/contributor-avatar.ts +27 -0
  116. package/app/utils/direction.ts +43 -0
  117. package/app/utils/duxt-config.ts +43 -0
  118. package/app/utils/duxt-text.ts +10 -0
  119. package/app/utils/format-date.ts +28 -0
  120. package/app/utils/generated-sections.ts +68 -12
  121. package/app/utils/generated-toc.ts +14 -7
  122. package/app/utils/locale-path.ts +43 -0
  123. package/app/utils/navigation-tree.ts +51 -1
  124. package/app/utils/nearest-page.ts +8 -0
  125. package/app/utils/openapi.ts +16 -11
  126. package/app/utils/page-controls.ts +215 -0
  127. package/app/utils/pill.ts +61 -0
  128. package/app/utils/prose-image.ts +128 -0
  129. package/app/utils/search-context.ts +110 -0
  130. package/app/utils/search-display.ts +248 -0
  131. package/app/utils/section-scope.ts +65 -4
  132. package/app/utils/stored-json.ts +31 -0
  133. package/app/utils/version-choices.ts +6 -13
  134. package/app/utils/version-paths.ts +21 -0
  135. package/bin/duxt-cache-key.mjs +61 -0
  136. package/bin/duxt-og-cache.mjs +58 -0
  137. package/bin/{duxt-report.mjs → duxt.mjs} +13 -7
  138. package/bruno-model.ts +169 -0
  139. package/bruno-parse.ts +656 -0
  140. package/bruno-zip.ts +195 -0
  141. package/cli.ts +240 -0
  142. package/duxt-app-config.ts +18 -1
  143. package/frontmatter.ts +49 -0
  144. package/git-contributors.ts +322 -0
  145. package/i18n/locales/de/duxt/announcement.json +7 -0
  146. package/i18n/locales/de/duxt/bruno.json +25 -0
  147. package/i18n/locales/de/duxt/changelog.json +1 -1
  148. package/i18n/locales/de/duxt/code.json +2 -1
  149. package/i18n/locales/de/duxt/page.json +9 -0
  150. package/i18n/locales/de/duxt/shortcuts.json +1 -0
  151. package/i18n/locales/de/duxt/theme.json +2 -1
  152. package/i18n/locales/en/duxt/announcement.json +7 -0
  153. package/i18n/locales/en/duxt/bruno.json +25 -0
  154. package/i18n/locales/en/duxt/changelog.json +1 -1
  155. package/i18n/locales/en/duxt/code.json +2 -1
  156. package/i18n/locales/en/duxt/page.json +9 -0
  157. package/i18n/locales/en/duxt/shortcuts.json +1 -0
  158. package/i18n/locales/en/duxt/theme.json +2 -1
  159. package/i18n/locales/es/duxt/announcement.json +7 -0
  160. package/i18n/locales/es/duxt/bruno.json +25 -0
  161. package/i18n/locales/es/duxt/changelog.json +1 -1
  162. package/i18n/locales/es/duxt/code.json +2 -1
  163. package/i18n/locales/es/duxt/page.json +9 -0
  164. package/i18n/locales/es/duxt/shortcuts.json +1 -0
  165. package/i18n/locales/es/duxt/theme.json +2 -1
  166. package/i18n/locales/fr/duxt/announcement.json +7 -0
  167. package/i18n/locales/fr/duxt/bruno.json +25 -0
  168. package/i18n/locales/fr/duxt/changelog.json +1 -1
  169. package/i18n/locales/fr/duxt/code.json +2 -1
  170. package/i18n/locales/fr/duxt/page.json +9 -0
  171. package/i18n/locales/fr/duxt/shortcuts.json +1 -0
  172. package/i18n/locales/fr/duxt/theme.json +2 -1
  173. package/i18n/locales/pt/duxt/announcement.json +7 -0
  174. package/i18n/locales/pt/duxt/bruno.json +25 -0
  175. package/i18n/locales/pt/duxt/changelog.json +1 -1
  176. package/i18n/locales/pt/duxt/code.json +2 -1
  177. package/i18n/locales/pt/duxt/page.json +9 -0
  178. package/i18n/locales/pt/duxt/shortcuts.json +1 -0
  179. package/i18n/locales/pt/duxt/theme.json +2 -1
  180. package/modules/bruno.ts +118 -0
  181. package/modules/config.ts +26 -0
  182. package/modules/devtools.ts +2 -3
  183. package/modules/git-meta.ts +16 -47
  184. package/modules/search-records.ts +132 -0
  185. package/nuxt.config.ts +81 -7
  186. package/og-image-cache.ts +742 -0
  187. package/package.json +41 -9
  188. package/public/devtools/checks.html +2 -2
  189. package/public/devtools/config.html +59 -4
  190. package/public/devtools/pages.html +8 -1
  191. package/public/devtools/paths.html +1 -1
  192. package/public/devtools/sources.html +2 -2
  193. package/public/devtools/versions.html +3 -0
  194. package/report.ts +28 -19
  195. package/search-records.ts +380 -0
  196. package/section-input.ts +142 -0
  197. package/section-markdown.ts +67 -0
  198. package/section-reports.ts +10 -4
  199. package/sections-bruno.ts +571 -0
  200. package/sections-changelog.ts +76 -43
  201. package/sections-openapi.ts +12 -83
  202. package/sections-resolve.ts +174 -8
  203. package/sections.ts +33 -10
  204. package/server/devtools/shell.ts +1 -1
  205. package/server/mcp/tools/list-pages.ts +77 -36
  206. package/server/mcp/tools/list-versions.ts +84 -0
  207. package/server/mcp/tools/read-page.ts +80 -26
  208. package/server/mcp/tools/search-docs.ts +87 -53
  209. package/server/middleware/raw-markdown.ts +1 -1
  210. package/server/routes/llms-full.txt.get.ts +6 -8
  211. package/server/routes/llms.txt.get.ts +1 -1
  212. package/server/utils/duxt-server-text.ts +0 -13
  213. package/server/utils/llms-pages.ts +24 -9
  214. package/server/utils/mcp-docs.ts +577 -0
  215. package/sources-cache.ts +376 -0
  216. package/sources-git.ts +186 -31
  217. package/sources-resolve.ts +59 -1
  218. package/sources.ts +122 -13
  219. package/tfplugindocs.ts +158 -0
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://www.schemastore.org/package.json",
3
3
  "name": "@kirchdev/duxt",
4
- "version": "0.3.4",
4
+ "version": "0.3.5-dev-main.43-3310f4b",
5
5
  "description": "Nuxt documentation layer on Content v3 — multi-repo, versioned docs from one compact source list.",
6
6
  "keywords": [
7
7
  "content-v3",
@@ -26,48 +26,68 @@
26
26
  "url": "git+https://github.com/kirchDev/duxt.git"
27
27
  },
28
28
  "bin": {
29
- "duxt-report": "./bin/duxt-report.mjs"
29
+ "duxt": "./bin/duxt.mjs",
30
+ "duxt-cache-key": "./bin/duxt-cache-key.mjs",
31
+ "duxt-og-cache": "./bin/duxt-og-cache.mjs"
30
32
  },
31
33
  "files": [
32
- "bin",
33
34
  "app",
35
+ "bruno-model.ts",
36
+ "bruno-parse.ts",
37
+ "bruno-zip.ts",
38
+ "cli.ts",
34
39
  "components.json",
35
40
  "content-cache.ts",
36
41
  "content.config.ts",
37
42
  "duxt-app-config.ts",
43
+ "frontmatter.ts",
44
+ "git-contributors.ts",
38
45
  "highlight-langs.ts",
39
46
  "i18n",
40
47
  "mdc.config.ts",
41
48
  "modules",
42
49
  "nuxt.config.ts",
50
+ "og-image-cache.ts",
43
51
  "openapi-model.ts",
44
52
  "openapi-parse.ts",
45
53
  "public",
46
54
  "report.ts",
47
55
  "repository-root.ts",
56
+ "search-records.ts",
57
+ "section-input.ts",
58
+ "section-markdown.ts",
59
+ "section-reports.ts",
60
+ "sections-bruno.ts",
48
61
  "sections-changelog.ts",
49
62
  "sections-openapi.ts",
50
63
  "sections-resolve.ts",
51
- "section-reports.ts",
52
64
  "sections.ts",
53
65
  "server",
66
+ "sources-cache.ts",
54
67
  "sources-git.ts",
55
68
  "sources-resolve.ts",
56
69
  "sources.ts",
70
+ "tfplugindocs.ts",
57
71
  "validate-report.ts"
58
72
  ],
59
73
  "type": "module",
60
74
  "main": "./nuxt.config.ts",
61
75
  "exports": {
62
76
  ".": "./nuxt.config.ts",
77
+ "./bruno-model": "./bruno-model.ts",
78
+ "./bruno-parse": "./bruno-parse.ts",
79
+ "./og-image-cache": "./og-image-cache.ts",
63
80
  "./openapi-model": "./openapi-model.ts",
64
81
  "./openapi-parse": "./openapi-parse.ts",
82
+ "./search-records": "./search-records.ts",
65
83
  "./sections": "./sections.ts",
84
+ "./sections-bruno": "./sections-bruno.ts",
66
85
  "./sections-openapi": "./sections-openapi.ts",
67
86
  "./sections-resolve": "./sections-resolve.ts",
68
87
  "./sources": "./sources.ts",
69
- "./sources-resolve": "./sources-resolve.ts",
70
- "./sources-git": "./sources-git.ts"
88
+ "./sources-cache": "./sources-cache.ts",
89
+ "./sources-git": "./sources-git.ts",
90
+ "./sources-resolve": "./sources-resolve.ts"
71
91
  },
72
92
  "publishConfig": {
73
93
  "access": "public"
@@ -92,10 +112,12 @@
92
112
  "@nuxtjs/i18n": "^10.6.0",
93
113
  "@nuxtjs/mcp-toolkit": "^0.19.0",
94
114
  "@nuxtjs/seo": "^5.3.14",
115
+ "@nuxtjs/sitemap": "^8.5.0",
95
116
  "@resvg/resvg-js": "^2.6.2",
96
117
  "@shikijs/transformers": "^4.4.3",
97
118
  "@tailwindcss/vite": "^4.3.3",
98
119
  "@vueuse/core": "^14.4.0",
120
+ "citty": "^0.2.2",
99
121
  "class-variance-authority": "^0.7.1",
100
122
  "clsx": "^2.1.1",
101
123
  "fuse.js": "^7.5.0",
@@ -125,6 +147,7 @@
125
147
  "nuxt": "^4.5.2",
126
148
  "oxfmt": "0.65.0",
127
149
  "oxlint": "1.80.0",
150
+ "playwright-core": "^1.63.0",
128
151
  "taze": "^21.1.0",
129
152
  "typescript": "^6.0.3",
130
153
  "vitest": "^4.1.11"
@@ -141,7 +164,7 @@
141
164
  "format": "oxfmt --check .",
142
165
  "format:fix": "oxfmt .",
143
166
  "typecheck": "tsc --noEmit",
144
- "check": "pnpm lint && pnpm format && pnpm typecheck && pnpm typecheck:app && pnpm test && pnpm check:policy && pnpm check:previews && pnpm build:app && pnpm check:a11y && pnpm check:seo",
167
+ "check": "pnpm lint && pnpm format && pnpm typecheck && pnpm typecheck:app && pnpm test && pnpm check:policy && pnpm check:previews && pnpm build:app && pnpm check:a11y && pnpm check:seo && pnpm check:images && pnpm check:keyboard && pnpm check:overflow",
145
168
  "check:fix": "pnpm lint:fix && pnpm format:fix",
146
169
  "previews": "node scripts/build-devtools-previews.ts",
147
170
  "check:previews": "node scripts/check-previews.ts",
@@ -152,10 +175,19 @@
152
175
  "typecheck:app": "pnpm --filter www typecheck",
153
176
  "test": "vitest run",
154
177
  "test:watch": "vitest",
155
- "report": "pnpm --filter www exec duxt-report",
178
+ "report": "pnpm --filter www exec duxt report",
179
+ "cache:key": "node ./bin/duxt-cache-key.mjs --root www",
180
+ "og:cache": "node ./bin/duxt-og-cache.mjs --root www",
156
181
  "build:app": "pnpm --filter www build",
182
+ "build:www": "pnpm --filter www run build:cf",
157
183
  "deploy:www": "pnpm --filter www run deploy",
184
+ "publish:www": "pnpm --filter www run publish:cf",
158
185
  "check:a11y": "node scripts/check-a11y.ts",
159
- "check:seo": "node scripts/check-seo.ts"
186
+ "check:seo": "node scripts/check-seo.ts",
187
+ "check:images": "node scripts/check-images.ts",
188
+ "check:keyboard": "node scripts/check-keyboard.ts",
189
+ "check:overflow": "node scripts/check-overflow.ts",
190
+ "check:adapters": "node scripts/check-adapters.ts",
191
+ "check:routes": "node scripts/check-routes.ts"
160
192
  }
161
193
  }
@@ -236,9 +236,9 @@
236
236
  <main>
237
237
  <h1>Checks</h1>
238
238
  <p class="hint">The build validator, run against what the site is serving now.</p>
239
- <div class="stats"><div class="stat "><b>34</b><span>pages checked</span></div><div class="stat "><b>6</b><span>collections</span></div><div class="stat ok"><b>0</b><span>errors</span></div><div class="stat warn"><b>5</b><span>warnings</span></div></div><h2>Warnings</h2><div class="scroll"><table>
239
+ <div class="stats"><div class="stat "><b>38</b><span>pages checked</span></div><div class="stat "><b>7</b><span>collections</span></div><div class="stat ok"><b>0</b><span>errors</span></div><div class="stat warn"><b>6</b><span>warnings</span></div></div><h2>Warnings</h2><div class="scroll"><table>
240
240
  <thead><tr><th scope="col"></th><th scope="col">Warning</th></tr></thead>
241
- <tbody><tr><td><span class="tag warn">warn</span></td><td>the generated section &quot;Releases&quot; (CHANGELOG.md): the heading &quot;1.3 (Feb 2026)&quot; on line 41 reads like a release but does not parse as one, so it became part of the release above it instead of a page of its own. A release heading is a version, optionally followed by a date in parentheses: `## 1.4.0 (2024-02-01)`.</td></tr><tr><td><span class="tag warn">warn</span></td><td><a class="file" href="/__nuxt_devtools__/open-in-editor?file=%2Fsrv%2Facme-docs%2Fdocs_sdk%2F3.reference%2F2.errors.md" target="_blank" title="/srv/acme-docs/docs_sdk/3.reference/2.errors.md">&quot;docs_sdk/3.reference/2.errors.md&quot;</a> has no title and no description.</td></tr><tr><td><span class="tag warn">warn</span></td><td><a class="file" href="/__nuxt_devtools__/open-in-editor?file=%2Fsrv%2Facme-docs%2Fdocs_de_sdk%2Fde%2F3.reference%2F2.errors.md" target="_blank" title="/srv/acme-docs/docs_de_sdk/de/3.reference/2.errors.md">&quot;docs_de_sdk/de/3.reference/2.errors.md&quot;</a> has no title and no description.</td></tr><tr><td><span class="tag warn">warn</span></td><td><a class="file" href="/__nuxt_devtools__/open-in-editor?file=%2Fsrv%2Facme-docs%2Fdocs_sdk_v1_9%2F3.reference%2F2.errors.md" target="_blank" title="/srv/acme-docs/docs_sdk_v1_9/3.reference/2.errors.md">&quot;docs_sdk_v1_9/3.reference/2.errors.md&quot;</a> has no title and no description.</td></tr><tr><td><span class="tag warn">warn</span></td><td><a class="file" href="/__nuxt_devtools__/open-in-editor?file=%2Fsrv%2Facme-docs%2Fdocs_sdk%2F1.getting-started%2Findex.md" target="_blank" title="/srv/acme-docs/docs_sdk/1.getting-started/index.md">&quot;docs_sdk/1.getting-started/index.md&quot;</a> links to &quot;/sdk/guides/cacheing&quot;, which no page serves.</td></tr></tbody>
241
+ <tbody><tr><td><span class="tag warn">warn</span></td><td>the generated section &quot;Releases&quot; (CHANGELOG.md): the heading &quot;1.3 (Feb 2026)&quot; on line 41 reads like a release but does not parse as one, so it became part of the release above it instead of a page of its own. A release heading is a version, optionally followed by a date in parentheses: `## 1.4.0 (2024-02-01)`.</td></tr><tr><td><span class="tag warn">warn</span></td><td>the generated section &quot;Releases&quot; (CHANGELOG.md): the heading &quot;1.3 (Feb 2026)&quot; on line 41 reads like a release but does not parse as one, so it became part of the release above it instead of a page of its own. A release heading is a version, optionally followed by a date in parentheses: `## 1.4.0 (2024-02-01)`.</td></tr><tr><td><span class="tag warn">warn</span></td><td><a class="file" href="/__nuxt_devtools__/open-in-editor?file=%2Fsrv%2Facme-docs%2Fdocs_sdk%2F3.reference%2F2.errors.md" target="_blank" title="/srv/acme-docs/docs_sdk/3.reference/2.errors.md">&quot;docs_sdk/3.reference/2.errors.md&quot;</a> has no title and no description.</td></tr><tr><td><span class="tag warn">warn</span></td><td><a class="file" href="/__nuxt_devtools__/open-in-editor?file=%2Fsrv%2Facme-docs%2Fdocs_de_sdk%2Fde%2F3.reference%2F2.errors.md" target="_blank" title="/srv/acme-docs/docs_de_sdk/de/3.reference/2.errors.md">&quot;docs_de_sdk/de/3.reference/2.errors.md&quot;</a> has no title and no description.</td></tr><tr><td><span class="tag warn">warn</span></td><td><a class="file" href="/__nuxt_devtools__/open-in-editor?file=%2Fsrv%2Facme-docs%2Fdocs_sdk_v1_9%2F3.reference%2F2.errors.md" target="_blank" title="/srv/acme-docs/docs_sdk_v1_9/3.reference/2.errors.md">&quot;docs_sdk_v1_9/3.reference/2.errors.md&quot;</a> has no title and no description.</td></tr><tr><td><span class="tag warn">warn</span></td><td><a class="file" href="/__nuxt_devtools__/open-in-editor?file=%2Fsrv%2Facme-docs%2Fdocs_sdk%2F1.getting-started%2Findex.md" target="_blank" title="/srv/acme-docs/docs_sdk/1.getting-started/index.md">&quot;docs_sdk/1.getting-started/index.md&quot;</a> links to &quot;/sdk/guides/cacheing&quot;, which no page serves.</td></tr></tbody>
242
242
  </table></div><h2>Translations</h2><ul class="steps"><li><strong>de under &quot;/sdk&quot;: 6/8 pages</strong></li><li class="dim" style="margin-left:1.5rem"><a class="file" href="/__nuxt_devtools__/open-in-editor?file=%2Fsrv%2Facme-docs%2Fdocs_sdk%2F2.guides%2F2.caching.md" target="_blank" title="/srv/acme-docs/docs_sdk/2.guides/2.caching.md">&quot;docs_sdk/2.guides/2.caching.md&quot;</a> has no de translation.</li><li class="dim" style="margin-left:1.5rem"><a class="file" href="/__nuxt_devtools__/open-in-editor?file=%2Fsrv%2Facme-docs%2Fdocs_sdk%2F4.changelog.md" target="_blank" title="/srv/acme-docs/docs_sdk/4.changelog.md">&quot;docs_sdk/4.changelog.md&quot;</a> has no de translation.</li><li><strong>de under &quot;/sdk/v1.9&quot;: 5/7 pages</strong></li><li class="dim" style="margin-left:1.5rem"><a class="file" href="/__nuxt_devtools__/open-in-editor?file=%2Fsrv%2Facme-docs%2Fdocs_sdk_v1_9%2F3.reference%2F2.errors.md" target="_blank" title="/srv/acme-docs/docs_sdk_v1_9/3.reference/2.errors.md">&quot;docs_sdk_v1_9/3.reference/2.errors.md&quot;</a> has no de translation.</li><li class="dim" style="margin-left:1.5rem"><a class="file" href="/__nuxt_devtools__/open-in-editor?file=%2Fsrv%2Facme-docs%2Fdocs_sdk_v1_9%2F4.changelog.md" target="_blank" title="/srv/acme-docs/docs_sdk_v1_9/4.changelog.md">&quot;docs_sdk_v1_9/4.changelog.md&quot;</a> has no de translation.</li></ul>
243
243
  </main>
244
244
  <script>
@@ -236,9 +236,29 @@
236
236
  <main>
237
237
  <h1>Config</h1>
238
238
  <p class="hint">The merged <code>duxt</code> config, and which side of the merge each value came from.</p>
239
- <div class="stats"><div class="stat "><b>15</b><span>keys</span></div><div class="stat ok"><b>6</b><span>from the site</span></div><div class="stat "><b>8</b><span>from the layer</span></div><div class="stat "><b>1</b><span>computed</span></div></div><div class="note">Arrays are replaced whole, objects merge key by key. A row marked <span class="tag">build</span> was computed by <code>modules/config.ts</code> and is written nowhere.</div><div class="filterbar"><input type="search" class="filter" data-filter placeholder="Filter keys" aria-label="Filter keys"><span class="count" data-filter-count role="status" aria-live="polite"></span></div><div class="scroll"><table>
239
+ <div class="stats"><div class="stat "><b>22</b><span>keys</span></div><div class="stat ok"><b>6</b><span>from the site</span></div><div class="stat "><b>15</b><span>from the layer</span></div><div class="stat "><b>1</b><span>computed</span></div></div><div class="note">Arrays are replaced whole, objects merge key by key. A row marked <span class="tag">build</span> was computed by <code>modules/config.ts</code> and is written nowhere.</div><div class="filterbar"><input type="search" class="filter" data-filter placeholder="Filter keys" aria-label="Filter keys"><span class="count" data-filter-count role="status" aria-live="polite"></span></div><div class="scroll"><table>
240
240
  <thead><tr><th scope="col">Key</th><th scope="col">From</th><th scope="col">Value</th></tr></thead>
241
- <tbody><tr><td><code>title</code></td><td><span class="tag ok">consumer</span></td><td><code>Acme SDK</code></td></tr><tr><td><code>navigation</code></td><td><span class="tag muted">layer</span></td><td><details class="json"><summary><span class="dim">1 entries</span> <code class="peek">[{&quot;label&quot;:&quot;duxt.defaults.navigation.docs&quot;,&quot;icon&quot;:&quot;lucide:book-open-text&quot;}]</code></summary><pre class="json">[
241
+ <tbody><tr><td><code>title</code></td><td><span class="tag ok">consumer</span></td><td><code>Acme SDK</code></td></tr><tr><td><code>copy</code></td><td><span class="tag muted">layer</span></td><td><details class="json"><summary><span class="dim">1 keys</span> <code class="peek">{&quot;models&quot;:[{&quot;label&quot;:&quot;duxt.page.copy.chatgpt&quot;,&quot;icon&quot;:&quot;simple-icons:openai&quot;,&quot;url&quot;:&quot;https://chatgpt…</code></summary><pre class="json">{
242
+ <span class="j-key">&quot;models&quot;</span>: [
243
+ {
244
+ <span class="j-key">&quot;label&quot;</span>: <span class="j-str">&quot;duxt.page.copy.chatgpt&quot;</span>,
245
+ <span class="j-key">&quot;icon&quot;</span>: <span class="j-str">&quot;simple-icons:openai&quot;</span>,
246
+ <span class="j-key">&quot;url&quot;</span>: <span class="j-str">&quot;https://chatgpt.com/?q=&quot;</span>
247
+ },
248
+ {
249
+ <span class="j-key">&quot;label&quot;</span>: <span class="j-str">&quot;duxt.page.copy.claude&quot;</span>,
250
+ <span class="j-key">&quot;icon&quot;</span>: <span class="j-str">&quot;simple-icons:claude&quot;</span>,
251
+ <span class="j-key">&quot;url&quot;</span>: <span class="j-str">&quot;https://claude.ai/new?q=&quot;</span>
252
+ }
253
+ ]
254
+ }</pre></details></td></tr><tr><td><code>contributors</code></td><td><span class="tag muted">layer</span></td><td><span class="dim">1 keys</span> <code>{&quot;avatarUrl&quot;:&quot;https://github.com/{username}.png?size=40&quot;}</code></td></tr><tr><td><code>toc</code></td><td><span class="tag muted">layer</span></td><td><span class="dim">2 keys</span> <code>{&quot;depth&quot;:3,&quot;scrollOffset&quot;:96}</code></td></tr><tr><td><code>search</code></td><td><span class="tag muted">layer</span></td><td><details class="json"><summary><span class="dim">2 keys</span> <code class="peek">{&quot;fuzzy&quot;:{&quot;threshold&quot;:0.35,&quot;minMatchCharLength&quot;:3,&quot;limit&quot;:20},&quot;recentPages&quot;:5}</code></summary><pre class="json">{
255
+ <span class="j-key">&quot;fuzzy&quot;</span>: {
256
+ <span class="j-key">&quot;threshold&quot;</span>: <span class="j-num">0.35</span>,
257
+ <span class="j-key">&quot;minMatchCharLength&quot;</span>: <span class="j-num">3</span>,
258
+ <span class="j-key">&quot;limit&quot;</span>: <span class="j-num">20</span>
259
+ },
260
+ <span class="j-key">&quot;recentPages&quot;</span>: <span class="j-num">5</span>
261
+ }</pre></details></td></tr><tr><td><code>openapi</code></td><td><span class="tag muted">layer</span></td><td><span class="dim">2 keys</span> <code>{&quot;exampleDepth&quot;:6,&quot;schemaDepth&quot;:8}</code></td></tr><tr><td><code>shortcuts</code></td><td><span class="tag muted">layer</span></td><td><span class="dim">1 keys</span> <code>{&quot;singleCharacter&quot;:true}</code></td></tr><tr><td><code>announcements</code></td><td><span class="tag muted">layer</span></td><td><span class="dim">0 entries</span> <code>[]</code></td></tr><tr><td><code>navigation</code></td><td><span class="tag muted">layer</span></td><td><details class="json"><summary><span class="dim">1 entries</span> <code class="peek">[{&quot;label&quot;:&quot;duxt.defaults.navigation.docs&quot;,&quot;icon&quot;:&quot;lucide:book-open-text&quot;}]</code></summary><pre class="json">[
242
262
  {
243
263
  <span class="j-key">&quot;label&quot;</span>: <span class="j-str">&quot;duxt.defaults.navigation.docs&quot;</span>,
244
264
  <span class="j-key">&quot;icon&quot;</span>: <span class="j-str">&quot;lucide:book-open-text&quot;</span>
@@ -280,7 +300,7 @@
280
300
  <span class="j-key">&quot;path&quot;</span>: <span class="j-str">&quot;docs&quot;</span>,
281
301
  <span class="j-key">&quot;repo&quot;</span>: <span class="j-str">&quot;acme/cli&quot;</span>
282
302
  }
283
- ]</pre></details></td></tr><tr><td><code>resolvedSources</code></td><td><span class="tag">build</span></td><td><details class="json"><summary><span class="dim">6 entries</span> <code class="peek">[{&quot;collection&quot;:&quot;docs_sdk&quot;,&quot;prefix&quot;:&quot;/sdk&quot;,&quot;repo&quot;:&quot;sdk&quot;,&quot;version&quot;:&quot;v2&quot;,&quot;isDefault&quot;:true,&quot;reposito…</code></summary><pre class="json">[
303
+ ]</pre></details></td></tr><tr><td><code>resolvedSources</code></td><td><span class="tag">build</span></td><td><details class="json"><summary><span class="dim">7 entries</span> <code class="peek">[{&quot;collection&quot;:&quot;docs_sdk&quot;,&quot;prefix&quot;:&quot;/sdk&quot;,&quot;repo&quot;:&quot;sdk&quot;,&quot;version&quot;:&quot;v2&quot;,&quot;isDefault&quot;:true,&quot;reposito…</code></summary><pre class="json">[
284
304
  {
285
305
  <span class="j-key">&quot;collection&quot;</span>: <span class="j-str">&quot;docs_sdk&quot;</span>,
286
306
  <span class="j-key">&quot;prefix&quot;</span>: <span class="j-str">&quot;/sdk&quot;</span>,
@@ -362,6 +382,7 @@
362
382
  <span class="j-key">&quot;collection&quot;</span>: <span class="j-str">&quot;docs_sdk_releases&quot;</span>,
363
383
  <span class="j-key">&quot;prefix&quot;</span>: <span class="j-str">&quot;/sdk/releases&quot;</span>,
364
384
  <span class="j-key">&quot;repo&quot;</span>: <span class="j-str">&quot;sdk&quot;</span>,
385
+ <span class="j-key">&quot;version&quot;</span>: <span class="j-str">&quot;v2&quot;</span>,
365
386
  <span class="j-key">&quot;isDefault&quot;</span>: <span class="j-word">true</span>,
366
387
  <span class="j-key">&quot;repository&quot;</span>: <span class="j-str">&quot;acme/sdk&quot;</span>,
367
388
  <span class="j-key">&quot;repositoryUrl&quot;</span>: <span class="j-str">&quot;https://github.com/acme/sdk&quot;</span>,
@@ -380,7 +401,41 @@
380
401
  <span class="j-key">&quot;navigation&quot;</span>: <span class="j-str">&quot;sections&quot;</span>,
381
402
  <span class="j-key">&quot;icon&quot;</span>: <span class="j-str">&quot;lucide:tag&quot;</span>,
382
403
  <span class="j-key">&quot;layout&quot;</span>: <span class="j-str">&quot;changelog&quot;</span>,
383
- <span class="j-key">&quot;versioning&quot;</span>: <span class="j-str">&quot;global&quot;</span>,
404
+ <span class="j-key">&quot;versioning&quot;</span>: <span class="j-str">&quot;per-version&quot;</span>,
405
+ <span class="j-key">&quot;localisation&quot;</span>: <span class="j-str">&quot;original&quot;</span>,
406
+ <span class="j-key">&quot;remote&quot;</span>: <span class="j-word">true</span>,
407
+ <span class="j-key">&quot;report&quot;</span>: {
408
+ <span class="j-key">&quot;pages&quot;</span>: <span class="j-num">4</span>,
409
+ <span class="j-key">&quot;warnings&quot;</span>: [
410
+ <span class="j-str">&quot;the heading \&quot;1.3 (Feb 2026)\&quot; on line 41 reads like a release but does not parse as one, so it became part of the release above it instead of a page of its own. A release heading is a version, optionally followed by a date in parentheses: `## 1.4.0 (2024-02-01)`.&quot;</span>
411
+ ]
412
+ }
413
+ }
414
+ },
415
+ {
416
+ <span class="j-key">&quot;collection&quot;</span>: <span class="j-str">&quot;docs_sdk_v1_9_releases&quot;</span>,
417
+ <span class="j-key">&quot;prefix&quot;</span>: <span class="j-str">&quot;/sdk/v1.9/releases&quot;</span>,
418
+ <span class="j-key">&quot;repo&quot;</span>: <span class="j-str">&quot;sdk&quot;</span>,
419
+ <span class="j-key">&quot;version&quot;</span>: <span class="j-str">&quot;v1.9&quot;</span>,
420
+ <span class="j-key">&quot;isDefault&quot;</span>: <span class="j-word">false</span>,
421
+ <span class="j-key">&quot;repository&quot;</span>: <span class="j-str">&quot;acme/sdk&quot;</span>,
422
+ <span class="j-key">&quot;repositoryUrl&quot;</span>: <span class="j-str">&quot;https://github.com/acme/sdk&quot;</span>,
423
+ <span class="j-key">&quot;ref&quot;</span>: <span class="j-str">&quot;v1.9.4&quot;</span>,
424
+ <span class="j-key">&quot;refKind&quot;</span>: <span class="j-str">&quot;tag&quot;</span>,
425
+ <span class="j-key">&quot;path&quot;</span>: <span class="j-str">&quot;CHANGELOG.md&quot;</span>,
426
+ <span class="j-key">&quot;locale&quot;</span>: <span class="j-str">&quot;en&quot;</span>,
427
+ <span class="j-key">&quot;isDefaultLocale&quot;</span>: <span class="j-word">true</span>,
428
+ <span class="j-key">&quot;status&quot;</span>: <span class="j-str">&quot;deprecated&quot;</span>,
429
+ <span class="j-key">&quot;history&quot;</span>: <span class="j-word">false</span>,
430
+ <span class="j-key">&quot;generated&quot;</span>: {
431
+ <span class="j-key">&quot;type&quot;</span>: <span class="j-str">&quot;changelog&quot;</span>,
432
+ <span class="j-key">&quot;label&quot;</span>: <span class="j-str">&quot;Releases&quot;</span>,
433
+ <span class="j-key">&quot;slug&quot;</span>: <span class="j-str">&quot;releases&quot;</span>,
434
+ <span class="j-key">&quot;declaration&quot;</span>: <span class="j-num">0</span>,
435
+ <span class="j-key">&quot;navigation&quot;</span>: <span class="j-str">&quot;sections&quot;</span>,
436
+ <span class="j-key">&quot;icon&quot;</span>: <span class="j-str">&quot;lucide:tag&quot;</span>,
437
+ <span class="j-key">&quot;layout&quot;</span>: <span class="j-str">&quot;changelog&quot;</span>,
438
+ <span class="j-key">&quot;versioning&quot;</span>: <span class="j-str">&quot;per-version&quot;</span>,
384
439
  <span class="j-key">&quot;localisation&quot;</span>: <span class="j-str">&quot;original&quot;</span>,
385
440
  <span class="j-key">&quot;remote&quot;</span>: <span class="j-word">true</span>,
386
441
  <span class="j-key">&quot;report&quot;</span>: {
@@ -236,7 +236,7 @@
236
236
  <main>
237
237
  <h1>Pages</h1>
238
238
  <p class="hint">Every page in every collection, with the frontmatter and git metadata attached to it.</p>
239
- <div class="stats"><div class="stat "><b>34</b><span>pages</span></div><div class="stat "><b>6</b><span>collections</span></div><div class="stat "><b>26</b><span>with history</span></div><div class="stat warn"><b>3</b><span>without a title</span></div></div><details open>
239
+ <div class="stats"><div class="stat "><b>38</b><span>pages</span></div><div class="stat "><b>7</b><span>collections</span></div><div class="stat "><b>26</b><span>with history</span></div><div class="stat warn"><b>3</b><span>without a title</span></div></div><details open>
240
240
  <summary>docs_sdk <span class="dim">8 pages</span></summary>
241
241
 
242
242
  <div class="scroll"><table>
@@ -277,6 +277,13 @@
277
277
  <div class="scroll"><table>
278
278
  <thead><tr><th scope="col">Path</th><th scope="col">Title</th><th scope="col">Description</th><th scope="col">Icon</th><th scope="col">Last updated</th><th scope="col">Contributors</th><th scope="col">File</th></tr></thead>
279
279
  <tbody><tr><td><code>/sdk/releases</code></td><td>Releases</td><td><span class="tag warn">missing</span></td><td><span class="dim">—</span></td><td><span class="dim">no history</span></td><td><span class="dim">—</span></td><td><a class="file" href="/__nuxt_devtools__/open-in-editor?file=%2Fsrv%2Facme-docs%2Fdocs_sdk_releases%2Findex.md" target="_blank" title="/srv/acme-docs/docs_sdk_releases/index.md">index.md</a></td></tr><tr><td><code>/sdk/releases/0.2.0</code></td><td>0.2.0</td><td><span class="tag warn">missing</span></td><td><span class="dim">—</span></td><td><span class="dim">no history</span></td><td><span class="dim">—</span></td><td><a class="file" href="/__nuxt_devtools__/open-in-editor?file=%2Fsrv%2Facme-docs%2Fdocs_sdk_releases%2F1.0.2.0.md" target="_blank" title="/srv/acme-docs/docs_sdk_releases/1.0.2.0.md">1.0.2.0.md</a></td></tr><tr><td><code>/sdk/releases/0.1.1</code></td><td>0.1.1</td><td><span class="tag warn">missing</span></td><td><span class="dim">—</span></td><td><span class="dim">no history</span></td><td><span class="dim">—</span></td><td><a class="file" href="/__nuxt_devtools__/open-in-editor?file=%2Fsrv%2Facme-docs%2Fdocs_sdk_releases%2F2.0.1.1.md" target="_blank" title="/srv/acme-docs/docs_sdk_releases/2.0.1.1.md">2.0.1.1.md</a></td></tr><tr><td><code>/sdk/releases/0.1.0</code></td><td>0.1.0</td><td><span class="tag warn">missing</span></td><td><span class="dim">—</span></td><td><span class="dim">no history</span></td><td><span class="dim">—</span></td><td><a class="file" href="/__nuxt_devtools__/open-in-editor?file=%2Fsrv%2Facme-docs%2Fdocs_sdk_releases%2F3.0.1.0.md" target="_blank" title="/srv/acme-docs/docs_sdk_releases/3.0.1.0.md">3.0.1.0.md</a></td></tr></tbody>
280
+ </table></div>
281
+ </details><details>
282
+ <summary>docs_sdk_v1_9_releases <span class="dim">4 pages</span></summary>
283
+
284
+ <div class="scroll"><table>
285
+ <thead><tr><th scope="col">Path</th><th scope="col">Title</th><th scope="col">Description</th><th scope="col">Icon</th><th scope="col">Last updated</th><th scope="col">Contributors</th><th scope="col">File</th></tr></thead>
286
+ <tbody><tr><td><code>/sdk/v1.9/releases</code></td><td>Releases</td><td><span class="tag warn">missing</span></td><td><span class="dim">—</span></td><td><span class="dim">no history</span></td><td><span class="dim">—</span></td><td><a class="file" href="/__nuxt_devtools__/open-in-editor?file=%2Fsrv%2Facme-docs%2Fdocs_sdk_v1_9_releases%2Findex.md" target="_blank" title="/srv/acme-docs/docs_sdk_v1_9_releases/index.md">index.md</a></td></tr><tr><td><code>/sdk/v1.9/releases/0.2.0</code></td><td>0.2.0</td><td><span class="tag warn">missing</span></td><td><span class="dim">—</span></td><td><span class="dim">no history</span></td><td><span class="dim">—</span></td><td><a class="file" href="/__nuxt_devtools__/open-in-editor?file=%2Fsrv%2Facme-docs%2Fdocs_sdk_v1_9_releases%2F1.0.2.0.md" target="_blank" title="/srv/acme-docs/docs_sdk_v1_9_releases/1.0.2.0.md">1.0.2.0.md</a></td></tr><tr><td><code>/sdk/v1.9/releases/0.1.1</code></td><td>0.1.1</td><td><span class="tag warn">missing</span></td><td><span class="dim">—</span></td><td><span class="dim">no history</span></td><td><span class="dim">—</span></td><td><a class="file" href="/__nuxt_devtools__/open-in-editor?file=%2Fsrv%2Facme-docs%2Fdocs_sdk_v1_9_releases%2F2.0.1.1.md" target="_blank" title="/srv/acme-docs/docs_sdk_v1_9_releases/2.0.1.1.md">2.0.1.1.md</a></td></tr><tr><td><code>/sdk/v1.9/releases/0.1.0</code></td><td>0.1.0</td><td><span class="tag warn">missing</span></td><td><span class="dim">—</span></td><td><span class="dim">no history</span></td><td><span class="dim">—</span></td><td><a class="file" href="/__nuxt_devtools__/open-in-editor?file=%2Fsrv%2Facme-docs%2Fdocs_sdk_v1_9_releases%2F3.0.1.0.md" target="_blank" title="/srv/acme-docs/docs_sdk_v1_9_releases/3.0.1.0.md">3.0.1.0.md</a></td></tr></tbody>
280
287
  </table></div>
281
288
  </details>
282
289
  </main>
@@ -241,7 +241,7 @@
241
241
  <button type="submit">Resolve</button>
242
242
  </form><ol class="steps"><li>Locale segment stripped: <code>/de/sdk/v1-9/guides/caching</code> → <code>/sdk/v1-9/guides/caching</code>, language <code>de</code>. <span class="dim">The locale translates the interface, never the content tree — but it does pick the collection.</span></li><li>Longest matching prefix is <code>/sdk</code> → collection <code>docs_de_sdk</code>, version <code>v2</code>, language <code>de</code>.</li><li>Falls back to <code>docs_sdk</code>. <span class="dim">A page is translated whole or not at all, so this is a chain of collections rather than a merge.</span></li><li><span class="tag error">stops here</span> Collection <code>docs_de_sdk</code> has no page at <code>/sdk/v1-9/guides/caching</code>.</li></ol><h2>The same page in other sources</h2><div class="scroll"><table>
243
243
  <thead><tr><th scope="col">Prefix</th><th scope="col">Version</th><th scope="col">Language</th><th scope="col">Would be</th><th scope="col">State</th></tr></thead>
244
- <tbody><tr><td><code>/sdk</code></td><td>v2</td><td>en <span class="tag">original</span></td><td><code>/sdk/v1-9/guides/caching</code></td><td><span class="tag muted">missing</span></td></tr><tr><td><code>/sdk</code></td><td>v2</td><td>de</td><td><code>/sdk/v1-9/guides/caching</code></td><td><span class="tag muted">missing</span></td></tr><tr><td><code>/sdk/v1.9</code></td><td>v1.9</td><td>en <span class="tag">original</span></td><td><code>/sdk/v1.9/v1-9/guides/caching</code></td><td><span class="tag muted">missing</span></td></tr><tr><td><code>/sdk/v1.9</code></td><td>v1.9</td><td>de</td><td><code>/sdk/v1.9/v1-9/guides/caching</code></td><td><span class="tag muted">missing</span></td></tr><tr><td><code>/sdk/releases</code></td><td>—</td><td>en <span class="tag">original</span></td><td><code>/sdk/releases/v1-9/guides/caching</code></td><td><span class="tag muted">missing</span></td></tr></tbody>
244
+ <tbody><tr><td><code>/sdk</code></td><td>v2</td><td>en <span class="tag">original</span></td><td><code>/sdk/v1-9/guides/caching</code></td><td><span class="tag muted">missing</span></td></tr><tr><td><code>/sdk</code></td><td>v2</td><td>de</td><td><code>/sdk/v1-9/guides/caching</code></td><td><span class="tag muted">missing</span></td></tr><tr><td><code>/sdk/v1.9</code></td><td>v1.9</td><td>en <span class="tag">original</span></td><td><code>/sdk/v1.9/v1-9/guides/caching</code></td><td><span class="tag muted">missing</span></td></tr><tr><td><code>/sdk/v1.9</code></td><td>v1.9</td><td>de</td><td><code>/sdk/v1.9/v1-9/guides/caching</code></td><td><span class="tag muted">missing</span></td></tr><tr><td><code>/sdk/releases</code></td><td>v2</td><td>en <span class="tag">original</span></td><td><code>/sdk/releases/v1-9/guides/caching</code></td><td><span class="tag muted">missing</span></td></tr><tr><td><code>/sdk/v1.9/releases</code></td><td>v1.9</td><td>en <span class="tag">original</span></td><td><code>/sdk/v1.9/releases/v1-9/guides/caching</code></td><td><span class="tag muted">missing</span></td></tr></tbody>
245
245
  </table></div><h2>Nearest paths in docs_de_sdk</h2><div class="scroll"><table>
246
246
  <thead><tr><th scope="col">Path</th></tr></thead>
247
247
  <tbody><tr><td><code>/sdk/getting-started</code></td></tr><tr><td><code>/sdk/getting-started/install</code></td></tr><tr><td><code>/sdk/guides/deploying</code></td></tr><tr><td><code>/sdk/reference/client</code></td></tr><tr><td><code>/sdk/reference/errors</code></td></tr><tr><td><code>/sdk</code></td></tr></tbody>
@@ -236,9 +236,9 @@
236
236
  <main>
237
237
  <h1>Sources</h1>
238
238
  <p class="hint">What <code>duxt.sources</code> became: one collection per source and version, and the URL prefix each serves.</p>
239
- <div class="stats"><div class="stat "><b>6</b><span>collections</span></div><div class="stat "><b>2</b><span>repositories</span></div><div class="stat "><b>2</b><span>versions</span></div><div class="stat "><b>1</b><span>generated section</span></div><div class="stat warn"><b>2</b><span>not current</span></div></div><div class="scroll"><table>
239
+ <div class="stats"><div class="stat "><b>7</b><span>collections</span></div><div class="stat "><b>2</b><span>repositories</span></div><div class="stat "><b>2</b><span>versions</span></div><div class="stat "><b>2</b><span>generated sections</span></div><div class="stat warn"><b>3</b><span>not current</span></div></div><div class="scroll"><table>
240
240
  <thead><tr><th scope="col">Prefix</th><th scope="col">Collection</th><th scope="col">Repository</th><th scope="col">Folder / artefact</th><th scope="col">Ref</th><th scope="col">Version</th><th scope="col">Status</th><th scope="col">Reserved segments</th></tr></thead>
241
- <tbody><tr><td><code>/sdk</code></td><td><code>docs_sdk</code></td><td><a class="file" href="https://github.com/acme/sdk" target="_blank">acme/sdk</a></td><td><code>docs</code></td><td>main <span class="dim">(branch)</span></td><td>v2 <span class="tag">default</span></td><td><span class="tag ok">current</span></td><td><code>v1.9</code> <code>releases</code></td></tr><tr><td><code>/sdk</code></td><td><code>docs_de_sdk</code></td><td><a class="file" href="https://github.com/acme/sdk" target="_blank">acme/sdk</a></td><td><code>docs/de</code></td><td>main <span class="dim">(branch)</span></td><td>v2 <span class="tag">default</span></td><td><span class="tag ok">current</span></td><td><code>v1.9</code> <code>releases</code></td></tr><tr><td><code>/sdk/v1.9</code></td><td><code>docs_sdk_v1_9</code></td><td><a class="file" href="https://github.com/acme/sdk" target="_blank">acme/sdk</a></td><td><code>docs</code></td><td>v1.9.4 <span class="dim">(tag)</span></td><td>v1.9</td><td><span class="tag warn">deprecated</span></td><td><span class="dim">—</span></td></tr><tr><td><code>/sdk/v1.9</code></td><td><code>docs_de_sdk_v1_9</code></td><td><a class="file" href="https://github.com/acme/sdk" target="_blank">acme/sdk</a></td><td><code>docs/de</code></td><td>v1.9.4 <span class="dim">(tag)</span></td><td>v1.9</td><td><span class="tag warn">deprecated</span></td><td><span class="dim">—</span></td></tr><tr><td><code>/cli</code></td><td><code>docs_cli</code></td><td><a class="file" href="https://github.com/acme/cli" target="_blank">acme/cli</a></td><td><code>docs</code></td><td><span class="dim">checkout</span></td><td>— <span class="tag">default</span></td><td><span class="tag ok">current</span></td><td><span class="dim">—</span></td></tr><tr><td><code>/sdk/releases</code></td><td><code>docs_sdk_releases</code> <span class="tag">changelog</span></td><td><a class="file" href="https://github.com/acme/sdk" target="_blank">acme/sdk</a></td><td><code>CHANGELOG.md</code></td><td>main <span class="dim">(branch)</span></td><td>— <span class="tag">default</span></td><td><span class="tag ok">current</span></td><td><span class="dim">—</span></td></tr></tbody>
241
+ <tbody><tr><td><code>/sdk</code></td><td><code>docs_sdk</code></td><td><a class="file" href="https://github.com/acme/sdk" target="_blank">acme/sdk</a></td><td><code>docs</code></td><td>main <span class="dim">(branch)</span></td><td>v2 <span class="tag">default</span></td><td><span class="tag ok">current</span></td><td><code>v1.9</code> <code>releases</code></td></tr><tr><td><code>/sdk</code></td><td><code>docs_de_sdk</code></td><td><a class="file" href="https://github.com/acme/sdk" target="_blank">acme/sdk</a></td><td><code>docs/de</code></td><td>main <span class="dim">(branch)</span></td><td>v2 <span class="tag">default</span></td><td><span class="tag ok">current</span></td><td><code>v1.9</code> <code>releases</code></td></tr><tr><td><code>/sdk/v1.9</code></td><td><code>docs_sdk_v1_9</code></td><td><a class="file" href="https://github.com/acme/sdk" target="_blank">acme/sdk</a></td><td><code>docs</code></td><td>v1.9.4 <span class="dim">(tag)</span></td><td>v1.9</td><td><span class="tag warn">deprecated</span></td><td><code>releases</code></td></tr><tr><td><code>/sdk/v1.9</code></td><td><code>docs_de_sdk_v1_9</code></td><td><a class="file" href="https://github.com/acme/sdk" target="_blank">acme/sdk</a></td><td><code>docs/de</code></td><td>v1.9.4 <span class="dim">(tag)</span></td><td>v1.9</td><td><span class="tag warn">deprecated</span></td><td><code>releases</code></td></tr><tr><td><code>/cli</code></td><td><code>docs_cli</code></td><td><a class="file" href="https://github.com/acme/cli" target="_blank">acme/cli</a></td><td><code>docs</code></td><td><span class="dim">checkout</span></td><td>— <span class="tag">default</span></td><td><span class="tag ok">current</span></td><td><span class="dim">—</span></td></tr><tr><td><code>/sdk/releases</code></td><td><code>docs_sdk_releases</code> <span class="tag">changelog</span></td><td><a class="file" href="https://github.com/acme/sdk" target="_blank">acme/sdk</a></td><td><code>CHANGELOG.md</code></td><td>main <span class="dim">(branch)</span></td><td>v2 <span class="tag">default</span></td><td><span class="tag ok">current</span></td><td><span class="dim">—</span></td></tr><tr><td><code>/sdk/v1.9/releases</code></td><td><code>docs_sdk_v1_9_releases</code> <span class="tag">changelog</span></td><td><a class="file" href="https://github.com/acme/sdk" target="_blank">acme/sdk</a></td><td><code>CHANGELOG.md</code></td><td>v1.9.4 <span class="dim">(tag)</span></td><td>v1.9</td><td><span class="tag warn">deprecated</span></td><td><span class="dim">—</span></td></tr></tbody>
242
242
  </table></div><p class="hint">Configured in /srv/acme-docs/app/app.config.ts.</p>
243
243
  </main>
244
244
  <script>
@@ -242,6 +242,9 @@
242
242
  </table></div><p class="hint">* the version served without a version segment.</p><h2>acme/sdk <span class="tag muted">de</span></h2><div class="scroll"><table class="matrix">
243
243
  <thead><tr><th scope="col">Page</th><th scope="col">v2 *</th><th scope="col">v1.9</th></tr></thead>
244
244
  <tbody><tr><td><code>/</code></td><td class="mark yes">✓</td><td class="mark yes">✓</td></tr><tr><td><code>/getting-started</code></td><td class="mark yes">✓</td><td class="mark yes">✓</td></tr><tr><td><code>/getting-started/install</code></td><td class="mark yes">✓</td><td class="mark yes">✓</td></tr><tr><td><code>/guides/deploying</code></td><td class="mark yes">✓</td><td class="mark yes">✓</td></tr><tr><td><code>/reference/client</code></td><td class="mark yes">✓</td><td class="mark yes">✓</td></tr><tr><td><code>/reference/errors</code></td><td class="mark yes">✓</td><td class="mark no">·</td></tr></tbody>
245
+ </table></div><p class="hint">* the version served without a version segment.</p><h2>acme/sdk <span class="tag muted">en</span> <span class="tag muted">Releases</span></h2><div class="scroll"><table class="matrix">
246
+ <thead><tr><th scope="col">Page</th><th scope="col">v2 *</th><th scope="col">v1.9</th></tr></thead>
247
+ <tbody><tr><td><code>/</code></td><td class="mark yes">✓</td><td class="mark yes">✓</td></tr><tr><td><code>/0.1.0</code></td><td class="mark yes">✓</td><td class="mark yes">✓</td></tr><tr><td><code>/0.1.1</code></td><td class="mark yes">✓</td><td class="mark yes">✓</td></tr><tr><td><code>/0.2.0</code></td><td class="mark yes">✓</td><td class="mark yes">✓</td></tr></tbody>
245
248
  </table></div><p class="hint">* the version served without a version segment.</p><h2>acme/sdk <span class="tag muted">v2</span></h2><div class="scroll"><table class="matrix">
246
249
  <thead><tr><th scope="col">Page</th><th scope="col">en *</th><th scope="col">de</th></tr></thead>
247
250
  <tbody><tr><td><code>/</code></td><td class="mark yes">✓</td><td class="mark yes">✓</td></tr><tr><td><code>/changelog</code></td><td class="mark yes">✓</td><td class="mark no">·</td></tr><tr><td><code>/getting-started</code></td><td class="mark yes">✓</td><td class="mark yes">✓</td></tr><tr><td><code>/getting-started/install</code></td><td class="mark yes">✓</td><td class="mark yes">✓</td></tr><tr><td><code>/guides/caching</code></td><td class="mark yes">✓</td><td class="mark no">·</td></tr><tr><td><code>/guides/deploying</code></td><td class="mark yes">✓</td><td class="mark yes">✓</td></tr><tr><td><code>/reference/client</code></td><td class="mark yes">✓</td><td class="mark yes">✓</td></tr><tr><td><code>/reference/errors</code></td><td class="mark yes">✓</td><td class="mark yes">✓</td></tr></tbody>
package/report.ts CHANGED
@@ -264,8 +264,11 @@ export function duxtReportMarkdown(data: DuxtReport): string {
264
264
  /* The command */
265
265
  /* -------------------------------------------------------------------------- */
266
266
 
267
+ /** The two shapes the same report is printed in. */
268
+ export type DuxtReportFormat = 'markdown' | 'json';
269
+
267
270
  /**
268
- * The command, as a function of its arguments and its data.
271
+ * The report as text, and the exit code that goes with it.
269
272
  *
270
273
  * HERE rather than in the bin, and that is not tidiness. The bin has to be
271
274
  * plain JavaScript — Node refuses to strip types from a file under
@@ -275,29 +278,35 @@ export function duxtReportMarkdown(data: DuxtReport): string {
275
278
  * therefore lives on this side, where it is typed and tested, and the bin is
276
279
  * left with nothing to get wrong.
277
280
  *
281
+ * It takes the format rather than the argv it was asked for in. Which spelling
282
+ * selects JSON is the command line's business, and `cli.ts` is where the
283
+ * command line is read — a second place sniffing argv is how the two drift
284
+ * into disagreeing about what a valid invocation is.
285
+ *
278
286
  * Returns the exit code rather than setting it: warnings do not fail, because
279
287
  * they are what somebody else's repository going stale looks like, and a check
280
288
  * that cannot survive that is a check that gets switched off.
281
289
  */
282
- export function runDuxtReportCli(
283
- argv: string[],
284
- data: DuxtReport
290
+ export function duxtReportOutput(
291
+ data: DuxtReport,
292
+ format: DuxtReportFormat = 'markdown'
285
293
  ): { output: string; exitCode: number } {
286
- const output = argv.includes('--json')
287
- ? JSON.stringify(
288
- {
289
- ...data,
290
- // A Set does not survive `JSON.stringify` — it serialises as `{}`,
291
- // which is a silently empty anchor list rather than an error.
292
- pages: data.pages?.map((page) => ({
293
- ...page,
294
- anchors: [...page.anchors]
295
- }))
296
- },
297
- undefined,
298
- 2
299
- )
300
- : duxtReportMarkdown(data);
294
+ const output =
295
+ format === 'json'
296
+ ? JSON.stringify(
297
+ {
298
+ ...data,
299
+ // A Set does not survive `JSON.stringify` — it serialises as `{}`,
300
+ // which is a silently empty anchor list rather than an error.
301
+ pages: data.pages?.map((page) => ({
302
+ ...page,
303
+ anchors: [...page.anchors]
304
+ }))
305
+ },
306
+ undefined,
307
+ 2
308
+ )
309
+ : duxtReportMarkdown(data);
301
310
 
302
311
  return { output, exitCode: data.findings.errors.length ? 1 : 0 };
303
312
  }