@vezham/docs-core 1.0.1

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 (201) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +5 -0
  3. package/dist/advanced-Ct13khZr.js +79 -0
  4. package/dist/algolia-C0E5qQhM.d.ts +66 -0
  5. package/dist/breadcrumb.d.ts +46 -0
  6. package/dist/breadcrumb.js +59 -0
  7. package/dist/build-doc-4OvfjVN2.js +85 -0
  8. package/dist/client-kQ39Ub0-.d.ts +247 -0
  9. package/dist/codeblock-utils-CyP8qsYv.d.ts +29 -0
  10. package/dist/content/github.d.ts +41 -0
  11. package/dist/content/github.js +28 -0
  12. package/dist/content/md/frontmatter.d.ts +15 -0
  13. package/dist/content/md/frontmatter.js +24 -0
  14. package/dist/content/md.d.ts +24 -0
  15. package/dist/content/md.js +43 -0
  16. package/dist/content/mdx/preset-bundler.d.ts +29 -0
  17. package/dist/content/mdx/preset-bundler.js +39 -0
  18. package/dist/content/mdx/preset-runtime.d.ts +26 -0
  19. package/dist/content/mdx/preset-runtime.js +36 -0
  20. package/dist/content/toc.d.ts +19 -0
  21. package/dist/content/toc.js +14 -0
  22. package/dist/definitions-CFOhwE1k.d.ts +72 -0
  23. package/dist/dynamic-CTsodhTH.js +905 -0
  24. package/dist/dynamic-link.d.ts +12 -0
  25. package/dist/dynamic-link.js +31 -0
  26. package/dist/endpoint-MyoBU5IC.js +28 -0
  27. package/dist/framework/astro.d.ts +21 -0
  28. package/dist/framework/astro.js +52 -0
  29. package/dist/framework/index.d.ts +40 -0
  30. package/dist/framework/index.js +66 -0
  31. package/dist/framework/next.d.ts +10 -0
  32. package/dist/framework/next.js +19 -0
  33. package/dist/framework/react-router.d.ts +10 -0
  34. package/dist/framework/react-router.js +43 -0
  35. package/dist/framework/tanstack.d.ts +13 -0
  36. package/dist/framework/tanstack.js +54 -0
  37. package/dist/framework/waku.d.ts +10 -0
  38. package/dist/framework/waku.js +46 -0
  39. package/dist/highlight/client.d.ts +11 -0
  40. package/dist/highlight/client.js +15 -0
  41. package/dist/highlight/index.d.ts +31 -0
  42. package/dist/highlight/index.js +30 -0
  43. package/dist/highlight/shiki/full.d.ts +7 -0
  44. package/dist/highlight/shiki/full.js +23 -0
  45. package/dist/highlight/shiki/index.d.ts +2 -0
  46. package/dist/highlight/shiki/index.js +27 -0
  47. package/dist/highlight/shiki/react.d.ts +23 -0
  48. package/dist/highlight/shiki/react.js +50 -0
  49. package/dist/i18n/index.d.ts +2 -0
  50. package/dist/i18n/index.js +63 -0
  51. package/dist/i18n/middleware.d.ts +34 -0
  52. package/dist/i18n/middleware.js +3855 -0
  53. package/dist/icon-BILaoXeg.js +17 -0
  54. package/dist/index-B-0R0VbS.d.ts +18 -0
  55. package/dist/index-BM36H-xw.d.ts +36 -0
  56. package/dist/index-BMEUQz-F.d.ts +21 -0
  57. package/dist/index-DAYtLGbx.d.ts +16 -0
  58. package/dist/index-DIwKCYOz.d.ts +513 -0
  59. package/dist/index-DydiXvgS.d.ts +90 -0
  60. package/dist/index-E8Qh_yQs.d.ts +49 -0
  61. package/dist/is-equal-LdLqRs0o.js +8 -0
  62. package/dist/link.d.ts +17 -0
  63. package/dist/link.js +23 -0
  64. package/dist/mdx-plugins/codeblock-utils.d.ts +2 -0
  65. package/dist/mdx-plugins/codeblock-utils.js +68 -0
  66. package/dist/mdx-plugins/index.d.ts +20 -0
  67. package/dist/mdx-plugins/index.js +18 -0
  68. package/dist/mdx-plugins/rehype-code.core.d.ts +3 -0
  69. package/dist/mdx-plugins/rehype-code.core.js +3 -0
  70. package/dist/mdx-plugins/rehype-code.d.ts +4 -0
  71. package/dist/mdx-plugins/rehype-code.js +24 -0
  72. package/dist/mdx-plugins/rehype-toc.d.ts +2 -0
  73. package/dist/mdx-plugins/rehype-toc.js +139 -0
  74. package/dist/mdx-plugins/remark-admonition.d.ts +2 -0
  75. package/dist/mdx-plugins/remark-admonition.js +71 -0
  76. package/dist/mdx-plugins/remark-block-id.d.ts +37 -0
  77. package/dist/mdx-plugins/remark-block-id.js +41 -0
  78. package/dist/mdx-plugins/remark-code-tab.d.ts +2 -0
  79. package/dist/mdx-plugins/remark-code-tab.js +190 -0
  80. package/dist/mdx-plugins/remark-directive-admonition.d.ts +2 -0
  81. package/dist/mdx-plugins/remark-directive-admonition.js +57 -0
  82. package/dist/mdx-plugins/remark-feedback-block.d.ts +2 -0
  83. package/dist/mdx-plugins/remark-feedback-block.js +54 -0
  84. package/dist/mdx-plugins/remark-gfm.d.ts +2 -0
  85. package/dist/mdx-plugins/remark-gfm.js +2 -0
  86. package/dist/mdx-plugins/remark-heading.d.ts +2 -0
  87. package/dist/mdx-plugins/remark-heading.js +46 -0
  88. package/dist/mdx-plugins/remark-image.d.ts +2 -0
  89. package/dist/mdx-plugins/remark-image.js +167 -0
  90. package/dist/mdx-plugins/remark-llms.d.ts +2 -0
  91. package/dist/mdx-plugins/remark-llms.js +338 -0
  92. package/dist/mdx-plugins/remark-llms.runtime.d.ts +10 -0
  93. package/dist/mdx-plugins/remark-llms.runtime.js +24 -0
  94. package/dist/mdx-plugins/remark-mdx-files.d.ts +2 -0
  95. package/dist/mdx-plugins/remark-mdx-files.js +182 -0
  96. package/dist/mdx-plugins/remark-mdx-mermaid.d.ts +2 -0
  97. package/dist/mdx-plugins/remark-mdx-mermaid.js +28 -0
  98. package/dist/mdx-plugins/remark-npm.d.ts +2 -0
  99. package/dist/mdx-plugins/remark-npm.js +76 -0
  100. package/dist/mdx-plugins/remark-steps.d.ts +2 -0
  101. package/dist/mdx-plugins/remark-steps.js +93 -0
  102. package/dist/mdx-plugins/remark-structure.d.ts +2 -0
  103. package/dist/mdx-plugins/remark-structure.js +118 -0
  104. package/dist/mdx-plugins/stringifier.d.ts +2 -0
  105. package/dist/mdx-plugins/stringifier.js +91 -0
  106. package/dist/mdx-plugins/transformer-icon.d.ts +2 -0
  107. package/dist/mdx-plugins/transformer-icon.js +145 -0
  108. package/dist/negotiation/index.d.ts +17 -0
  109. package/dist/negotiation/index.js +378 -0
  110. package/dist/page-tree/index.d.ts +3 -0
  111. package/dist/page-tree/index.js +2 -0
  112. package/dist/path-1H5VzYiT.js +75 -0
  113. package/dist/rehype-code-D-RFJb9W.d.ts +14 -0
  114. package/dist/rehype-code.core-BUwNuchP.js +548 -0
  115. package/dist/rehype-code.core-BjH1uHWj.d.ts +115 -0
  116. package/dist/rehype-toc-K51AGb5U.d.ts +43 -0
  117. package/dist/remark-admonition-BwTcmI_S.d.ts +20 -0
  118. package/dist/remark-code-tab-DE_4bdnu.d.ts +34 -0
  119. package/dist/remark-directive-admonition-BLiJ5l43.d.ts +27 -0
  120. package/dist/remark-feedback-block-BxtINXN-.d.ts +45 -0
  121. package/dist/remark-gfm-DpVfAX1x.d.ts +2 -0
  122. package/dist/remark-heading-DEIzTkU5.d.ts +33 -0
  123. package/dist/remark-image-BI2S9LOb.d.ts +57 -0
  124. package/dist/remark-llms-bD3WvU2V.d.ts +73 -0
  125. package/dist/remark-mdx-files-Buvxc-sa.d.ts +54 -0
  126. package/dist/remark-mdx-mermaid-C1bCHHc6.d.ts +15 -0
  127. package/dist/remark-npm-BbpvkJaT.d.ts +31 -0
  128. package/dist/remark-steps-DqVEo0iq.d.ts +23 -0
  129. package/dist/remark-structure-CnHwvNZr.d.ts +87 -0
  130. package/dist/remove-markdown-DfKNMl9w.js +40 -0
  131. package/dist/remove-undefined-CzMSKybq.js +24 -0
  132. package/dist/rolldown-runtime-DC62tzP2.js +33 -0
  133. package/dist/search/algolia.d.ts +2 -0
  134. package/dist/search/algolia.js +75 -0
  135. package/dist/search/client/algolia.d.ts +2 -0
  136. package/dist/search/client/algolia.js +53 -0
  137. package/dist/search/client/fetch.d.ts +2 -0
  138. package/dist/search/client/fetch.js +28 -0
  139. package/dist/search/client/flexsearch-static.d.ts +2 -0
  140. package/dist/search/client/flexsearch-static.js +42 -0
  141. package/dist/search/client/mixedbread.d.ts +2 -0
  142. package/dist/search/client/mixedbread.js +65 -0
  143. package/dist/search/client/orama-cloud-legacy.d.ts +2 -0
  144. package/dist/search/client/orama-cloud-legacy.js +84 -0
  145. package/dist/search/client/orama-cloud.d.ts +2 -0
  146. package/dist/search/client/orama-cloud.js +86 -0
  147. package/dist/search/client/orama-static.d.ts +2 -0
  148. package/dist/search/client/orama-static.js +75 -0
  149. package/dist/search/client.d.ts +2 -0
  150. package/dist/search/client.js +97 -0
  151. package/dist/search/flexsearch.d.ts +56 -0
  152. package/dist/search/flexsearch.js +128 -0
  153. package/dist/search/index.d.ts +2 -0
  154. package/dist/search/index.js +74 -0
  155. package/dist/search/mixedbread.d.ts +49 -0
  156. package/dist/search/mixedbread.js +77 -0
  157. package/dist/search/orama-cloud-legacy.d.ts +75 -0
  158. package/dist/search/orama-cloud-legacy.js +48 -0
  159. package/dist/search/orama-cloud.d.ts +75 -0
  160. package/dist/search/orama-cloud.js +50 -0
  161. package/dist/search/server.d.ts +2 -0
  162. package/dist/search/server.js +237 -0
  163. package/dist/server-CCqACwlF.d.ts +165 -0
  164. package/dist/server.browser.d.ts +13 -0
  165. package/dist/server.browser.js +22 -0
  166. package/dist/server.d.ts +42 -0
  167. package/dist/server.js +398 -0
  168. package/dist/source/client/index.d.ts +2 -0
  169. package/dist/source/client/index.js +37 -0
  170. package/dist/source/dynamic.d.ts +2 -0
  171. package/dist/source/dynamic.js +2 -0
  172. package/dist/source/index.d.ts +2 -0
  173. package/dist/source/index.js +5 -0
  174. package/dist/source/llms.d.ts +2 -0
  175. package/dist/source/llms.js +74 -0
  176. package/dist/source/plugins/lucide-icons.d.ts +11 -0
  177. package/dist/source/plugins/lucide-icons.js +21 -0
  178. package/dist/source/plugins/slugs.d.ts +2 -0
  179. package/dist/source/plugins/slugs.js +75 -0
  180. package/dist/source/plugins/status-badges.d.ts +50 -0
  181. package/dist/source/plugins/status-badges.js +52 -0
  182. package/dist/source/schema.d.ts +30 -0
  183. package/dist/source/schema.js +28 -0
  184. package/dist/stringifier-B_QUcUyo.d.ts +63 -0
  185. package/dist/toc-CtW5lwA1.d.ts +64 -0
  186. package/dist/toc.d.ts +2 -0
  187. package/dist/toc.js +245 -0
  188. package/dist/transformer-icon-DlrneIS3.d.ts +17 -0
  189. package/dist/types-D89QoQR-.d.ts +4 -0
  190. package/dist/url-BVHvi3_K.js +29 -0
  191. package/dist/util-BDsqOxh3.d.ts +6 -0
  192. package/dist/util-DjBr9b3w.js +8 -0
  193. package/dist/utils/use-media-query.d.ts +4 -0
  194. package/dist/utils/use-media-query.js +20 -0
  195. package/dist/utils/use-on-change.d.ts +9 -0
  196. package/dist/utils/use-on-change.js +17 -0
  197. package/dist/utils-Bvy3V-fv.js +59 -0
  198. package/dist/utils-Cgs-6U-z.js +39 -0
  199. package/dist/utils-DEVq3cEC.js +151 -0
  200. package/dist/utils-Yx0IL9eW.js +48 -0
  201. package/package.json +251 -0
@@ -0,0 +1,50 @@
1
+ import { a as Separator$1, n as Item$1, t as Folder$1 } from "../../definitions-CFOhwE1k.js";
2
+ import { x as LoaderPlugin } from "../../index-DIwKCYOz.js";
3
+ import { ReactNode } from "react";
4
+ //#region src/source/plugins/status-badges.d.ts
5
+ interface Item extends Item$1 {
6
+ /**
7
+ * Status badge to display in the sidebar (e.g., "new", "beta", "deprecated", "experimental").
8
+ */
9
+ status?: string;
10
+ }
11
+ interface Folder extends Omit<Folder$1, 'children' | 'index'> {
12
+ index?: Item;
13
+ children: Node[];
14
+ }
15
+ type Separator = Separator$1;
16
+ type Node = Item | Folder | Separator;
17
+ /**
18
+ * Plugin to add status badges to pages in the sidebar.
19
+ *
20
+ * This reads the `status` field from page frontmatter and adds it to the page tree item.
21
+ * Define the `renderBadge` option to render it.
22
+ *
23
+ * @example
24
+ * ```tsx
25
+ * import { loader } from '@vezham/docs-core/source';
26
+ * import { statusBadgesPlugin } from '@vezham/docs-core/source/status-badges';
27
+ *
28
+ * export const source = loader({
29
+ * plugins: [
30
+ * statusBadgesPlugin({
31
+ * renderBadge: (status) => <span>{status}</span>,
32
+ * }),
33
+ * ],
34
+ * // ...
35
+ * });
36
+ * ```
37
+ *
38
+ * Then in your frontmatter:
39
+ * ```yaml
40
+ * ---
41
+ * title: My Page
42
+ * status: new
43
+ * ---
44
+ * ```
45
+ */
46
+ declare function statusBadgesPlugin(options?: {
47
+ renderBadge?: (status: string) => ReactNode;
48
+ }): LoaderPlugin;
49
+ //#endregion
50
+ export { Folder, Item, Node, Separator, statusBadgesPlugin };
@@ -0,0 +1,52 @@
1
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
+ //#region src/source/plugins/status-badges.tsx
3
+ /**
4
+ * Plugin to add status badges to pages in the sidebar.
5
+ *
6
+ * This reads the `status` field from page frontmatter and adds it to the page tree item.
7
+ * Define the `renderBadge` option to render it.
8
+ *
9
+ * @example
10
+ * ```tsx
11
+ * import { loader } from '@vezham/docs-core/source';
12
+ * import { statusBadgesPlugin } from '@vezham/docs-core/source/status-badges';
13
+ *
14
+ * export const source = loader({
15
+ * plugins: [
16
+ * statusBadgesPlugin({
17
+ * renderBadge: (status) => <span>{status}</span>,
18
+ * }),
19
+ * ],
20
+ * // ...
21
+ * });
22
+ * ```
23
+ *
24
+ * Then in your frontmatter:
25
+ * ```yaml
26
+ * ---
27
+ * title: My Page
28
+ * status: new
29
+ * ---
30
+ * ```
31
+ */
32
+ function statusBadgesPlugin(options = {}) {
33
+ const { renderBadge = (status) => /* @__PURE__ */ jsx("span", {
34
+ "data-status": status,
35
+ children: status
36
+ }) } = options;
37
+ return {
38
+ name: "fumadocs:status-badges",
39
+ transformPageTree: { file(node, filePath) {
40
+ if (!filePath) return node;
41
+ const file = this.storage.read(filePath);
42
+ if (file?.format === "page" && "status" in file.data && typeof file.data.status === "string") {
43
+ const status = file.data.status;
44
+ node.name = /* @__PURE__ */ jsxs(Fragment, { children: [node.name, renderBadge(status)] });
45
+ node.status = status;
46
+ }
47
+ return node;
48
+ } }
49
+ };
50
+ }
51
+ //#endregion
52
+ export { statusBadgesPlugin };
@@ -0,0 +1,30 @@
1
+ import { z } from "zod";
2
+ //#region src/source/schema.d.ts
3
+ /**
4
+ * Zod 4 schema
5
+ */
6
+ declare const metaSchema: z.ZodObject<{
7
+ title: z.ZodOptional<z.ZodString>;
8
+ pages: z.ZodOptional<z.ZodArray<z.ZodString>>;
9
+ pagesIndex: z.ZodOptional<z.ZodString>;
10
+ description: z.ZodOptional<z.ZodString>;
11
+ root: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodString]>>;
12
+ defaultOpen: z.ZodOptional<z.ZodBoolean>;
13
+ collapsible: z.ZodOptional<z.ZodBoolean>;
14
+ icon: z.ZodOptional<z.ZodString>;
15
+ }, z.core.$strip>;
16
+ type _JSONType = number | boolean | string | null | _JSONType[] | {
17
+ [key: string]: _JSONType;
18
+ };
19
+ /**
20
+ * Zod 4 schema
21
+ */
22
+ declare const pageSchema: z.ZodObject<{
23
+ title: z.ZodString;
24
+ description: z.ZodOptional<z.ZodString>;
25
+ icon: z.ZodOptional<z.ZodString>;
26
+ full: z.ZodOptional<z.ZodBoolean>;
27
+ _openapi: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodCustom<_JSONType, _JSONType>>>;
28
+ }, z.core.$strip>;
29
+ //#endregion
30
+ export { _JSONType, metaSchema, pageSchema };
@@ -0,0 +1,28 @@
1
+ import { z } from "zod";
2
+ //#region src/source/schema.ts
3
+ /**
4
+ * Zod 4 schema
5
+ */
6
+ const metaSchema = z.object({
7
+ title: z.string().optional(),
8
+ pages: z.array(z.string()).optional(),
9
+ /** specify a index page for folder */
10
+ pagesIndex: z.string().optional(),
11
+ description: z.string().optional(),
12
+ root: z.union([z.boolean(), z.string()]).optional(),
13
+ defaultOpen: z.boolean().optional(),
14
+ collapsible: z.boolean().optional(),
15
+ icon: z.string().optional()
16
+ });
17
+ /**
18
+ * Zod 4 schema
19
+ */
20
+ const pageSchema = z.object({
21
+ title: z.string(),
22
+ description: z.string().optional(),
23
+ icon: z.string().optional(),
24
+ full: z.boolean().optional(),
25
+ _openapi: z.record(z.string(), z.custom()).optional()
26
+ });
27
+ //#endregion
28
+ export { metaSchema, pageSchema };
@@ -0,0 +1,63 @@
1
+ import { MdxJsxAttribute, MdxJsxExpressionAttribute, MdxJsxFlowElement, MdxJsxTextElement } from "mdast-util-mdx";
2
+ import { Info, Options, State } from "mdast-util-to-markdown";
3
+ import { Processor } from "unified";
4
+ import { Nodes, Parents } from "mdast";
5
+ //#region src/mdx-plugins/stringifier.d.ts
6
+ declare module 'mdast' {
7
+ interface Data {
8
+ /**
9
+ * [Fumadocs: stringify] Extra info for stringifying the node:
10
+ * - `children-only`: only stringify its children.
11
+ * - `{ node }`: stringify as another node.
12
+ * - `{ text }`: the stringified form of node.
13
+ */
14
+ _stringify?: 'children-only' | {
15
+ node: Nodes;
16
+ } | {
17
+ text: string;
18
+ };
19
+ }
20
+ }
21
+ type Stringifier<Context> = ((this: Processor, node: Nodes, ctx: Context) => string) | ((node: Nodes, ctx: Context) => string);
22
+ interface StringifyOptions<Context = undefined> extends Options {
23
+ /**
24
+ * Filter the elements to be included in the output:
25
+ *
26
+ * - `true`: include element & its children.
27
+ * - `children-only`: exclude element but keep its children.
28
+ * - `false`: exclude element & its children.
29
+ *
30
+ * Default:
31
+ *
32
+ * ```ts
33
+ * filterElement = (node) => {
34
+ * switch (node.type) {
35
+ * case 'mdxJsxFlowElement':
36
+ * case 'mdxJsxTextElement':
37
+ * switch (node.name) {
38
+ * case 'File':
39
+ * case 'TypeTable':
40
+ * case 'Callout':
41
+ * case 'Card':
42
+ * return true;
43
+ * }
44
+ * return 'children-only';
45
+ * }
46
+ *
47
+ * return true;
48
+ * },
49
+ * ```
50
+ */
51
+ filterElement?: (node: Nodes) => boolean | 'children-only';
52
+ /**
53
+ * Filter the attributes to stringify.
54
+ */
55
+ filterMdxAttributes?: (node: MdxJsxFlowElement | MdxJsxTextElement, attribute: MdxJsxAttribute | MdxJsxExpressionAttribute) => boolean;
56
+ /**
57
+ * override default stringifier
58
+ */
59
+ stringify?: (node: Nodes, parent: Parents | undefined, state: State, info: Info, ctx: Context) => string | undefined;
60
+ }
61
+ declare function defaultStringifier<Context = undefined>(config?: StringifyOptions<Context>): Stringifier<Context>;
62
+ //#endregion
63
+ export { StringifyOptions as n, defaultStringifier as r, Stringifier as t };
@@ -0,0 +1,64 @@
1
+ import { ComponentProps, ReactNode, RefObject } from "react";
2
+ //#region src/toc.d.ts
3
+ interface TOCItemType {
4
+ title: ReactNode;
5
+ url: string;
6
+ depth: number;
7
+ /** [remark-steps] the step number */
8
+ _step?: number;
9
+ }
10
+ type TableOfContents = TOCItemType[];
11
+ interface TOCItemInfo {
12
+ id: string;
13
+ active: boolean;
14
+ /** last time the item is updated */
15
+ t: number;
16
+ /** currently active but not intersecting in viewport */
17
+ fallback: boolean;
18
+ original: TOCItemType;
19
+ }
20
+ interface AnchorProviderProps {
21
+ toc: TOCItemType[];
22
+ /**
23
+ * Only accept one active item at most
24
+ *
25
+ * @defaultValue false
26
+ */
27
+ single?: boolean;
28
+ children?: ReactNode;
29
+ }
30
+ interface ScrollProviderProps {
31
+ /**
32
+ * Scroll into the view of container when active
33
+ */
34
+ containerRef: RefObject<HTMLElement | null>;
35
+ children?: ReactNode;
36
+ }
37
+ /** Optional: add auto-scroll to TOC items. */
38
+ declare function ScrollProvider({ containerRef, children }: ScrollProviderProps): import("react").JSX.Element;
39
+ declare function AnchorProvider({ toc, single, children }: AnchorProviderProps): import("react").JSX.Element;
40
+ interface TOCItemProps extends ComponentProps<'a'> {
41
+ autoScroll?: boolean;
42
+ onActiveChange?: (v: boolean) => void;
43
+ }
44
+ declare function TOCItem({ ref, onActiveChange, autoScroll, ...props }: TOCItemProps): import("react").JSX.Element;
45
+ /** @returns static info object, useful for custom rendering logic */
46
+ declare function useTOC(): {
47
+ get(): TOCItemInfo[];
48
+ listen: (listener: ChangeListener) => void;
49
+ unlisten: (listener: ChangeListener) => void;
50
+ };
51
+ declare function useTOCListener(listener: ChangeListener): void;
52
+ declare function useTOCSelector<T>(select: (items: TOCItemInfo[]) => T, isEqual?: (a: T, b: T) => boolean): T;
53
+ /**
54
+ * The estimated active heading ID
55
+ */
56
+ declare function useActiveAnchor(): string | undefined;
57
+ /**
58
+ * The id of visible anchors
59
+ */
60
+ declare function useActiveAnchors(): string[];
61
+ declare function useItems(): TOCItemInfo[];
62
+ type ChangeListener = (items: TOCItemInfo[]) => void;
63
+ //#endregion
64
+ export { TOCItem as a, TOCItemType as c, useActiveAnchors as d, useItems as f, useTOCSelector as h, ScrollProviderProps as i, TableOfContents as l, useTOCListener as m, AnchorProviderProps as n, TOCItemInfo as o, useTOC as p, ScrollProvider as r, TOCItemProps as s, AnchorProvider as t, useActiveAnchor as u };
package/dist/toc.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ import { a as TOCItem, c as TOCItemType, d as useActiveAnchors, f as useItems, h as useTOCSelector, i as ScrollProviderProps, l as TableOfContents, m as useTOCListener, n as AnchorProviderProps, o as TOCItemInfo, p as useTOC, r as ScrollProvider, s as TOCItemProps, t as AnchorProvider, u as useActiveAnchor } from "./toc-CtW5lwA1.js";
2
+ export { AnchorProvider, AnchorProviderProps, ScrollProvider, ScrollProviderProps, TOCItem, TOCItemInfo, TOCItemProps, TOCItemType, TableOfContents, useActiveAnchor, useActiveAnchors, useItems, useTOC, useTOCListener, useTOCSelector };
package/dist/toc.js ADDED
@@ -0,0 +1,245 @@
1
+ "use client";
2
+ import { t as isEqualShallow } from "./is-equal-LdLqRs0o.js";
3
+ import { createContext, use, useEffect, useEffectEvent, useMemo, useRef, useState } from "react";
4
+ import { jsx } from "react/jsx-runtime";
5
+ import scrollIntoView from "scroll-into-view-if-needed";
6
+ //#region src/utils/merge-refs.ts
7
+ function mergeRefs(...refs) {
8
+ return (value) => {
9
+ refs.forEach((ref) => {
10
+ if (typeof ref === "function") ref(value);
11
+ else if (ref != null) ref.current = value;
12
+ });
13
+ };
14
+ }
15
+ //#endregion
16
+ //#region src/toc.tsx
17
+ const ObserverContext = createContext(null);
18
+ const ScrollContext = createContext(null);
19
+ /** Optional: add auto-scroll to TOC items. */
20
+ function ScrollProvider({ containerRef, children }) {
21
+ return /* @__PURE__ */ jsx(ScrollContext, {
22
+ value: containerRef,
23
+ children
24
+ });
25
+ }
26
+ function AnchorProvider({ toc, single = false, children }) {
27
+ const observer = useMemo(() => new Observer(), []);
28
+ observer.single = single;
29
+ useEffect(() => {
30
+ observer.setItems(toc);
31
+ }, [observer, toc]);
32
+ useEffect(() => {
33
+ observer.watch({ threshold: .9 });
34
+ return () => observer.unwatch();
35
+ }, [observer]);
36
+ return /* @__PURE__ */ jsx(ObserverContext, {
37
+ value: observer,
38
+ children
39
+ });
40
+ }
41
+ function TOCItem({ ref, onActiveChange = () => null, autoScroll = true, ...props }) {
42
+ const id = props.href ? getItemId(props.href) : null;
43
+ const containerRef = use(ScrollContext);
44
+ const anchorRef = useRef(null);
45
+ const isInitialRef = useRef(true);
46
+ const observer = useObserver();
47
+ const [active, setActive] = useState(() => observer.items.some((item) => item.id === id && item.active));
48
+ const onUpdate = useEffectEvent((items, initial) => {
49
+ const itemData = id ? items.find((item) => item.id === id) : null;
50
+ if (!itemData) return;
51
+ if (itemData.active !== active) {
52
+ setActive(itemData.active);
53
+ onActiveChange(itemData.active);
54
+ }
55
+ const anchor = anchorRef.current;
56
+ const container = containerRef?.current;
57
+ if (!autoScroll || !anchor || !container) return;
58
+ let lastActive;
59
+ for (const item of items) {
60
+ if (!item.active) continue;
61
+ if (!lastActive || lastActive.t < item.t) lastActive = item;
62
+ }
63
+ if (lastActive?.id === id) scrollIntoView(anchor, {
64
+ behavior: initial ? "instant" : "smooth",
65
+ block: "center",
66
+ inline: "center",
67
+ scrollMode: "always",
68
+ boundary: container
69
+ });
70
+ });
71
+ useEffect(() => {
72
+ if (autoScroll) onUpdate(observer.items, isInitialRef.current);
73
+ isInitialRef.current = false;
74
+ }, [observer, autoScroll]);
75
+ useEffect(() => {
76
+ const listener = (items) => onUpdate(items, false);
77
+ observer.listen(listener);
78
+ return () => observer.unlisten(listener);
79
+ }, [observer]);
80
+ return /* @__PURE__ */ jsx("a", {
81
+ ref: mergeRefs(anchorRef, ref),
82
+ "data-active": active,
83
+ ...props
84
+ });
85
+ }
86
+ function useObserver() {
87
+ const observer = use(ObserverContext);
88
+ if (!observer) throw new Error(`Component must be used under the <AnchorProvider /> component.`);
89
+ return observer;
90
+ }
91
+ /** @returns static info object, useful for custom rendering logic */
92
+ function useTOC() {
93
+ const observer = useObserver();
94
+ return useMemo(() => ({
95
+ get() {
96
+ return observer.items;
97
+ },
98
+ listen: observer.listen.bind(observer),
99
+ unlisten: observer.unlisten.bind(observer)
100
+ }), [observer]);
101
+ }
102
+ function useTOCListener(listener) {
103
+ const observer = useObserver();
104
+ const callback = useEffectEvent(listener);
105
+ useEffect(() => {
106
+ observer.listen(callback);
107
+ return () => observer.unlisten(callback);
108
+ }, [observer]);
109
+ }
110
+ function useTOCSelector(select, isEqual = isEqualShallow) {
111
+ const observer = useObserver();
112
+ const [value, setValue] = useState(() => select(observer.items));
113
+ useTOCListener((items) => {
114
+ const next = select(items);
115
+ if (!isEqual(value, next)) setValue(next);
116
+ });
117
+ return value;
118
+ }
119
+ /**
120
+ * The estimated active heading ID
121
+ */
122
+ function useActiveAnchor() {
123
+ return useTOCSelector((items) => {
124
+ let out;
125
+ for (const item of items) {
126
+ if (!item.active) continue;
127
+ if (!out || item.t > out.t) out = item;
128
+ }
129
+ return out?.id;
130
+ });
131
+ }
132
+ /**
133
+ * The id of visible anchors
134
+ */
135
+ function useActiveAnchors() {
136
+ return useTOCSelector((items) => {
137
+ const out = [];
138
+ for (const item of items) if (item.active) out.push(item.id);
139
+ return out;
140
+ });
141
+ }
142
+ function useItems() {
143
+ return useTOCSelector((items) => items);
144
+ }
145
+ function getItemId(url) {
146
+ if (url.startsWith("#")) return url.slice(1);
147
+ return null;
148
+ }
149
+ var Observer = class {
150
+ constructor() {
151
+ this.items = [];
152
+ this.single = false;
153
+ this.observer = null;
154
+ this.listeners = /* @__PURE__ */ new Set();
155
+ }
156
+ listen(listener) {
157
+ this.listeners.add(listener);
158
+ }
159
+ unlisten(listener) {
160
+ this.listeners.delete(listener);
161
+ }
162
+ setItems(newItems) {
163
+ const observer = this.observer;
164
+ if (observer) for (const item of this.items) {
165
+ const element = document.getElementById(item.id);
166
+ if (!element) continue;
167
+ observer.unobserve(element);
168
+ }
169
+ const next = [];
170
+ for (const item of newItems) {
171
+ const id = getItemId(item.url);
172
+ if (!id) continue;
173
+ next.push({
174
+ id,
175
+ active: false,
176
+ fallback: false,
177
+ t: 0,
178
+ original: item
179
+ });
180
+ }
181
+ this.update(next);
182
+ this.observeItems();
183
+ }
184
+ watch(options) {
185
+ if (this.observer) return;
186
+ this.observer = new IntersectionObserver(this.callback.bind(this), options);
187
+ this.observeItems();
188
+ }
189
+ unwatch() {
190
+ this.observer?.disconnect();
191
+ this.observer = null;
192
+ }
193
+ callback(entries) {
194
+ if (entries.length === 0) return;
195
+ let hasActive = false;
196
+ const updated = this.items.map((item) => {
197
+ const entry = entries.find((entry) => entry.target.id === item.id);
198
+ let active = entry ? entry.isIntersecting : item.active && !item.fallback;
199
+ if (this.single && hasActive) active = false;
200
+ if (item.active !== active) item = {
201
+ ...item,
202
+ t: Date.now(),
203
+ active,
204
+ fallback: false
205
+ };
206
+ if (active) hasActive = true;
207
+ return item;
208
+ });
209
+ if (!hasActive && entries[0].rootBounds) {
210
+ const viewTop = entries[0].rootBounds.top;
211
+ let min = Number.MAX_VALUE;
212
+ let fallbackIdx = -1;
213
+ for (let i = 0; i < updated.length; i++) {
214
+ const element = document.getElementById(updated[i].id);
215
+ if (!element) continue;
216
+ const d = Math.abs(viewTop - element.getBoundingClientRect().top);
217
+ if (d < min) {
218
+ fallbackIdx = i;
219
+ min = d;
220
+ }
221
+ }
222
+ if (fallbackIdx !== -1) updated[fallbackIdx] = {
223
+ ...updated[fallbackIdx],
224
+ active: true,
225
+ fallback: true,
226
+ t: Date.now()
227
+ };
228
+ }
229
+ this.update(updated);
230
+ }
231
+ observeItems() {
232
+ if (!this.observer) return;
233
+ for (const item of this.items) {
234
+ const element = document.getElementById(item.id);
235
+ if (!element) continue;
236
+ this.observer.observe(element);
237
+ }
238
+ }
239
+ update(next) {
240
+ this.items = next;
241
+ for (const listener of this.listeners) listener(next);
242
+ }
243
+ };
244
+ //#endregion
245
+ export { AnchorProvider, ScrollProvider, TOCItem, useActiveAnchor, useActiveAnchors, useItems, useTOC, useTOCListener, useTOCSelector };
@@ -0,0 +1,17 @@
1
+ import { ShikiTransformer } from "shiki";
2
+ //#region src/mdx-plugins/transformer-icon.d.ts
3
+ type CodeBlockIcon = {
4
+ viewBox: string;
5
+ fill: string;
6
+ d: string;
7
+ } | string;
8
+ interface IconOptions {
9
+ shortcuts?: Record<string, string>;
10
+ extend?: Record<string, CodeBlockIcon>;
11
+ }
12
+ /**
13
+ * Inject icons to `icon` property (as HTML)
14
+ */
15
+ declare function transformerIcon(options?: IconOptions): ShikiTransformer;
16
+ //#endregion
17
+ export { IconOptions as n, transformerIcon as r, CodeBlockIcon as t };
@@ -0,0 +1,4 @@
1
+ //#region src/types.d.ts
2
+ type Awaitable<T> = T | PromiseLike<T>;
3
+ //#endregion
4
+ export { Awaitable as t };
@@ -0,0 +1,29 @@
1
+ //#region src/utils/url.tsx
2
+ /**
3
+ * The base path (Vite)
4
+ */
5
+ const BASE_PATH = typeof import.meta.env !== "undefined" && typeof import.meta.env.BASE_URL === "string" ? import.meta.env.BASE_URL : "/";
6
+ function join(...paths) {
7
+ let out = "";
8
+ for (let p of paths) {
9
+ if (out.length > 0) {
10
+ if (p.startsWith("/")) p = p.slice(1);
11
+ if (!out.endsWith("/")) out += "/";
12
+ }
13
+ out += p;
14
+ }
15
+ return out;
16
+ }
17
+ /**
18
+ * normalize URL into the Fumadocs standard form (`/slug-1/slug-2`).
19
+ *
20
+ * This includes URLs with trailing slashes.
21
+ */
22
+ function normalizeUrl(url) {
23
+ if (url.startsWith("http://") || url.startsWith("https://")) return url;
24
+ if (!url.startsWith("/")) url = "/" + url;
25
+ if (url.length > 1 && url.endsWith("/")) url = url.slice(0, -1);
26
+ return url;
27
+ }
28
+ //#endregion
29
+ export { join as n, normalizeUrl as r, BASE_PATH as t };
@@ -0,0 +1,6 @@
1
+ import { Pluggable } from "unified";
2
+ //#region src/content/mdx/util.d.ts
3
+ type Thenable<T> = T | PromiseLike<T>;
4
+ type ResolvePlugins = Thenable<Pluggable>[] | ((v: Pluggable[]) => Thenable<Pluggable>[]);
5
+ //#endregion
6
+ export { ResolvePlugins as t };
@@ -0,0 +1,8 @@
1
+ //#region src/content/mdx/util.ts
2
+ async function resolvePlugins(def, options = []) {
3
+ const list = (await Promise.all(def(Array.isArray(options) ? options : []))).filter((v) => v !== false);
4
+ if (typeof options === "function") return Promise.all(options(list));
5
+ return list;
6
+ }
7
+ //#endregion
8
+ export { resolvePlugins as t };
@@ -0,0 +1,4 @@
1
+ //#region src/utils/use-media-query.d.ts
2
+ declare function useMediaQuery(query: string, disabled?: boolean): boolean | null;
3
+ //#endregion
4
+ export { useMediaQuery };
@@ -0,0 +1,20 @@
1
+ import { useEffect, useState } from "react";
2
+ //#region src/utils/use-media-query.ts
3
+ function useMediaQuery(query, disabled = false) {
4
+ const [isMatch, setMatch] = useState(null);
5
+ useEffect(() => {
6
+ if (disabled) return;
7
+ const mediaQueryList = window.matchMedia(query);
8
+ const handleChange = () => {
9
+ setMatch(mediaQueryList.matches);
10
+ };
11
+ handleChange();
12
+ mediaQueryList.addEventListener("change", handleChange);
13
+ return () => {
14
+ mediaQueryList.removeEventListener("change", handleChange);
15
+ };
16
+ }, [disabled, query]);
17
+ return isMatch;
18
+ }
19
+ //#endregion
20
+ export { useMediaQuery };
@@ -0,0 +1,9 @@
1
+ //#region src/utils/use-on-change.d.ts
2
+ /**
3
+ * @param value - state to watch
4
+ * @param onChange - when the state changed
5
+ * @param isUpdated - a function that determines if the state is updated
6
+ */
7
+ declare function useOnChange<T>(value: T, onChange: (current: T, previous: T) => void, isUpdated?: (prev: T, current: T) => boolean): void;
8
+ //#endregion
9
+ export { useOnChange };
@@ -0,0 +1,17 @@
1
+ import { t as isEqualShallow } from "../is-equal-LdLqRs0o.js";
2
+ import { useState } from "react";
3
+ //#region src/utils/use-on-change.ts
4
+ /**
5
+ * @param value - state to watch
6
+ * @param onChange - when the state changed
7
+ * @param isUpdated - a function that determines if the state is updated
8
+ */
9
+ function useOnChange(value, onChange, isUpdated = (a, b) => !isEqualShallow(a, b)) {
10
+ const [prev, setPrev] = useState(value);
11
+ if (isUpdated(prev, value)) {
12
+ onChange(value, prev);
13
+ setPrev(value);
14
+ }
15
+ }
16
+ //#endregion
17
+ export { useOnChange };