fumadocs-core 16.4.7 → 16.4.8

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 (255) hide show
  1. package/dist/{advanced-tbtFDsHU.js → advanced-BiZjLx5X.js} +3 -4
  2. package/dist/{algolia-BFVpYDZ_.d.ts → algolia-DWUn4vqa.d.ts} +2 -3
  3. package/dist/{algolia-Dbt0kj8j.js → algolia-IT2aRQE6.js} +2 -3
  4. package/dist/breadcrumb.d.ts +2 -3
  5. package/dist/breadcrumb.js +3 -4
  6. package/dist/{codeblock-utils-CdA7nXLP.d.ts → codeblock-utils-DA5Ql7wp.d.ts} +1 -2
  7. package/dist/content/github.d.ts +1 -2
  8. package/dist/content/github.js +1 -2
  9. package/dist/content/index.d.ts +3 -4
  10. package/dist/content/index.js +1 -2
  11. package/dist/content/mdx/preset-bundler.d.ts +9 -10
  12. package/dist/content/mdx/preset-bundler.js +2 -3
  13. package/dist/content/mdx/preset-runtime.d.ts +9 -10
  14. package/dist/content/mdx/preset-runtime.js +2 -3
  15. package/dist/content/toc.d.ts +1 -2
  16. package/dist/content/toc.js +2 -3
  17. package/dist/{definitions-Ca2P2viV.d.ts → definitions-fBNEDML4.d.ts} +1 -2
  18. package/dist/dynamic-link.d.ts +1 -2
  19. package/dist/dynamic-link.js +1 -2
  20. package/dist/{fetch-CiphcAUR.js → fetch-B9AxBORJ.js} +1 -2
  21. package/dist/framework/index.d.ts +1 -2
  22. package/dist/framework/index.js +1 -2
  23. package/dist/framework/next.d.ts +1 -2
  24. package/dist/framework/next.js +1 -2
  25. package/dist/framework/react-router.d.ts +1 -2
  26. package/dist/framework/react-router.js +1 -2
  27. package/dist/framework/tanstack.d.ts +3 -4
  28. package/dist/framework/tanstack.js +1 -2
  29. package/dist/framework/waku.d.ts +3 -4
  30. package/dist/framework/waku.js +1 -2
  31. package/dist/highlight/client.d.ts +2 -3
  32. package/dist/highlight/client.js +2 -3
  33. package/dist/highlight/index.d.ts +1 -1
  34. package/dist/highlight/index.js +1 -1
  35. package/dist/i18n/index.d.ts +1 -1
  36. package/dist/i18n/index.js +1 -2
  37. package/dist/i18n/middleware.d.ts +2 -3
  38. package/dist/i18n/middleware.js +1 -2
  39. package/dist/{icon-CL3r1pNG.js → icon-D9W4ODUt.js} +1 -2
  40. package/dist/{index-aE27-b16.d.ts → index-Bn_dIR1t.d.ts} +5 -6
  41. package/dist/{index-DxhhLscI.d.ts → index-CNd0mkPr.d.ts} +1 -2
  42. package/dist/{index-BaMZ8PEK.d.ts → index-DbVQNAN8.d.ts} +2 -3
  43. package/dist/{index-CmGSoB4T.d.ts → index-Skpc1DNd.d.ts} +4 -4
  44. package/dist/link.d.ts +3 -4
  45. package/dist/link.js +1 -2
  46. package/dist/{mdast-utils-B8O-41y4.js → mdast-utils-BqE5966y.js} +1 -2
  47. package/dist/mdx-plugins/codeblock-utils.d.ts +1 -1
  48. package/dist/mdx-plugins/codeblock-utils.js +1 -2
  49. package/dist/mdx-plugins/index.d.ts +15 -15
  50. package/dist/mdx-plugins/index.js +4 -4
  51. package/dist/mdx-plugins/rehype-code.d.ts +1 -1
  52. package/dist/mdx-plugins/rehype-code.js +2 -2
  53. package/dist/mdx-plugins/rehype-toc.d.ts +1 -1
  54. package/dist/mdx-plugins/rehype-toc.js +1 -1
  55. package/dist/mdx-plugins/remark-admonition.d.ts +1 -1
  56. package/dist/mdx-plugins/remark-admonition.js +2 -3
  57. package/dist/mdx-plugins/remark-code-tab.d.ts +1 -1
  58. package/dist/mdx-plugins/remark-code-tab.js +1 -2
  59. package/dist/mdx-plugins/remark-directive-admonition.d.ts +1 -1
  60. package/dist/mdx-plugins/remark-directive-admonition.js +1 -2
  61. package/dist/mdx-plugins/remark-feedback-block.d.ts +1 -1
  62. package/dist/mdx-plugins/remark-feedback-block.js +2 -3
  63. package/dist/mdx-plugins/remark-gfm.d.ts +1 -1
  64. package/dist/mdx-plugins/remark-heading.d.ts +1 -1
  65. package/dist/mdx-plugins/remark-heading.js +2 -3
  66. package/dist/mdx-plugins/remark-image.d.ts +1 -1
  67. package/dist/mdx-plugins/remark-image.js +1 -2
  68. package/dist/mdx-plugins/remark-mdx-files.d.ts +1 -1
  69. package/dist/mdx-plugins/remark-mdx-files.js +1 -2
  70. package/dist/mdx-plugins/remark-mdx-mermaid.d.ts +1 -1
  71. package/dist/mdx-plugins/remark-mdx-mermaid.js +1 -2
  72. package/dist/mdx-plugins/remark-npm.d.ts +1 -1
  73. package/dist/mdx-plugins/remark-npm.js +1 -2
  74. package/dist/mdx-plugins/remark-steps.d.ts +1 -1
  75. package/dist/mdx-plugins/remark-steps.js +1 -2
  76. package/dist/mdx-plugins/remark-structure.d.ts +1 -1
  77. package/dist/mdx-plugins/remark-structure.js +2 -3
  78. package/dist/{mixedbread-CPGJEgwq.js → mixedbread-B4x0e8AJ.js} +5 -4
  79. package/dist/negotiation/index.d.ts +1 -2
  80. package/dist/negotiation/index.js +1 -2
  81. package/dist/{normalize-url-CEfNKxaE.js → normalize-url-D88zV54r.js} +1 -2
  82. package/dist/{orama-cloud-yicpgD0c.js → orama-cloud-CiI54EU9.js} +3 -4
  83. package/dist/{orama-cloud-legacy-NJTbB19B.js → orama-cloud-legacy-DG0asrcn.js} +3 -4
  84. package/dist/page-tree/index.d.ts +2 -2
  85. package/dist/page-tree/index.js +1 -1
  86. package/dist/{path-CECfI3nn.js → path-B48ZWv8k.js} +2 -3
  87. package/dist/{rehype-code-Ct5Pb6BZ.js → rehype-code-8Te7jiPm.js} +2 -3
  88. package/dist/{rehype-code-BUrju-yF.d.ts → rehype-code-9wJ_hsjl.d.ts} +1 -2
  89. package/dist/{rehype-toc-Dcgzd_Vy.d.ts → rehype-toc-Bt9Ng_4w.d.ts} +1 -2
  90. package/dist/{rehype-toc-CTG0x7La.js → rehype-toc-CRXB92Tc.js} +1 -2
  91. package/dist/{remark-admonition-BvgS4oU1.d.ts → remark-admonition-DVevS9Wn.d.ts} +1 -2
  92. package/dist/{remark-code-tab-Ds_BdYXz.d.ts → remark-code-tab-DwGhoHpj.d.ts} +1 -2
  93. package/dist/{remark-directive-admonition-02cR5K1L.d.ts → remark-directive-admonition-DA7-ewEx.d.ts} +1 -2
  94. package/dist/{remark-feedback-block-fAyt4LdQ.d.ts → remark-feedback-block-PpERWDdJ.d.ts} +1 -2
  95. package/dist/{remark-heading-CSButCYt.d.ts → remark-heading-B02bkQ09.d.ts} +1 -2
  96. package/dist/{remark-image-C3MnP-3r.d.ts → remark-image-k8SDn3Hf.d.ts} +1 -2
  97. package/dist/{remark-mdx-files-BXUiiX3M.d.ts → remark-mdx-files-DXQKQsPS.d.ts} +1 -2
  98. package/dist/{remark-mdx-mermaid-C5ZBxx8x.d.ts → remark-mdx-mermaid-CzeZXfYX.d.ts} +1 -2
  99. package/dist/{remark-npm-DADZg0pf.d.ts → remark-npm-DS3cHDxB.d.ts} +1 -2
  100. package/dist/{remark-steps-CWEE34cT.d.ts → remark-steps-Bz-6C0tE.d.ts} +1 -2
  101. package/dist/{remark-structure-ChKxMXnK.d.ts → remark-structure-dZprfvCG.d.ts} +1 -2
  102. package/dist/{remove-undefined-Buxsprgu.js → remove-undefined-CiwokjLP.js} +1 -2
  103. package/dist/search/algolia.d.ts +2 -2
  104. package/dist/search/algolia.js +1 -2
  105. package/dist/search/client.d.ts +8 -9
  106. package/dist/search/client.js +7 -8
  107. package/dist/search/index.d.ts +1 -2
  108. package/dist/search/index.js +1 -1
  109. package/dist/search/orama-cloud-legacy.d.ts +6 -7
  110. package/dist/search/orama-cloud-legacy.js +1 -2
  111. package/dist/search/orama-cloud.d.ts +6 -7
  112. package/dist/search/orama-cloud.js +1 -2
  113. package/dist/search/server.d.ts +6 -6
  114. package/dist/search/server.js +5 -6
  115. package/dist/{search-DzqmOjzV.js → search-CBAFoCmV.js} +1 -2
  116. package/dist/{server-CLPpotS9.d.ts → server-BqqfVZaS.d.ts} +4 -5
  117. package/dist/{shiki-B4NO99XD.js → shiki-BMakKE6A.js} +1 -2
  118. package/dist/{shiki-vKy7H_iw.d.ts → shiki-BjMLCq9L.d.ts} +1 -2
  119. package/dist/source/client/index.d.ts +4 -4
  120. package/dist/source/client/index.js +6 -4
  121. package/dist/source/index.d.ts +4 -4
  122. package/dist/source/index.js +108 -59
  123. package/dist/source/plugins/lucide-icons.d.ts +5 -6
  124. package/dist/source/plugins/lucide-icons.js +2 -3
  125. package/dist/source/plugins/slugs.d.ts +4 -4
  126. package/dist/source/plugins/slugs.js +2 -3
  127. package/dist/source/plugins/status-badges.d.ts +53 -0
  128. package/dist/source/plugins/status-badges.js +54 -0
  129. package/dist/source/schema.d.ts +1 -2
  130. package/dist/source/schema.js +1 -2
  131. package/dist/{static-C_WBOzek.js → static-Dg4_dKaf.js} +2 -3
  132. package/dist/toc.d.ts +1 -2
  133. package/dist/toc.js +1 -2
  134. package/dist/{util-d5FlPx1Z.d.ts → util-C1pcIt82.d.ts} +1 -2
  135. package/dist/{util-Dn-wseQ5.js → util-E8U2ttCR.js} +1 -2
  136. package/dist/utils/use-effect-event.d.ts +1 -2
  137. package/dist/utils/use-effect-event.js +1 -2
  138. package/dist/utils/use-media-query.d.ts +1 -2
  139. package/dist/utils/use-media-query.js +1 -2
  140. package/dist/utils/use-on-change.d.ts +1 -2
  141. package/dist/utils/use-on-change.js +1 -2
  142. package/dist/{utils-D10VxgVc.js → utils-BllAiz19.js} +1 -2
  143. package/package.json +13 -13
  144. package/dist/advanced-tbtFDsHU.js.map +0 -1
  145. package/dist/algolia-BFVpYDZ_.d.ts.map +0 -1
  146. package/dist/algolia-Dbt0kj8j.js.map +0 -1
  147. package/dist/breadcrumb.d.ts.map +0 -1
  148. package/dist/breadcrumb.js.map +0 -1
  149. package/dist/codeblock-utils-CdA7nXLP.d.ts.map +0 -1
  150. package/dist/content/github.d.ts.map +0 -1
  151. package/dist/content/github.js.map +0 -1
  152. package/dist/content/index.d.ts.map +0 -1
  153. package/dist/content/index.js.map +0 -1
  154. package/dist/content/mdx/preset-bundler.d.ts.map +0 -1
  155. package/dist/content/mdx/preset-bundler.js.map +0 -1
  156. package/dist/content/mdx/preset-runtime.d.ts.map +0 -1
  157. package/dist/content/mdx/preset-runtime.js.map +0 -1
  158. package/dist/content/toc.d.ts.map +0 -1
  159. package/dist/content/toc.js.map +0 -1
  160. package/dist/definitions-Ca2P2viV.d.ts.map +0 -1
  161. package/dist/dynamic-link.d.ts.map +0 -1
  162. package/dist/dynamic-link.js.map +0 -1
  163. package/dist/fetch-CiphcAUR.js.map +0 -1
  164. package/dist/framework/index.d.ts.map +0 -1
  165. package/dist/framework/index.js.map +0 -1
  166. package/dist/framework/next.d.ts.map +0 -1
  167. package/dist/framework/next.js.map +0 -1
  168. package/dist/framework/react-router.d.ts.map +0 -1
  169. package/dist/framework/react-router.js.map +0 -1
  170. package/dist/framework/tanstack.d.ts.map +0 -1
  171. package/dist/framework/tanstack.js.map +0 -1
  172. package/dist/framework/waku.d.ts.map +0 -1
  173. package/dist/framework/waku.js.map +0 -1
  174. package/dist/highlight/client.d.ts.map +0 -1
  175. package/dist/highlight/client.js.map +0 -1
  176. package/dist/i18n/index.js.map +0 -1
  177. package/dist/i18n/middleware.d.ts.map +0 -1
  178. package/dist/i18n/middleware.js.map +0 -1
  179. package/dist/icon-CL3r1pNG.js.map +0 -1
  180. package/dist/index-BaMZ8PEK.d.ts.map +0 -1
  181. package/dist/index-CmGSoB4T.d.ts.map +0 -1
  182. package/dist/index-DxhhLscI.d.ts.map +0 -1
  183. package/dist/index-aE27-b16.d.ts.map +0 -1
  184. package/dist/link.d.ts.map +0 -1
  185. package/dist/link.js.map +0 -1
  186. package/dist/mdast-utils-B8O-41y4.js.map +0 -1
  187. package/dist/mdx-plugins/codeblock-utils.js.map +0 -1
  188. package/dist/mdx-plugins/remark-admonition.js.map +0 -1
  189. package/dist/mdx-plugins/remark-code-tab.js.map +0 -1
  190. package/dist/mdx-plugins/remark-directive-admonition.js.map +0 -1
  191. package/dist/mdx-plugins/remark-feedback-block.js.map +0 -1
  192. package/dist/mdx-plugins/remark-heading.js.map +0 -1
  193. package/dist/mdx-plugins/remark-image.js.map +0 -1
  194. package/dist/mdx-plugins/remark-mdx-files.js.map +0 -1
  195. package/dist/mdx-plugins/remark-mdx-mermaid.js.map +0 -1
  196. package/dist/mdx-plugins/remark-npm.js.map +0 -1
  197. package/dist/mdx-plugins/remark-steps.js.map +0 -1
  198. package/dist/mdx-plugins/remark-structure.js.map +0 -1
  199. package/dist/mixedbread-CPGJEgwq.js.map +0 -1
  200. package/dist/negotiation/index.d.ts.map +0 -1
  201. package/dist/negotiation/index.js.map +0 -1
  202. package/dist/normalize-url-CEfNKxaE.js.map +0 -1
  203. package/dist/orama-cloud-legacy-NJTbB19B.js.map +0 -1
  204. package/dist/orama-cloud-yicpgD0c.js.map +0 -1
  205. package/dist/path-CECfI3nn.js.map +0 -1
  206. package/dist/rehype-code-BUrju-yF.d.ts.map +0 -1
  207. package/dist/rehype-code-Ct5Pb6BZ.js.map +0 -1
  208. package/dist/rehype-toc-CTG0x7La.js.map +0 -1
  209. package/dist/rehype-toc-Dcgzd_Vy.d.ts.map +0 -1
  210. package/dist/remark-admonition-BvgS4oU1.d.ts.map +0 -1
  211. package/dist/remark-code-tab-Ds_BdYXz.d.ts.map +0 -1
  212. package/dist/remark-directive-admonition-02cR5K1L.d.ts.map +0 -1
  213. package/dist/remark-feedback-block-fAyt4LdQ.d.ts.map +0 -1
  214. package/dist/remark-heading-CSButCYt.d.ts.map +0 -1
  215. package/dist/remark-image-C3MnP-3r.d.ts.map +0 -1
  216. package/dist/remark-mdx-files-BXUiiX3M.d.ts.map +0 -1
  217. package/dist/remark-mdx-mermaid-C5ZBxx8x.d.ts.map +0 -1
  218. package/dist/remark-npm-DADZg0pf.d.ts.map +0 -1
  219. package/dist/remark-steps-CWEE34cT.d.ts.map +0 -1
  220. package/dist/remark-structure-ChKxMXnK.d.ts.map +0 -1
  221. package/dist/remove-undefined-Buxsprgu.js.map +0 -1
  222. package/dist/search/algolia.js.map +0 -1
  223. package/dist/search/client.d.ts.map +0 -1
  224. package/dist/search/client.js.map +0 -1
  225. package/dist/search/index.d.ts.map +0 -1
  226. package/dist/search/orama-cloud-legacy.d.ts.map +0 -1
  227. package/dist/search/orama-cloud-legacy.js.map +0 -1
  228. package/dist/search/orama-cloud.d.ts.map +0 -1
  229. package/dist/search/orama-cloud.js.map +0 -1
  230. package/dist/search/server.js.map +0 -1
  231. package/dist/search-DzqmOjzV.js.map +0 -1
  232. package/dist/server-CLPpotS9.d.ts.map +0 -1
  233. package/dist/shiki-B4NO99XD.js.map +0 -1
  234. package/dist/shiki-vKy7H_iw.d.ts.map +0 -1
  235. package/dist/source/client/index.js.map +0 -1
  236. package/dist/source/index.js.map +0 -1
  237. package/dist/source/plugins/lucide-icons.d.ts.map +0 -1
  238. package/dist/source/plugins/lucide-icons.js.map +0 -1
  239. package/dist/source/plugins/slugs.js.map +0 -1
  240. package/dist/source/schema.d.ts.map +0 -1
  241. package/dist/source/schema.js.map +0 -1
  242. package/dist/static-C_WBOzek.js.map +0 -1
  243. package/dist/toc.d.ts.map +0 -1
  244. package/dist/toc.js.map +0 -1
  245. package/dist/util-Dn-wseQ5.js.map +0 -1
  246. package/dist/util-d5FlPx1Z.d.ts.map +0 -1
  247. package/dist/utils/use-effect-event.d.ts.map +0 -1
  248. package/dist/utils/use-effect-event.js.map +0 -1
  249. package/dist/utils/use-media-query.d.ts.map +0 -1
  250. package/dist/utils/use-media-query.js.map +0 -1
  251. package/dist/utils/use-on-change.d.ts.map +0 -1
  252. package/dist/utils/use-on-change.js.map +0 -1
  253. package/dist/utils-D10VxgVc.js.map +0 -1
  254. /package/dist/{chunk-C9UIFEcR.js → chunk-CQNP8FC4.js} +0 -0
  255. /package/dist/{remark-gfm-jrvaEZw5.d.ts → remark-gfm-Cvcfjik1.d.ts} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","names":["source","path","path","source","path","path"],"sources":["../../src/source/source.ts","../../src/source/storage/file-system.ts","../../src/source/storage/content.ts","../../src/source/page-tree/transformer-fallback.ts","../../src/source/page-tree/builder.ts","../../src/source/loader.ts"],"sourcesContent":["export interface Source<Config extends SourceConfig = SourceConfig> {\n files: VirtualFile<Config>[];\n}\n\nexport interface SourceConfig {\n pageData: PageData;\n metaData: MetaData;\n}\n\nexport interface MetaData {\n icon?: string | undefined;\n title?: string | undefined;\n root?: boolean | undefined;\n pages?: string[] | undefined;\n defaultOpen?: boolean | undefined;\n collapsible?: boolean | undefined;\n\n description?: string | undefined;\n}\n\nexport interface PageData {\n icon?: string | undefined;\n title?: string;\n description?: string | undefined;\n}\n\nexport type VirtualFile<Config extends SourceConfig = SourceConfig> =\n | VirtualPage<Config['pageData']>\n | VirtualMeta<Config['metaData']>;\n\ninterface BaseVirtualFile {\n /**\n * Virtualized path (relative to content directory)\n *\n * @example `docs/page.mdx`\n */\n path: string;\n\n /**\n * Absolute path of the file\n */\n absolutePath?: string;\n}\n\ninterface VirtualPage<Data extends PageData> extends BaseVirtualFile {\n type: 'page';\n /**\n * Specified Slugs for page\n */\n slugs?: string[];\n data: Data;\n}\n\ninterface VirtualMeta<Data extends MetaData> extends BaseVirtualFile {\n type: 'meta';\n data: Data;\n}\n\nexport type _ConfigUnion_<T extends Record<string, Source>> = {\n [K in keyof T]: T[K] extends Source<infer Config>\n ? {\n pageData: Config['pageData'] & { type: K };\n metaData: Config['metaData'] & { type: K };\n }\n : never;\n}[keyof T];\n\nexport function multiple<T extends Record<string, Source>>(sources: T) {\n const out: Source<_ConfigUnion_<T>> = { files: [] };\n\n for (const [type, source] of Object.entries(sources)) {\n for (const file of source.files) {\n out.files.push({\n ...file,\n data: {\n ...file.data,\n type,\n },\n });\n }\n }\n\n return out;\n}\n\nexport function source<Page extends PageData, Meta extends MetaData>(config: {\n pages: VirtualPage<Page>[];\n metas: VirtualMeta<Meta>[];\n}): Source<{\n pageData: Page;\n metaData: Meta;\n}> {\n return {\n files: [...config.pages, ...config.metas],\n };\n}\n\nexport interface _SourceUpdate_<Config extends SourceConfig> {\n files: <Page extends PageData, Meta extends MetaData>(\n fn: (files: VirtualFile<Config>[]) => (VirtualPage<Page> | VirtualMeta<Meta>)[],\n ) => _SourceUpdate_<{\n pageData: Page;\n metaData: Meta;\n }>;\n page: <V extends PageData>(\n fn: (page: VirtualPage<Config['pageData']>) => VirtualPage<V>,\n ) => _SourceUpdate_<{\n pageData: V;\n metaData: Config['metaData'];\n }>;\n\n meta: <V extends MetaData>(\n fn: (meta: VirtualMeta<Config['metaData']>) => VirtualMeta<V>,\n ) => _SourceUpdate_<{\n pageData: Config['pageData'];\n metaData: V;\n }>;\n build: () => Source<Config>;\n}\n\n/**\n * update a source object in-place.\n */\nexport function update<Config extends SourceConfig>(\n source: Source<Config>,\n): _SourceUpdate_<Config> {\n return {\n files(fn) {\n source.files = fn(source.files);\n return this as _SourceUpdate_<never>;\n },\n page(fn) {\n for (let i = 0; i < source.files.length; i++) {\n const file = source.files[i];\n if (file.type === 'page') source.files[i] = fn(file);\n }\n\n return this as _SourceUpdate_<never>;\n },\n meta(fn) {\n for (let i = 0; i < source.files.length; i++) {\n const file = source.files[i];\n if (file.type === 'meta') source.files[i] = fn(file);\n }\n\n return this as _SourceUpdate_<never>;\n },\n build() {\n return source;\n },\n };\n}\n","import { dirname, splitPath } from '../path';\n\n/**\n * In memory file system.\n */\nexport class FileSystem<File> {\n files = new Map<string, File>();\n folders = new Map<string, string[]>();\n\n constructor(inherit?: FileSystem<File>) {\n if (inherit) {\n for (const [k, v] of inherit.folders) {\n this.folders.set(k, v);\n }\n\n for (const [k, v] of inherit.files) {\n this.files.set(k, v);\n }\n } else {\n this.folders.set('', []);\n }\n }\n\n read(path: string): File | undefined {\n return this.files.get(path);\n }\n\n /**\n * get the direct children of folder (in virtual file path)\n */\n readDir(path: string): string[] | undefined {\n return this.folders.get(path);\n }\n\n write(path: string, file: File): void {\n if (!this.files.has(path)) {\n const dir = dirname(path);\n this.makeDir(dir);\n this.readDir(dir)?.push(path);\n }\n\n this.files.set(path, file);\n }\n\n /**\n * Delete files at specified path.\n *\n * @param path - the target path.\n * @param [recursive=false] - if set to `true`, it will also delete directories.\n */\n delete(path: string, recursive = false): boolean {\n if (this.files.delete(path)) return true;\n\n if (recursive) {\n const folder = this.folders.get(path);\n if (!folder) return false;\n\n this.folders.delete(path);\n for (const child of folder) {\n this.delete(child);\n }\n return true;\n }\n\n return false;\n }\n\n getFiles(): string[] {\n return Array.from(this.files.keys());\n }\n\n makeDir(path: string): void {\n const segments = splitPath(path);\n\n for (let i = 0; i < segments.length; i++) {\n const segment = segments.slice(0, i + 1).join('/');\n if (this.folders.has(segment)) continue;\n\n this.folders.set(segment, []);\n this.folders.get(dirname(segment))!.push(segment);\n }\n }\n}\n","import { FileSystem } from '@/source/storage/file-system';\nimport { basename, dirname, joinPath, slash, splitPath } from '@/source/path';\nimport type { ResolvedLoaderConfig } from '../loader';\nimport type { SourceConfig } from '../source';\n\nexport type ContentStorage<Config extends SourceConfig = SourceConfig> = FileSystem<\n ContentStorageFile<Config>\n>;\n\nexport type ContentStorageFile<Config extends SourceConfig = SourceConfig> =\n | ContentStorageMetaFile<Config>\n | ContentStoragePageFile<Config>;\n\nexport interface ContentStorageMetaFile<Config extends SourceConfig = SourceConfig> {\n path: string;\n absolutePath?: string;\n\n format: 'meta';\n data: Config['metaData'];\n}\n\nexport interface ContentStoragePageFile<Config extends SourceConfig = SourceConfig> {\n path: string;\n absolutePath?: string;\n\n format: 'page';\n slugs: string[];\n data: Config['pageData'];\n}\n\nfunction isLocaleValid(locale: string) {\n return locale.length > 0 && !/\\d+/.test(locale);\n}\n\nconst parsers = {\n dir(path: string): [string, string?] {\n const [locale, ...segs] = path.split('/');\n\n if (locale && segs.length > 0 && isLocaleValid(locale)) return [segs.join('/'), locale];\n\n return [path];\n },\n dot(path: string): [string, string?] {\n const dir = dirname(path);\n const base = basename(path);\n const parts = base.split('.');\n if (parts.length < 3) return [path];\n\n const [locale] = parts.splice(parts.length - 2, 1);\n if (!isLocaleValid(locale)) return [path];\n\n return [joinPath(dir, parts.join('.')), locale];\n },\n none(path: string): [string, string?] {\n return [path];\n },\n};\n\n/**\n * @param defaultLanguage - language to use when i18n is not configured.\n * @returns a map of locale and its content storage.\n *\n * in the storage, locale codes are removed from file paths, hence the same file will have same file paths in every storage.\n */\nexport function buildContentStorage(\n loaderConfig: ResolvedLoaderConfig,\n defaultLanguage: string,\n): Record<string, ContentStorage> {\n const {\n source,\n plugins = [],\n i18n = {\n defaultLanguage,\n parser: 'none',\n languages: [defaultLanguage],\n },\n } = loaderConfig;\n\n const parser = parsers[i18n.parser ?? 'dot'];\n const storages: Record<string, ContentStorage> = {};\n const normalized = new Map<\n string,\n {\n pathWithoutLocale: string;\n file: ContentStorageFile;\n }[]\n >();\n\n for (const inputFile of source.files) {\n let file: ContentStorageFile;\n if (inputFile.type === 'page') {\n file = {\n format: 'page',\n path: normalizePath(inputFile.path),\n // will be generated by the slugs plugin if unspecified\n slugs: inputFile.slugs as string[],\n data: inputFile.data,\n absolutePath: inputFile.absolutePath,\n };\n } else {\n file = {\n format: 'meta',\n path: normalizePath(inputFile.path),\n absolutePath: inputFile.absolutePath,\n data: inputFile.data,\n };\n }\n\n const [pathWithoutLocale, locale = i18n.defaultLanguage] = parser(file.path);\n const list = normalized.get(locale) ?? [];\n list.push({\n pathWithoutLocale,\n file,\n });\n normalized.set(locale, list);\n }\n\n const fallbackLang =\n i18n.fallbackLanguage !== null ? (i18n.fallbackLanguage ?? i18n.defaultLanguage) : null;\n\n function scan(lang: string) {\n if (storages[lang]) return;\n\n let storage: ContentStorage;\n if (fallbackLang && fallbackLang !== lang) {\n scan(fallbackLang);\n storage = new FileSystem(storages[fallbackLang]);\n } else {\n storage = new FileSystem();\n }\n\n for (const { pathWithoutLocale, file } of normalized.get(lang) ?? []) {\n storage.write(pathWithoutLocale, file);\n }\n\n const context = {\n storage,\n };\n for (const plugin of plugins) {\n plugin.transformStorage?.(context);\n }\n\n storages[lang] = storage;\n }\n\n for (const lang of i18n.languages) scan(lang);\n return storages;\n}\n\n/**\n * @param path - Relative path\n * @returns Normalized path, with no trailing/leading slashes\n * @throws Throws error if path starts with `./` or `../`\n */\nfunction normalizePath(path: string): string {\n const segments = splitPath(slash(path));\n if (segments[0] === '.' || segments[0] === '..')\n throw new Error(\"It must not start with './' or '../'\");\n return segments.join('/');\n}\n","import type { ContentStorage, PageTreeTransformer } from '@/source';\nimport { FileSystem } from '@/source';\n\nexport function transformerFallback(): PageTreeTransformer {\n const addedFiles = new Set<string>();\n\n return {\n root(root) {\n const isolatedStorage: ContentStorage = new FileSystem();\n\n for (const file of this.storage.getFiles()) {\n if (addedFiles.has(file)) continue;\n\n const content = this.storage.read(file);\n if (content) isolatedStorage.write(file, content);\n }\n\n if (isolatedStorage.getFiles().length === 0) return root;\n\n root.fallback = this.builder.build(isolatedStorage, {\n ...this.options,\n id: `fallback-${root.$id ?? ''}`,\n generateFallback: false,\n });\n\n addedFiles.clear();\n return root;\n },\n file(node, file) {\n if (file) addedFiles.add(file);\n\n return node;\n },\n folder(node, _dir, metaPath) {\n if (metaPath) addedFiles.add(metaPath);\n\n return node;\n },\n };\n}\n","import type * as PageTree from '@/page-tree/definitions';\nimport type { LoaderConfig, ResolvedLoaderConfig } from '@/source/loader';\nimport type { ContentStorage } from '@/source/storage/content';\nimport { basename, extname, joinPath } from '@/source/path';\nimport { transformerFallback } from '@/source/page-tree/transformer-fallback';\nimport type { SourceConfig } from '../source';\n\nexport interface PageTreeBuilderContext<Config extends SourceConfig = SourceConfig> {\n rootId: string;\n generateNodeId: () => string;\n options: PageTreeOptions;\n transformers: PageTreeTransformer<Config>[];\n\n builder: PageTreeBuilder;\n storage: ContentStorage<Config>;\n getUrl: ResolvedLoaderConfig['url'];\n\n storages?: Record<string, ContentStorage<Config>>;\n locale?: string;\n}\n\nexport interface PageTreeTransformer<Config extends SourceConfig = SourceConfig> {\n file?: (\n this: PageTreeBuilderContext<Config>,\n node: PageTree.Item,\n filePath?: string,\n ) => PageTree.Item;\n folder?: (\n this: PageTreeBuilderContext<Config>,\n node: PageTree.Folder,\n folderPath: string,\n metaPath?: string,\n ) => PageTree.Folder;\n separator?: (\n this: PageTreeBuilderContext<Config>,\n node: PageTree.Separator,\n ) => PageTree.Separator;\n root?: (this: PageTreeBuilderContext<Config>, node: PageTree.Root) => PageTree.Root;\n}\n\nexport interface PageTreeOptions<Config extends LoaderConfig = LoaderConfig> {\n id?: string;\n /**\n * Remove references to the file path of original nodes (`$ref`)\n *\n * @defaultValue false\n */\n noRef?: boolean;\n /**\n * generate fallback page tree\n *\n * @defaultValue true\n */\n generateFallback?: boolean;\n\n /**\n * Additional page tree transformers to apply\n */\n transformers?: PageTreeTransformer<Config['source']>[];\n}\n\nexport interface PageTreeBuilder {\n build: (storage: ContentStorage, options?: PageTreeOptions) => PageTree.Root;\n\n buildI18n: (\n storages: Record<string, ContentStorage>,\n options?: PageTreeOptions,\n ) => Record<string, PageTree.Root>;\n}\n\nconst group = /^\\((?<name>.+)\\)$/;\nconst link = /^(?<external>external:)?(?:\\[(?<icon>[^\\]]+)])?\\[(?<name>[^\\]]+)]\\((?<url>[^)]+)\\)$/;\nconst separator = /^---(?:\\[(?<icon>[^\\]]+)])?(?<name>.+)---|^---$/;\nconst rest = '...' as const;\nconst restReversed = 'z...a' as const;\nconst extractPrefix = '...';\nconst excludePrefix = '!';\n\nexport function createPageTreeBuilder(loaderConfig: ResolvedLoaderConfig): PageTreeBuilder {\n const { plugins = [], url, pageTree: defaultOptions = {} } = loaderConfig;\n\n return {\n build(storage, options = defaultOptions) {\n const key = '';\n return this.buildI18n({ [key]: storage }, options)[key];\n },\n buildI18n(storages, options = defaultOptions) {\n let nextId = 0;\n const out: Record<string, PageTree.Root> = {};\n const transformers: PageTreeTransformer[] = [];\n\n if (options.transformers) {\n transformers.push(...options.transformers);\n }\n\n for (const plugin of plugins) {\n if (plugin.transformPageTree) transformers.push(plugin.transformPageTree);\n }\n\n if (options.generateFallback ?? true) {\n transformers.push(transformerFallback());\n }\n\n for (const [locale, storage] of Object.entries(storages)) {\n let rootId = locale.length === 0 ? 'root' : locale;\n if (options.id) rootId = `${options.id}-${rootId}`;\n\n out[locale] = createPageTreeBuilderUtils({\n rootId,\n transformers,\n builder: this,\n options,\n getUrl: url,\n locale,\n storage,\n storages,\n generateNodeId() {\n return '_' + nextId++;\n },\n }).root();\n }\n\n return out;\n },\n };\n}\n\nfunction createFlattenPathResolver(storage: ContentStorage) {\n const map = new Map<string, string>();\n const files = storage.getFiles();\n for (const file of files) {\n const content = storage.read(file)!;\n const flattenPath = file.substring(0, file.length - extname(file).length);\n\n map.set(flattenPath + '.' + content.format, file);\n }\n\n return (name: string, format: string) => {\n return map.get(name + '.' + format) ?? name;\n };\n}\n\nfunction createPageTreeBuilderUtils(ctx: PageTreeBuilderContext) {\n const resolveFlattenPath = createFlattenPathResolver(ctx.storage);\n const visitedPaths = new Set<string>();\n\n function nextNodeId(localId = ctx.generateNodeId()) {\n return `${ctx.rootId}:${localId}`;\n }\n\n return {\n buildPaths(paths: string[], reversed = false): PageTree.Node[] {\n const items: PageTree.Node[] = [];\n const folders: PageTree.Folder[] = [];\n const sortedPaths = paths.sort((a, b) => a.localeCompare(b) * (reversed ? -1 : 1));\n\n for (const path of sortedPaths) {\n const fileNode = this.file(path);\n if (fileNode) {\n if (basename(path, extname(path)) === 'index') items.unshift(fileNode);\n else items.push(fileNode);\n\n continue;\n }\n\n const dirNode = this.folder(path, false);\n if (dirNode) folders.push(dirNode);\n }\n\n items.push(...folders);\n return items;\n },\n resolveFolderItem(folderPath: string, item: string): PageTree.Node[] | '...' | 'z...a' {\n if (item === rest || item === restReversed) return item;\n\n let match = separator.exec(item);\n if (match?.groups) {\n let node: PageTree.Separator = {\n $id: nextNodeId(),\n type: 'separator',\n icon: match.groups.icon,\n name: match.groups.name,\n };\n\n for (const transformer of ctx.transformers) {\n if (!transformer.separator) continue;\n node = transformer.separator.call(ctx, node);\n }\n\n return [node];\n }\n\n match = link.exec(item);\n if (match?.groups) {\n const { icon, url, name, external } = match.groups;\n\n let node: PageTree.Item = {\n $id: nextNodeId(),\n type: 'page',\n icon,\n name,\n url,\n external: external ? true : undefined,\n };\n\n for (const transformer of ctx.transformers) {\n if (!transformer.file) continue;\n node = transformer.file.call(ctx, node);\n }\n\n return [node];\n }\n\n const isExcept = item.startsWith(excludePrefix);\n const isExtract = !isExcept && item.startsWith(extractPrefix);\n\n let filename = item;\n if (isExcept) {\n filename = item.slice(excludePrefix.length);\n } else if (isExtract) {\n filename = item.slice(extractPrefix.length);\n }\n\n const path = resolveFlattenPath(joinPath(folderPath, filename), 'page');\n\n if (isExcept) {\n visitedPaths.add(path);\n return [];\n }\n\n const dirNode = this.folder(path, false);\n if (dirNode) {\n return isExtract ? dirNode.children : [dirNode];\n }\n\n const fileNode = this.file(path);\n return fileNode ? [fileNode] : [];\n },\n folder(folderPath: string, isGlobalRoot: boolean): PageTree.Folder | undefined {\n const { storage, options, transformers } = ctx;\n const files = storage.readDir(folderPath);\n if (!files) return;\n\n const metaPath = resolveFlattenPath(joinPath(folderPath, 'meta'), 'meta');\n const indexPath = resolveFlattenPath(joinPath(folderPath, 'index'), 'page');\n\n let meta = storage.read(metaPath);\n if (meta && meta.format !== 'meta') meta = undefined;\n\n const metadata = meta?.data ?? {};\n const { root = isGlobalRoot, pages } = metadata;\n let index: PageTree.Item | undefined;\n let children: PageTree.Node[];\n\n if (pages) {\n const resolved = pages.flatMap<PageTree.Node | typeof rest | typeof restReversed>((item) =>\n this.resolveFolderItem(folderPath, item),\n );\n\n if (!root && !visitedPaths.has(indexPath)) {\n index = this.file(indexPath);\n }\n\n for (let i = 0; i < resolved.length; i++) {\n const item = resolved[i];\n if (item !== rest && item !== restReversed) continue;\n\n const items = this.buildPaths(\n files.filter((file) => !visitedPaths.has(file)),\n item === restReversed,\n );\n\n resolved.splice(i, 1, ...items);\n break;\n }\n\n children = resolved as PageTree.Node[];\n } else {\n if (!root && !visitedPaths.has(indexPath)) {\n index = this.file(indexPath);\n }\n\n children = this.buildPaths(files.filter((file) => !visitedPaths.has(file)));\n }\n\n let node: PageTree.Folder = {\n type: 'folder',\n name:\n metadata.title ??\n index?.name ??\n (() => {\n const folderName = basename(folderPath);\n return pathToName(group.exec(folderName)?.[1] ?? folderName);\n })(),\n icon: metadata.icon ?? index?.icon,\n root: metadata.root,\n defaultOpen: metadata.defaultOpen,\n description: metadata.description,\n collapsible: metadata.collapsible,\n index,\n children,\n $id: nextNodeId(folderPath),\n $ref:\n !options.noRef && meta\n ? {\n metaFile: metaPath,\n }\n : undefined,\n };\n\n visitedPaths.add(folderPath);\n for (const transformer of transformers) {\n if (!transformer.folder) continue;\n node = transformer.folder.call(ctx, node, folderPath, metaPath);\n }\n\n return node;\n },\n file(path: string): PageTree.Item | undefined {\n const { options, getUrl, storage, locale, transformers } = ctx;\n\n const page = storage.read(path);\n if (page?.format !== 'page') return;\n\n const { title, description, icon } = page.data;\n let item: PageTree.Item = {\n $id: nextNodeId(path),\n type: 'page',\n name: title ?? pathToName(basename(path, extname(path))),\n description,\n icon,\n url: getUrl(page.slugs, locale),\n $ref: !options.noRef\n ? {\n file: path,\n }\n : undefined,\n };\n\n visitedPaths.add(path);\n for (const transformer of transformers) {\n if (!transformer.file) continue;\n item = transformer.file.call(ctx, item, path);\n }\n\n return item;\n },\n root(): PageTree.Root {\n const folder = this.folder('', true)!;\n let root: PageTree.Root = {\n $id: ctx.rootId,\n name: folder.name || 'Docs',\n children: folder.children,\n };\n\n for (const transformer of ctx.transformers) {\n if (!transformer.root) continue;\n root = transformer.root.call(ctx, root);\n }\n\n return root;\n },\n };\n}\n\n/**\n * Get item name from file name\n *\n * @param name - file name\n */\nfunction pathToName(name: string): string {\n const result = [];\n for (const c of name) {\n if (result.length === 0) result.push(c.toLocaleUpperCase());\n else if (c === '-') result.push(' ');\n else result.push(c);\n }\n\n return result.join('');\n}\n","import type * as PageTree from '@/page-tree/definitions';\nimport type { I18nConfig } from '@/i18n';\nimport { buildContentStorage, type ContentStorage } from './storage/content';\nimport { createPageTreeBuilder, type PageTreeOptions } from '@/source/page-tree/builder';\nimport { joinPath } from './path';\nimport { normalizeUrl } from '@/utils/normalize-url';\nimport { SlugFn, slugsPlugin } from '@/source/plugins/slugs';\nimport { iconPlugin, type IconResolver } from '@/source/plugins/icon';\nimport type { MetaData, PageData, Source, SourceConfig } from './source';\nimport { visit } from '@/page-tree/utils';\nimport path from 'node:path';\nimport type { PageTreeTransformer } from '@/source/page-tree/builder';\nimport type { SerializedPageTree } from './client';\n\nexport interface LoaderConfig {\n source: SourceConfig;\n i18n: I18nConfig | undefined;\n}\n\nexport interface LoaderOptions<C extends LoaderConfig = LoaderConfig> {\n baseUrl: string;\n i18n?: C['i18n'];\n url?: (slugs: string[], locale?: string) => string;\n\n /**\n * Additional options for page tree builder\n */\n pageTree?: PageTreeOptions<C>;\n\n plugins?:\n | LoaderPluginOption[]\n | ((context: {\n typedPlugin: (plugin: LoaderPlugin<C>) => LoaderPlugin;\n }) => LoaderPluginOption[]);\n icon?: IconResolver;\n slugs?: SlugFn<C>;\n}\n\nexport interface ResolvedLoaderConfig {\n source: Source;\n url: (slugs: string[], locale?: string) => string;\n\n plugins?: LoaderPlugin[];\n pageTree?: PageTreeOptions;\n i18n?: I18nConfig | undefined;\n}\n\ninterface SharedFileInfo {\n /**\n * Virtualized file path (relative to content directory)\n *\n * @example `docs/page.mdx`\n */\n path: string;\n\n /**\n * Absolute path of the file\n */\n absolutePath?: string;\n}\n\nexport interface Page<Data = PageData> extends SharedFileInfo {\n slugs: string[];\n url: string;\n data: Data;\n\n locale?: string | undefined;\n}\n\nexport interface Meta<Data = MetaData> extends SharedFileInfo {\n data: Data;\n}\n\nexport interface LoaderOutput<Config extends LoaderConfig> {\n pageTree: Config['i18n'] extends I18nConfig ? Record<string, PageTree.Root> : PageTree.Root;\n\n getPageTree: (locale?: string) => PageTree.Root;\n /**\n * get referenced page from href, supported:\n *\n * - relative file paths, like `./my/page.mdx`.\n * - generated page pathname, like `/docs/my/page`.\n */\n getPageByHref: (\n href: string,\n options?: {\n language?: string;\n\n /**\n * resolve relative file paths in `href` from specified dirname, must be a virtual path.\n */\n dir?: string;\n },\n ) =>\n | {\n page: Page<Config['source']['pageData']>;\n hash?: string;\n }\n | undefined;\n /**\n * resolve special hrefs in a page, including:\n *\n * - relative file paths, like `./my/page.mdx`.\n */\n resolveHref: (href: string, parent: Page<Config['source']['pageData']>) => string;\n\n /**\n * @internal\n */\n _i18n?: I18nConfig;\n\n /**\n * Get a list of pages from specified language\n *\n * @param language - If empty, list pages from all languages.\n */\n getPages: (language?: string) => Page<Config['source']['pageData']>[];\n\n /**\n * get each language and its pages, empty if i18n is not enabled.\n */\n getLanguages: () => {\n language: string;\n pages: Page<Config['source']['pageData']>[];\n }[];\n\n /**\n * Get page with slugs, the slugs can also be URI encoded.\n *\n * @param language - If empty, the default language will be used\n */\n getPage: (\n slugs: string[] | undefined,\n language?: string,\n ) => Page<Config['source']['pageData']> | undefined;\n\n getNodePage: (\n node: PageTree.Item,\n language?: string,\n ) => Page<Config['source']['pageData']> | undefined;\n\n getNodeMeta: (\n node: PageTree.Folder,\n language?: string,\n ) => Meta<Config['source']['metaData']> | undefined;\n\n /**\n * generate static params for Next.js SSG\n *\n * @param slug - customise parameter name for slugs\n * @param lang - customise parameter name for lang\n */\n generateParams: <TSlug extends string = 'slug', TLang extends string = 'lang'>(\n slug?: TSlug,\n lang?: TLang,\n ) => (Record<TSlug, string[]> & Record<TLang, string>)[];\n\n /**\n * serialize page tree for non-RSC environments\n */\n serializePageTree: (tree: PageTree.Root) => Promise<SerializedPageTree>;\n}\n\nfunction indexPages(storages: Record<string, ContentStorage>, { url }: ResolvedLoaderConfig) {\n const result = {\n // (locale.slugs -> page)\n pages: new Map<string, Page>(),\n // (locale.path -> page)\n pathToMeta: new Map<string, Meta>(),\n // (locale.path -> meta)\n pathToPage: new Map<string, Page>(),\n };\n\n for (const [lang, storage] of Object.entries(storages)) {\n for (const filePath of storage.getFiles()) {\n const item = storage.read(filePath)!;\n const path = `${lang}.${filePath}`;\n\n if (item.format === 'meta') {\n result.pathToMeta.set(path, {\n path: item.path,\n absolutePath: item.absolutePath,\n data: item.data,\n });\n continue;\n }\n\n const page: Page = {\n absolutePath: item.absolutePath,\n path: item.path,\n url: url(item.slugs, lang),\n slugs: item.slugs,\n data: item.data,\n locale: lang,\n };\n result.pathToPage.set(path, page);\n result.pages.set(`${lang}.${page.slugs.join('/')}`, page);\n }\n }\n\n return result;\n}\n\nexport function createGetUrl(baseUrl: string, i18n?: I18nConfig): ResolvedLoaderConfig['url'] {\n const baseSlugs = baseUrl.split('/');\n\n return (slugs, locale) => {\n const hideLocale = i18n?.hideLocale ?? 'never';\n let urlLocale: string | undefined;\n\n if (hideLocale === 'never') {\n urlLocale = locale;\n } else if (hideLocale === 'default-locale' && locale !== i18n?.defaultLanguage) {\n urlLocale = locale;\n }\n\n const paths = [...baseSlugs, ...slugs];\n if (urlLocale) paths.unshift(urlLocale);\n\n return `/${paths.filter((v) => v.length > 0).join('/')}`;\n };\n}\n\nexport function loader<\n Config extends SourceConfig,\n I18n extends I18nConfig | undefined = undefined,\n>(\n source: Source<Config>,\n options: LoaderOptions<{\n source: NoInfer<Config>;\n i18n: I18n;\n }>,\n): LoaderOutput<{\n source: Config;\n i18n: I18n;\n}>;\n\nexport function loader<\n Config extends SourceConfig,\n I18n extends I18nConfig | undefined = undefined,\n>(\n options: LoaderOptions<{\n source: NoInfer<Config>;\n i18n: I18n;\n }> & {\n source: Source<Config>;\n },\n): LoaderOutput<{\n source: Config;\n i18n: I18n;\n}>;\n\nexport function loader(\n ...args:\n | [\n LoaderOptions & {\n source: Source;\n },\n ]\n | [Source, LoaderOptions]\n): LoaderOutput<LoaderConfig> {\n const loaderConfig =\n args.length === 2 ? resolveConfig(args[0], args[1]) : resolveConfig(args[0].source, args[0]);\n const { i18n } = loaderConfig;\n const defaultLanguage = i18n?.defaultLanguage ?? '';\n const storages = buildContentStorage(loaderConfig, defaultLanguage);\n const walker = indexPages(storages, loaderConfig);\n const builder = createPageTreeBuilder(loaderConfig);\n let pageTrees: Record<string, PageTree.Root> | undefined;\n function getPageTrees() {\n return (pageTrees ??= builder.buildI18n(storages));\n }\n\n return {\n _i18n: i18n,\n get pageTree() {\n const trees = getPageTrees();\n\n return i18n\n ? (trees as unknown as LoaderOutput<LoaderConfig>['pageTree'])\n : trees[defaultLanguage];\n },\n set pageTree(v) {\n if (i18n) {\n pageTrees = v as unknown as Record<string, PageTree.Root>;\n } else {\n pageTrees ??= {};\n pageTrees[defaultLanguage] = v;\n }\n },\n getPageByHref(href, { dir = '', language = defaultLanguage } = {}) {\n const [value, hash] = href.split('#', 2);\n let target;\n\n if (value.startsWith('./')) {\n const path = joinPath(dir, value);\n\n target = walker.pathToPage.get(`${language}.${path}`);\n } else {\n target = this.getPages(language).find((item) => item.url === value);\n }\n\n if (target)\n return {\n page: target,\n hash,\n };\n },\n resolveHref(href, parent) {\n if (href.startsWith('./')) {\n const target = this.getPageByHref(href, {\n dir: path.dirname(parent.path),\n language: parent.locale,\n });\n\n if (target) {\n return target.hash ? `${target.page.url}#${target.hash}` : target.page.url;\n }\n }\n\n return href;\n },\n getPages(language) {\n const pages: Page[] = [];\n\n for (const [key, value] of walker.pages.entries()) {\n if (language === undefined || key.startsWith(`${language}.`)) {\n pages.push(value);\n }\n }\n\n return pages;\n },\n getLanguages() {\n const list: {\n language: string;\n pages: Page[];\n }[] = [];\n\n if (!i18n) return list;\n for (const language of i18n.languages) {\n list.push({\n language,\n pages: this.getPages(language),\n });\n }\n\n return list;\n },\n // the slugs plugin generates encoded slugs by default.\n // we can assume page slugs are always URI encoded.\n getPage(slugs = [], language = defaultLanguage) {\n // `slugs` is already decoded\n let page = walker.pages.get(`${language}.${slugs.join('/')}`);\n if (page) return page;\n\n // `slugs` is URI encoded\n page = walker.pages.get(`${language}.${slugs.map(decodeURI).join('/')}`);\n if (page) return page;\n },\n getNodeMeta(node, language = defaultLanguage) {\n const ref = node.$ref?.metaFile;\n if (!ref) return;\n\n return walker.pathToMeta.get(`${language}.${ref}`);\n },\n getNodePage(node, language = defaultLanguage) {\n const ref = node.$ref?.file;\n if (!ref) return;\n\n return walker.pathToPage.get(`${language}.${ref}`);\n },\n getPageTree(locale = defaultLanguage) {\n const trees = getPageTrees();\n return trees[locale] ?? trees[defaultLanguage];\n },\n // @ts-expect-error -- ignore this\n generateParams(slug, lang) {\n if (i18n) {\n return this.getLanguages().flatMap((entry) =>\n entry.pages.map((page) => ({\n [slug ?? 'slug']: page.slugs,\n [lang ?? 'lang']: entry.language,\n })),\n );\n }\n\n return this.getPages().map((page) => ({\n [slug ?? 'slug']: page.slugs,\n }));\n },\n async serializePageTree(tree) {\n const { renderToString } = await import('react-dom/server.edge');\n\n return {\n $fumadocs_loader: 'page-tree',\n data: visit(tree, (node) => {\n node = { ...node };\n if ('icon' in node && node.icon) {\n node.icon = renderToString(node.icon);\n }\n if (node.name) {\n node.name = renderToString(node.name);\n }\n if ('children' in node) {\n node.children = [...node.children];\n }\n\n return node;\n }),\n };\n },\n };\n}\n\nfunction resolveConfig(\n source: Source,\n { slugs, icon, plugins = [], baseUrl, url, ...base }: LoaderOptions,\n): ResolvedLoaderConfig {\n let config: ResolvedLoaderConfig = {\n ...base,\n url: url ? (...args) => normalizeUrl(url(...args)) : createGetUrl(baseUrl, base.i18n),\n source,\n plugins: buildPlugins([\n icon && iconPlugin(icon),\n ...(typeof plugins === 'function'\n ? plugins({\n typedPlugin: (plugin) => plugin as unknown as LoaderPlugin,\n })\n : plugins),\n slugsPlugin(slugs),\n ]),\n };\n\n for (const plugin of config.plugins ?? []) {\n const result = plugin.config?.(config);\n if (result) config = result;\n }\n\n return config;\n}\n\nexport interface LoaderPlugin<Config extends LoaderConfig = LoaderConfig> {\n name?: string;\n\n /**\n * Change the order of plugin:\n * - `pre`: before normal plugins\n * - `post`: after normal plugins\n */\n enforce?: 'pre' | 'post';\n\n /**\n * receive & replace loader options\n */\n config?: (config: ResolvedLoaderConfig) => ResolvedLoaderConfig | void | undefined;\n\n /**\n * transform the storage after loading\n */\n transformStorage?: (context: { storage: ContentStorage<Config['source']> }) => void;\n\n /**\n * transform the generated page tree\n */\n transformPageTree?: PageTreeTransformer<Config['source']>;\n}\n\nexport type LoaderPluginOption<Config extends LoaderConfig = LoaderConfig> =\n | LoaderPlugin<Config>\n | LoaderPluginOption<Config>[]\n | undefined;\n\nconst priorityMap = {\n pre: 1,\n default: 0,\n post: -1,\n};\n\nfunction buildPlugins(plugins: LoaderPluginOption[], sort = true): LoaderPlugin[] {\n const flatten: LoaderPlugin[] = [];\n\n for (const plugin of plugins) {\n if (Array.isArray(plugin)) flatten.push(...buildPlugins(plugin, false));\n else if (plugin) flatten.push(plugin);\n }\n\n if (sort)\n return flatten.sort(\n (a, b) => priorityMap[b.enforce ?? 'default'] - priorityMap[a.enforce ?? 'default'],\n );\n return flatten;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- infer types\nexport type InferPageType<Utils extends LoaderOutput<any>> =\n Utils extends LoaderOutput<infer Config> ? Page<Config['source']['pageData']> : never;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- infer types\nexport type InferMetaType<Utils extends LoaderOutput<any>> =\n Utils extends LoaderOutput<infer Config> ? Meta<Config['source']['metaData']> : never;\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"lucide-icons.d.ts","names":[],"sources":["../../../src/source/plugins/lucide-icons.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;iBAQgB,iBAAA,QAAhB;6BAE+B;AAF/B,CAAA,CAAA,EAIG,YAJa"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"lucide-icons.js","names":[],"sources":["../../../src/source/plugins/lucide-icons.ts"],"sourcesContent":["import type { LoaderPlugin } from '@/source';\nimport { iconPlugin } from '@/source/plugins/icon';\nimport { icons } from 'lucide-react';\nimport { createElement } from 'react';\n\n/**\n * Convert icon names into Lucide Icons, requires `lucide-react` to be installed.\n */\nexport function lucideIconsPlugin(\n options: {\n defaultIcon?: keyof typeof icons;\n } = {},\n): LoaderPlugin {\n const { defaultIcon } = options;\n return iconPlugin((icon = defaultIcon) => {\n if (icon === undefined) return;\n const Icon = icons[icon as keyof typeof icons];\n if (!Icon) {\n console.warn(`[lucide-icons-plugin] Unknown icon detected: ${icon}.`);\n return;\n }\n\n return createElement(Icon);\n });\n}\n"],"mappings":";;;;;;;;AAQA,SAAgB,kBACd,UAEI,EAAE,EACQ;CACd,MAAM,EAAE,gBAAgB;AACxB,QAAO,YAAY,OAAO,gBAAgB;AACxC,MAAI,SAAS,OAAW;EACxB,MAAM,OAAO,MAAM;AACnB,MAAI,CAAC,MAAM;AACT,WAAQ,KAAK,gDAAgD,KAAK,GAAG;AACrE;;AAGF,SAAO,cAAc,KAAK;GAC1B"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"slugs.js","names":[],"sources":["../../../src/source/plugins/slugs.ts"],"sourcesContent":["import { basename, dirname, extname } from '@/source/path';\nimport type { ContentStoragePageFile } from '../storage/content';\nimport type { LoaderConfig, LoaderPlugin } from '../loader';\n\n/**\n * a function to generate slugs, return `undefined` to fallback to default generation.\n */\nexport type SlugFn<Config extends LoaderConfig = LoaderConfig> = (\n file: ContentStoragePageFile<Config['source']>,\n) => string[] | undefined;\n\n/**\n * Generate slugs for pages if missing\n */\nexport function slugsPlugin<Config extends LoaderConfig = LoaderConfig>(\n slugFn?: SlugFn<Config>,\n): LoaderPlugin<Config> {\n function isIndex(file: string) {\n return basename(file, extname(file)) === 'index';\n }\n\n return {\n name: 'fumadocs:slugs',\n transformStorage({ storage }) {\n const indexFiles: string[] = [];\n const taken = new Set<string>();\n\n for (const path of storage.getFiles()) {\n const file = storage.read(path);\n if (!file || file.format !== 'page' || file.slugs) continue;\n\n const customSlugs = slugFn?.(file);\n // for custom slugs function, don't handle conflicting cases like `dir/index.mdx` vs `dir.mdx`\n if (customSlugs === undefined && isIndex(path)) {\n indexFiles.push(path);\n continue;\n }\n\n file.slugs = customSlugs ?? getSlugs(path);\n const key = file.slugs.join('/');\n if (taken.has(key)) throw new Error(`Duplicated slugs: ${key}`);\n taken.add(key);\n }\n\n for (const path of indexFiles) {\n const file = storage.read(path);\n if (file?.format !== 'page') continue;\n\n file.slugs = getSlugs(path);\n if (taken.has(file.slugs.join('/'))) file.slugs.push('index');\n }\n },\n };\n}\n\n/**\n * Generate slugs from file data (e.g. frontmatter).\n *\n * @param key - the property name in file data to generate slugs, default to `slug`.\n */\nexport function slugsFromData<Config extends LoaderConfig = LoaderConfig>(\n key = 'slug',\n): SlugFn<Config> {\n return (file) => {\n const k = key as keyof typeof file.data;\n\n if (k in file.data && typeof file.data[k] === 'string') {\n return file.data[k].split('/').filter((v) => v.length > 0);\n }\n };\n}\n\nconst GroupRegex = /^\\(.+\\)$/;\n\n/**\n * Convert file path into slugs, also encode non-ASCII characters, so they can work in pathname\n */\nexport function getSlugs(file: string): string[] {\n const dir = dirname(file);\n const name = basename(file, extname(file));\n const slugs: string[] = [];\n\n for (const seg of dir.split('/')) {\n // filter empty names and file groups like (group_name)\n if (seg.length > 0 && !GroupRegex.test(seg)) slugs.push(encodeURI(seg));\n }\n\n if (GroupRegex.test(name)) throw new Error(`Cannot use folder group in file names: ${file}`);\n\n if (name !== 'index') {\n slugs.push(encodeURI(name));\n }\n\n return slugs;\n}\n"],"mappings":";;;;;;AAcA,SAAgB,YACd,QACsB;CACtB,SAAS,QAAQ,MAAc;AAC7B,SAAO,SAAS,MAAM,QAAQ,KAAK,CAAC,KAAK;;AAG3C,QAAO;EACL,MAAM;EACN,iBAAiB,EAAE,WAAW;GAC5B,MAAM,aAAuB,EAAE;GAC/B,MAAM,wBAAQ,IAAI,KAAa;AAE/B,QAAK,MAAM,QAAQ,QAAQ,UAAU,EAAE;IACrC,MAAM,OAAO,QAAQ,KAAK,KAAK;AAC/B,QAAI,CAAC,QAAQ,KAAK,WAAW,UAAU,KAAK,MAAO;IAEnD,MAAM,cAAc,SAAS,KAAK;AAElC,QAAI,gBAAgB,UAAa,QAAQ,KAAK,EAAE;AAC9C,gBAAW,KAAK,KAAK;AACrB;;AAGF,SAAK,QAAQ,eAAe,SAAS,KAAK;IAC1C,MAAM,MAAM,KAAK,MAAM,KAAK,IAAI;AAChC,QAAI,MAAM,IAAI,IAAI,CAAE,OAAM,IAAI,MAAM,qBAAqB,MAAM;AAC/D,UAAM,IAAI,IAAI;;AAGhB,QAAK,MAAM,QAAQ,YAAY;IAC7B,MAAM,OAAO,QAAQ,KAAK,KAAK;AAC/B,QAAI,MAAM,WAAW,OAAQ;AAE7B,SAAK,QAAQ,SAAS,KAAK;AAC3B,QAAI,MAAM,IAAI,KAAK,MAAM,KAAK,IAAI,CAAC,CAAE,MAAK,MAAM,KAAK,QAAQ;;;EAGlE;;;;;;;AAQH,SAAgB,cACd,MAAM,QACU;AAChB,SAAQ,SAAS;EACf,MAAM,IAAI;AAEV,MAAI,KAAK,KAAK,QAAQ,OAAO,KAAK,KAAK,OAAO,SAC5C,QAAO,KAAK,KAAK,GAAG,MAAM,IAAI,CAAC,QAAQ,MAAM,EAAE,SAAS,EAAE;;;AAKhE,MAAM,aAAa;;;;AAKnB,SAAgB,SAAS,MAAwB;CAC/C,MAAM,MAAM,QAAQ,KAAK;CACzB,MAAM,OAAO,SAAS,MAAM,QAAQ,KAAK,CAAC;CAC1C,MAAM,QAAkB,EAAE;AAE1B,MAAK,MAAM,OAAO,IAAI,MAAM,IAAI,CAE9B,KAAI,IAAI,SAAS,KAAK,CAAC,WAAW,KAAK,IAAI,CAAE,OAAM,KAAK,UAAU,IAAI,CAAC;AAGzE,KAAI,WAAW,KAAK,KAAK,CAAE,OAAM,IAAI,MAAM,0CAA0C,OAAO;AAE5F,KAAI,SAAS,QACX,OAAM,KAAK,UAAU,KAAK,CAAC;AAG7B,QAAO"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"schema.d.ts","names":[],"sources":["../../src/source/schema.ts"],"sourcesContent":[],"mappings":";;;;;;AAKA;cAAa,YAAU,CAAA,CAAA;;;;;;;;;;;;cAaV,YAAU,CAAA,CAAA;;;;EAbA,IAAA,eAAA,aAAA,CAAA;EAAA,QAAA,eAAA,YAAA,CAAA,CAAA,CAAA,eAAA,CAAA,CAAA;AAavB,CAAA,eAAa,CAQX"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"schema.js","names":[],"sources":["../../src/source/schema.ts"],"sourcesContent":["import { z } from 'zod';\n\n/**\n * Zod 4 schema\n */\nexport const metaSchema = z.object({\n title: z.string().optional(),\n pages: z.array(z.string()).optional(),\n description: z.string().optional(),\n root: z.boolean().optional(),\n defaultOpen: z.boolean().optional(),\n collapsible: z.boolean().optional(),\n icon: z.string().optional(),\n});\n\n/**\n * Zod 4 schema\n */\nexport const pageSchema = z.object({\n title: z.string(),\n description: z.string().optional(),\n icon: z.string().optional(),\n full: z.boolean().optional(),\n\n // Fumadocs OpenAPI generated\n _openapi: z.looseObject({}).optional(),\n});\n"],"mappings":";;;;;;AAKA,MAAa,aAAa,EAAE,OAAO;CACjC,OAAO,EAAE,QAAQ,CAAC,UAAU;CAC5B,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,UAAU;CACrC,aAAa,EAAE,QAAQ,CAAC,UAAU;CAClC,MAAM,EAAE,SAAS,CAAC,UAAU;CAC5B,aAAa,EAAE,SAAS,CAAC,UAAU;CACnC,aAAa,EAAE,SAAS,CAAC,UAAU;CACnC,MAAM,EAAE,QAAQ,CAAC,UAAU;CAC5B,CAAC;;;;AAKF,MAAa,aAAa,EAAE,OAAO;CACjC,OAAO,EAAE,QAAQ;CACjB,aAAa,EAAE,QAAQ,CAAC,UAAU;CAClC,MAAM,EAAE,QAAQ,CAAC,UAAU;CAC3B,MAAM,EAAE,SAAS,CAAC,UAAU;CAG5B,UAAU,EAAE,YAAY,EAAE,CAAC,CAAC,UAAU;CACvC,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"static-C_WBOzek.js","names":["db"],"sources":["../src/search/client/static.ts"],"sourcesContent":["import { type AnyOrama, create, load, type Orama } from '@orama/orama';\nimport { searchSimple } from '@/search/orama/search/simple';\nimport { searchAdvanced } from '@/search/orama/search/advanced';\nimport { type advancedSchema, type simpleSchema } from '@/search/orama/create-db';\nimport type { ExportedData } from '@/search/server';\n\nexport interface StaticOptions {\n /**\n * Where to download exported search indexes (URL)\n *\n * @defaultValue '/api/search'\n */\n from?: string;\n\n initOrama?: (locale?: string) => AnyOrama | Promise<AnyOrama>;\n\n /**\n * Filter results with specific tag(s).\n */\n tag?: string | string[];\n\n /**\n * Filter by locale (unsupported at the moment)\n */\n locale?: string;\n}\n\nconst cache = new Map<string, Promise<Database>>();\n\n// locale -> db\ntype Database = Map<\n string,\n {\n type: 'simple' | 'advanced';\n db: AnyOrama;\n }\n>;\n\nasync function loadDB({\n from = '/api/search',\n initOrama = (locale) => create({ schema: { _: 'string' }, language: locale }),\n}: StaticOptions): Promise<Database> {\n const cacheKey = from;\n const cached = cache.get(cacheKey);\n if (cached) return cached;\n\n async function init() {\n const res = await fetch(from);\n\n if (!res.ok)\n throw new Error(\n `failed to fetch exported search indexes from ${from}, make sure the search database is exported and available for client.`,\n );\n\n const data = (await res.json()) as ExportedData;\n const dbs: Database = new Map();\n\n if (data.type === 'i18n') {\n await Promise.all(\n Object.entries(data.data).map(async ([k, v]) => {\n const db = await initOrama(k);\n\n load(db, v);\n dbs.set(k, {\n type: v.type,\n db,\n });\n }),\n );\n\n return dbs;\n }\n\n const db = await initOrama();\n load(db, data);\n dbs.set('', {\n type: data.type,\n db,\n });\n return dbs;\n }\n\n const result = init();\n cache.set(cacheKey, result);\n return result;\n}\n\nexport async function search(query: string, options: StaticOptions) {\n const { tag, locale } = options;\n\n const db = (await loadDB(options)).get(locale ?? '');\n\n if (!db) return [];\n if (db.type === 'simple') return searchSimple(db as unknown as Orama<typeof simpleSchema>, query);\n\n return searchAdvanced(db.db as Orama<typeof advancedSchema>, query, tag);\n}\n"],"mappings":";;;;AA2BA,MAAM,wBAAQ,IAAI,KAAgC;AAWlD,eAAe,OAAO,EACpB,OAAO,eACP,aAAa,WAAW,OAAO;CAAE,QAAQ,EAAE,GAAG,UAAU;CAAE,UAAU;CAAQ,CAAC,IAC1C;CACnC,MAAM,WAAW;CACjB,MAAM,SAAS,MAAM,IAAI,SAAS;AAClC,KAAI,OAAQ,QAAO;CAEnB,eAAe,OAAO;EACpB,MAAM,MAAM,MAAM,MAAM,KAAK;AAE7B,MAAI,CAAC,IAAI,GACP,OAAM,IAAI,MACR,gDAAgD,KAAK,uEACtD;EAEH,MAAM,OAAQ,MAAM,IAAI,MAAM;EAC9B,MAAM,sBAAgB,IAAI,KAAK;AAE/B,MAAI,KAAK,SAAS,QAAQ;AACxB,SAAM,QAAQ,IACZ,OAAO,QAAQ,KAAK,KAAK,CAAC,IAAI,OAAO,CAAC,GAAG,OAAO;IAC9C,MAAMA,OAAK,MAAM,UAAU,EAAE;AAE7B,SAAKA,MAAI,EAAE;AACX,QAAI,IAAI,GAAG;KACT,MAAM,EAAE;KACR;KACD,CAAC;KACF,CACH;AAED,UAAO;;EAGT,MAAM,KAAK,MAAM,WAAW;AAC5B,OAAK,IAAI,KAAK;AACd,MAAI,IAAI,IAAI;GACV,MAAM,KAAK;GACX;GACD,CAAC;AACF,SAAO;;CAGT,MAAM,SAAS,MAAM;AACrB,OAAM,IAAI,UAAU,OAAO;AAC3B,QAAO;;AAGT,eAAsB,OAAO,OAAe,SAAwB;CAClE,MAAM,EAAE,KAAK,WAAW;CAExB,MAAM,MAAM,MAAM,OAAO,QAAQ,EAAE,IAAI,UAAU,GAAG;AAEpD,KAAI,CAAC,GAAI,QAAO,EAAE;AAClB,KAAI,GAAG,SAAS,SAAU,QAAO,aAAa,IAA6C,MAAM;AAEjG,QAAO,eAAe,GAAG,IAAoC,OAAO,IAAI"}
package/dist/toc.d.ts.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"toc.d.ts","names":[],"sources":["../src/toc.tsx"],"sourcesContent":[],"mappings":";;;;UAiBiB,WAAA;SACR;;EADQ,KAAA,EAAA,MAAA;AAMjB;AAWgB,KAXJ,eAAA,GAAkB,WAWC,EAAA;AAO/B;AAIA;AAWA;AAI0B,iBA1BV,eAAA,CAAA,CA0BU,EAAA,MAAA,GAAA,SAAA;;;;AAKV,iBAxBA,gBAAA,CAAA,CAwBc,EAAA,MAAA,EAAA;AAAG,UApBhB,mBAAA,CAoBgB;EAAc,GAAA,EAnBxC,eAmBwC;EAAY;;;AAI3D;;EAAsC,MAAA,CAAA,EAAA,OAAA;EAAgB,QAAA,CAAA,EAhBzC,SAgByC;;AAA+B,UAbpE,mBAAA,CAaoE;EAAA;AAYrF;AAKA;EAA0B,YAAA,EA1BV,SA0BU,CA1BA,WA0BA,GAAA,IAAA,CAAA;EAAK,QAAA,CAAA,EAxBlB,SAwBkB;;AAAqD,iBArBpE,cAAA,CAqBoE;EAAA,YAAA;EAAA;AAAA,CAAA,EArBzB,mBAqByB,CAAA,EArBN,kBAAA,CAAA,GAAA,CAAA,OAqBM;AAAA,iBAjBpE,cAAA,CAiBoE;EAAA,GAAA;EAAA,MAAA;EAAA;AAAA,CAAA,EAjBlB,mBAiBkB,CAAA,EAjBC,kBAAA,CAAA,GAAA,CAAA,OAiBD;UALnE,YAAA,SAAqB,KAAK;;;;iBAK3B,OAAA;;;;GAAwD,eAAY,kBAAA,CAAA,GAAA,CAAA"}
package/dist/toc.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"toc.js","names":[],"sources":["../src/utils/merge-refs.ts","../src/toc.tsx"],"sourcesContent":["import type * as React from 'react';\n\nexport function mergeRefs<T>(...refs: (React.Ref<T> | undefined)[]): React.RefCallback<T> {\n return (value) => {\n refs.forEach((ref) => {\n if (typeof ref === 'function') {\n ref(value);\n } else if (ref != null) {\n ref.current = value;\n }\n });\n };\n}\n","'use client';\nimport {\n type ComponentProps,\n createContext,\n type ReactNode,\n type RefObject,\n useContext,\n useEffect,\n useEffectEvent,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport scrollIntoView from 'scroll-into-view-if-needed';\nimport { mergeRefs } from '@/utils/merge-refs';\n\nexport interface TOCItemType {\n title: ReactNode;\n url: string;\n depth: number;\n}\n\nexport type TableOfContents = TOCItemType[];\n\nconst ActiveAnchorContext = createContext<string[]>([]);\n\nconst ScrollContext = createContext<RefObject<HTMLElement | null>>({\n current: null,\n});\n\n/**\n * The estimated active heading ID\n */\nexport function useActiveAnchor(): string | undefined {\n return useContext(ActiveAnchorContext)[0];\n}\n\n/**\n * The id of visible anchors\n */\nexport function useActiveAnchors(): string[] {\n return useContext(ActiveAnchorContext);\n}\n\nexport interface AnchorProviderProps {\n toc: TableOfContents;\n /**\n * Only accept one active item at most\n *\n * @defaultValue false\n */\n single?: boolean;\n children?: ReactNode;\n}\n\nexport interface ScrollProviderProps {\n /**\n * Scroll into the view of container when active\n */\n containerRef: RefObject<HTMLElement | null>;\n\n children?: ReactNode;\n}\n\nexport function ScrollProvider({ containerRef, children }: ScrollProviderProps) {\n return <ScrollContext.Provider value={containerRef}>{children}</ScrollContext.Provider>;\n}\n\nexport function AnchorProvider({ toc, single = false, children }: AnchorProviderProps) {\n const headings = useMemo(() => {\n return toc.map((item) => item.url.split('#')[1]);\n }, [toc]);\n\n return (\n <ActiveAnchorContext.Provider value={useAnchorObserver(headings, single)}>\n {children}\n </ActiveAnchorContext.Provider>\n );\n}\n\nexport interface TOCItemProps extends Omit<ComponentProps<'a'>, 'href'> {\n href: string;\n onActiveChange?: (v: boolean) => void;\n}\n\nexport function TOCItem({ ref, onActiveChange = () => null, ...props }: TOCItemProps) {\n const containerRef = useContext(ScrollContext);\n const anchorRef = useRef<HTMLAnchorElement>(null);\n const activeOrder = useActiveAnchors().indexOf(props.href.slice(1));\n const isActive = activeOrder !== -1;\n const shouldScroll = activeOrder === 0;\n const onActiveChangeEvent = useEffectEvent(onActiveChange);\n\n useLayoutEffect(() => {\n const anchor = anchorRef.current;\n const container = containerRef.current;\n\n if (container && anchor && shouldScroll)\n scrollIntoView(anchor, {\n behavior: 'smooth',\n block: 'center',\n inline: 'center',\n scrollMode: 'always',\n boundary: container,\n });\n }, [containerRef, shouldScroll]);\n\n useEffect(() => {\n return () => onActiveChangeEvent(isActive);\n }, [isActive]);\n\n return (\n <a ref={mergeRefs(anchorRef, ref)} data-active={isActive} {...props}>\n {props.children}\n </a>\n );\n}\n\n/**\n * Find the active heading of page\n *\n * It selects the top heading by default, and the last item when reached the bottom of page.\n *\n * @param watch - An array of element ids to watch\n * @param single - only one active item at most\n * @returns Active anchor\n */\nfunction useAnchorObserver(watch: string[], single: boolean): string[] {\n const observerRef = useRef<IntersectionObserver>(null);\n const [activeAnchor, setActiveAnchor] = useState<string[]>(() => []);\n const stateRef = useRef<{\n visible: Set<string>;\n }>(null);\n\n const onChange = useEffectEvent((entries: IntersectionObserverEntry[]) => {\n stateRef.current ??= {\n visible: new Set(),\n };\n const state = stateRef.current;\n\n for (const entry of entries) {\n if (entry.isIntersecting) {\n state.visible.add(entry.target.id);\n } else {\n state.visible.delete(entry.target.id);\n }\n }\n\n if (state.visible.size === 0) {\n const viewTop = entries.length > 0 ? (entries[0]?.rootBounds?.top ?? 0) : 0;\n let fallback: Element | undefined;\n let min = -1;\n\n for (const id of watch) {\n const element = document.getElementById(id);\n if (!element) continue;\n\n const d = Math.abs(viewTop - element.getBoundingClientRect().top);\n if (min === -1 || d < min) {\n fallback = element;\n min = d;\n }\n }\n\n setActiveAnchor(fallback ? [fallback.id] : []);\n } else {\n const items = watch.filter((item) => state.visible.has(item));\n setActiveAnchor(single ? items.slice(0, 1) : items);\n }\n });\n\n useEffect(() => {\n if (observerRef.current) return;\n observerRef.current = new IntersectionObserver(onChange, {\n rootMargin: '0px',\n threshold: 0.98,\n });\n\n return () => {\n observerRef.current?.disconnect();\n observerRef.current = null;\n };\n }, []);\n\n useEffect(() => {\n const observer = observerRef.current;\n if (!observer) return;\n const elements = watch.flatMap((heading) => document.getElementById(heading) ?? []);\n\n for (const element of elements) observer.observe(element);\n return () => {\n for (const element of elements) observer.unobserve(element);\n };\n }, [watch]);\n\n return activeAnchor;\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"util-Dn-wseQ5.js","names":[],"sources":["../src/content/mdx/util.ts"],"sourcesContent":["import type { Pluggable } from 'unified';\n\ntype Thenable<T> = T | PromiseLike<T>;\n\nexport type ResolvePlugins = Thenable<Pluggable>[] | ((v: Pluggable[]) => Thenable<Pluggable>[]);\n\nexport async function resolvePlugins(\n def: (v: Thenable<Pluggable>[]) => Thenable<Pluggable | false>[],\n options: ResolvePlugins = [],\n): Promise<Pluggable[]> {\n const list = (await Promise.all(def(Array.isArray(options) ? options : []))).filter(\n (v) => v !== false,\n );\n\n if (typeof options === 'function') {\n return Promise.all(options(list));\n }\n\n return list;\n}\n"],"mappings":";AAMA,eAAsB,eACpB,KACA,UAA0B,EAAE,EACN;CACtB,MAAM,QAAQ,MAAM,QAAQ,IAAI,IAAI,MAAM,QAAQ,QAAQ,GAAG,UAAU,EAAE,CAAC,CAAC,EAAE,QAC1E,MAAM,MAAM,MACd;AAED,KAAI,OAAO,YAAY,WACrB,QAAO,QAAQ,IAAI,QAAQ,KAAK,CAAC;AAGnC,QAAO"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"util-d5FlPx1Z.d.ts","names":[],"sources":["../src/content/mdx/util.ts"],"sourcesContent":[],"mappings":";;;KAEK,cAAc,IAAI,YAAY;KAEvB,cAAA,GAAiB,SAAS,oBAAoB,gBAAgB,SAAS"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"use-effect-event.d.ts","names":[],"sources":["../../src/utils/use-effect-event.ts"],"sourcesContent":[],"mappings":";KAGK,cAAA,yDAAuE,MAAM;;AAOlF;;;;cAAa,gBAAgB"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"use-effect-event.js","names":[],"sources":["../../src/utils/use-effect-event.ts"],"sourcesContent":["'use client';\nimport * as React from 'react';\n\ntype UseEffectEvent = <F extends (...params: never[]) => unknown>(callback: F) => F;\n\n/**\n * Polyfill for React.js 19.2 `useEffectEvent`.\n *\n * @internal Don't use this, could be deleted anytime.\n */\nexport const useEffectEvent: UseEffectEvent =\n 'useEffectEvent' in React\n ? { ...React }.useEffectEvent\n : <F extends (...params: never[]) => unknown>(callback: F) => {\n const ref = React.useRef(callback);\n ref.current = callback;\n\n return React.useCallback(((...params) => ref.current(...params)) as F, []);\n };\n"],"mappings":";;;;;;;;;;AAUA,MAAa,iBACX,oBAAoB,QAChB,EAAE,GAAG,OAAO,CAAC,kBAC+B,aAAgB;CAC1D,MAAM,MAAM,MAAM,OAAO,SAAS;AAClC,KAAI,UAAU;AAEd,QAAO,MAAM,cAAc,GAAG,WAAW,IAAI,QAAQ,GAAG,OAAO,GAAQ,EAAE,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"use-media-query.d.ts","names":[],"sources":["../../src/utils/use-media-query.ts"],"sourcesContent":[],"mappings":";iBAEgB,aAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"use-media-query.js","names":[],"sources":["../../src/utils/use-media-query.ts"],"sourcesContent":["import { useEffect, useState } from 'react';\n\nexport function useMediaQuery(query: string, disabled = false): boolean | null {\n const [isMatch, setMatch] = useState<boolean | null>(null);\n\n useEffect(() => {\n if (disabled) return;\n const mediaQueryList = window.matchMedia(query);\n\n const handleChange = () => {\n setMatch(mediaQueryList.matches);\n };\n handleChange();\n mediaQueryList.addEventListener('change', handleChange);\n return () => {\n mediaQueryList.removeEventListener('change', handleChange);\n };\n }, [disabled, query]);\n\n return isMatch;\n}\n"],"mappings":";;;AAEA,SAAgB,cAAc,OAAe,WAAW,OAAuB;CAC7E,MAAM,CAAC,SAAS,YAAY,SAAyB,KAAK;AAE1D,iBAAgB;AACd,MAAI,SAAU;EACd,MAAM,iBAAiB,OAAO,WAAW,MAAM;EAE/C,MAAM,qBAAqB;AACzB,YAAS,eAAe,QAAQ;;AAElC,gBAAc;AACd,iBAAe,iBAAiB,UAAU,aAAa;AACvD,eAAa;AACX,kBAAe,oBAAoB,UAAU,aAAa;;IAE3D,CAAC,UAAU,MAAM,CAAC;AAErB,QAAO"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"use-on-change.d.ts","names":[],"sources":["../../src/utils/use-on-change.ts"],"sourcesContent":[],"mappings":";;AAeA;;;;AAGoB,iBAHJ,WAGI,CAAA,CAAA,CAAA,CAAA,KAAA,EAFX,CAEW,EAAA,QAAA,EAAA,CAAA,OAAA,EADE,CACF,EAAA,QAAA,EADe,CACf,EAAA,GAAA,IAAA,EAAA,SAAA,CAAA,EAAA,CAAA,IAAA,EAAA,CAAA,EAAA,OAAA,EAAY,CAAZ,EAAA,GAAA,OAAA,CAAA,EAAA,IAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"use-on-change.js","names":[],"sources":["../../src/utils/use-on-change.ts"],"sourcesContent":["import { useState } from 'react';\n\nfunction isDifferent(a: unknown, b: unknown): boolean {\n if (Array.isArray(a) && Array.isArray(b)) {\n return b.length !== a.length || a.some((v, i) => isDifferent(v, b[i]));\n }\n\n return a !== b;\n}\n\n/**\n * @param value - state to watch\n * @param onChange - when the state changed\n * @param isUpdated - a function that determines if the state is updated\n */\nexport function useOnChange<T>(\n value: T,\n onChange: (current: T, previous: T) => void,\n isUpdated: (prev: T, current: T) => boolean = isDifferent,\n): void {\n const [prev, setPrev] = useState<T>(value);\n\n if (isUpdated(prev, value)) {\n onChange(value, prev);\n setPrev(value);\n }\n}\n"],"mappings":";;;AAEA,SAAS,YAAY,GAAY,GAAqB;AACpD,KAAI,MAAM,QAAQ,EAAE,IAAI,MAAM,QAAQ,EAAE,CACtC,QAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,YAAY,GAAG,EAAE,GAAG,CAAC;AAGxE,QAAO,MAAM;;;;;;;AAQf,SAAgB,YACd,OACA,UACA,YAA8C,aACxC;CACN,MAAM,CAAC,MAAM,WAAW,SAAY,MAAM;AAE1C,KAAI,UAAU,MAAM,MAAM,EAAE;AAC1B,WAAS,OAAO,KAAK;AACrB,UAAQ,MAAM"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"utils-D10VxgVc.js","names":["nodes"],"sources":["../src/page-tree/utils.ts"],"sourcesContent":["import type * as PageTree from '@/page-tree/definitions';\n\n/**\n * Flatten tree to an array of page nodes\n */\nexport function flattenTree(nodes: PageTree.Node[]): PageTree.Item[] {\n const out: PageTree.Item[] = [];\n\n for (const node of nodes) {\n if (node.type === 'folder') {\n if (node.index) out.push(node.index);\n out.push(...flattenTree(node.children));\n } else if (node.type === 'page') {\n out.push(node);\n }\n }\n\n return out;\n}\n\n/**\n * Get neighbours of a page, useful for implementing \"previous & next\" buttons\n */\nexport function findNeighbour(\n tree: PageTree.Root,\n url: string,\n options?: {\n separateRoot?: boolean;\n },\n): {\n previous?: PageTree.Item;\n next?: PageTree.Item;\n} {\n const { separateRoot = true } = options ?? {};\n const roots = separateRoot ? getPageTreeRoots(tree) : [tree];\n if (tree.fallback) roots.push(tree.fallback);\n\n for (const root of roots) {\n const list = flattenTree(root.children);\n const idx = list.findIndex((item) => item.url === url);\n if (idx === -1) continue;\n\n return {\n previous: list[idx - 1],\n next: list[idx + 1],\n };\n }\n\n return {};\n}\n\nexport function getPageTreeRoots(\n pageTree: PageTree.Root | PageTree.Folder,\n): (PageTree.Root | PageTree.Folder)[] {\n const result = pageTree.children.flatMap((child) => {\n if (child.type !== 'folder') return [];\n const roots = getPageTreeRoots(child);\n\n if (child.root) roots.push(child);\n return roots;\n });\n\n if (!('type' in pageTree)) result.push(pageTree);\n return result;\n}\n\n/**\n * Get other item nodes that lives under the same parent.\n */\nexport function getPageTreePeers(\n treeOrTrees: PageTree.Root | Record<string, PageTree.Root>,\n url: string,\n): PageTree.Item[] {\n return findSiblings(treeOrTrees, url).filter((item) => item.type === 'page');\n}\n\n/**\n * Get other tree nodes that lives under the same parent.\n */\nexport function findSiblings(\n treeOrTrees: PageTree.Root | Record<string, PageTree.Root>,\n url: string,\n): PageTree.Node[] {\n // Check if it's a single tree or multiple trees (i18n)\n if ('children' in treeOrTrees) {\n // Single tree case\n const tree = treeOrTrees as PageTree.Root;\n const parent = findParent(tree, url);\n if (!parent) return [];\n\n return parent.children.filter((item) => item.type !== 'page' || item.url !== url);\n }\n\n // Multiple trees case\n for (const lang in treeOrTrees) {\n const result = getPageTreePeers(treeOrTrees[lang], url);\n if (result) return result;\n }\n\n return [];\n}\n\nexport function findParent(\n from: PageTree.Root | PageTree.Folder,\n url: string,\n): PageTree.Root | PageTree.Folder | undefined {\n let result: PageTree.Root | PageTree.Folder | undefined;\n\n visit(from, (node, parent) => {\n if ('type' in node && node.type === 'page' && node.url === url) {\n result = parent;\n return 'break';\n }\n });\n\n return result;\n}\n\n/**\n * Search the path of a node in the tree matched by the matcher.\n *\n * @returns The path to the target node (from starting root), or null if the page doesn't exist\n */\nexport function findPath(\n nodes: PageTree.Node[],\n matcher: (node: PageTree.Node) => boolean,\n options: {\n includeSeparator?: boolean;\n } = {},\n): PageTree.Node[] | null {\n const { includeSeparator = true } = options;\n\n function run(nodes: PageTree.Node[]): PageTree.Node[] | undefined {\n let separator: PageTree.Separator | undefined;\n\n for (const node of nodes) {\n if (matcher(node)) {\n const items: PageTree.Node[] = [];\n if (separator) items.push(separator);\n items.push(node);\n\n return items;\n }\n\n if (node.type === 'separator' && includeSeparator) {\n separator = node;\n continue;\n }\n\n if (node.type === 'folder') {\n const items = node.index && matcher(node.index) ? [node.index] : run(node.children);\n\n if (items) {\n items.unshift(node);\n if (separator) items.unshift(separator);\n\n return items;\n }\n }\n }\n }\n\n return run(nodes) ?? null;\n}\n\nconst VisitBreak = Symbol('VisitBreak');\n\n/**\n * Perform a depth-first search on page tree visiting every node.\n *\n * @param root - the root of page tree to visit.\n * @param visitor - function to receive nodes, return `skip` to skip the children of current node, `break` to stop the search entirely.\n */\nexport function visit<Root extends PageTree.Node | PageTree.Root>(\n root: Root,\n visitor: <T extends PageTree.Node | PageTree.Root>(\n node: T,\n parent?: PageTree.Root | PageTree.Folder,\n ) => 'skip' | 'break' | T | void,\n): Root {\n function onNode<T extends PageTree.Node | PageTree.Root>(\n node: T,\n parent?: PageTree.Root | PageTree.Folder,\n ): T {\n const result = visitor(node, parent);\n switch (result) {\n case 'skip':\n return node;\n case 'break':\n throw VisitBreak;\n default:\n if (result) node = result;\n }\n\n if ('index' in node && node.index) {\n node.index = onNode(node.index, node);\n }\n\n if ('fallback' in node && node.fallback) {\n node.fallback = onNode(node.fallback, node);\n }\n\n if ('children' in node) {\n for (let i = 0; i < node.children.length; i++) {\n node.children[i] = onNode(node.children[i], node);\n }\n }\n\n return node;\n }\n\n try {\n return onNode(root);\n } catch (e) {\n if (e === VisitBreak) return root;\n throw e;\n }\n}\n"],"mappings":"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"}
File without changes