blodemd 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (289) hide show
  1. package/dist/cli.mjs +50 -174
  2. package/dist/cli.mjs.map +1 -1
  3. package/package.json +3 -36
  4. package/dev-server/app/[[...slug]]/page.tsx +0 -140
  5. package/dev-server/app/blodemd-dev/invalidate/route.ts +0 -12
  6. package/dev-server/app/blodemd-dev/static/[...path]/route.ts +0 -32
  7. package/dev-server/app/blodemd-dev/version/route.ts +0 -14
  8. package/dev-server/app/blodemd-internal/proxy/route.ts +0 -86
  9. package/dev-server/app/error.tsx +0 -24
  10. package/dev-server/app/favicon.ico +0 -0
  11. package/dev-server/app/globals.css +0 -4
  12. package/dev-server/app/layout.tsx +0 -38
  13. package/dev-server/app/not-found.tsx +0 -18
  14. package/dev-server/app/search/route.ts +0 -17
  15. package/dev-server/components/dev-reload-script.tsx +0 -86
  16. package/dev-server/components/providers.tsx +0 -15
  17. package/dev-server/lib/dev-state.ts +0 -8
  18. package/dev-server/lib/local-content-source.ts +0 -103
  19. package/dev-server/lib/local-runtime.tsx +0 -555
  20. package/dev-server/next-env.d.ts +0 -5
  21. package/dev-server/next.config.js +0 -54
  22. package/dev-server/package.json +0 -61
  23. package/dev-server/postcss.config.mjs +0 -7
  24. package/dev-server/public/glide-variable.woff2 +0 -0
  25. package/dev-server/tsconfig.json +0 -50
  26. package/docs/app/globals.css +0 -471
  27. package/docs/components/animate-ui/primitives/buttons/button.tsx +0 -14
  28. package/docs/components/api/api-playground.tsx +0 -467
  29. package/docs/components/api/api-reference.tsx +0 -157
  30. package/docs/components/content/collection-index.tsx +0 -114
  31. package/docs/components/docs/contextual-menu.tsx +0 -495
  32. package/docs/components/docs/copy-page-menu.tsx +0 -364
  33. package/docs/components/docs/doc-header.tsx +0 -223
  34. package/docs/components/docs/doc-shell.tsx +0 -355
  35. package/docs/components/docs/doc-sidebar.tsx +0 -256
  36. package/docs/components/docs/doc-toc.tsx +0 -46
  37. package/docs/components/docs/mobile-nav.tsx +0 -195
  38. package/docs/components/docs/sidebar-active-highlight.tsx +0 -34
  39. package/docs/components/docs/sidebar-scroll-area.tsx +0 -63
  40. package/docs/components/git/repo-picker.tsx +0 -529
  41. package/docs/components/icons/doc-icon.tsx +0 -96
  42. package/docs/components/mdx/accordion.tsx +0 -83
  43. package/docs/components/mdx/agent-instructions.tsx +0 -17
  44. package/docs/components/mdx/badge.tsx +0 -79
  45. package/docs/components/mdx/callout.tsx +0 -88
  46. package/docs/components/mdx/card.tsx +0 -110
  47. package/docs/components/mdx/code-block.tsx +0 -80
  48. package/docs/components/mdx/code-group.tsx +0 -203
  49. package/docs/components/mdx/color.tsx +0 -87
  50. package/docs/components/mdx/columns.tsx +0 -25
  51. package/docs/components/mdx/expandable.tsx +0 -45
  52. package/docs/components/mdx/field-layout.tsx +0 -77
  53. package/docs/components/mdx/frame.tsx +0 -23
  54. package/docs/components/mdx/get-text-content.ts +0 -18
  55. package/docs/components/mdx/icon.tsx +0 -12
  56. package/docs/components/mdx/iframe.tsx +0 -62
  57. package/docs/components/mdx/index.tsx +0 -121
  58. package/docs/components/mdx/installer.tsx +0 -20
  59. package/docs/components/mdx/panel.tsx +0 -11
  60. package/docs/components/mdx/param-field.tsx +0 -56
  61. package/docs/components/mdx/preview.tsx +0 -36
  62. package/docs/components/mdx/prompt.tsx +0 -63
  63. package/docs/components/mdx/request-example.tsx +0 -27
  64. package/docs/components/mdx/response-field.tsx +0 -42
  65. package/docs/components/mdx/steps.tsx +0 -92
  66. package/docs/components/mdx/tabs.tsx +0 -193
  67. package/docs/components/mdx/tile.tsx +0 -43
  68. package/docs/components/mdx/tooltip.tsx +0 -71
  69. package/docs/components/mdx/tree.tsx +0 -120
  70. package/docs/components/mdx/type-table.tsx +0 -71
  71. package/docs/components/mdx/update.tsx +0 -44
  72. package/docs/components/mdx/video.tsx +0 -45
  73. package/docs/components/mdx/view.tsx +0 -66
  74. package/docs/components/posthog-provider.tsx +0 -42
  75. package/docs/components/providers.tsx +0 -15
  76. package/docs/components/tenant-analytics.tsx +0 -49
  77. package/docs/components/third-parties.tsx +0 -32
  78. package/docs/components/ui/badge.tsx +0 -61
  79. package/docs/components/ui/breadcrumb.tsx +0 -112
  80. package/docs/components/ui/button-group.tsx +0 -83
  81. package/docs/components/ui/button.tsx +0 -65
  82. package/docs/components/ui/card.tsx +0 -92
  83. package/docs/components/ui/command.tsx +0 -167
  84. package/docs/components/ui/copy-button.tsx +0 -129
  85. package/docs/components/ui/dialog.tsx +0 -146
  86. package/docs/components/ui/field.tsx +0 -237
  87. package/docs/components/ui/input.tsx +0 -23
  88. package/docs/components/ui/kbd.tsx +0 -98
  89. package/docs/components/ui/label.tsx +0 -22
  90. package/docs/components/ui/morph-icon.tsx +0 -79
  91. package/docs/components/ui/popover.tsx +0 -267
  92. package/docs/components/ui/search-dialog.tsx +0 -431
  93. package/docs/components/ui/search.tsx +0 -101
  94. package/docs/components/ui/separator.tsx +0 -26
  95. package/docs/components/ui/sheet.tsx +0 -133
  96. package/docs/components/ui/sidebar.tsx +0 -758
  97. package/docs/components/ui/skeleton.tsx +0 -11
  98. package/docs/components/ui/switch.tsx +0 -32
  99. package/docs/components/ui/tabs.tsx +0 -138
  100. package/docs/components/ui/theme-toggle.tsx +0 -62
  101. package/docs/components/ui/tooltip.tsx +0 -53
  102. package/docs/components/web-mcp.tsx +0 -115
  103. package/docs/lib/agent-skills.ts +0 -48
  104. package/docs/lib/api-client.ts +0 -72
  105. package/docs/lib/config.ts +0 -6
  106. package/docs/lib/content-root.ts +0 -33
  107. package/docs/lib/content-source.ts +0 -70
  108. package/docs/lib/contextual-options.ts +0 -222
  109. package/docs/lib/dashboard-session.ts +0 -167
  110. package/docs/lib/db.ts +0 -13
  111. package/docs/lib/docs-collection.ts +0 -7
  112. package/docs/lib/docs-runtime.tsx +0 -745
  113. package/docs/lib/edge-config.ts +0 -95
  114. package/docs/lib/env.ts +0 -23
  115. package/docs/lib/etag.ts +0 -22
  116. package/docs/lib/github-install.ts +0 -33
  117. package/docs/lib/llms-full.ts +0 -82
  118. package/docs/lib/marketing-markdown.ts +0 -79
  119. package/docs/lib/marketing-site.ts +0 -31
  120. package/docs/lib/mdx.ts +0 -98
  121. package/docs/lib/navigation.ts +0 -288
  122. package/docs/lib/openapi-proxy.ts +0 -88
  123. package/docs/lib/openapi.ts +0 -158
  124. package/docs/lib/platform-config.ts +0 -6
  125. package/docs/lib/project-authz.ts +0 -46
  126. package/docs/lib/routes.ts +0 -103
  127. package/docs/lib/server-cache.ts +0 -83
  128. package/docs/lib/shiki.ts +0 -44
  129. package/docs/lib/supabase.ts +0 -37
  130. package/docs/lib/tenancy.ts +0 -364
  131. package/docs/lib/tenant-headers.ts +0 -43
  132. package/docs/lib/tenant-static.ts +0 -705
  133. package/docs/lib/tenant-utility-context.ts +0 -62
  134. package/docs/lib/tenants.ts +0 -72
  135. package/docs/lib/theme.ts +0 -29
  136. package/docs/lib/time-ago.ts +0 -24
  137. package/docs/lib/toc.ts +0 -2
  138. package/docs/lib/use-mobile.ts +0 -19
  139. package/docs/lib/use-tab-observer.ts +0 -71
  140. package/docs/lib/utils.ts +0 -5
  141. package/packages/@repo/common/dist/index.d.ts +0 -16
  142. package/packages/@repo/common/dist/index.d.ts.map +0 -1
  143. package/packages/@repo/common/dist/index.js +0 -84
  144. package/packages/@repo/common/package.json +0 -34
  145. package/packages/@repo/common/src/index.ts +0 -101
  146. package/packages/@repo/contracts/dist/analytics.d.ts +0 -21
  147. package/packages/@repo/contracts/dist/analytics.d.ts.map +0 -1
  148. package/packages/@repo/contracts/dist/analytics.js +0 -18
  149. package/packages/@repo/contracts/dist/api-key.d.ts +0 -27
  150. package/packages/@repo/contracts/dist/api-key.d.ts.map +0 -1
  151. package/packages/@repo/contracts/dist/api-key.js +0 -20
  152. package/packages/@repo/contracts/dist/dates.d.ts +0 -4
  153. package/packages/@repo/contracts/dist/dates.d.ts.map +0 -1
  154. package/packages/@repo/contracts/dist/dates.js +0 -2
  155. package/packages/@repo/contracts/dist/deployment.d.ts +0 -71
  156. package/packages/@repo/contracts/dist/deployment.d.ts.map +0 -1
  157. package/packages/@repo/contracts/dist/deployment.js +0 -46
  158. package/packages/@repo/contracts/dist/domain.d.ts +0 -94
  159. package/packages/@repo/contracts/dist/domain.d.ts.map +0 -1
  160. package/packages/@repo/contracts/dist/domain.js +0 -36
  161. package/packages/@repo/contracts/dist/git.d.ts +0 -28
  162. package/packages/@repo/contracts/dist/git.d.ts.map +0 -1
  163. package/packages/@repo/contracts/dist/git.js +0 -24
  164. package/packages/@repo/contracts/dist/ids.d.ts +0 -14
  165. package/packages/@repo/contracts/dist/ids.d.ts.map +0 -1
  166. package/packages/@repo/contracts/dist/ids.js +0 -11
  167. package/packages/@repo/contracts/dist/index.d.ts +0 -12
  168. package/packages/@repo/contracts/dist/index.d.ts.map +0 -1
  169. package/packages/@repo/contracts/dist/index.js +0 -13
  170. package/packages/@repo/contracts/dist/pagination.d.ts +0 -23
  171. package/packages/@repo/contracts/dist/pagination.d.ts.map +0 -1
  172. package/packages/@repo/contracts/dist/pagination.js +0 -15
  173. package/packages/@repo/contracts/dist/project.d.ts +0 -42
  174. package/packages/@repo/contracts/dist/project.d.ts.map +0 -1
  175. package/packages/@repo/contracts/dist/project.js +0 -25
  176. package/packages/@repo/contracts/dist/tenant.d.ts +0 -147
  177. package/packages/@repo/contracts/dist/tenant.d.ts.map +0 -1
  178. package/packages/@repo/contracts/dist/tenant.js +0 -58
  179. package/packages/@repo/contracts/dist/user.d.ts +0 -9
  180. package/packages/@repo/contracts/dist/user.d.ts.map +0 -1
  181. package/packages/@repo/contracts/dist/user.js +0 -9
  182. package/packages/@repo/contracts/package.json +0 -37
  183. package/packages/@repo/contracts/src/analytics.ts +0 -33
  184. package/packages/@repo/contracts/src/api-key.ts +0 -27
  185. package/packages/@repo/contracts/src/dates.ts +0 -4
  186. package/packages/@repo/contracts/src/deployment.ts +0 -73
  187. package/packages/@repo/contracts/src/domain.ts +0 -51
  188. package/packages/@repo/contracts/src/git.ts +0 -31
  189. package/packages/@repo/contracts/src/ids.ts +0 -23
  190. package/packages/@repo/contracts/src/index.ts +0 -13
  191. package/packages/@repo/contracts/src/pagination.ts +0 -21
  192. package/packages/@repo/contracts/src/project.ts +0 -32
  193. package/packages/@repo/contracts/src/tenant.ts +0 -94
  194. package/packages/@repo/contracts/src/user.ts +0 -12
  195. package/packages/@repo/models/dist/docs-config.d.ts +0 -961
  196. package/packages/@repo/models/dist/docs-config.d.ts.map +0 -1
  197. package/packages/@repo/models/dist/docs-config.js +0 -531
  198. package/packages/@repo/models/dist/index.d.ts +0 -3
  199. package/packages/@repo/models/dist/index.d.ts.map +0 -1
  200. package/packages/@repo/models/dist/index.js +0 -3
  201. package/packages/@repo/models/dist/tenant.d.ts +0 -37
  202. package/packages/@repo/models/dist/tenant.d.ts.map +0 -1
  203. package/packages/@repo/models/dist/tenant.js +0 -1
  204. package/packages/@repo/models/package.json +0 -37
  205. package/packages/@repo/models/src/docs-config.ts +0 -629
  206. package/packages/@repo/models/src/index.ts +0 -3
  207. package/packages/@repo/models/src/tenant.ts +0 -44
  208. package/packages/@repo/prebuild/dist/index.d.ts +0 -2
  209. package/packages/@repo/prebuild/dist/index.d.ts.map +0 -1
  210. package/packages/@repo/prebuild/dist/index.js +0 -2
  211. package/packages/@repo/prebuild/dist/openapi.d.ts +0 -43
  212. package/packages/@repo/prebuild/dist/openapi.d.ts.map +0 -1
  213. package/packages/@repo/prebuild/dist/openapi.js +0 -86
  214. package/packages/@repo/prebuild/package.json +0 -39
  215. package/packages/@repo/prebuild/src/index.ts +0 -2
  216. package/packages/@repo/prebuild/src/openapi.ts +0 -154
  217. package/packages/@repo/previewing/dist/blob-source.d.ts +0 -16
  218. package/packages/@repo/previewing/dist/blob-source.d.ts.map +0 -1
  219. package/packages/@repo/previewing/dist/blob-source.js +0 -128
  220. package/packages/@repo/previewing/dist/config-loader.d.ts +0 -134
  221. package/packages/@repo/previewing/dist/config-loader.d.ts.map +0 -1
  222. package/packages/@repo/previewing/dist/config-loader.js +0 -231
  223. package/packages/@repo/previewing/dist/constants.d.ts +0 -15
  224. package/packages/@repo/previewing/dist/constants.d.ts.map +0 -1
  225. package/packages/@repo/previewing/dist/constants.js +0 -14
  226. package/packages/@repo/previewing/dist/content-index.d.ts +0 -7
  227. package/packages/@repo/previewing/dist/content-index.d.ts.map +0 -1
  228. package/packages/@repo/previewing/dist/content-index.js +0 -291
  229. package/packages/@repo/previewing/dist/content-source.d.ts +0 -12
  230. package/packages/@repo/previewing/dist/content-source.d.ts.map +0 -1
  231. package/packages/@repo/previewing/dist/content-source.js +0 -1
  232. package/packages/@repo/previewing/dist/fs-source.d.ts +0 -11
  233. package/packages/@repo/previewing/dist/fs-source.d.ts.map +0 -1
  234. package/packages/@repo/previewing/dist/fs-source.js +0 -71
  235. package/packages/@repo/previewing/dist/index.d.ts +0 -16
  236. package/packages/@repo/previewing/dist/index.d.ts.map +0 -1
  237. package/packages/@repo/previewing/dist/index.js +0 -13
  238. package/packages/@repo/previewing/dist/markdown/agent-markdown.d.ts +0 -3
  239. package/packages/@repo/previewing/dist/markdown/agent-markdown.d.ts.map +0 -1
  240. package/packages/@repo/previewing/dist/markdown/agent-markdown.js +0 -176
  241. package/packages/@repo/previewing/dist/markdown/format.d.ts +0 -8
  242. package/packages/@repo/previewing/dist/markdown/format.d.ts.map +0 -1
  243. package/packages/@repo/previewing/dist/markdown/format.js +0 -43
  244. package/packages/@repo/previewing/dist/markdown/links.d.ts +0 -3
  245. package/packages/@repo/previewing/dist/markdown/links.d.ts.map +0 -1
  246. package/packages/@repo/previewing/dist/markdown/links.js +0 -31
  247. package/packages/@repo/previewing/dist/openapi-pages.d.ts +0 -7
  248. package/packages/@repo/previewing/dist/openapi-pages.d.ts.map +0 -1
  249. package/packages/@repo/previewing/dist/openapi-pages.js +0 -200
  250. package/packages/@repo/previewing/dist/search-index.d.ts +0 -4
  251. package/packages/@repo/previewing/dist/search-index.d.ts.map +0 -1
  252. package/packages/@repo/previewing/dist/search-index.js +0 -23
  253. package/packages/@repo/previewing/dist/serialization.d.ts +0 -13
  254. package/packages/@repo/previewing/dist/serialization.d.ts.map +0 -1
  255. package/packages/@repo/previewing/dist/serialization.js +0 -108
  256. package/packages/@repo/previewing/dist/toc-index.d.ts +0 -5
  257. package/packages/@repo/previewing/dist/toc-index.d.ts.map +0 -1
  258. package/packages/@repo/previewing/dist/toc-index.js +0 -53
  259. package/packages/@repo/previewing/dist/types.d.ts +0 -92
  260. package/packages/@repo/previewing/dist/types.d.ts.map +0 -1
  261. package/packages/@repo/previewing/dist/types.js +0 -1
  262. package/packages/@repo/previewing/dist/utility-index.d.ts +0 -7
  263. package/packages/@repo/previewing/dist/utility-index.d.ts.map +0 -1
  264. package/packages/@repo/previewing/dist/utility-index.js +0 -201
  265. package/packages/@repo/previewing/package.json +0 -41
  266. package/packages/@repo/previewing/src/blob-source.ts +0 -185
  267. package/packages/@repo/previewing/src/config-loader.ts +0 -316
  268. package/packages/@repo/previewing/src/constants.ts +0 -16
  269. package/packages/@repo/previewing/src/content-index.ts +0 -384
  270. package/packages/@repo/previewing/src/content-source.ts +0 -12
  271. package/packages/@repo/previewing/src/fs-source.ts +0 -103
  272. package/packages/@repo/previewing/src/index.ts +0 -71
  273. package/packages/@repo/previewing/src/markdown/agent-markdown.ts +0 -254
  274. package/packages/@repo/previewing/src/markdown/format.ts +0 -63
  275. package/packages/@repo/previewing/src/markdown/links.ts +0 -46
  276. package/packages/@repo/previewing/src/openapi-pages.ts +0 -319
  277. package/packages/@repo/previewing/src/search-index.ts +0 -38
  278. package/packages/@repo/previewing/src/serialization.ts +0 -191
  279. package/packages/@repo/previewing/src/toc-index.ts +0 -72
  280. package/packages/@repo/previewing/src/types.ts +0 -105
  281. package/packages/@repo/previewing/src/utility-index.ts +0 -304
  282. package/packages/@repo/validation/dist/index.d.ts +0 -12
  283. package/packages/@repo/validation/dist/index.d.ts.map +0 -1
  284. package/packages/@repo/validation/dist/index.js +0 -30
  285. package/packages/@repo/validation/package.json +0 -38
  286. package/packages/@repo/validation/src/blodemd-docs-schema.json +0 -3575
  287. package/packages/@repo/validation/src/index.ts +0 -59
  288. package/scripts/prepare-package.mjs +0 -53
  289. package/scripts/repo-packages.mjs +0 -8
@@ -1,231 +0,0 @@
1
- import path from "node:path";
2
- import { normalizePath } from "@repo/common";
3
- import { validateDocsConfig, validateSiteConfig } from "@repo/validation";
4
- import { LEGACY_PROJECT_NAME_FALLBACK_WARNING } from "./constants.js";
5
- const DOCS_CONFIG_FILE = "docs.json";
6
- const defaultLinkLabel = (input) => {
7
- if (input.label) {
8
- return input.label;
9
- }
10
- if (input.type === "github") {
11
- return "GitHub";
12
- }
13
- if (input.type === "discord") {
14
- return "Discord";
15
- }
16
- try {
17
- return new URL(input.href).hostname;
18
- }
19
- catch {
20
- return input.href;
21
- }
22
- };
23
- // oxlint-disable-next-line eslint/complexity
24
- const mapDocsConfig = (docs) => {
25
- const navigation = {
26
- global: docs.navbar?.links?.length || docs.navigation.global?.anchors?.length
27
- ? {
28
- anchors: docs.navigation.global?.anchors?.map((anchor) => ({
29
- href: anchor.href,
30
- label: anchor.anchor,
31
- })),
32
- links: docs.navbar?.links?.map((link) => ({
33
- href: link.href,
34
- label: defaultLinkLabel(link),
35
- })),
36
- }
37
- : undefined,
38
- groups: docs.navigation.groups?.map((group) => ({
39
- expanded: group.expanded,
40
- group: group.group,
41
- hidden: group.hidden,
42
- pages: group.root
43
- ? [
44
- group.root,
45
- ...(group.pages ?? []).filter((page) => page !== group.root),
46
- ]
47
- : group.pages,
48
- })),
49
- languages: docs.navigation.languages?.map((language) => ({
50
- label: language.language,
51
- locale: language.language,
52
- url: language.href,
53
- })),
54
- pages: docs.navigation.pages,
55
- tabs: docs.navigation.tabs?.map((tab) => ({
56
- groups: tab.groups?.map((group) => ({
57
- expanded: group.expanded,
58
- group: group.group,
59
- hidden: group.hidden,
60
- pages: group.root
61
- ? [
62
- group.root,
63
- ...(group.pages ?? []).filter((page) => page !== group.root),
64
- ]
65
- : group.pages,
66
- })),
67
- href: tab.href,
68
- icon: tab.icon,
69
- label: tab.tab,
70
- pages: tab.pages,
71
- })),
72
- versions: docs.navigation.versions?.map((version) => ({
73
- label: version.version,
74
- url: version.href,
75
- })),
76
- };
77
- return {
78
- collections: [
79
- {
80
- id: "docs",
81
- navigation,
82
- openapi: docs.api?.openapi,
83
- root: "",
84
- type: "docs",
85
- },
86
- ],
87
- contextual: docs.contextual,
88
- description: docs.description,
89
- favicon: typeof docs.favicon === "string" ? docs.favicon : docs.favicon?.light,
90
- features: {
91
- rightToc: true,
92
- search: true,
93
- themeToggle: docs.appearance?.strict !== true,
94
- toc: true,
95
- },
96
- logo: docs.logo
97
- ? {
98
- dark: typeof docs.logo === "string" ? docs.logo : docs.logo.dark,
99
- href: typeof docs.logo === "string" ? undefined : docs.logo.href,
100
- light: typeof docs.logo === "string" ? docs.logo : docs.logo.light,
101
- }
102
- : undefined,
103
- name: docs.name,
104
- navigation,
105
- openapiProxy: {
106
- enabled: docs.api?.playground?.proxy !== false &&
107
- Boolean(docs.api?.openapi || docs.api?.asyncapi),
108
- },
109
- seo: docs.seo,
110
- slug: docs.slug,
111
- };
112
- };
113
- const getProjectWarnings = (config) => config.slug ? [] : [LEGACY_PROJECT_NAME_FALLBACK_WARNING];
114
- const readJsonConfig = async (source, relativePath) => JSON.parse(await source.readFile(relativePath));
115
- const normalizeRefPath = (baseDirectory, reference) => {
116
- if (reference.startsWith("/") ||
117
- reference.startsWith("\\") ||
118
- reference.startsWith("http://") ||
119
- reference.startsWith("https://")) {
120
- throw new Error(`Invalid $ref "${reference}". Only relative JSON files are supported.`);
121
- }
122
- const normalized = normalizePath(path.posix.join(baseDirectory, reference));
123
- if (!normalized ||
124
- normalized === "." ||
125
- normalized.startsWith("../") ||
126
- normalized.includes("/../")) {
127
- throw new Error(`Invalid $ref "${reference}".`);
128
- }
129
- return normalized;
130
- };
131
- const resolveJsonRefs = async (source, value, baseDirectory, seen) => {
132
- if (Array.isArray(value)) {
133
- return await Promise.all(value.map((item) => resolveJsonRefs(source, item, baseDirectory, seen)));
134
- }
135
- if (!value || typeof value !== "object") {
136
- return value;
137
- }
138
- const record = value;
139
- const reference = record.$ref;
140
- if (typeof reference === "string") {
141
- const resolvedPath = normalizeRefPath(baseDirectory, reference);
142
- if (seen.has(resolvedPath)) {
143
- throw new Error(`Circular $ref detected for "${resolvedPath}".`);
144
- }
145
- const nextSeen = new Set(seen);
146
- // oxlint-disable-next-line eslint-plugin-unicorn/no-immediate-mutation
147
- nextSeen.add(resolvedPath);
148
- const referenced = await readJsonConfig(source, resolvedPath);
149
- const referencedValue = await resolveJsonRefs(source, referenced, path.posix.dirname(resolvedPath) === "."
150
- ? ""
151
- : normalizePath(path.posix.dirname(resolvedPath)), nextSeen);
152
- const siblingEntries = Object.entries(record).filter(([key]) => key !== "$ref");
153
- if (!siblingEntries.length ||
154
- !referencedValue ||
155
- typeof referencedValue !== "object" ||
156
- Array.isArray(referencedValue)) {
157
- return referencedValue;
158
- }
159
- const siblingValue = await resolveJsonRefs(source, Object.fromEntries(siblingEntries), baseDirectory, seen);
160
- return {
161
- ...referencedValue,
162
- ...siblingValue,
163
- };
164
- }
165
- const resolvedEntries = await Promise.all(Object.entries(record).map(async ([key, entryValue]) => [
166
- key,
167
- await resolveJsonRefs(source, entryValue, baseDirectory, seen),
168
- ]));
169
- return Object.fromEntries(resolvedEntries);
170
- };
171
- const readResolvedJsonConfig = async (source, relativePath) => await resolveJsonRefs(source, await readJsonConfig(source, relativePath), path.posix.dirname(relativePath) === "."
172
- ? ""
173
- : normalizePath(path.posix.dirname(relativePath)), new Set([relativePath]));
174
- const loadDocsConfig = async (source) => {
175
- if (!(await source.exists(DOCS_CONFIG_FILE))) {
176
- return null;
177
- }
178
- try {
179
- const parsed = await readResolvedJsonConfig(source, DOCS_CONFIG_FILE);
180
- // Try SiteConfig format first (has collections, theme, colors, etc.)
181
- const siteResult = validateSiteConfig(parsed);
182
- if (siteResult.success) {
183
- return {
184
- config: siteResult.data,
185
- ok: true,
186
- warnings: getProjectWarnings(siteResult.data),
187
- };
188
- }
189
- // Fall back to DocsConfig format (Mintlify-compatible) and map to SiteConfig
190
- const docsResult = validateDocsConfig(parsed);
191
- if (docsResult.success) {
192
- return {
193
- config: mapDocsConfig(docsResult.data),
194
- ok: true,
195
- warnings: getProjectWarnings(docsResult.data),
196
- };
197
- }
198
- return { errors: docsResult.errors, ok: false };
199
- }
200
- catch (error) {
201
- return {
202
- errors: [
203
- error instanceof Error
204
- ? error.message
205
- : `Failed to load ${DOCS_CONFIG_FILE}`,
206
- ],
207
- ok: false,
208
- };
209
- }
210
- };
211
- export const loadSiteConfig = async (source) => {
212
- const docsConfig = await loadDocsConfig(source);
213
- if (docsConfig) {
214
- return docsConfig;
215
- }
216
- return {
217
- errors: [`${DOCS_CONFIG_FILE} not found.`],
218
- ok: false,
219
- };
220
- };
221
- export const getDocsCollection = (config) => config.collections.find((collection) => collection.type === "docs");
222
- export const getDocsNavigation = (config) => getDocsCollection(config)?.navigation ?? config.navigation;
223
- export const getDocsCollectionWithNavigation = (config) => {
224
- const docsCollection = getDocsCollection(config);
225
- const docsNavigation = getDocsNavigation(config);
226
- return docsCollection &&
227
- docsNavigation &&
228
- docsCollection.navigation !== docsNavigation
229
- ? { ...docsCollection, navigation: docsNavigation }
230
- : docsCollection;
231
- };
@@ -1,15 +0,0 @@
1
- export declare const PREBUILT_INDEX_PATH = "_content-index.json";
2
- export declare const PREBUILT_OPENAPI_INDEX_PATH = "_openapi-index.json";
3
- export declare const PREBUILT_SEARCH_INDEX_PATH = "_search-index.json";
4
- export declare const PREBUILT_TOC_INDEX_PATH = "_toc-index.json";
5
- export declare const PREBUILT_UTILITY_INDEX_PATH = "_utility-index.json";
6
- export declare const PREBUILT_UTILITY_SITEMAP_PATH = "_utility/sitemap.xml";
7
- export declare const PREBUILT_UTILITY_LLMS_PATH = "_utility/llms.txt";
8
- export declare const PREBUILT_UTILITY_LLMS_FULL_PATH = "_utility/llms-full.txt";
9
- export declare const PREBUILT_UTILITY_LLMS_SEGMENT_PREFIX = "_utility/llms/";
10
- export declare const PREBUILT_UTILITY_SKILLS_INDEX_PATH = "_utility/skills-index.json";
11
- export declare const PREBUILT_UTILITY_SKILLS_MD_PREFIX = "_utility/skills/";
12
- export declare const UTILITY_DOCS_ROOT_TOKEN = "__BLODEMD_DOCS_ROOT__";
13
- export declare const LEGACY_PROJECT_NAME_FALLBACK_WARNING = "docs.json.slug is recommended. Falling back to docs.json.name as the deployment slug is deprecated.";
14
- export declare const NEWLINE_REGEX: RegExp;
15
- //# sourceMappingURL=constants.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,mBAAmB,wBAAwB,CAAC;AACzD,eAAO,MAAM,2BAA2B,wBAAwB,CAAC;AACjE,eAAO,MAAM,0BAA0B,uBAAuB,CAAC;AAC/D,eAAO,MAAM,uBAAuB,oBAAoB,CAAC;AACzD,eAAO,MAAM,2BAA2B,wBAAwB,CAAC;AACjE,eAAO,MAAM,6BAA6B,yBAAyB,CAAC;AACpE,eAAO,MAAM,0BAA0B,sBAAsB,CAAC;AAC9D,eAAO,MAAM,+BAA+B,2BAA2B,CAAC;AACxE,eAAO,MAAM,oCAAoC,mBAAmB,CAAC;AACrE,eAAO,MAAM,kCAAkC,+BAA+B,CAAC;AAC/E,eAAO,MAAM,iCAAiC,qBAAqB,CAAC;AACpE,eAAO,MAAM,uBAAuB,0BAA0B,CAAC;AAC/D,eAAO,MAAM,oCAAoC,wGACsD,CAAC;AAExG,eAAO,MAAM,aAAa,QAAU,CAAC"}
@@ -1,14 +0,0 @@
1
- export const PREBUILT_INDEX_PATH = "_content-index.json";
2
- export const PREBUILT_OPENAPI_INDEX_PATH = "_openapi-index.json";
3
- export const PREBUILT_SEARCH_INDEX_PATH = "_search-index.json";
4
- export const PREBUILT_TOC_INDEX_PATH = "_toc-index.json";
5
- export const PREBUILT_UTILITY_INDEX_PATH = "_utility-index.json";
6
- export const PREBUILT_UTILITY_SITEMAP_PATH = "_utility/sitemap.xml";
7
- export const PREBUILT_UTILITY_LLMS_PATH = "_utility/llms.txt";
8
- export const PREBUILT_UTILITY_LLMS_FULL_PATH = "_utility/llms-full.txt";
9
- export const PREBUILT_UTILITY_LLMS_SEGMENT_PREFIX = "_utility/llms/";
10
- export const PREBUILT_UTILITY_SKILLS_INDEX_PATH = "_utility/skills-index.json";
11
- export const PREBUILT_UTILITY_SKILLS_MD_PREFIX = "_utility/skills/";
12
- export const UTILITY_DOCS_ROOT_TOKEN = "__BLODEMD_DOCS_ROOT__";
13
- export const LEGACY_PROJECT_NAME_FALLBACK_WARNING = "docs.json.slug is recommended. Falling back to docs.json.name as the deployment slug is deprecated.";
14
- export const NEWLINE_REGEX = /\r?\n/;
@@ -1,7 +0,0 @@
1
- import type { SiteConfig } from "@repo/models";
2
- import type { ContentSource } from "./content-source.js";
3
- import type { ContentEntry, ContentIndex, PageMetadata } from "./types.js";
4
- export declare const buildPageMetadataMap: (index: ContentIndex) => Map<string, PageMetadata>;
5
- export declare const buildContentIndex: (source: ContentSource, config: SiteConfig) => Promise<ContentIndex>;
6
- export declare const shouldIncludeSearchEntry: (entry: ContentEntry, pageMetadataMap: Map<string, PageMetadata>, config: SiteConfig) => boolean;
7
- //# sourceMappingURL=content-index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"content-index.d.ts","sourceRoot":"","sources":["../src/content-index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAKV,UAAU,EACX,MAAM,cAAc,CAAC;AAItB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAI3E,eAAO,MAAM,oBAAoB,GAC/B,OAAO,YAAY,KAClB,GAAG,CAAC,MAAM,EAAE,YAAY,CAiD1B,CAAC;AA8MF,eAAO,MAAM,iBAAiB,GAC5B,QAAQ,aAAa,EACrB,QAAQ,UAAU,KACjB,OAAO,CAAC,YAAY,CAkFtB,CAAC;AAEF,eAAO,MAAM,wBAAwB,GACnC,OAAO,YAAY,EACnB,iBAAiB,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,EAC1C,QAAQ,UAAU,YAiBnB,CAAC"}
@@ -1,291 +0,0 @@
1
- import path from "node:path";
2
- import { normalizePath } from "@repo/common";
3
- import { PageModeSchema } from "@repo/models";
4
- import { validateFrontmatter } from "@repo/validation";
5
- import { parseFrontmatter } from "./markdown/format.js";
6
- const validModes = new Set(PageModeSchema.options);
7
- export const buildPageMetadataMap = (index) => {
8
- const map = new Map();
9
- for (const entry of index.entries) {
10
- if (entry.kind !== "entry") {
11
- continue;
12
- }
13
- const fm = entry.frontmatter;
14
- const meta = {
15
- title: entry.title,
16
- };
17
- if (typeof fm.sidebarTitle === "string") {
18
- meta.sidebarTitle = fm.sidebarTitle;
19
- }
20
- if (typeof fm.icon === "string") {
21
- meta.icon = fm.icon;
22
- }
23
- if (typeof fm.iconType === "string") {
24
- meta.iconType = fm.iconType;
25
- }
26
- if (typeof fm.tag === "string") {
27
- meta.tag = fm.tag;
28
- }
29
- if (typeof fm.hidden === "boolean") {
30
- meta.hidden = fm.hidden;
31
- }
32
- if (typeof fm.deprecated === "boolean") {
33
- meta.deprecated = fm.deprecated;
34
- }
35
- if (typeof fm.url === "string") {
36
- meta.url = fm.url;
37
- }
38
- if (typeof fm.mode === "string" && validModes.has(fm.mode)) {
39
- meta.mode = fm.mode;
40
- }
41
- if (typeof fm.noindex === "boolean") {
42
- meta.noindex = fm.noindex;
43
- }
44
- if (typeof fm.hideFooterPagination === "boolean") {
45
- meta.hideFooterPagination = fm.hideFooterPagination;
46
- }
47
- if (typeof fm.hideApiMarker === "boolean") {
48
- meta.hideApiMarker = fm.hideApiMarker;
49
- }
50
- if (Array.isArray(fm.keywords)) {
51
- meta.keywords = fm.keywords;
52
- }
53
- map.set(entry.slug, meta);
54
- }
55
- return map;
56
- };
57
- const DOC_FILE_EXTENSION_REGEX = /\.(mdx|md)$/;
58
- const INDEX_SUFFIX = "/index";
59
- const titleFromSlug = (slug) => {
60
- const clean = slug.replaceAll("-", " ").split("/").pop() ?? slug;
61
- if (clean === "index") {
62
- return "Overview";
63
- }
64
- return clean.replaceAll(/\b\w/g, (char) => char.toUpperCase());
65
- };
66
- const slugFromFile = (relativePath) => {
67
- const clean = normalizePath(relativePath);
68
- const withoutExt = clean.replace(DOC_FILE_EXTENSION_REGEX, "");
69
- if (withoutExt.endsWith(INDEX_SUFFIX)) {
70
- const trimmed = withoutExt.slice(0, -INDEX_SUFFIX.length);
71
- return trimmed.length ? trimmed : "index";
72
- }
73
- return withoutExt.length ? withoutExt : "index";
74
- };
75
- const listContentFiles = async (source, directory) => {
76
- const files = await source.listFiles(directory);
77
- return files.filter((file) => DOC_FILE_EXTENSION_REGEX.test(file));
78
- };
79
- const sortDefaults = {
80
- blog: { direction: "desc", field: "date" },
81
- courses: { direction: "asc", field: "order" },
82
- docs: { direction: "asc", field: "title" },
83
- forms: { direction: "asc", field: "title" },
84
- notes: { direction: "desc", field: "date" },
85
- products: { direction: "asc", field: "title" },
86
- sheets: { direction: "asc", field: "title" },
87
- site: { direction: "asc", field: "title" },
88
- slides: { direction: "asc", field: "title" },
89
- todos: { direction: "desc", field: "date" },
90
- };
91
- const normalizeSortValue = (value) => {
92
- if (typeof value === "number") {
93
- return value;
94
- }
95
- if (typeof value === "string") {
96
- const timestamp = Date.parse(value);
97
- if (!Number.isNaN(timestamp)) {
98
- return timestamp;
99
- }
100
- return value.toLowerCase();
101
- }
102
- return null;
103
- };
104
- const compareValues = (a, b, direction) => {
105
- const left = normalizeSortValue(a);
106
- const right = normalizeSortValue(b);
107
- if (left === null && right === null) {
108
- return 0;
109
- }
110
- if (left === null) {
111
- return 1;
112
- }
113
- if (right === null) {
114
- return -1;
115
- }
116
- const multiplier = direction === "desc" ? -1 : 1;
117
- if (typeof left === "number" && typeof right === "number") {
118
- return (left - right) * multiplier;
119
- }
120
- if (left < right) {
121
- return -1 * multiplier;
122
- }
123
- if (left > right) {
124
- return 1 * multiplier;
125
- }
126
- return 0;
127
- };
128
- const autoIndexTypes = new Set([
129
- "blog",
130
- "courses",
131
- "products",
132
- "notes",
133
- "forms",
134
- "sheets",
135
- "slides",
136
- "todos",
137
- ]);
138
- const getCollectionIndex = (collection, slugPrefix) => {
139
- if (collection.index) {
140
- return collection.index;
141
- }
142
- if (autoIndexTypes.has(collection.type)) {
143
- const slug = slugPrefix || collection.id;
144
- return {
145
- slug,
146
- title: titleFromSlug(slug),
147
- };
148
- }
149
- return null;
150
- };
151
- const addEntry = (entry, index, errors) => {
152
- if (index.bySlug.has(entry.slug)) {
153
- errors.push(`slug "${entry.slug}" is defined more than once`);
154
- return;
155
- }
156
- index.entries.push(entry);
157
- index.bySlug.set(entry.slug, entry);
158
- };
159
- const resolveEntrySlug = (relativeSlug, slugPrefix) => {
160
- if (!slugPrefix) {
161
- return relativeSlug;
162
- }
163
- if (relativeSlug === "index") {
164
- return slugPrefix;
165
- }
166
- return normalizePath(`${slugPrefix}/${relativeSlug}`);
167
- };
168
- const buildEntryFromFile = async ({ collection, errors, file, root, slugPrefix, source, }) => {
169
- const sourcePath = root
170
- ? normalizePath(path.join(root, file))
171
- : normalizePath(file);
172
- let entrySource = "";
173
- try {
174
- entrySource = await source.readFile(sourcePath);
175
- }
176
- catch (error) {
177
- errors.push(error instanceof Error ? error.message : `Failed to read ${sourcePath}`);
178
- return null;
179
- }
180
- const { frontmatter } = parseFrontmatter(entrySource);
181
- const frontmatterResult = validateFrontmatter(collection.type, frontmatter);
182
- if (!frontmatterResult.success) {
183
- for (const issue of frontmatterResult.errors) {
184
- errors.push(`${sourcePath}: ${issue}`);
185
- }
186
- }
187
- const resolvedFrontmatter = frontmatterResult.success
188
- ? frontmatterResult.data
189
- : frontmatter;
190
- const relativeSlug = slugFromFile(file);
191
- const slug = resolveEntrySlug(relativeSlug, slugPrefix);
192
- const title = typeof resolvedFrontmatter?.title === "string"
193
- ? resolvedFrontmatter.title
194
- : titleFromSlug(slug);
195
- const description = typeof resolvedFrontmatter?.description === "string"
196
- ? resolvedFrontmatter.description
197
- : undefined;
198
- const hidden = typeof resolvedFrontmatter?.hidden === "boolean"
199
- ? resolvedFrontmatter.hidden
200
- : undefined;
201
- return {
202
- collectionId: collection.id,
203
- description,
204
- frontmatter: resolvedFrontmatter,
205
- hidden: hidden || undefined,
206
- kind: "entry",
207
- relativePath: sourcePath,
208
- slug,
209
- sourcePath,
210
- title,
211
- type: collection.type,
212
- };
213
- };
214
- export const buildContentIndex = async (source, config) => {
215
- const errors = [];
216
- const index = {
217
- byCollection: new Map(),
218
- bySlug: new Map(),
219
- entries: [],
220
- errors,
221
- };
222
- for (const collection of config.collections) {
223
- const root = normalizePath(collection.root ?? "");
224
- const slugPrefix = normalizePath(collection.slugPrefix ?? "");
225
- let files = [];
226
- try {
227
- files = await listContentFiles(source, root);
228
- }
229
- catch (error) {
230
- errors.push(error instanceof Error ? error.message : `Failed to read ${root || "."}`);
231
- continue;
232
- }
233
- const collectionEntries = [];
234
- const resolvedEntries = await Promise.all(files.map(async (file) => await buildEntryFromFile({
235
- collection,
236
- errors,
237
- file,
238
- root,
239
- slugPrefix,
240
- source,
241
- })));
242
- for (const entry of resolvedEntries) {
243
- if (!entry) {
244
- continue;
245
- }
246
- collectionEntries.push(entry);
247
- addEntry(entry, index, errors);
248
- }
249
- const sortConfig = {
250
- ...sortDefaults[collection.type],
251
- ...collection.sort,
252
- };
253
- const sortField = sortConfig.field ?? "title";
254
- const sortDirection = sortConfig.direction ?? "asc";
255
- collectionEntries.sort((left, right) => {
256
- const leftValue = left.kind === "entry"
257
- ? left.frontmatter[sortField]
258
- : undefined;
259
- const rightValue = right.kind === "entry"
260
- ? right.frontmatter[sortField]
261
- : undefined;
262
- return compareValues(leftValue, rightValue, sortDirection);
263
- });
264
- index.byCollection.set(collection.id, collectionEntries);
265
- const collectionIndex = getCollectionIndex(collection, slugPrefix);
266
- if (collectionIndex) {
267
- const indexEntry = {
268
- collectionId: collection.id,
269
- description: collectionIndex.description,
270
- kind: "index",
271
- slug: collectionIndex.slug,
272
- title: collectionIndex.title ?? titleFromSlug(collectionIndex.slug),
273
- type: collection.type,
274
- };
275
- addEntry(indexEntry, index, errors);
276
- }
277
- }
278
- return index;
279
- };
280
- export const shouldIncludeSearchEntry = (entry, pageMetadataMap, config) => {
281
- const pageMeta = pageMetadataMap.get(entry.slug);
282
- if (pageMeta?.hidden || pageMeta?.noindex) {
283
- return false;
284
- }
285
- if (config.seo?.indexing !== "all" &&
286
- entry.kind === "entry" &&
287
- entry.hidden === true) {
288
- return false;
289
- }
290
- return true;
291
- };
@@ -1,12 +0,0 @@
1
- export interface CompiledMdxResult {
2
- compiledSource: string;
3
- version: number;
4
- }
5
- export interface ContentSource {
6
- readFile(relativePath: string): Promise<string>;
7
- listFiles(directory: string): Promise<string[]>;
8
- exists(relativePath: string): Promise<boolean>;
9
- resolveUrl?(relativePath: string): Promise<string | null> | string | null;
10
- readCompiledMdx?(relativePath: string): Promise<CompiledMdxResult | null>;
11
- }
12
- //# sourceMappingURL=content-source.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"content-source.d.ts","sourceRoot":"","sources":["../src/content-source.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,iBAAiB;IAChC,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAChD,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAChD,MAAM,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/C,UAAU,CAAC,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,MAAM,GAAG,IAAI,CAAC;IAC1E,eAAe,CAAC,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAC;CAC3E"}
@@ -1 +0,0 @@
1
- export {};
@@ -1,11 +0,0 @@
1
- import type { ContentSource } from "./content-source.js";
2
- export declare class FsContentSource implements ContentSource {
3
- private readonly root;
4
- constructor(root: string);
5
- readFile(relativePath: string): Promise<string>;
6
- listFiles(directory: string): Promise<string[]>;
7
- exists(relativePath: string): Promise<boolean>;
8
- resolveUrl(): string | null;
9
- }
10
- export declare const createFsSource: (root: string) => ContentSource;
11
- //# sourceMappingURL=fs-source.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"fs-source.d.ts","sourceRoot":"","sources":["../src/fs-source.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AA4DzD,qBAAa,eAAgB,YAAW,aAAa;IACnD,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;gBAElB,IAAI,EAAE,MAAM;IAIlB,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAO/C,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAI/C,MAAM,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAapD,UAAU,IAAI,MAAM,GAAG,IAAI;CAG5B;AAED,eAAO,MAAM,cAAc,GAAI,MAAM,MAAM,KAAG,aACnB,CAAC"}
@@ -1,71 +0,0 @@
1
- import fs from "node:fs/promises";
2
- import path from "node:path";
3
- import { normalizePath, shouldIgnoreRootDocsFile } from "@repo/common";
4
- const IGNORED_DIRECTORIES = new Set(["app", "lib", "node_modules", "public"]);
5
- const isNotFoundError = (error) => Boolean(error &&
6
- typeof error === "object" &&
7
- "code" in error &&
8
- error.code === "ENOENT");
9
- const isWithinRoot = (root, candidate) => candidate === root || candidate.startsWith(`${root}${path.sep}`);
10
- const resolveWithinRoot = (root, relativePath) => {
11
- const normalized = normalizePath(relativePath);
12
- const absolutePath = path.resolve(root, normalized);
13
- if (!isWithinRoot(root, absolutePath)) {
14
- throw new Error(`Path "${relativePath}" escapes the content source root.`);
15
- }
16
- return absolutePath;
17
- };
18
- const walkFiles = async (directory, prefix) => {
19
- const entries = await fs.readdir(directory, { withFileTypes: true });
20
- const files = [];
21
- for (const entry of entries) {
22
- if (entry.name.startsWith(".")) {
23
- continue;
24
- }
25
- const absolutePath = path.join(directory, entry.name);
26
- const relativePath = prefix ? path.join(prefix, entry.name) : entry.name;
27
- if (entry.isDirectory()) {
28
- if (IGNORED_DIRECTORIES.has(entry.name)) {
29
- continue;
30
- }
31
- files.push(...(await walkFiles(absolutePath, relativePath)));
32
- continue;
33
- }
34
- if (entry.isFile()) {
35
- if (!prefix && shouldIgnoreRootDocsFile(entry.name)) {
36
- continue;
37
- }
38
- files.push(normalizePath(relativePath));
39
- }
40
- }
41
- return files;
42
- };
43
- export class FsContentSource {
44
- root;
45
- constructor(root) {
46
- this.root = path.resolve(root);
47
- }
48
- async readFile(relativePath) {
49
- return await fs.readFile(resolveWithinRoot(this.root, relativePath), "utf8");
50
- }
51
- async listFiles(directory) {
52
- return await walkFiles(resolveWithinRoot(this.root, directory), "");
53
- }
54
- async exists(relativePath) {
55
- try {
56
- await fs.access(resolveWithinRoot(this.root, relativePath));
57
- return true;
58
- }
59
- catch (error) {
60
- if (isNotFoundError(error)) {
61
- return false;
62
- }
63
- throw error;
64
- }
65
- }
66
- // oxlint-disable-next-line eslint/class-methods-use-this
67
- resolveUrl() {
68
- return null;
69
- }
70
- }
71
- export const createFsSource = (root) => new FsContentSource(root);