blodemd 0.0.12 → 0.0.14

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 (138) hide show
  1. package/README.md +1 -1
  2. package/dev-server/lib/local-runtime.tsx +12 -15
  3. package/dev-server/next.config.js +19 -9
  4. package/dev-server/package.json +5 -1
  5. package/dev-server/tsconfig.json +0 -3
  6. package/dist/cli.mjs +1205 -969
  7. package/dist/cli.mjs.map +1 -1
  8. package/docs/app/globals.css +1 -1
  9. package/docs/components/api/api-playground.tsx +2 -5
  10. package/docs/components/api/api-reference.tsx +29 -3
  11. package/docs/components/docs/contextual-menu.tsx +37 -33
  12. package/docs/components/docs/copy-page-menu.tsx +18 -0
  13. package/docs/components/docs/doc-header.tsx +4 -1
  14. package/docs/components/docs/doc-shell.tsx +48 -18
  15. package/docs/components/docs/doc-sidebar.tsx +131 -89
  16. package/docs/components/docs/doc-toc.tsx +1 -0
  17. package/docs/components/docs/mobile-nav.tsx +72 -68
  18. package/docs/components/docs/sidebar-active-highlight.tsx +34 -0
  19. package/docs/components/docs/sidebar-scroll-area.tsx +9 -4
  20. package/docs/components/git/repo-picker.tsx +5 -2
  21. package/docs/components/mdx/index.tsx +31 -21
  22. package/docs/components/posthog-provider.tsx +42 -0
  23. package/docs/components/tenant-analytics.tsx +49 -0
  24. package/docs/components/third-parties.tsx +4 -1
  25. package/docs/components/ui/copy-button.tsx +16 -2
  26. package/docs/components/ui/search-dialog.tsx +431 -0
  27. package/docs/components/ui/search.tsx +44 -427
  28. package/docs/components/web-mcp.tsx +115 -0
  29. package/docs/lib/agent-skills.ts +48 -0
  30. package/docs/lib/config.ts +4 -5
  31. package/docs/lib/docs-collection.ts +7 -22
  32. package/docs/lib/docs-runtime.tsx +160 -10
  33. package/docs/lib/llms-full.ts +82 -0
  34. package/docs/lib/marketing-markdown.ts +79 -0
  35. package/docs/lib/marketing-site.ts +31 -0
  36. package/docs/lib/mdx.ts +17 -6
  37. package/docs/lib/routes.ts +19 -3
  38. package/docs/lib/shiki.ts +4 -0
  39. package/docs/lib/tenancy.ts +15 -2
  40. package/docs/lib/tenant-headers.ts +29 -0
  41. package/docs/lib/tenant-static.ts +73 -99
  42. package/package.json +10 -5
  43. package/packages/@repo/common/package.json +3 -3
  44. package/packages/@repo/contracts/dist/analytics.d.ts +21 -0
  45. package/packages/@repo/contracts/dist/analytics.d.ts.map +1 -0
  46. package/packages/@repo/contracts/dist/analytics.js +18 -0
  47. package/packages/@repo/contracts/dist/deployment.js +1 -1
  48. package/packages/@repo/contracts/dist/git.js +2 -2
  49. package/packages/@repo/contracts/dist/ids.d.ts.map +1 -1
  50. package/packages/@repo/contracts/dist/ids.js +2 -1
  51. package/packages/@repo/contracts/dist/index.d.ts +1 -0
  52. package/packages/@repo/contracts/dist/index.d.ts.map +1 -1
  53. package/packages/@repo/contracts/dist/index.js +1 -0
  54. package/packages/@repo/contracts/dist/project.d.ts +18 -1
  55. package/packages/@repo/contracts/dist/project.d.ts.map +1 -1
  56. package/packages/@repo/contracts/dist/project.js +3 -1
  57. package/packages/@repo/contracts/dist/tenant.d.ts +36 -0
  58. package/packages/@repo/contracts/dist/tenant.d.ts.map +1 -1
  59. package/packages/@repo/contracts/dist/tenant.js +2 -0
  60. package/packages/@repo/contracts/package.json +3 -3
  61. package/packages/@repo/contracts/src/analytics.ts +33 -0
  62. package/packages/@repo/contracts/src/deployment.ts +1 -1
  63. package/packages/@repo/contracts/src/git.ts +2 -2
  64. package/packages/@repo/contracts/src/ids.ts +2 -1
  65. package/packages/@repo/contracts/src/index.ts +1 -0
  66. package/packages/@repo/contracts/src/project.ts +3 -1
  67. package/packages/@repo/contracts/src/tenant.ts +2 -0
  68. package/packages/@repo/models/dist/docs-config.d.ts +0 -198
  69. package/packages/@repo/models/dist/docs-config.d.ts.map +1 -1
  70. package/packages/@repo/models/dist/docs-config.js +3 -2
  71. package/packages/@repo/models/dist/tenant.d.ts +12 -0
  72. package/packages/@repo/models/dist/tenant.d.ts.map +1 -1
  73. package/packages/@repo/models/package.json +3 -3
  74. package/packages/@repo/models/src/docs-config.ts +3 -3
  75. package/packages/@repo/models/src/tenant.ts +15 -0
  76. package/packages/@repo/prebuild/dist/openapi.d.ts.map +1 -1
  77. package/packages/@repo/prebuild/dist/openapi.js +32 -4
  78. package/packages/@repo/prebuild/package.json +3 -3
  79. package/packages/@repo/prebuild/src/openapi.ts +42 -4
  80. package/packages/@repo/previewing/dist/blob-source.d.ts.map +1 -1
  81. package/packages/@repo/previewing/dist/blob-source.js +18 -5
  82. package/packages/@repo/previewing/dist/config-loader.d.ts +134 -0
  83. package/packages/@repo/previewing/dist/config-loader.d.ts.map +1 -0
  84. package/packages/@repo/previewing/dist/config-loader.js +231 -0
  85. package/packages/@repo/previewing/dist/constants.d.ts +15 -0
  86. package/packages/@repo/previewing/dist/constants.d.ts.map +1 -0
  87. package/packages/@repo/previewing/dist/constants.js +14 -0
  88. package/packages/@repo/previewing/dist/content-index.d.ts +7 -0
  89. package/packages/@repo/previewing/dist/content-index.d.ts.map +1 -0
  90. package/packages/@repo/previewing/dist/content-index.js +291 -0
  91. package/packages/@repo/previewing/dist/index.d.ts +13 -121
  92. package/packages/@repo/previewing/dist/index.d.ts.map +1 -1
  93. package/packages/@repo/previewing/dist/index.js +11 -1003
  94. package/packages/@repo/previewing/dist/markdown/agent-markdown.d.ts +3 -0
  95. package/packages/@repo/previewing/dist/markdown/agent-markdown.d.ts.map +1 -0
  96. package/packages/@repo/previewing/dist/markdown/agent-markdown.js +176 -0
  97. package/packages/@repo/previewing/dist/markdown/format.d.ts +8 -0
  98. package/packages/@repo/previewing/dist/markdown/format.d.ts.map +1 -0
  99. package/packages/@repo/previewing/dist/markdown/format.js +43 -0
  100. package/packages/@repo/previewing/dist/markdown/links.d.ts +3 -0
  101. package/packages/@repo/previewing/dist/markdown/links.d.ts.map +1 -0
  102. package/packages/@repo/previewing/dist/markdown/links.js +31 -0
  103. package/packages/@repo/previewing/dist/openapi-pages.d.ts +7 -0
  104. package/packages/@repo/previewing/dist/openapi-pages.d.ts.map +1 -0
  105. package/packages/@repo/previewing/dist/openapi-pages.js +200 -0
  106. package/packages/@repo/previewing/dist/search-index.d.ts +4 -0
  107. package/packages/@repo/previewing/dist/search-index.d.ts.map +1 -0
  108. package/packages/@repo/previewing/dist/search-index.js +23 -0
  109. package/packages/@repo/previewing/dist/serialization.d.ts +13 -0
  110. package/packages/@repo/previewing/dist/serialization.d.ts.map +1 -0
  111. package/packages/@repo/previewing/dist/serialization.js +108 -0
  112. package/packages/@repo/previewing/dist/toc-index.d.ts +5 -0
  113. package/packages/@repo/previewing/dist/toc-index.d.ts.map +1 -0
  114. package/packages/@repo/previewing/dist/toc-index.js +53 -0
  115. package/packages/@repo/previewing/dist/types.d.ts +92 -0
  116. package/packages/@repo/previewing/dist/types.d.ts.map +1 -0
  117. package/packages/@repo/previewing/dist/types.js +1 -0
  118. package/packages/@repo/previewing/dist/utility-index.d.ts +7 -0
  119. package/packages/@repo/previewing/dist/utility-index.d.ts.map +1 -0
  120. package/packages/@repo/previewing/dist/utility-index.js +201 -0
  121. package/packages/@repo/previewing/package.json +3 -3
  122. package/packages/@repo/previewing/src/blob-source.ts +20 -5
  123. package/packages/@repo/previewing/src/config-loader.ts +316 -0
  124. package/packages/@repo/previewing/src/constants.ts +16 -0
  125. package/packages/@repo/previewing/src/content-index.ts +384 -0
  126. package/packages/@repo/previewing/src/index.ts +69 -1515
  127. package/packages/@repo/previewing/src/markdown/agent-markdown.ts +254 -0
  128. package/packages/@repo/previewing/src/markdown/format.ts +63 -0
  129. package/packages/@repo/previewing/src/markdown/links.ts +46 -0
  130. package/packages/@repo/previewing/src/openapi-pages.ts +319 -0
  131. package/packages/@repo/previewing/src/search-index.ts +38 -0
  132. package/packages/@repo/previewing/src/serialization.ts +191 -0
  133. package/packages/@repo/previewing/src/toc-index.ts +72 -0
  134. package/packages/@repo/previewing/src/types.ts +105 -0
  135. package/packages/@repo/previewing/src/utility-index.ts +304 -0
  136. package/packages/@repo/validation/package.json +3 -3
  137. package/scripts/repo-packages.mjs +8 -0
  138. package/docs/components/ui/site-footer.tsx +0 -41
@@ -39,21 +39,38 @@ export interface OpenApiOperation {
39
39
  responses?: Record<string, unknown>;
40
40
  }
41
41
 
42
+ const isRecord = (value: unknown): value is Record<string, unknown> =>
43
+ typeof value === "object" && value !== null && !Array.isArray(value);
44
+
45
+ // A YAML/JSON document can parse to a scalar, null, or array — none of which
46
+ // are usable as an OpenAPI spec. Validate the shape before the cast so callers
47
+ // fail with a clear message instead of crashing while iterating `paths`.
48
+ const asOpenApiSpec = (value: unknown, sourcePath: string): OpenApiSpec => {
49
+ const label = sourcePath ? ` (${sourcePath})` : "";
50
+ if (!isRecord(value)) {
51
+ throw new Error(`OpenAPI spec${label} must be an object.`);
52
+ }
53
+ if (value.paths !== undefined && !isRecord(value.paths)) {
54
+ throw new Error(`OpenAPI spec${label} has an invalid "paths" section.`);
55
+ }
56
+ return value as OpenApiSpec;
57
+ };
58
+
42
59
  export const parseOpenApiSpec = (raw: string, sourcePath = ""): OpenApiSpec => {
43
60
  const ext = path.extname(sourcePath).toLowerCase();
44
61
 
45
62
  if (ext === ".json") {
46
- return JSON.parse(raw) as OpenApiSpec;
63
+ return asOpenApiSpec(JSON.parse(raw), sourcePath);
47
64
  }
48
65
 
49
66
  if (ext === ".yaml" || ext === ".yml") {
50
- return YAML.parse(raw) as OpenApiSpec;
67
+ return asOpenApiSpec(YAML.parse(raw), sourcePath);
51
68
  }
52
69
 
53
70
  try {
54
- return JSON.parse(raw) as OpenApiSpec;
71
+ return asOpenApiSpec(JSON.parse(raw), sourcePath);
55
72
  } catch {
56
- return YAML.parse(raw) as OpenApiSpec;
73
+ return asOpenApiSpec(YAML.parse(raw), sourcePath);
57
74
  }
58
75
  };
59
76
 
@@ -80,6 +97,20 @@ export const openApiSlug = (
80
97
  return normalizePath(path.join(directory, slug));
81
98
  };
82
99
 
100
+ const HTTP_METHODS = new Set([
101
+ "delete",
102
+ "get",
103
+ "head",
104
+ "options",
105
+ "patch",
106
+ "post",
107
+ "put",
108
+ "trace",
109
+ ]);
110
+
111
+ const isOperationObject = (value: unknown): value is OpenApiOperationSpec =>
112
+ typeof value === "object" && value !== null && !Array.isArray(value);
113
+
83
114
  export const extractOpenApiOperations = (
84
115
  spec: OpenApiSpec,
85
116
  directory?: string
@@ -89,6 +120,13 @@ export const extractOpenApiOperations = (
89
120
 
90
121
  for (const [routePath, methods] of Object.entries(paths)) {
91
122
  for (const [method, operation] of Object.entries(methods)) {
123
+ if (
124
+ !(
125
+ HTTP_METHODS.has(method.toLowerCase()) && isOperationObject(operation)
126
+ )
127
+ ) {
128
+ continue;
129
+ }
92
130
  const upper = method.toUpperCase();
93
131
  const id = operation.operationId ?? openApiIdentifier(upper, routePath);
94
132
 
@@ -1 +1 @@
1
- {"version":3,"file":"blob-source.d.ts","sourceRoot":"","sources":["../src/blob-source.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AA8C5E,qBAAa,iBAAkB,YAAW,aAAa;IACrD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAS;IACnC,OAAO,CAAC,eAAe,CAAC,CAA+B;gBAE3C,WAAW,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM;IAKlD,OAAO,CAAC,eAAe;YAaT,YAAY;IA2BpB,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAc/C,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAe/C,MAAM,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAK9C,UAAU,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAKxD,eAAe,CACnB,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC;CAuBrC;AAED,eAAO,MAAM,gBAAgB,GAC3B,aAAa,MAAM,EACnB,WAAW,MAAM,KAChB,aAA6D,CAAC"}
1
+ {"version":3,"file":"blob-source.d.ts","sourceRoot":"","sources":["../src/blob-source.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AA8C5E,qBAAa,iBAAkB,YAAW,aAAa;IACrD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAS;IACnC,OAAO,CAAC,eAAe,CAAC,CAA+B;gBAE3C,WAAW,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM;IAKlD,OAAO,CAAC,eAAe;YAaT,YAAY;IA2BpB,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAc/C,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IA8B/C,MAAM,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAK9C,UAAU,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAKxD,eAAe,CACnB,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC;CAuBrC;AAED,eAAO,MAAM,gBAAgB,GAC3B,aAAa,MAAM,EACnB,WAAW,MAAM,KAChB,aAA6D,CAAC"}
@@ -72,12 +72,25 @@ export class BlobContentSource {
72
72
  async listFiles(directory) {
73
73
  const manifest = await this.loadManifest();
74
74
  const prefix = normalizeDirectory(directory);
75
- const files = [...manifest.keys()].filter((file) => {
76
- if (shouldIgnoreRootDocsFile(file)) {
77
- return false;
75
+ const files = [];
76
+ for (const file of manifest.keys()) {
77
+ if (prefix && !file.startsWith(prefix)) {
78
+ continue;
78
79
  }
79
- return prefix ? file.startsWith(prefix) : true;
80
- });
80
+ // Return paths relative to the listed directory, matching
81
+ // FsContentSource so callers can join them onto the collection root.
82
+ const relativePath = prefix ? file.slice(prefix.length) : file;
83
+ if (!relativePath) {
84
+ continue;
85
+ }
86
+ // Only top-level entries of the listed directory are subject to the
87
+ // root-docs-file ignore list, again matching FsContentSource.
88
+ if (!relativePath.includes("/") &&
89
+ shouldIgnoreRootDocsFile(relativePath)) {
90
+ continue;
91
+ }
92
+ files.push(relativePath);
93
+ }
81
94
  // oxlint-disable-next-line eslint-plugin-unicorn/no-array-sort
82
95
  files.sort();
83
96
  return files;
@@ -0,0 +1,134 @@
1
+ import type { SiteConfig } from "@repo/models";
2
+ import type { ContentSource } from "./content-source.js";
3
+ import type { SiteConfigResult } from "./types.js";
4
+ export declare const loadSiteConfig: (source: ContentSource) => Promise<SiteConfigResult>;
5
+ export declare const getDocsCollection: (config: SiteConfig) => {
6
+ id: string;
7
+ type: "site" | "blog" | "docs" | "courses" | "products" | "notes" | "forms" | "sheets" | "slides" | "todos";
8
+ index?: {
9
+ slug: string;
10
+ description?: string | undefined;
11
+ hidden?: boolean | undefined;
12
+ title?: string | undefined;
13
+ } | undefined;
14
+ navigation?: {
15
+ global?: {
16
+ anchors?: {
17
+ href: string;
18
+ label: string;
19
+ }[] | undefined;
20
+ links?: {
21
+ href: string;
22
+ label: string;
23
+ }[] | undefined;
24
+ } | undefined;
25
+ groups?: {
26
+ expanded?: boolean | undefined;
27
+ group?: string | undefined;
28
+ hidden?: boolean | undefined;
29
+ openapi?: string | {
30
+ source: string;
31
+ basePath?: string | undefined;
32
+ directory?: string | undefined;
33
+ include?: string[] | undefined;
34
+ } | undefined;
35
+ pages?: string[] | undefined;
36
+ }[] | undefined;
37
+ hidden?: string[] | undefined;
38
+ languages?: {
39
+ label: string;
40
+ url: string;
41
+ locale?: string | undefined;
42
+ }[] | undefined;
43
+ pages?: string[] | undefined;
44
+ tabs?: {
45
+ label: string;
46
+ groups?: {
47
+ expanded?: boolean | undefined;
48
+ group?: string | undefined;
49
+ hidden?: boolean | undefined;
50
+ openapi?: string | {
51
+ source: string;
52
+ basePath?: string | undefined;
53
+ directory?: string | undefined;
54
+ include?: string[] | undefined;
55
+ } | undefined;
56
+ pages?: string[] | undefined;
57
+ }[] | undefined;
58
+ href?: string | undefined;
59
+ icon?: string | undefined;
60
+ pages?: string[] | undefined;
61
+ }[] | undefined;
62
+ versions?: {
63
+ label: string;
64
+ url: string;
65
+ }[] | undefined;
66
+ } | undefined;
67
+ openapi?: string | string[] | {
68
+ source: string;
69
+ basePath?: string | undefined;
70
+ directory?: string | undefined;
71
+ include?: string[] | undefined;
72
+ } | undefined;
73
+ root?: string | undefined;
74
+ slugPrefix?: string | undefined;
75
+ sort?: {
76
+ direction?: "asc" | "desc" | undefined;
77
+ field?: "date" | "title" | "order" | "price" | undefined;
78
+ } | undefined;
79
+ } | undefined;
80
+ export declare const getDocsNavigation: (config: SiteConfig) => {
81
+ global?: {
82
+ anchors?: {
83
+ href: string;
84
+ label: string;
85
+ }[] | undefined;
86
+ links?: {
87
+ href: string;
88
+ label: string;
89
+ }[] | undefined;
90
+ } | undefined;
91
+ groups?: {
92
+ expanded?: boolean | undefined;
93
+ group?: string | undefined;
94
+ hidden?: boolean | undefined;
95
+ openapi?: string | {
96
+ source: string;
97
+ basePath?: string | undefined;
98
+ directory?: string | undefined;
99
+ include?: string[] | undefined;
100
+ } | undefined;
101
+ pages?: string[] | undefined;
102
+ }[] | undefined;
103
+ hidden?: string[] | undefined;
104
+ languages?: {
105
+ label: string;
106
+ url: string;
107
+ locale?: string | undefined;
108
+ }[] | undefined;
109
+ pages?: string[] | undefined;
110
+ tabs?: {
111
+ label: string;
112
+ groups?: {
113
+ expanded?: boolean | undefined;
114
+ group?: string | undefined;
115
+ hidden?: boolean | undefined;
116
+ openapi?: string | {
117
+ source: string;
118
+ basePath?: string | undefined;
119
+ directory?: string | undefined;
120
+ include?: string[] | undefined;
121
+ } | undefined;
122
+ pages?: string[] | undefined;
123
+ }[] | undefined;
124
+ href?: string | undefined;
125
+ icon?: string | undefined;
126
+ pages?: string[] | undefined;
127
+ }[] | undefined;
128
+ versions?: {
129
+ label: string;
130
+ url: string;
131
+ }[] | undefined;
132
+ } | undefined;
133
+ export declare const getDocsCollectionWithNavigation: (config: SiteConfig) => SiteConfig["collections"][number] | undefined;
134
+ //# sourceMappingURL=config-loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-loader.d.ts","sourceRoot":"","sources":["../src/config-loader.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAc,UAAU,EAAE,MAAM,cAAc,CAAC;AAI3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAoRnD,eAAO,MAAM,cAAc,GACzB,QAAQ,aAAa,KACpB,OAAO,CAAC,gBAAgB,CAU1B,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAI,QAAQ,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aACiB,CAAC;AAEtE,eAAO,MAAM,iBAAiB,GAAI,QAAQ,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aACQ,CAAC;AAE7D,eAAO,MAAM,+BAA+B,GAC1C,QAAQ,UAAU,KACjB,UAAU,CAAC,aAAa,CAAC,CAAC,MAAM,CAAC,GAAG,SAStC,CAAC"}
@@ -0,0 +1,231 @@
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
+ };
@@ -0,0 +1,15 @@
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
@@ -0,0 +1 @@
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"}
@@ -0,0 +1,14 @@
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/;
@@ -0,0 +1,7 @@
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
@@ -0,0 +1 @@
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"}