specra 0.1.13 → 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 (276) hide show
  1. package/LICENSE.MD +25 -4
  2. package/README.md +67 -58
  3. package/config/specra.config.schema.json +16 -0
  4. package/config/svelte-config.js +63 -0
  5. package/dist/api-parser.types.d.ts +59 -0
  6. package/dist/api-parser.types.js +5 -0
  7. package/dist/api.types.d.ts +137 -0
  8. package/dist/api.types.js +5 -0
  9. package/dist/category.d.ts +21 -0
  10. package/dist/category.js +48 -0
  11. package/dist/components/ConfigProvider.svelte +13 -0
  12. package/dist/components/ConfigProvider.svelte.d.ts +31 -0
  13. package/dist/components/docs/Accordion.svelte +18 -0
  14. package/dist/components/docs/Accordion.svelte.d.ts +10 -0
  15. package/dist/components/docs/AccordionItem.svelte +41 -0
  16. package/dist/components/docs/AccordionItem.svelte.d.ts +10 -0
  17. package/dist/components/docs/Badge.svelte +28 -0
  18. package/dist/components/docs/Badge.svelte.d.ts +9 -0
  19. package/dist/components/docs/Breadcrumb.svelte +80 -0
  20. package/dist/components/docs/Breadcrumb.svelte.d.ts +8 -0
  21. package/dist/components/docs/Callout.svelte +96 -0
  22. package/dist/components/docs/Callout.svelte.d.ts +10 -0
  23. package/dist/components/docs/Card.svelte +63 -0
  24. package/dist/components/docs/Card.svelte.d.ts +12 -0
  25. package/dist/components/docs/CardGrid.svelte +24 -0
  26. package/dist/components/docs/CardGrid.svelte.d.ts +8 -0
  27. package/dist/components/docs/CategoryIndex.svelte +110 -0
  28. package/dist/components/docs/CategoryIndex.svelte.d.ts +29 -0
  29. package/dist/components/docs/CodeBlock.svelte +172 -0
  30. package/dist/components/docs/CodeBlock.svelte.d.ts +8 -0
  31. package/dist/components/docs/Column.svelte +25 -0
  32. package/dist/components/docs/Column.svelte.d.ts +8 -0
  33. package/dist/components/docs/Columns.svelte +38 -0
  34. package/dist/components/docs/Columns.svelte.d.ts +13 -0
  35. package/dist/components/docs/DevModeBadge.svelte +15 -0
  36. package/dist/components/docs/DevModeBadge.svelte.d.ts +18 -0
  37. package/dist/components/docs/DocBadge.svelte +28 -0
  38. package/dist/components/docs/DocBadge.svelte.d.ts +9 -0
  39. package/dist/components/docs/DocLayout.svelte +107 -0
  40. package/dist/components/docs/DocLayout.svelte.d.ts +32 -0
  41. package/dist/components/docs/DocLoading.svelte +53 -0
  42. package/dist/components/docs/DocLoading.svelte.d.ts +18 -0
  43. package/dist/components/docs/DocMetadata.svelte +106 -0
  44. package/dist/components/docs/DocMetadata.svelte.d.ts +18 -0
  45. package/dist/components/docs/DocNavigation.svelte +56 -0
  46. package/dist/components/docs/DocNavigation.svelte.d.ts +12 -0
  47. package/dist/components/docs/DocTags.svelte +22 -0
  48. package/dist/components/docs/DocTags.svelte.d.ts +6 -0
  49. package/dist/components/docs/DraftBadge.svelte +10 -0
  50. package/dist/components/docs/DraftBadge.svelte.d.ts +18 -0
  51. package/dist/components/docs/Footer.svelte +72 -0
  52. package/dist/components/docs/Footer.svelte.d.ts +7 -0
  53. package/dist/components/docs/Frame.svelte +27 -0
  54. package/dist/components/docs/Frame.svelte.d.ts +9 -0
  55. package/dist/components/docs/Header.svelte +123 -0
  56. package/dist/components/docs/Header.svelte.d.ts +9 -0
  57. package/dist/components/docs/HeaderWithMenu.svelte +34 -0
  58. package/dist/components/docs/HeaderWithMenu.svelte.d.ts +17 -0
  59. package/dist/components/docs/HotReloadIndicator.svelte +44 -0
  60. package/dist/components/docs/HotReloadIndicator.svelte.d.ts +3 -0
  61. package/dist/components/docs/Icon.svelte +103 -0
  62. package/dist/components/docs/Icon.svelte.d.ts +11 -0
  63. package/dist/components/docs/Image.svelte +88 -0
  64. package/dist/components/docs/Image.svelte.d.ts +11 -0
  65. package/dist/components/docs/ImageCard.svelte +91 -0
  66. package/dist/components/docs/ImageCard.svelte.d.ts +12 -0
  67. package/dist/components/docs/ImageCardGrid.svelte +25 -0
  68. package/dist/components/docs/ImageCardGrid.svelte.d.ts +8 -0
  69. package/dist/components/docs/LayoutProviders.svelte +57 -0
  70. package/dist/components/docs/LayoutProviders.svelte.d.ts +9 -0
  71. package/dist/components/docs/Logo.svelte +25 -0
  72. package/dist/components/docs/Logo.svelte.d.ts +11 -0
  73. package/dist/components/docs/Math.svelte +54 -0
  74. package/dist/components/docs/Math.svelte.d.ts +7 -0
  75. package/dist/components/docs/MdxContent.svelte +41 -0
  76. package/dist/components/docs/MdxHotReload.svelte +78 -0
  77. package/dist/components/docs/MdxHotReload.svelte.d.ts +9 -0
  78. package/dist/components/docs/MdxLayout.svelte +16 -0
  79. package/dist/components/docs/MdxLayout.svelte.d.ts +6 -0
  80. package/dist/components/docs/Mermaid.svelte +88 -0
  81. package/dist/components/docs/Mermaid.svelte.d.ts +7 -0
  82. package/dist/components/docs/MobileDocLayout.svelte +211 -0
  83. package/dist/components/docs/MobileDocLayout.svelte.d.ts +35 -0
  84. package/dist/components/docs/MobileSidebar.svelte +122 -0
  85. package/dist/components/docs/MobileSidebar.svelte.d.ts +31 -0
  86. package/dist/components/docs/MobileSidebarWrapper.svelte +122 -0
  87. package/dist/components/docs/MobileSidebarWrapper.svelte.d.ts +32 -0
  88. package/dist/components/docs/NotFoundContent.svelte +40 -0
  89. package/dist/components/docs/NotFoundContent.svelte.d.ts +6 -0
  90. package/dist/components/docs/SearchHighlight.svelte +116 -0
  91. package/dist/components/docs/SearchHighlight.svelte.d.ts +3 -0
  92. package/dist/components/docs/SearchModal.svelte +239 -0
  93. package/dist/components/docs/SearchModal.svelte.d.ts +9 -0
  94. package/dist/components/docs/Sidebar.svelte +69 -0
  95. package/dist/components/docs/Sidebar.svelte.d.ts +31 -0
  96. package/dist/components/docs/SidebarMenuItems.svelte +344 -0
  97. package/dist/components/docs/SidebarMenuItems.svelte.d.ts +33 -0
  98. package/dist/components/docs/SidebarSkeleton.svelte +50 -0
  99. package/dist/components/docs/SidebarSkeleton.svelte.d.ts +18 -0
  100. package/dist/components/docs/SiteBanner.svelte +92 -0
  101. package/dist/components/docs/SiteBanner.svelte.d.ts +7 -0
  102. package/dist/components/docs/Step.svelte +44 -0
  103. package/dist/components/docs/Step.svelte.d.ts +8 -0
  104. package/dist/components/docs/Steps.svelte +15 -0
  105. package/dist/components/docs/Steps.svelte.d.ts +7 -0
  106. package/dist/components/docs/Tab.svelte +40 -0
  107. package/dist/components/docs/Tab.svelte.d.ts +8 -0
  108. package/dist/components/docs/TabGroups.svelte +183 -0
  109. package/dist/components/docs/TabGroups.svelte.d.ts +25 -0
  110. package/dist/components/docs/TableOfContents.svelte +100 -0
  111. package/dist/components/docs/TableOfContents.svelte.d.ts +9 -0
  112. package/dist/components/docs/Tabs.svelte +69 -0
  113. package/dist/components/docs/Tabs.svelte.d.ts +8 -0
  114. package/dist/components/docs/ThemeToggle.svelte +16 -0
  115. package/dist/components/docs/ThemeToggle.svelte.d.ts +18 -0
  116. package/dist/components/docs/Tooltip.svelte +44 -0
  117. package/dist/components/docs/Tooltip.svelte.d.ts +10 -0
  118. package/dist/components/docs/VersionSwitcher.svelte +95 -0
  119. package/dist/components/docs/VersionSwitcher.svelte.d.ts +7 -0
  120. package/dist/components/docs/Video.svelte +84 -0
  121. package/dist/components/docs/Video.svelte.d.ts +12 -0
  122. package/dist/components/docs/api/ApiEndpoint.svelte +61 -0
  123. package/dist/components/docs/api/ApiEndpoint.svelte.d.ts +11 -0
  124. package/dist/components/docs/api/ApiParams.svelte +80 -0
  125. package/dist/components/docs/api/ApiParams.svelte.d.ts +14 -0
  126. package/dist/components/docs/api/ApiPlayground.svelte +259 -0
  127. package/dist/components/docs/api/ApiPlayground.svelte.d.ts +16 -0
  128. package/dist/components/docs/api/ApiReference.svelte +278 -0
  129. package/dist/components/docs/api/ApiReference.svelte.d.ts +23 -0
  130. package/dist/components/docs/api/ApiResponse.svelte +66 -0
  131. package/dist/components/docs/api/ApiResponse.svelte.d.ts +9 -0
  132. package/dist/components/docs/api/index.d.ts +5 -0
  133. package/dist/components/docs/api/index.js +5 -0
  134. package/dist/components/docs/componentTextProps.d.ts +3 -0
  135. package/dist/components/docs/componentTextProps.js +61 -0
  136. package/dist/components/docs/index.d.ts +54 -0
  137. package/dist/components/docs/index.js +56 -0
  138. package/dist/components/global/VersionNotFound.svelte +48 -0
  139. package/dist/components/global/VersionNotFound.svelte.d.ts +7 -0
  140. package/dist/components/global/index.d.ts +1 -0
  141. package/dist/components/global/index.js +1 -0
  142. package/dist/components/index.d.ts +6 -822
  143. package/dist/components/index.js +11 -3854
  144. package/dist/components/ui/Badge.svelte +48 -0
  145. package/dist/components/ui/Badge.svelte.d.ts +15 -0
  146. package/dist/components/ui/Button.svelte +58 -0
  147. package/dist/components/ui/Button.svelte.d.ts +17 -0
  148. package/dist/components/ui/Dialog.svelte +16 -0
  149. package/dist/components/ui/Dialog.svelte.d.ts +9 -0
  150. package/dist/components/ui/DialogClose.svelte +16 -0
  151. package/dist/components/ui/DialogClose.svelte.d.ts +9 -0
  152. package/dist/components/ui/DialogContent.svelte +43 -0
  153. package/dist/components/ui/DialogContent.svelte.d.ts +10 -0
  154. package/dist/components/ui/DialogDescription.svelte +21 -0
  155. package/dist/components/ui/DialogDescription.svelte.d.ts +9 -0
  156. package/dist/components/ui/DialogFooter.svelte +20 -0
  157. package/dist/components/ui/DialogFooter.svelte.d.ts +9 -0
  158. package/dist/components/ui/DialogHeader.svelte +20 -0
  159. package/dist/components/ui/DialogHeader.svelte.d.ts +9 -0
  160. package/dist/components/ui/DialogTitle.svelte +21 -0
  161. package/dist/components/ui/DialogTitle.svelte.d.ts +9 -0
  162. package/dist/components/ui/Input.svelte +23 -0
  163. package/dist/components/ui/Input.svelte.d.ts +8 -0
  164. package/dist/components/ui/Textarea.svelte +19 -0
  165. package/dist/components/ui/Textarea.svelte.d.ts +7 -0
  166. package/dist/components/ui/index.d.ts +11 -0
  167. package/dist/components/ui/index.js +11 -0
  168. package/dist/config.d.ts +8 -0
  169. package/dist/config.js +9 -0
  170. package/dist/config.schema.json +471 -0
  171. package/dist/config.server.d.ts +46 -0
  172. package/dist/config.server.js +149 -0
  173. package/dist/{mdx-ColN3Cyg.d.mts → config.types.d.ts} +22 -75
  174. package/dist/config.types.js +39 -0
  175. package/dist/dev-utils.d.ts +29 -0
  176. package/dist/dev-utils.js +63 -0
  177. package/dist/index.d.ts +19 -4
  178. package/dist/index.js +25 -4861
  179. package/dist/mdx-cache.d.ts +41 -0
  180. package/dist/mdx-cache.js +160 -0
  181. package/dist/mdx-components.js +50 -1931
  182. package/dist/mdx-security.d.ts +76 -0
  183. package/dist/mdx-security.js +217 -0
  184. package/dist/mdx.d.ts +73 -0
  185. package/dist/mdx.js +1099 -0
  186. package/dist/middleware/index.d.ts +1 -0
  187. package/dist/middleware/index.js +2 -0
  188. package/dist/middleware/security.d.ts +22 -47
  189. package/dist/middleware/security.js +111 -137
  190. package/dist/parsers/base-parser.d.ts +14 -0
  191. package/dist/parsers/base-parser.js +1 -0
  192. package/dist/parsers/index.d.ts +16 -0
  193. package/dist/parsers/index.js +51 -0
  194. package/dist/parsers/openapi-parser.d.ts +18 -0
  195. package/dist/parsers/openapi-parser.js +209 -0
  196. package/dist/parsers/postman-parser.d.ts +20 -0
  197. package/dist/parsers/postman-parser.js +260 -0
  198. package/dist/parsers/specra-parser.d.ts +10 -0
  199. package/dist/parsers/specra-parser.js +18 -0
  200. package/dist/redirects.d.ts +12 -0
  201. package/dist/redirects.js +30 -0
  202. package/dist/remark-code-meta.d.ts +6 -0
  203. package/dist/remark-code-meta.js +21 -0
  204. package/dist/sidebar-utils.d.ts +59 -0
  205. package/dist/sidebar-utils.js +144 -0
  206. package/dist/stores/config.d.ts +20 -0
  207. package/dist/stores/config.js +45 -0
  208. package/dist/stores/index.d.ts +4 -0
  209. package/dist/stores/index.js +4 -0
  210. package/dist/stores/sidebar.d.ts +7 -0
  211. package/dist/stores/sidebar.js +12 -0
  212. package/dist/stores/tabs.d.ts +6 -0
  213. package/dist/stores/tabs.js +41 -0
  214. package/dist/stores/theme.d.ts +7 -0
  215. package/dist/stores/theme.js +75 -0
  216. package/dist/{styles.css → styles/globals.css} +136 -6
  217. package/dist/toc.d.ts +9 -0
  218. package/dist/toc.js +15 -0
  219. package/dist/utils.d.ts +13 -0
  220. package/dist/utils.js +30 -0
  221. package/package.json +47 -90
  222. package/dist/app/api/mdx-watch/route.d.mts +0 -10
  223. package/dist/app/api/mdx-watch/route.d.ts +0 -10
  224. package/dist/app/api/mdx-watch/route.js +0 -118
  225. package/dist/app/api/mdx-watch/route.js.map +0 -1
  226. package/dist/app/api/mdx-watch/route.mjs +0 -91
  227. package/dist/app/api/mdx-watch/route.mjs.map +0 -1
  228. package/dist/chunk-6S3EJVEO.mjs +0 -259
  229. package/dist/chunk-6S3EJVEO.mjs.map +0 -1
  230. package/dist/chunk-BE7EROIW.mjs +0 -212
  231. package/dist/chunk-BE7EROIW.mjs.map +0 -1
  232. package/dist/chunk-CWHRZHZO.mjs +0 -168
  233. package/dist/chunk-CWHRZHZO.mjs.map +0 -1
  234. package/dist/chunk-D5VDVYFY.mjs +0 -1325
  235. package/dist/chunk-D5VDVYFY.mjs.map +0 -1
  236. package/dist/chunk-WMCO2UX5.mjs +0 -585
  237. package/dist/chunk-WMCO2UX5.mjs.map +0 -1
  238. package/dist/chunk-XEMGCPZZ.mjs +0 -475
  239. package/dist/chunk-XEMGCPZZ.mjs.map +0 -1
  240. package/dist/components/index.d.mts +0 -822
  241. package/dist/components/index.js.map +0 -1
  242. package/dist/components/index.mjs +0 -3741
  243. package/dist/components/index.mjs.map +0 -1
  244. package/dist/index.d.mts +0 -4
  245. package/dist/index.js.map +0 -1
  246. package/dist/index.mjs +0 -1897
  247. package/dist/index.mjs.map +0 -1
  248. package/dist/layouts/index.d.mts +0 -34
  249. package/dist/layouts/index.d.ts +0 -34
  250. package/dist/layouts/index.js +0 -453
  251. package/dist/layouts/index.js.map +0 -1
  252. package/dist/layouts/index.mjs +0 -173
  253. package/dist/layouts/index.mjs.map +0 -1
  254. package/dist/lib/index.d.mts +0 -583
  255. package/dist/lib/index.d.ts +0 -583
  256. package/dist/lib/index.js +0 -1595
  257. package/dist/lib/index.js.map +0 -1
  258. package/dist/lib/index.mjs +0 -111
  259. package/dist/lib/index.mjs.map +0 -1
  260. package/dist/mdx-ColN3Cyg.d.ts +0 -352
  261. package/dist/mdx-components.d.mts +0 -86
  262. package/dist/mdx-components.d.ts +0 -86
  263. package/dist/mdx-components.js.map +0 -1
  264. package/dist/mdx-components.mjs +0 -206
  265. package/dist/mdx-components.mjs.map +0 -1
  266. package/dist/middleware/security.d.mts +0 -82
  267. package/dist/middleware/security.js.map +0 -1
  268. package/dist/middleware/security.mjs +0 -84
  269. package/dist/middleware/security.mjs.map +0 -1
  270. package/dist/styles.css.map +0 -1
  271. package/dist/styles.d.mts +0 -2
  272. package/dist/styles.d.ts +0 -2
  273. package/dist/styles.js +0 -2
  274. package/dist/styles.js.map +0 -1
  275. package/dist/styles.mjs +0 -1
  276. package/dist/styles.mjs.map +0 -1
package/dist/lib/index.js DELETED
@@ -1,1595 +0,0 @@
1
- "use strict";
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __export = (target, all) => {
9
- for (var name in all)
10
- __defProp(target, name, { get: all[name], enumerable: true });
11
- };
12
- var __copyProps = (to, from, except, desc) => {
13
- if (from && typeof from === "object" || typeof from === "function") {
14
- for (let key of __getOwnPropNames(from))
15
- if (!__hasOwnProp.call(to, key) && key !== except)
16
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
- }
18
- return to;
19
- };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
-
30
- // src/lib/index.ts
31
- var lib_exports = {};
32
- __export(lib_exports, {
33
- CSP_DIRECTIVES: () => CSP_DIRECTIVES,
34
- OpenApiParser: () => OpenApiParser,
35
- PerfTimer: () => PerfTimer,
36
- PostmanParser: () => PostmanParser,
37
- SAFE_MDX_COMPONENTS: () => SAFE_MDX_COMPONENTS,
38
- SpecraParser: () => SpecraParser,
39
- buildRedirectMappings: () => buildRedirectMappings,
40
- buildSidebarStructure: () => buildSidebarStructure,
41
- clearAllCaches: () => clearAllCaches,
42
- cn: () => cn,
43
- debugLog: () => debugLog,
44
- defaultConfig: () => defaultConfig,
45
- detectParserType: () => detectParserType,
46
- extractHeadings: () => extractHeadings,
47
- extractTableOfContents: () => extractTableOfContents,
48
- findRedirect: () => findRedirect,
49
- generateCSPHeader: () => generateCSPHeader,
50
- getAdjacentDocs: () => getAdjacentDocs,
51
- getAllCategoryConfigs: () => getAllCategoryConfigs,
52
- getAllDocs: () => getAllDocs,
53
- getAssetPath: () => getAssetPath,
54
- getCacheStats: () => getCacheStats,
55
- getCachedAllDocs: () => getCachedAllDocs,
56
- getCachedDocBySlug: () => getCachedDocBySlug,
57
- getCachedVersions: () => getCachedVersions,
58
- getCategoryConfig: () => getCategoryConfig,
59
- getConfig: () => getConfig,
60
- getConfigValue: () => getConfigValue,
61
- getDocBySlug: () => getDocBySlug,
62
- getI18nConfig: () => getI18nConfig,
63
- getVersions: () => getVersions,
64
- initConfig: () => initConfig,
65
- isCategoryPage: () => isCategoryPage,
66
- loadConfig: () => loadConfig,
67
- logCacheOperation: () => logCacheOperation,
68
- logFsOperation: () => logFsOperation,
69
- logMemoryUsage: () => logMemoryUsage,
70
- parseApiSpec: () => parseApiSpec,
71
- processContentWithEnv: () => processContentWithEnv,
72
- reloadConfig: () => reloadConfig,
73
- replaceEnvVariables: () => replaceEnvVariables,
74
- sanitizeMDXContent: () => sanitizeMDXContent,
75
- sanitizePath: () => sanitizePath,
76
- scanMDXForDangerousPatterns: () => scanMDXForDangerousPatterns,
77
- sortSidebarGroups: () => sortSidebarGroups,
78
- sortSidebarItems: () => sortSidebarItems,
79
- validateConfig: () => validateConfig,
80
- validateMDXComponents: () => validateMDXComponents,
81
- validateMDXSecurity: () => validateMDXSecurity,
82
- validatePathWithinDirectory: () => validatePathWithinDirectory
83
- });
84
- module.exports = __toCommonJS(lib_exports);
85
-
86
- // src/lib/mdx.ts
87
- var import_fs2 = __toESM(require("fs"));
88
- var import_path3 = __toESM(require("path"));
89
- var import_gray_matter = __toESM(require("gray-matter"));
90
-
91
- // src/lib/category.ts
92
- var import_fs = __toESM(require("fs"));
93
- var import_path = __toESM(require("path"));
94
- var DOCS_DIR = import_path.default.join(process.cwd(), "docs");
95
- function getCategoryConfig(folderPath) {
96
- try {
97
- const categoryPath = import_path.default.join(folderPath, "_category_.json");
98
- if (!import_fs.default.existsSync(categoryPath)) {
99
- return null;
100
- }
101
- const content = import_fs.default.readFileSync(categoryPath, "utf8");
102
- return JSON.parse(content);
103
- } catch (error) {
104
- console.error(`Error reading category config from ${folderPath}:`, error);
105
- return null;
106
- }
107
- }
108
- function getAllCategoryConfigs(version) {
109
- const configs = /* @__PURE__ */ new Map();
110
- const versionDir = import_path.default.join(DOCS_DIR, version);
111
- if (!import_fs.default.existsSync(versionDir)) {
112
- return configs;
113
- }
114
- function scanDirectory(dir, relativePath = "") {
115
- const entries = import_fs.default.readdirSync(dir, { withFileTypes: true });
116
- for (const entry of entries) {
117
- if (entry.isDirectory()) {
118
- const fullPath = import_path.default.join(dir, entry.name);
119
- const relPath = relativePath ? `${relativePath}/${entry.name}` : entry.name;
120
- const config = getCategoryConfig(fullPath);
121
- if (config) {
122
- configs.set(relPath, config);
123
- }
124
- scanDirectory(fullPath, relPath);
125
- }
126
- }
127
- }
128
- scanDirectory(versionDir);
129
- return configs;
130
- }
131
-
132
- // src/lib/sidebar-utils.ts
133
- function sortSidebarItems(items) {
134
- return [...items].sort((a, b) => {
135
- const posA = a.sidebar_position ?? a.meta?.sidebar_position ?? a.meta?.order ?? 999;
136
- const posB = b.sidebar_position ?? b.meta?.sidebar_position ?? b.meta?.order ?? 999;
137
- return posA - posB;
138
- });
139
- }
140
- function sortSidebarGroups(groups) {
141
- return Object.entries(groups).sort(([, a], [, b]) => {
142
- const posA = a.position ?? 999;
143
- const posB = b.position ?? 999;
144
- return posA - posB;
145
- });
146
- }
147
- function buildSidebarStructure(docs) {
148
- const rootGroups = {};
149
- const standalone = [];
150
- const categoryMetadata = /* @__PURE__ */ new Map();
151
- docs.forEach((doc) => {
152
- const pathParts = doc.filePath.split("/");
153
- const folderPath = pathParts.length > 1 ? pathParts.slice(0, -1).join("/") : "";
154
- if (folderPath && doc.categoryLabel) {
155
- categoryMetadata.set(folderPath, {
156
- label: doc.categoryLabel,
157
- position: doc.categoryPosition,
158
- icon: doc.categoryIcon,
159
- collapsible: doc.categoryCollapsible,
160
- collapsed: doc.categoryCollapsed
161
- });
162
- }
163
- });
164
- docs.forEach((doc) => {
165
- const pathParts = doc.filePath.split("/");
166
- const isIndexFile = doc.filePath.endsWith("/index") || doc.filePath === "index" || pathParts.length > 1 && doc.slug === pathParts.slice(0, -1).join("/");
167
- const customGroup = doc.meta.sidebar || doc.meta.group;
168
- if (customGroup) {
169
- const groupName = customGroup.charAt(0).toUpperCase() + customGroup.slice(1);
170
- if (!rootGroups[groupName]) {
171
- rootGroups[groupName] = {
172
- label: groupName,
173
- path: customGroup,
174
- items: [],
175
- position: 999,
176
- collapsible: doc.categoryCollapsible ?? true,
177
- defaultCollapsed: doc.categoryCollapsed ?? false,
178
- children: {}
179
- };
180
- }
181
- if (isIndexFile) {
182
- rootGroups[groupName].position = doc.categoryPosition ?? doc.meta.sidebar_position ?? 999;
183
- rootGroups[groupName].icon = doc.categoryIcon;
184
- } else {
185
- rootGroups[groupName].items.push(doc);
186
- }
187
- return;
188
- }
189
- if (pathParts.length > 1) {
190
- const folderParts = pathParts.slice(0, -1);
191
- let currentLevel = rootGroups;
192
- let currentPath = "";
193
- for (let i = 0; i < folderParts.length; i++) {
194
- const folder = folderParts[i];
195
- currentPath = currentPath ? `${currentPath}/${folder}` : folder;
196
- const folderLabel = folder.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
197
- const metadata = categoryMetadata.get(currentPath);
198
- if (!currentLevel[folder]) {
199
- currentLevel[folder] = {
200
- label: metadata?.label ?? folderLabel,
201
- path: currentPath,
202
- icon: metadata?.icon,
203
- items: [],
204
- position: metadata?.position ?? 999,
205
- collapsible: metadata?.collapsible ?? true,
206
- defaultCollapsed: metadata?.collapsed ?? false,
207
- children: {}
208
- };
209
- }
210
- if (i === folderParts.length - 1) {
211
- if (isIndexFile) {
212
- currentLevel[folder].position = doc.categoryPosition ?? doc.meta.sidebar_position ?? currentLevel[folder].position;
213
- if (doc.categoryLabel) {
214
- currentLevel[folder].label = doc.categoryLabel;
215
- }
216
- if (doc.categoryIcon) {
217
- currentLevel[folder].icon = doc.categoryIcon;
218
- }
219
- if (doc.categoryCollapsible !== void 0) {
220
- currentLevel[folder].collapsible = doc.categoryCollapsible;
221
- }
222
- if (doc.categoryCollapsed !== void 0) {
223
- currentLevel[folder].defaultCollapsed = doc.categoryCollapsed;
224
- }
225
- } else {
226
- currentLevel[folder].items.push(doc);
227
- }
228
- }
229
- currentLevel = currentLevel[folder].children;
230
- }
231
- } else {
232
- if (!isIndexFile) {
233
- standalone.push(doc);
234
- }
235
- }
236
- });
237
- return { rootGroups, standalone };
238
- }
239
-
240
- // src/lib/mdx-security.ts
241
- var import_path2 = __toESM(require("path"));
242
- function sanitizePath(userPath) {
243
- const decoded = decodeURIComponent(userPath);
244
- if (decoded.includes("../") || decoded.includes("..\\") || decoded.includes("%2e%2e") || decoded.includes("%252e%252e") || import_path2.default.isAbsolute(decoded)) {
245
- throw new Error("Path traversal detected");
246
- }
247
- const normalized = import_path2.default.normalize(decoded).replace(/\\/g, "/");
248
- if (normalized.startsWith("..") || normalized.includes("/../")) {
249
- throw new Error("Invalid path detected");
250
- }
251
- return normalized;
252
- }
253
- function validatePathWithinDirectory(filePath, allowedDir) {
254
- const resolvedPath = import_path2.default.resolve(allowedDir, filePath);
255
- const resolvedDir = import_path2.default.resolve(allowedDir);
256
- return resolvedPath.startsWith(resolvedDir + import_path2.default.sep) || resolvedPath === resolvedDir;
257
- }
258
- var DANGEROUS_PATTERNS = [
259
- // JavaScript execution
260
- /eval\s*\(/gi,
261
- /Function\s*\(/gi,
262
- /import\s*\(/gi,
263
- /require\s*\(/gi,
264
- // File system access
265
- /fs\.[a-z]+/gi,
266
- /readFile/gi,
267
- /writeFile/gi,
268
- /process\.env/gi,
269
- // Network requests during SSR (legitimate client-side usage should use components)
270
- /fetch\s*\(/gi,
271
- // Dangerous Node.js modules
272
- /child_process/gi,
273
- /exec\s*\(/gi,
274
- /spawn\s*\(/gi,
275
- // Script tag injection
276
- /<script[>\s]/gi,
277
- /javascript:/gi,
278
- /\bon(abort|blur|cancel|canplay|canplaythrough|change|click|close|contextmenu|cuechange|dblclick|drag|dragend|dragenter|dragleave|dragover|dragstart|drop|durationchange|emptied|ended|error|focus|input|invalid|keydown|keypress|keyup|load|loadeddata|loadedmetadata|loadstart|mousedown|mouseenter|mouseleave|mousemove|mouseout|mouseover|mouseup|mousewheel|pause|play|playing|progress|ratechange|reset|resize|scroll|seeked|seeking|select|show|stalled|submit|suspend|timeupdate|toggle|volumechange|waiting|wheel)\s*=/gi
279
- // onclick, onerror, onload, etc.
280
- ];
281
- function removeCodeBlocks(content) {
282
- let withoutCodeBlocks = content.replace(/```[\s\S]*?```/g, "");
283
- withoutCodeBlocks = withoutCodeBlocks.replace(/`[^`]*`/g, "");
284
- return withoutCodeBlocks;
285
- }
286
- function scanMDXForDangerousPatterns(content) {
287
- const issues = [];
288
- const contentWithoutCode = removeCodeBlocks(content);
289
- for (const pattern of DANGEROUS_PATTERNS) {
290
- const matches = contentWithoutCode.match(pattern);
291
- if (matches) {
292
- issues.push(`Dangerous pattern detected: ${pattern.source}`);
293
- }
294
- }
295
- return issues;
296
- }
297
- function sanitizeMDXContent(content, strict = false) {
298
- if (strict) {
299
- const issues = scanMDXForDangerousPatterns(content);
300
- if (issues.length > 0) {
301
- throw new Error(`MDX content contains dangerous patterns: ${issues.join(", ")}`);
302
- }
303
- }
304
- let sanitized = content.replace(/<script[^>]*>[\s\S]*?<\/script>/gi, "");
305
- sanitized = sanitized.replace(/\s+on\w+\s*=\s*["'][^"']*["']/gi, "");
306
- sanitized = sanitized.replace(/javascript:/gi, "");
307
- return sanitized;
308
- }
309
- var CSP_DIRECTIVES = {
310
- "default-src": ["'self'"],
311
- "script-src": [
312
- "'self'",
313
- "'unsafe-inline'",
314
- // Required for Next.js
315
- "'unsafe-eval'"
316
- // Required for dev mode - remove in production
317
- ],
318
- "style-src": ["'self'", "'unsafe-inline'"],
319
- // Required for styled-components/emotion
320
- "img-src": ["'self'", "data:", "https:"],
321
- "font-src": ["'self'", "data:"],
322
- "connect-src": ["'self'"],
323
- "frame-src": ["'self'"],
324
- "object-src": ["'none'"],
325
- "base-uri": ["'self'"],
326
- "form-action": ["'self'"],
327
- "frame-ancestors": ["'self'"],
328
- "upgrade-insecure-requests": []
329
- };
330
- function generateCSPHeader(customDirectives, production = true) {
331
- const directives = { ...CSP_DIRECTIVES, ...customDirectives };
332
- if (production && directives["script-src"]) {
333
- directives["script-src"] = directives["script-src"].filter(
334
- (src) => src !== "'unsafe-eval'"
335
- );
336
- }
337
- return Object.entries(directives).map(([key, values]) => `${key} ${values.join(" ")}`).join("; ");
338
- }
339
- var SAFE_MDX_COMPONENTS = /* @__PURE__ */ new Set([
340
- // Standard HTML elements (automatically allowed by MDX)
341
- "h1",
342
- "h2",
343
- "h3",
344
- "h4",
345
- "h5",
346
- "h6",
347
- "p",
348
- "a",
349
- "ul",
350
- "ol",
351
- "li",
352
- "code",
353
- "pre",
354
- "blockquote",
355
- "table",
356
- "thead",
357
- "tbody",
358
- "tr",
359
- "th",
360
- "td",
361
- "img",
362
- "video",
363
- "audio",
364
- "br",
365
- "hr",
366
- "strong",
367
- "em",
368
- // Custom safe components
369
- "Callout",
370
- "CodeBlock",
371
- "Accordion",
372
- "AccordionItem",
373
- "Tabs",
374
- "Tab",
375
- "Image",
376
- "Video",
377
- "Card",
378
- "CardGrid",
379
- "ImageCard",
380
- "ImageCardGrid",
381
- "Steps",
382
- "Step",
383
- "Icon",
384
- "Mermaid",
385
- "Math",
386
- "Columns",
387
- "Column",
388
- "Badge",
389
- "Tooltip",
390
- "Frame",
391
- "ApiEndpoint",
392
- "ApiParams",
393
- "ApiResponse",
394
- "ApiPlayground",
395
- "ApiReference"
396
- ]);
397
- function validateMDXComponents(content) {
398
- const issues = [];
399
- const componentRegex = /<([A-Z][a-zA-Z0-9]*)/g;
400
- let match;
401
- while ((match = componentRegex.exec(content)) !== null) {
402
- const componentName = match[1];
403
- if (!SAFE_MDX_COMPONENTS.has(componentName)) {
404
- issues.push(`Unsafe component detected: ${componentName}`);
405
- }
406
- }
407
- return {
408
- valid: issues.length === 0,
409
- issues
410
- };
411
- }
412
- function validateMDXSecurity(content, options = {}) {
413
- const {
414
- strictMode = false,
415
- allowCustomComponents = true,
416
- blockDangerousPatterns = true
417
- } = options;
418
- const issues = [];
419
- if (blockDangerousPatterns) {
420
- const patternIssues = scanMDXForDangerousPatterns(content);
421
- issues.push(...patternIssues);
422
- }
423
- if (!allowCustomComponents) {
424
- const componentValidation = validateMDXComponents(content);
425
- if (!componentValidation.valid) {
426
- issues.push(...componentValidation.issues);
427
- }
428
- }
429
- if (strictMode && issues.length > 0) {
430
- return { valid: false, issues };
431
- }
432
- const sanitized = sanitizeMDXContent(content, false);
433
- return {
434
- valid: true,
435
- issues,
436
- sanitized
437
- };
438
- }
439
-
440
- // src/lib/config.types.ts
441
- var defaultConfig = {
442
- site: {
443
- title: "Documentation",
444
- description: "Project documentation",
445
- baseUrl: "/",
446
- language: "en"
447
- },
448
- theme: {
449
- defaultMode: "system",
450
- respectPrefersColorScheme: true
451
- },
452
- navigation: {
453
- showSidebar: true,
454
- collapsibleSidebar: true,
455
- showBreadcrumbs: true,
456
- showTableOfContents: true,
457
- tocPosition: "right",
458
- tocMaxDepth: 3
459
- },
460
- search: {
461
- enabled: true,
462
- provider: "local",
463
- placeholder: "Search documentation..."
464
- },
465
- features: {
466
- showLastUpdated: true,
467
- showReadingTime: true,
468
- showAuthors: false,
469
- showTags: true,
470
- versioning: true,
471
- i18n: false
472
- }
473
- };
474
-
475
- // src/lib/config.server.ts
476
- function deepMerge(target, source) {
477
- const result = { ...target };
478
- for (const key in source) {
479
- const sourceValue = source[key];
480
- const targetValue = result[key];
481
- if (sourceValue && typeof sourceValue === "object" && !Array.isArray(sourceValue)) {
482
- result[key] = deepMerge(
483
- targetValue && typeof targetValue === "object" ? targetValue : {},
484
- sourceValue
485
- );
486
- } else if (sourceValue !== void 0) {
487
- result[key] = sourceValue;
488
- }
489
- }
490
- return result;
491
- }
492
- function loadConfig(userConfig) {
493
- try {
494
- const config = deepMerge(defaultConfig, userConfig);
495
- return config;
496
- } catch (error) {
497
- console.error(`\u274C Error loading configuration:`, error);
498
- console.warn("Using default configuration.");
499
- return defaultConfig;
500
- }
501
- }
502
- function getConfigValue(path4, config) {
503
- const cfg = config || loadConfig({});
504
- const keys = path4.split(".");
505
- let value = cfg;
506
- for (const key of keys) {
507
- if (value && typeof value === "object" && key in value) {
508
- value = value[key];
509
- } else {
510
- return void 0;
511
- }
512
- }
513
- return value;
514
- }
515
- function replaceEnvVariables(text, config) {
516
- const cfg = config || loadConfig({});
517
- const envVars = cfg.env || {};
518
- let result = text;
519
- result = result.replace(/\$\{([^}]+)\}/g, (match, varName) => {
520
- return envVars[varName] || match;
521
- });
522
- result = result.replace(/\{\{([^}]+)\}\}/g, (match, varName) => {
523
- return envVars[varName] || match;
524
- });
525
- return result;
526
- }
527
- function processContentWithEnv(content, config) {
528
- return replaceEnvVariables(content, config);
529
- }
530
- function validateConfig(config) {
531
- const errors = [];
532
- if (!config.site?.title) {
533
- errors.push("site.title is required");
534
- }
535
- if (config.site?.url) {
536
- try {
537
- new URL(config.site.url);
538
- } catch {
539
- errors.push("site.url must be a valid URL");
540
- }
541
- }
542
- if (config.social) {
543
- const socialKeys = ["github", "twitter", "discord", "linkedin", "youtube"];
544
- for (const key of socialKeys) {
545
- const url = config.social[key];
546
- if (url) {
547
- try {
548
- new URL(url);
549
- } catch {
550
- errors.push(`social.${key} must be a valid URL`);
551
- }
552
- }
553
- }
554
- }
555
- return {
556
- valid: errors.length === 0,
557
- errors
558
- };
559
- }
560
- var configInstance = null;
561
- function initConfig(userConfig) {
562
- configInstance = loadConfig(userConfig);
563
- return configInstance;
564
- }
565
- function getConfig() {
566
- if (!configInstance) {
567
- configInstance = loadConfig({});
568
- }
569
- return configInstance;
570
- }
571
- function reloadConfig(userConfig) {
572
- configInstance = loadConfig(userConfig);
573
- return configInstance;
574
- }
575
-
576
- // src/lib/mdx.ts
577
- var DOCS_DIR2 = import_path3.default.join(process.cwd(), "docs");
578
- function calculateReadingTime(content) {
579
- const words = content.trim().split(/\s+/).length;
580
- const minutes = Math.ceil(words / 200);
581
- return { minutes, words };
582
- }
583
- function getVersions() {
584
- try {
585
- const versions = import_fs2.default.readdirSync(DOCS_DIR2);
586
- return versions.filter((v) => import_fs2.default.statSync(import_path3.default.join(DOCS_DIR2, v)).isDirectory());
587
- } catch (error) {
588
- return ["v1.0.0"];
589
- }
590
- }
591
- function findMdxFiles(dir, baseDir = dir) {
592
- const files = [];
593
- try {
594
- const entries = import_fs2.default.readdirSync(dir, { withFileTypes: true });
595
- for (const entry of entries) {
596
- const fullPath = import_path3.default.join(dir, entry.name);
597
- if (entry.isDirectory()) {
598
- files.push(...findMdxFiles(fullPath, baseDir));
599
- } else if (entry.isFile() && entry.name.endsWith(".mdx")) {
600
- const relativePath = import_path3.default.relative(baseDir, fullPath).replace(/\\/g, "/");
601
- files.push(relativePath);
602
- }
603
- }
604
- } catch (error) {
605
- console.error(`Error reading directory ${dir}:`, error);
606
- }
607
- return files;
608
- }
609
- function readDocFromFile(filePath, originalSlug) {
610
- try {
611
- if (!import_fs2.default.existsSync(filePath)) {
612
- return null;
613
- }
614
- if (!validatePathWithinDirectory(filePath, DOCS_DIR2)) {
615
- console.error(`[Security] Path traversal attempt blocked: ${filePath}`);
616
- return null;
617
- }
618
- const fileContents = import_fs2.default.readFileSync(filePath, "utf8");
619
- const { data, content } = (0, import_gray_matter.default)(fileContents);
620
- const securityCheck = validateMDXSecurity(content, {
621
- strictMode: process.env.NODE_ENV === "production",
622
- blockDangerousPatterns: true
623
- });
624
- if (!securityCheck.valid) {
625
- console.error(`[Security] MDX validation failed for ${filePath}:`, securityCheck.issues);
626
- if (process.env.NODE_ENV === "production") {
627
- return null;
628
- }
629
- console.warn("[Security] Continuing in development mode with sanitized content");
630
- }
631
- const safeContent = securityCheck.sanitized || content;
632
- const { minutes, words } = calculateReadingTime(safeContent);
633
- let finalSlug = originalSlug;
634
- if (data.slug) {
635
- const customSlug = data.slug.replace(/^\//, "");
636
- const parts = originalSlug.split("/");
637
- if (parts.length > 1) {
638
- parts[parts.length - 1] = customSlug;
639
- finalSlug = parts.join("/");
640
- } else {
641
- finalSlug = customSlug;
642
- }
643
- }
644
- return {
645
- slug: finalSlug,
646
- filePath: originalSlug,
647
- // Keep original file path for sidebar
648
- title: data.title || originalSlug,
649
- meta: {
650
- ...data,
651
- content: safeContent,
652
- reading_time: minutes,
653
- word_count: words
654
- },
655
- content: safeContent
656
- };
657
- } catch (error) {
658
- console.error(`Error reading file ${filePath}:`, error);
659
- return null;
660
- }
661
- }
662
- function getI18nConfig() {
663
- const config = getConfig();
664
- const i18n = config.features?.i18n;
665
- if (!i18n) return null;
666
- if (typeof i18n === "boolean") {
667
- return i18n ? {
668
- defaultLocale: "en",
669
- locales: ["en"],
670
- localeNames: { en: "English" }
671
- } : null;
672
- }
673
- return i18n;
674
- }
675
- async function getDocBySlug(slug, version = "v1.0.0", locale) {
676
- try {
677
- const sanitizedVersion = sanitizePath(version);
678
- let sanitizedSlug = sanitizePath(slug);
679
- const i18nConfig = getI18nConfig();
680
- let detectedLocale = locale || i18nConfig?.defaultLocale;
681
- if (i18nConfig) {
682
- const parts = sanitizedSlug.split("/");
683
- if (parts.length > 0 && i18nConfig.locales.includes(parts[0])) {
684
- detectedLocale = parts[0];
685
- sanitizedSlug = parts.slice(1).join("/");
686
- if (sanitizedSlug === "") sanitizedSlug = "index";
687
- }
688
- }
689
- const targetLocale = detectedLocale;
690
- const isDefaultLocale = targetLocale === i18nConfig?.defaultLocale;
691
- const basePath = import_path3.default.join(DOCS_DIR2, sanitizedVersion);
692
- if (targetLocale) {
693
- const localizedPath = import_path3.default.join(basePath, `${sanitizedSlug}.${targetLocale}.mdx`);
694
- const doc2 = readDocFromFile(localizedPath, sanitizedSlug);
695
- if (doc2) {
696
- doc2.slug = i18nConfig ? `${targetLocale}/${sanitizedSlug}` : sanitizedSlug;
697
- doc2.meta.locale = targetLocale;
698
- return doc2;
699
- }
700
- }
701
- const defaultPath = import_path3.default.join(basePath, `${sanitizedSlug}.mdx`);
702
- const doc = readDocFromFile(defaultPath, sanitizedSlug);
703
- if (doc) {
704
- if (isDefaultLocale || !i18nConfig) {
705
- const usePrefix = i18nConfig && (i18nConfig.prefixDefault || targetLocale !== i18nConfig.defaultLocale);
706
- if (usePrefix && targetLocale) {
707
- doc.slug = `${targetLocale}/${doc.slug}`;
708
- }
709
- doc.meta.locale = targetLocale || "en";
710
- return doc;
711
- }
712
- }
713
- return null;
714
- } catch (error) {
715
- console.error(`Error reading doc ${slug}:`, error);
716
- return null;
717
- }
718
- }
719
- async function getAllDocs(version = "v1.0.0", locale) {
720
- try {
721
- const versionDir = import_path3.default.join(DOCS_DIR2, version);
722
- if (!import_fs2.default.existsSync(versionDir)) {
723
- return [];
724
- }
725
- const i18nConfig = getI18nConfig();
726
- const targetLocale = locale || i18nConfig?.defaultLocale || "en";
727
- const mdxFiles = findMdxFiles(versionDir);
728
- const categoryConfigs = getAllCategoryConfigs(version);
729
- const docs = await Promise.all(
730
- mdxFiles.map(async (file) => {
731
- let originalFilePath = file.replace(/\.mdx$/, "");
732
- let isLocalized = false;
733
- let fileLocale = i18nConfig?.defaultLocale || "en";
734
- if (i18nConfig) {
735
- const parts = originalFilePath.split(".");
736
- const lastPart = parts[parts.length - 1];
737
- if (i18nConfig.locales.includes(lastPart)) {
738
- fileLocale = lastPart;
739
- isLocalized = true;
740
- originalFilePath = parts.slice(0, -1).join(".");
741
- }
742
- }
743
- const doc = await getDocBySlug(originalFilePath, version, isLocalized ? fileLocale : void 0);
744
- if (!doc) return null;
745
- doc.filePath = originalFilePath;
746
- const folderPath = import_path3.default.dirname(originalFilePath).replace(/\\/g, "/");
747
- if (folderPath !== ".") {
748
- const categoryConfig = categoryConfigs.get(folderPath);
749
- if (categoryConfig) {
750
- doc.categoryLabel = categoryConfig.label;
751
- doc.categoryPosition = categoryConfig.position ?? categoryConfig.sidebar_position;
752
- doc.categoryCollapsible = categoryConfig.collapsible;
753
- doc.categoryCollapsed = categoryConfig.collapsed;
754
- doc.categoryIcon = categoryConfig.icon;
755
- doc.categoryTabGroup = categoryConfig.tab_group;
756
- }
757
- }
758
- return doc;
759
- })
760
- );
761
- const isDevelopment3 = process.env.NODE_ENV === "development";
762
- const uniqueDocs = /* @__PURE__ */ new Map();
763
- const validDocs = docs.filter((doc) => doc !== null && (isDevelopment3 || !doc.meta.draft));
764
- validDocs.forEach((doc) => {
765
- if (locale === "all") {
766
- uniqueDocs.set(doc.slug, doc);
767
- return;
768
- }
769
- let logicalSlug = doc.slug;
770
- if (i18nConfig) {
771
- const parts = logicalSlug.split("/");
772
- if (i18nConfig.locales.includes(parts[0])) {
773
- logicalSlug = parts.slice(1).join("/");
774
- }
775
- }
776
- const existing = uniqueDocs.get(logicalSlug);
777
- if (!existing) {
778
- if (doc.meta.locale === targetLocale) {
779
- uniqueDocs.set(logicalSlug, doc);
780
- } else if (doc.meta.locale === i18nConfig?.defaultLocale) {
781
- uniqueDocs.set(logicalSlug, doc);
782
- }
783
- } else {
784
- if (doc.meta.locale === targetLocale && existing.meta.locale !== targetLocale) {
785
- uniqueDocs.set(logicalSlug, doc);
786
- }
787
- }
788
- });
789
- return Array.from(uniqueDocs.values()).sort((a, b) => {
790
- const orderA = a.meta.sidebar_position ?? a.meta.order ?? 999;
791
- const orderB = b.meta.sidebar_position ?? b.meta.order ?? 999;
792
- return orderA - orderB;
793
- });
794
- } catch (error) {
795
- console.error(`Error getting all docs for version ${version}:`, error);
796
- return [];
797
- }
798
- }
799
- function flattenSidebarOrder(rootGroups, standalone) {
800
- const flatDocs = [];
801
- const flattenGroup = (group) => {
802
- const sortedChildren = sortSidebarGroups(group.children);
803
- const sortedItems = sortSidebarItems(group.items);
804
- const merged = [
805
- ...sortedChildren.map(([, childGroup]) => ({
806
- type: "group",
807
- group: childGroup,
808
- position: childGroup.position
809
- })),
810
- ...sortedItems.map((doc) => ({
811
- type: "item",
812
- doc,
813
- position: doc.meta.sidebar_position ?? doc.meta.order ?? 999
814
- }))
815
- ];
816
- merged.sort((a, b) => a.position - b.position);
817
- merged.forEach((item) => {
818
- if (item.type === "group") {
819
- flattenGroup(item.group);
820
- } else {
821
- flatDocs.push(item.doc);
822
- }
823
- });
824
- };
825
- sortSidebarItems(standalone).forEach((doc) => {
826
- flatDocs.push(doc);
827
- });
828
- const sortedRootGroups = sortSidebarGroups(rootGroups);
829
- sortedRootGroups.forEach(([, group]) => {
830
- flattenGroup(group);
831
- });
832
- return flatDocs;
833
- }
834
- function getAdjacentDocs(currentSlug, allDocs) {
835
- const { rootGroups, standalone } = buildSidebarStructure(allDocs);
836
- const orderedDocs = flattenSidebarOrder(rootGroups, standalone);
837
- const currentIndex = orderedDocs.findIndex((doc) => doc.slug === currentSlug);
838
- if (currentIndex === -1) {
839
- return {};
840
- }
841
- const currentDoc = orderedDocs[currentIndex];
842
- const currentTabGroup = currentDoc.meta?.tab_group || currentDoc.categoryTabGroup;
843
- const filteredDocs = orderedDocs.filter((doc) => {
844
- const docTabGroup = doc.meta?.tab_group || doc.categoryTabGroup;
845
- if (currentTabGroup) {
846
- return docTabGroup === currentTabGroup;
847
- }
848
- return !docTabGroup;
849
- });
850
- const filteredIndex = filteredDocs.findIndex((doc) => doc.slug === currentSlug);
851
- if (filteredIndex === -1) {
852
- return {};
853
- }
854
- return {
855
- previous: filteredIndex > 0 ? filteredDocs[filteredIndex - 1] : void 0,
856
- next: filteredIndex < filteredDocs.length - 1 ? filteredDocs[filteredIndex + 1] : void 0
857
- };
858
- }
859
- function extractTableOfContents(content) {
860
- const headingRegex = /^(#{2,3})\s+(.+)$/gm;
861
- const toc = [];
862
- let match;
863
- while ((match = headingRegex.exec(content)) !== null) {
864
- const level = match[1].length;
865
- const text = match[2];
866
- const id = text.toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, "").replace(/^-|-$/g, "");
867
- toc.push({ id, title: text, level });
868
- }
869
- return toc;
870
- }
871
- function isCategoryPage(slug, allDocs) {
872
- return allDocs.some((doc) => {
873
- const parts = doc.slug.split("/");
874
- const docParent = parts.slice(0, -1).join("/");
875
- return docParent === slug && doc.slug !== slug;
876
- });
877
- }
878
-
879
- // src/lib/mdx-cache.ts
880
- var import_fs3 = require("fs");
881
- var import_path4 = require("path");
882
-
883
- // src/lib/dev-utils.ts
884
- var isDevelopment = process.env.NODE_ENV === "development";
885
- var PerfTimer = class {
886
- constructor(label) {
887
- this.label = label;
888
- this.startTime = isDevelopment ? performance.now() : 0;
889
- }
890
- end() {
891
- if (!isDevelopment) return;
892
- const duration = performance.now() - this.startTime;
893
- const color = duration > 1e3 ? "\x1B[31m" : duration > 500 ? "\x1B[33m" : "\x1B[32m";
894
- const reset = "\x1B[0m";
895
- console.log(`${color}\u23F1\uFE0F ${this.label}: ${duration.toFixed(2)}ms${reset}`);
896
- }
897
- };
898
- function logFsOperation(operation, path4, details) {
899
- if (!isDevelopment) return;
900
- console.log(`\u{1F4C1} [FS] ${operation}: ${path4}`, details || "");
901
- }
902
- function logCacheOperation(operation, key) {
903
- if (!isDevelopment) return;
904
- const emoji = operation === "hit" ? "\u2705" : operation === "miss" ? "\u274C" : "\u{1F504}";
905
- console.log(`${emoji} [Cache] ${operation}: ${key}`);
906
- }
907
- function logMemoryUsage(label) {
908
- if (!isDevelopment) return;
909
- const used = process.memoryUsage();
910
- const prefix = label ? `[${label}] ` : "";
911
- console.log(`\u{1F4BE} ${prefix}Memory Usage:`, {
912
- rss: `${Math.round(used.rss / 1024 / 1024)}MB`,
913
- heapTotal: `${Math.round(used.heapTotal / 1024 / 1024)}MB`,
914
- heapUsed: `${Math.round(used.heapUsed / 1024 / 1024)}MB`
915
- });
916
- }
917
- function debugLog(label, data) {
918
- if (!isDevelopment) return;
919
- console.log(`
920
- \u{1F50D} ${label}:`);
921
- console.dir(data, { depth: null, colors: true });
922
- console.log("");
923
- }
924
-
925
- // src/lib/mdx-cache.ts
926
- var isDevelopment2 = process.env.NODE_ENV === "development";
927
- var versionsCache = {
928
- data: null,
929
- timestamp: 0
930
- };
931
- var allDocsCache = /* @__PURE__ */ new Map();
932
- var docBySlugCache = /* @__PURE__ */ new Map();
933
- var CACHE_TTL = isDevelopment2 ? 5e3 : 6e4;
934
- var watchersInitialized = false;
935
- function initializeWatchers() {
936
- if (!isDevelopment2 || watchersInitialized) return;
937
- watchersInitialized = true;
938
- const docsPath = (0, import_path4.join)(process.cwd(), "docs");
939
- try {
940
- (0, import_fs3.watch)(docsPath, { recursive: true }, (eventType, filename) => {
941
- if (!filename) return;
942
- if (filename.endsWith(".mdx") || filename.endsWith(".json")) {
943
- const parts = filename.split(/[/\\]/);
944
- const version = parts[0];
945
- allDocsCache.delete(version);
946
- const cacheKeysToDelete = [];
947
- docBySlugCache.forEach((_, key) => {
948
- if (key.startsWith(`${version}:`)) {
949
- cacheKeysToDelete.push(key);
950
- }
951
- });
952
- cacheKeysToDelete.forEach((key) => docBySlugCache.delete(key));
953
- if (eventType === "rename") {
954
- versionsCache.data = null;
955
- }
956
- console.log(`[MDX Cache] Invalidated cache for: ${filename}`);
957
- }
958
- });
959
- console.log("[MDX Cache] File watchers initialized");
960
- } catch (error) {
961
- console.error("[MDX Cache] Failed to initialize watchers:", error);
962
- }
963
- }
964
- function isCacheValid(timestamp) {
965
- return Date.now() - timestamp < CACHE_TTL;
966
- }
967
- function getCachedVersions() {
968
- initializeWatchers();
969
- if (versionsCache.data && isCacheValid(versionsCache.timestamp)) {
970
- logCacheOperation("hit", "versions");
971
- return versionsCache.data;
972
- }
973
- logCacheOperation("miss", "versions");
974
- const timer = new PerfTimer("getVersions");
975
- const versions = getVersions();
976
- timer.end();
977
- versionsCache.data = versions;
978
- versionsCache.timestamp = Date.now();
979
- return versions;
980
- }
981
- async function getCachedAllDocs(version = "v1.0.0", locale) {
982
- initializeWatchers();
983
- const cacheKey = locale ? `${version}:${locale}` : version;
984
- const cached = allDocsCache.get(cacheKey);
985
- if (cached && isCacheValid(cached.timestamp)) {
986
- logCacheOperation("hit", `getAllDocs:${cacheKey}`);
987
- return cached.data;
988
- }
989
- logCacheOperation("miss", `getAllDocs:${cacheKey}`);
990
- const timer = new PerfTimer(`getAllDocs(${cacheKey})`);
991
- const docs = await getAllDocs(version, locale);
992
- timer.end();
993
- allDocsCache.set(cacheKey, {
994
- data: docs,
995
- timestamp: Date.now()
996
- });
997
- return docs;
998
- }
999
- async function getCachedDocBySlug(slug, version = "v1.0.0") {
1000
- initializeWatchers();
1001
- const cacheKey = `${version}:${slug}`;
1002
- const cached = docBySlugCache.get(cacheKey);
1003
- if (cached && isCacheValid(cached.timestamp)) {
1004
- logCacheOperation("hit", `getDocBySlug:${cacheKey}`);
1005
- return cached.data;
1006
- }
1007
- logCacheOperation("miss", `getDocBySlug:${cacheKey}`);
1008
- const timer = new PerfTimer(`getDocBySlug(${slug})`);
1009
- const doc = await getDocBySlug(slug, version);
1010
- timer.end();
1011
- docBySlugCache.set(cacheKey, {
1012
- data: doc,
1013
- timestamp: Date.now()
1014
- });
1015
- return doc;
1016
- }
1017
- function clearAllCaches() {
1018
- versionsCache.data = null;
1019
- allDocsCache.clear();
1020
- docBySlugCache.clear();
1021
- console.log("[MDX Cache] All caches cleared");
1022
- }
1023
- function getCacheStats() {
1024
- return {
1025
- versions: {
1026
- cached: versionsCache.data !== null,
1027
- age: versionsCache.timestamp ? Date.now() - versionsCache.timestamp : 0
1028
- },
1029
- allDocs: {
1030
- entries: allDocsCache.size,
1031
- versions: Array.from(allDocsCache.keys())
1032
- },
1033
- docBySlug: {
1034
- entries: docBySlugCache.size
1035
- }
1036
- };
1037
- }
1038
-
1039
- // src/lib/toc.ts
1040
- function extractHeadings(html) {
1041
- const headingRegex = /<h([2-3])[^>]*id="([^"]*)"[^>]*>(.*?)<\/h\1>/g;
1042
- const toc = [];
1043
- let match;
1044
- while ((match = headingRegex.exec(html)) !== null) {
1045
- const level = Number.parseInt(match[1]);
1046
- const id = match[2];
1047
- const title = match[3].replace(/<[^>]*>/g, "");
1048
- toc.push({ id, title, level });
1049
- }
1050
- return toc;
1051
- }
1052
-
1053
- // src/lib/parsers/specra-parser.ts
1054
- var SpecraParser = class {
1055
- validate(input) {
1056
- return typeof input === "object" && input !== null && "endpoints" in input && Array.isArray(input.endpoints);
1057
- }
1058
- parse(input) {
1059
- if (!this.validate(input)) {
1060
- throw new Error("Invalid Specra API spec format");
1061
- }
1062
- return input;
1063
- }
1064
- };
1065
-
1066
- // src/lib/parsers/openapi-parser.ts
1067
- var OpenApiParser = class {
1068
- validate(input) {
1069
- return typeof input === "object" && input !== null && ("openapi" in input || "swagger" in input) && "paths" in input;
1070
- }
1071
- parse(input) {
1072
- if (!this.validate(input)) {
1073
- throw new Error("Invalid OpenAPI spec format");
1074
- }
1075
- const baseUrl = this.extractBaseUrl(input);
1076
- const endpoints = [];
1077
- for (const [path4, pathItem] of Object.entries(input.paths || {})) {
1078
- const methods = ["get", "post", "put", "patch", "delete"];
1079
- for (const method of methods) {
1080
- const operation = pathItem[method];
1081
- if (!operation) continue;
1082
- const endpoint = this.parseOperation(path4, method.toUpperCase(), operation, input);
1083
- endpoints.push(endpoint);
1084
- }
1085
- }
1086
- return {
1087
- version: input.info?.version,
1088
- title: input.info?.title,
1089
- description: input.info?.description,
1090
- baseUrl,
1091
- auth: this.extractAuth(input),
1092
- endpoints
1093
- };
1094
- }
1095
- extractBaseUrl(spec) {
1096
- if (spec.servers && spec.servers.length > 0) {
1097
- return spec.servers[0].url;
1098
- }
1099
- if (spec.host) {
1100
- const scheme = spec.schemes?.[0] || "https";
1101
- const basePath = spec.basePath || "";
1102
- return `${scheme}://${spec.host}${basePath}`;
1103
- }
1104
- return "";
1105
- }
1106
- extractAuth(spec) {
1107
- const securitySchemes = spec.components?.securitySchemes || spec.securityDefinitions;
1108
- if (!securitySchemes) return void 0;
1109
- const firstScheme = Object.values(securitySchemes)[0];
1110
- if (!firstScheme) return void 0;
1111
- if (firstScheme.type === "http" && firstScheme.scheme === "bearer") {
1112
- return {
1113
- type: "bearer",
1114
- description: firstScheme.description,
1115
- tokenPrefix: "Bearer"
1116
- };
1117
- }
1118
- if (firstScheme.type === "apiKey") {
1119
- return {
1120
- type: "apiKey",
1121
- description: firstScheme.description,
1122
- headerName: firstScheme.name || "X-API-Key"
1123
- };
1124
- }
1125
- if (firstScheme.type === "http" && firstScheme.scheme === "basic") {
1126
- return {
1127
- type: "basic",
1128
- description: firstScheme.description
1129
- };
1130
- }
1131
- return void 0;
1132
- }
1133
- parseOperation(path4, method, operation, spec) {
1134
- const endpoint = {
1135
- title: operation.summary || operation.operationId || `${method} ${path4}`,
1136
- method,
1137
- path: this.convertPathParams(path4),
1138
- description: operation.description
1139
- };
1140
- const params = this.parseParameters(operation.parameters || [], spec);
1141
- if (params.path.length > 0) endpoint.pathParams = params.path;
1142
- if (params.query.length > 0) endpoint.queryParams = params.query;
1143
- if (params.header.length > 0) {
1144
- endpoint.headers = params.header.map((p) => ({
1145
- name: p.name,
1146
- value: p.example || "",
1147
- description: p.description
1148
- }));
1149
- }
1150
- if (operation.requestBody) {
1151
- endpoint.body = this.parseRequestBody(operation.requestBody, spec);
1152
- }
1153
- const responses = this.parseResponses(operation.responses || {}, spec);
1154
- if (responses.success) endpoint.successResponse = responses.success;
1155
- if (responses.errors.length > 0) endpoint.errorResponses = responses.errors;
1156
- return endpoint;
1157
- }
1158
- convertPathParams(path4) {
1159
- return path4.replace(/\{([^}]+)\}/g, ":$1");
1160
- }
1161
- parseParameters(parameters, spec) {
1162
- const result = { path: [], query: [], header: [] };
1163
- for (const param of parameters) {
1164
- const resolved = param.$ref ? this.resolveRef(param.$ref, spec) : param;
1165
- const apiParam = {
1166
- name: resolved.name,
1167
- type: resolved.schema?.type || resolved.type || "string",
1168
- required: resolved.required,
1169
- description: resolved.description,
1170
- example: resolved.example || resolved.schema?.example
1171
- };
1172
- if (resolved.in === "path") result.path.push(apiParam);
1173
- else if (resolved.in === "query") result.query.push(apiParam);
1174
- else if (resolved.in === "header") result.header.push(apiParam);
1175
- }
1176
- return result;
1177
- }
1178
- parseRequestBody(requestBody, spec) {
1179
- const content = requestBody.content?.["application/json"];
1180
- if (!content) return void 0;
1181
- return {
1182
- description: requestBody.description,
1183
- example: content.example || this.generateExample(content.schema, spec),
1184
- schema: content.schema
1185
- };
1186
- }
1187
- parseResponses(responses, spec) {
1188
- const result = { errors: [] };
1189
- for (const [statusCode, response] of Object.entries(responses)) {
1190
- const status = parseInt(statusCode);
1191
- if (isNaN(status)) continue;
1192
- const resolved = response.$ref ? this.resolveRef(response.$ref, spec) : response;
1193
- const content = resolved.content?.["application/json"];
1194
- const apiResponse = {
1195
- status,
1196
- description: resolved.description,
1197
- example: content?.example || this.generateExample(content?.schema, spec),
1198
- schema: content?.schema
1199
- };
1200
- if (status >= 200 && status < 300) {
1201
- result.success = apiResponse;
1202
- } else {
1203
- result.errors.push(apiResponse);
1204
- }
1205
- }
1206
- return result;
1207
- }
1208
- generateExample(schema, spec) {
1209
- if (!schema) return void 0;
1210
- if (schema.$ref) schema = this.resolveRef(schema.$ref, spec);
1211
- if (schema.example) return schema.example;
1212
- if (schema.type === "object" && schema.properties) {
1213
- const example = {};
1214
- for (const [key, prop] of Object.entries(schema.properties)) {
1215
- example[key] = this.generateExample(prop, spec);
1216
- }
1217
- return example;
1218
- }
1219
- if (schema.type === "array" && schema.items) {
1220
- return [this.generateExample(schema.items, spec)];
1221
- }
1222
- const defaults = {
1223
- string: "string",
1224
- number: 0,
1225
- integer: 0,
1226
- boolean: false,
1227
- object: {},
1228
- array: []
1229
- };
1230
- return defaults[schema.type] || null;
1231
- }
1232
- resolveRef(ref, spec) {
1233
- const path4 = ref.replace(/^#\//, "").split("/");
1234
- let current = spec;
1235
- for (const segment of path4) {
1236
- current = current[segment];
1237
- if (!current) return {};
1238
- }
1239
- return current;
1240
- }
1241
- };
1242
-
1243
- // src/lib/parsers/postman-parser.ts
1244
- var PostmanParser = class {
1245
- validate(input) {
1246
- return typeof input === "object" && input !== null && "info" in input && input.info?.schema?.includes("v2");
1247
- }
1248
- parse(input) {
1249
- if (!this.validate(input)) {
1250
- throw new Error("Invalid Postman Collection format (requires v2.0 or v2.1)");
1251
- }
1252
- const baseUrl = this.extractBaseUrl(input);
1253
- const endpoints = [];
1254
- this.parseItems(input.item || [], endpoints, baseUrl, input);
1255
- return {
1256
- version: input.info?.version,
1257
- title: input.info?.name,
1258
- description: input.info?.description,
1259
- baseUrl,
1260
- auth: this.extractAuth(input.auth),
1261
- globalHeaders: this.extractGlobalHeaders(input),
1262
- endpoints
1263
- };
1264
- }
1265
- extractBaseUrl(collection) {
1266
- const baseUrlVar = collection.variable?.find(
1267
- (v) => v.key === "baseUrl" || v.key === "base_url" || v.key === "url"
1268
- );
1269
- if (baseUrlVar) return baseUrlVar.value;
1270
- if (collection.item && collection.item.length > 0) {
1271
- const firstRequest = this.findFirstRequest(collection.item);
1272
- if (firstRequest?.request?.url) {
1273
- const url = this.parseUrl(firstRequest.request.url);
1274
- if (url.host) {
1275
- return `${url.protocol}://${url.host.join(".")}`;
1276
- }
1277
- }
1278
- }
1279
- return "";
1280
- }
1281
- findFirstRequest(items) {
1282
- for (const item of items) {
1283
- if (item.request) return item;
1284
- if (item.item) {
1285
- const found = this.findFirstRequest(item.item);
1286
- if (found) return found;
1287
- }
1288
- }
1289
- return null;
1290
- }
1291
- extractAuth(auth) {
1292
- if (!auth) return void 0;
1293
- if (auth.type === "bearer") {
1294
- return {
1295
- type: "bearer",
1296
- tokenPrefix: "Bearer"
1297
- };
1298
- }
1299
- if (auth.type === "apikey") {
1300
- const keyData = auth.apikey?.find((a) => a.key === "key");
1301
- const keyName = keyData?.value || "X-API-Key";
1302
- return {
1303
- type: "apiKey",
1304
- headerName: keyName
1305
- };
1306
- }
1307
- if (auth.type === "basic") {
1308
- return {
1309
- type: "basic"
1310
- };
1311
- }
1312
- return void 0;
1313
- }
1314
- extractGlobalHeaders(collection) {
1315
- return [];
1316
- }
1317
- parseItems(items, endpoints, baseUrl, collection) {
1318
- for (const item of items) {
1319
- if (item.item && Array.isArray(item.item)) {
1320
- this.parseItems(item.item, endpoints, baseUrl, collection);
1321
- } else if (item.request) {
1322
- const endpoint = this.parseRequest(item, baseUrl, collection);
1323
- endpoints.push(endpoint);
1324
- }
1325
- }
1326
- }
1327
- parseRequest(item, baseUrl, collection) {
1328
- const request = item.request;
1329
- const url = this.parseUrl(request.url);
1330
- const endpoint = {
1331
- title: item.name,
1332
- method: request.method.toUpperCase(),
1333
- path: this.buildPath(url, baseUrl),
1334
- description: item.request.description || item.description
1335
- };
1336
- const params = this.parseUrlParams(url);
1337
- if (params.path.length > 0) endpoint.pathParams = params.path;
1338
- if (params.query.length > 0) endpoint.queryParams = params.query;
1339
- if (request.header && request.header.length > 0) {
1340
- endpoint.headers = request.header.filter((h) => !h.disabled).map((h) => ({
1341
- name: h.key,
1342
- value: h.value || "",
1343
- description: h.description
1344
- }));
1345
- }
1346
- if (request.body) {
1347
- endpoint.body = this.parseBody(request.body);
1348
- }
1349
- const responses = this.parseResponses(item.response || []);
1350
- if (responses.success) endpoint.successResponse = responses.success;
1351
- if (responses.errors.length > 0) endpoint.errorResponses = responses.errors;
1352
- return endpoint;
1353
- }
1354
- parseUrl(url) {
1355
- if (typeof url === "string") {
1356
- const urlObj = new URL(url);
1357
- return {
1358
- protocol: urlObj.protocol.replace(":", ""),
1359
- host: urlObj.hostname.split("."),
1360
- path: urlObj.pathname.split("/").filter(Boolean),
1361
- query: [],
1362
- variable: []
1363
- };
1364
- }
1365
- return {
1366
- protocol: url.protocol || "https",
1367
- host: url.host || [],
1368
- path: url.path || [],
1369
- query: url.query || [],
1370
- variable: url.variable || []
1371
- };
1372
- }
1373
- buildPath(url, baseUrl) {
1374
- let path4 = "/";
1375
- if (url.path && url.path.length > 0) {
1376
- path4 += url.path.join("/");
1377
- }
1378
- path4 = path4.replace(/\{\{([^}]+)\}\}/g, ":$1");
1379
- return path4;
1380
- }
1381
- parseUrlParams(url) {
1382
- const result = { path: [], query: [] };
1383
- if (url.variable && url.variable.length > 0) {
1384
- for (const v of url.variable) {
1385
- result.path.push({
1386
- name: v.key,
1387
- type: v.type || "string",
1388
- description: v.description,
1389
- example: v.value
1390
- });
1391
- }
1392
- }
1393
- if (url.path && url.path.length > 0) {
1394
- for (const segment of url.path) {
1395
- if (segment.startsWith(":")) {
1396
- const paramName = segment.slice(1);
1397
- if (!result.path.find((p) => p.name === paramName)) {
1398
- result.path.push({
1399
- name: paramName,
1400
- type: "string"
1401
- });
1402
- }
1403
- }
1404
- }
1405
- }
1406
- if (url.query && url.query.length > 0) {
1407
- for (const q of url.query) {
1408
- if (q.disabled) continue;
1409
- result.query.push({
1410
- name: q.key,
1411
- type: "string",
1412
- description: q.description,
1413
- example: q.value
1414
- });
1415
- }
1416
- }
1417
- return result;
1418
- }
1419
- parseBody(body) {
1420
- if (!body) return void 0;
1421
- let example;
1422
- let description = body.description;
1423
- if (body.mode === "raw") {
1424
- try {
1425
- example = JSON.parse(body.raw);
1426
- } catch {
1427
- example = body.raw;
1428
- }
1429
- } else if (body.mode === "formdata" || body.mode === "urlencoded") {
1430
- example = {};
1431
- for (const item of body[body.mode] || []) {
1432
- if (!item.disabled) {
1433
- example[item.key] = item.value;
1434
- }
1435
- }
1436
- }
1437
- return {
1438
- description,
1439
- example
1440
- };
1441
- }
1442
- parseResponses(responses) {
1443
- const result = { errors: [] };
1444
- for (const response of responses) {
1445
- let example;
1446
- try {
1447
- example = JSON.parse(response.body);
1448
- } catch {
1449
- example = response.body;
1450
- }
1451
- const apiResponse = {
1452
- status: response.code || 200,
1453
- description: response.name,
1454
- example
1455
- };
1456
- if (apiResponse.status >= 200 && apiResponse.status < 300) {
1457
- if (!result.success) result.success = apiResponse;
1458
- } else {
1459
- result.errors.push(apiResponse);
1460
- }
1461
- }
1462
- return result;
1463
- }
1464
- };
1465
-
1466
- // src/lib/parsers/index.ts
1467
- var parsers = /* @__PURE__ */ new Map([
1468
- ["specra", new SpecraParser()],
1469
- ["openapi", new OpenApiParser()],
1470
- ["postman", new PostmanParser()]
1471
- ]);
1472
- function detectParserType(input) {
1473
- if (!input || typeof input !== "object") {
1474
- throw new Error("Invalid API spec: input must be an object");
1475
- }
1476
- if (input.info?.schema?.includes("v2")) {
1477
- return "postman";
1478
- }
1479
- if (input.openapi || input.swagger) {
1480
- return "openapi";
1481
- }
1482
- if (input.endpoints && Array.isArray(input.endpoints)) {
1483
- return "specra";
1484
- }
1485
- throw new Error(
1486
- "Unable to auto-detect API spec format. Supported formats: Specra, OpenAPI 3.x, Postman Collection v2.x"
1487
- );
1488
- }
1489
- function parseApiSpec(input, parserType = "auto") {
1490
- const actualType = parserType === "auto" ? detectParserType(input) : parserType;
1491
- const parser = parsers.get(actualType);
1492
- if (!parser) {
1493
- throw new Error(`Unknown parser type: ${actualType}`);
1494
- }
1495
- if (!parser.validate(input)) {
1496
- throw new Error(`Input does not match ${actualType} format`);
1497
- }
1498
- return parser.parse(input);
1499
- }
1500
-
1501
- // src/lib/utils.ts
1502
- var import_clsx = require("clsx");
1503
- var import_tailwind_merge = require("tailwind-merge");
1504
- function cn(...inputs) {
1505
- return (0, import_tailwind_merge.twMerge)((0, import_clsx.clsx)(inputs));
1506
- }
1507
- function getAssetPath(path4) {
1508
- const basePath = process.env.NEXT_PUBLIC_BASE_PATH || process.env.__NEXT_ROUTER_BASEPATH || "";
1509
- const normalizedPath = path4.startsWith("/") ? path4 : `/${path4}`;
1510
- if (basePath) {
1511
- const normalizedBase = basePath.startsWith("/") ? basePath : `/${basePath}`;
1512
- const cleanBase = normalizedBase.replace(/\/$/, "");
1513
- return `${cleanBase}${normalizedPath}`;
1514
- }
1515
- return normalizedPath;
1516
- }
1517
-
1518
- // src/lib/redirects.ts
1519
- async function buildRedirectMappings() {
1520
- const versions = getVersions();
1521
- const redirects = [];
1522
- for (const version of versions) {
1523
- const docs = await getAllDocs(version);
1524
- for (const doc of docs) {
1525
- if (doc.meta.redirect_from && Array.isArray(doc.meta.redirect_from)) {
1526
- for (const oldPath of doc.meta.redirect_from) {
1527
- redirects.push({
1528
- from: oldPath,
1529
- to: `/docs/${version}/${doc.slug}`
1530
- });
1531
- }
1532
- }
1533
- }
1534
- }
1535
- return redirects;
1536
- }
1537
- async function findRedirect(path4) {
1538
- const redirects = await buildRedirectMappings();
1539
- const redirect = redirects.find((r) => r.from === path4);
1540
- return redirect ? redirect.to : null;
1541
- }
1542
- // Annotate the CommonJS export names for ESM import in node:
1543
- 0 && (module.exports = {
1544
- CSP_DIRECTIVES,
1545
- OpenApiParser,
1546
- PerfTimer,
1547
- PostmanParser,
1548
- SAFE_MDX_COMPONENTS,
1549
- SpecraParser,
1550
- buildRedirectMappings,
1551
- buildSidebarStructure,
1552
- clearAllCaches,
1553
- cn,
1554
- debugLog,
1555
- defaultConfig,
1556
- detectParserType,
1557
- extractHeadings,
1558
- extractTableOfContents,
1559
- findRedirect,
1560
- generateCSPHeader,
1561
- getAdjacentDocs,
1562
- getAllCategoryConfigs,
1563
- getAllDocs,
1564
- getAssetPath,
1565
- getCacheStats,
1566
- getCachedAllDocs,
1567
- getCachedDocBySlug,
1568
- getCachedVersions,
1569
- getCategoryConfig,
1570
- getConfig,
1571
- getConfigValue,
1572
- getDocBySlug,
1573
- getI18nConfig,
1574
- getVersions,
1575
- initConfig,
1576
- isCategoryPage,
1577
- loadConfig,
1578
- logCacheOperation,
1579
- logFsOperation,
1580
- logMemoryUsage,
1581
- parseApiSpec,
1582
- processContentWithEnv,
1583
- reloadConfig,
1584
- replaceEnvVariables,
1585
- sanitizeMDXContent,
1586
- sanitizePath,
1587
- scanMDXForDangerousPatterns,
1588
- sortSidebarGroups,
1589
- sortSidebarItems,
1590
- validateConfig,
1591
- validateMDXComponents,
1592
- validateMDXSecurity,
1593
- validatePathWithinDirectory
1594
- });
1595
- //# sourceMappingURL=index.js.map