fumadocs-core 12.5.6 → 13.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.
@@ -26,13 +26,6 @@ type RehypeCodeOptions = RehypeShikiOptions & {
26
26
  * Filter meta string before processing
27
27
  */
28
28
  filterMetaString?: (metaString: string) => string;
29
- /**
30
- * Default language
31
- *
32
- * @defaultValue plaintext
33
- * @deprecated Use `defaultLanguage` instead
34
- */
35
- defaultLang?: string;
36
29
  /**
37
30
  * Add icon to code blocks
38
31
  */
@@ -85,4 +78,19 @@ interface RemarkHeadingOptions {
85
78
  */
86
79
  declare function remarkHeading({ slug: defaultSlug, customId, }?: RemarkHeadingOptions): Transformer<Root$1, Root$1>;
87
80
 
88
- export { type CodeBlockIcon, type RehypeCodeOptions, type RemarkHeadingOptions, type RemarkImageOptions, rehypeCode, rehypeCodeDefaultOptions, remarkHeading, remarkImage, transformerIcon };
81
+ interface RemarkAdmonitionOptions {
82
+ tag?: string;
83
+ types?: string[];
84
+ /**
85
+ * Map type to another type
86
+ */
87
+ typeMap?: Record<string, string>;
88
+ }
89
+ /**
90
+ * Remark Plugin to support Admonition syntax
91
+ *
92
+ * Useful when Migrating from Docusaurus
93
+ */
94
+ declare function remarkAdmonition(options?: RemarkAdmonitionOptions): Transformer<Root$1, Root$1>;
95
+
96
+ export { type CodeBlockIcon, type RehypeCodeOptions, type RemarkAdmonitionOptions, type RemarkHeadingOptions, type RemarkImageOptions, rehypeCode, rehypeCodeDefaultOptions, remarkAdmonition, remarkHeading, remarkImage, transformerIcon };
@@ -241,9 +241,6 @@ function rehypeCode(options = {}) {
241
241
  if (codeOptions.tab !== false) {
242
242
  codeOptions.transformers = [...codeOptions.transformers, transformerTab()];
243
243
  }
244
- if (codeOptions.defaultLang) {
245
- codeOptions.defaultLanguage = codeOptions.defaultLang;
246
- }
247
244
  return rehypeShiki.call(this, codeOptions);
248
245
  }
249
246
  function transformerTab() {
@@ -406,9 +403,74 @@ function structure(content, remarkPlugins = [], options = {}) {
406
403
  const result = remark().use(remarkGfm).use(remarkMdx).use(remarkPlugins).use(remarkStructure, options).processSync(content);
407
404
  return result.data.structuredData;
408
405
  }
406
+
407
+ // src/mdx-plugins/remark-admonition.ts
408
+ import { visit as visit3 } from "unist-util-visit";
409
+ function remarkAdmonition(options = {}) {
410
+ const types = options.types ?? ["warn", "info", "error"];
411
+ const tag = options.tag ?? ":::";
412
+ const typeMap = options.typeMap ?? {
413
+ note: "info",
414
+ tip: "info",
415
+ warning: "warn",
416
+ danger: "error"
417
+ };
418
+ function replaceNodes(nodes) {
419
+ if (nodes.length === 0) return nodes;
420
+ let open = -1, end = -1;
421
+ const attributes = [];
422
+ for (let i = 0; i < nodes.length; i++) {
423
+ if (nodes[i].type !== "paragraph") continue;
424
+ const text = flattenNode(nodes[i]);
425
+ const start = types.find((type) => text.startsWith(`${tag}${type}`));
426
+ if (start) {
427
+ if (open !== -1) throw new Error("Nested callout is not supported");
428
+ open = i;
429
+ attributes.push({
430
+ type: "mdxJsxAttribute",
431
+ name: "type",
432
+ value: start in typeMap ? typeMap[start] : start
433
+ });
434
+ const rest = text.slice(`${tag}${start}`.length);
435
+ if (rest.startsWith("[") && rest.endsWith("]")) {
436
+ attributes.push({
437
+ type: "mdxJsxAttribute",
438
+ name: "title",
439
+ value: rest.slice(1, -1)
440
+ });
441
+ }
442
+ }
443
+ if (open !== -1 && text === tag) {
444
+ end = i;
445
+ break;
446
+ }
447
+ }
448
+ if (open === -1 || end === -1) return nodes;
449
+ return [
450
+ ...nodes.slice(0, open),
451
+ {
452
+ type: "mdxJsxFlowElement",
453
+ name: "Callout",
454
+ attributes,
455
+ children: nodes.slice(open + 1, end)
456
+ },
457
+ ...replaceNodes(nodes.slice(end + 1))
458
+ ];
459
+ }
460
+ return (tree) => {
461
+ visit3(tree, (node) => {
462
+ if (!("children" in node)) return "skip";
463
+ const result = replaceNodes(node.children);
464
+ if (result === node.children) return;
465
+ node.children = result;
466
+ return "skip";
467
+ });
468
+ };
469
+ }
409
470
  export {
410
471
  rehypeCode,
411
472
  rehypeCodeDefaultOptions,
473
+ remarkAdmonition,
412
474
  default2 as remarkGfm,
413
475
  remarkHeading,
414
476
  remarkImage,
package/dist/toc.d.ts CHANGED
@@ -1,28 +1,28 @@
1
1
  import * as react from 'react';
2
- import { HTMLAttributes, RefObject, ReactNode, AnchorHTMLAttributes } from 'react';
2
+ import { ReactNode, RefObject, AnchorHTMLAttributes } from 'react';
3
3
  import { T as TableOfContents } from './get-toc-CM4X3hbw.js';
4
4
 
5
- declare const useActiveAnchor: (url: string) => boolean;
6
- interface TOCProviderProps extends HTMLAttributes<HTMLDivElement> {
5
+ /**
6
+ * The id of active anchor (doesn't include hash)
7
+ */
8
+ declare function useActiveAnchor(): string | undefined;
9
+ interface AnchorProviderProps {
7
10
  toc: TableOfContents;
11
+ children?: ReactNode;
8
12
  }
9
- declare const TOCProvider: react.ForwardRefExoticComponent<TOCProviderProps & react.RefAttributes<HTMLDivElement>>;
10
- interface TOCScrollProvider {
13
+ interface ScrollProviderProps {
11
14
  /**
12
15
  * Scroll into the view of container when active
13
16
  */
14
- containerRef?: RefObject<HTMLElement>;
15
- toc: TableOfContents;
16
- children: ReactNode;
17
+ containerRef: RefObject<HTMLElement>;
18
+ children?: ReactNode;
17
19
  }
18
- declare function TOCScrollProvider({ toc, containerRef, children, }: TOCScrollProvider): React.ReactElement;
19
- interface TOCItemProps extends AnchorHTMLAttributes<HTMLAnchorElement> {
20
+ declare function ScrollProvider({ containerRef, children, }: ScrollProviderProps): React.ReactElement;
21
+ declare function AnchorProvider({ toc, children, }: AnchorProviderProps): React.ReactElement;
22
+ interface TOCItemProps extends Omit<AnchorHTMLAttributes<HTMLAnchorElement>, 'href'> {
20
23
  href: string;
21
- /**
22
- * Scroll into the view of container when active
23
- */
24
- containerRef?: RefObject<HTMLElement>;
24
+ onActiveChange?: (v: boolean) => void;
25
25
  }
26
26
  declare const TOCItem: react.ForwardRefExoticComponent<TOCItemProps & react.RefAttributes<HTMLAnchorElement>>;
27
27
 
28
- export { TOCItem, type TOCItemProps, TOCProvider, type TOCProviderProps, TOCScrollProvider, useActiveAnchor };
28
+ export { AnchorProvider, type AnchorProviderProps, ScrollProvider, type ScrollProviderProps, TOCItem, type TOCItemProps, useActiveAnchor };
package/dist/toc.js CHANGED
@@ -1,53 +1,92 @@
1
1
  import {
2
- mergeRefs,
3
- useAnchorObserver
4
- } from "./chunk-V6DBK6TW.js";
2
+ useOnChange
3
+ } from "./chunk-KGMG4N3Y.js";
5
4
  import "./chunk-MLKGABMK.js";
6
5
 
7
6
  // src/toc.tsx
8
- import {
9
- createContext,
10
- forwardRef,
11
- useContext,
12
- useEffect,
13
- useMemo,
14
- useRef
15
- } from "react";
7
+ import { createContext, forwardRef, useContext, useMemo, useRef } from "react";
16
8
  import scrollIntoView from "scroll-into-view-if-needed";
9
+
10
+ // src/utils/merge-refs.ts
11
+ function mergeRefs(...refs) {
12
+ return (value) => {
13
+ refs.forEach((ref) => {
14
+ if (typeof ref === "function") {
15
+ ref(value);
16
+ } else if (ref !== null) {
17
+ ref.current = value;
18
+ }
19
+ });
20
+ };
21
+ }
22
+
23
+ // src/utils/use-anchor-observer.ts
24
+ import { useEffect, useState } from "react";
25
+ function useAnchorObserver(watch) {
26
+ const [activeAnchor, setActiveAnchor] = useState();
27
+ useEffect(() => {
28
+ const observer = new IntersectionObserver(
29
+ (entries) => {
30
+ setActiveAnchor((f) => {
31
+ for (const entry of entries) {
32
+ const aboveHalf = window.innerHeight / 2 > entry.boundingClientRect.y;
33
+ const active = aboveHalf && entry.isIntersecting;
34
+ if (active) {
35
+ return entry.target.id;
36
+ }
37
+ }
38
+ return f ?? watch[0];
39
+ });
40
+ },
41
+ { rootMargin: `0% 0% -80% 0%` }
42
+ );
43
+ for (const heading of watch) {
44
+ const element = document.getElementById(heading);
45
+ if (element !== null) {
46
+ observer.observe(element);
47
+ }
48
+ }
49
+ return () => {
50
+ observer.disconnect();
51
+ };
52
+ }, [watch]);
53
+ return activeAnchor;
54
+ }
55
+
56
+ // src/toc.tsx
17
57
  import { jsx } from "react/jsx-runtime";
18
- var ActiveAnchorContext = createContext({});
19
- var useActiveAnchor = (url) => {
20
- const { activeAnchor } = useContext(ActiveAnchorContext);
21
- return activeAnchor === url.split("#")[1];
22
- };
23
- var TOCProvider = forwardRef(
24
- ({ toc, ...props }, ref) => {
25
- const containerRef = useRef(null);
26
- const mergedRef = mergeRefs(containerRef, ref);
27
- return /* @__PURE__ */ jsx("div", { ref: mergedRef, ...props, children: /* @__PURE__ */ jsx(TOCScrollProvider, { toc, containerRef, children: props.children }) });
28
- }
29
- );
30
- TOCProvider.displayName = "TOCProvider";
31
- function TOCScrollProvider({
32
- toc,
58
+ var ActiveAnchorContext = createContext(void 0);
59
+ var ScrollContext = createContext({ current: null });
60
+ function useActiveAnchor() {
61
+ return useContext(ActiveAnchorContext);
62
+ }
63
+ function ScrollProvider({
33
64
  containerRef,
34
65
  children
66
+ }) {
67
+ return /* @__PURE__ */ jsx(ScrollContext.Provider, { value: containerRef, children });
68
+ }
69
+ function AnchorProvider({
70
+ toc,
71
+ children
35
72
  }) {
36
73
  const headings = useMemo(() => {
37
74
  return toc.map((item) => item.url.split("#")[1]);
38
75
  }, [toc]);
39
76
  const activeAnchor = useAnchorObserver(headings);
40
- return /* @__PURE__ */ jsx(ActiveAnchorContext.Provider, { value: { containerRef, activeAnchor }, children });
77
+ return /* @__PURE__ */ jsx(ActiveAnchorContext.Provider, { value: activeAnchor, children });
41
78
  }
42
79
  var TOCItem = forwardRef(
43
- ({ containerRef: container, ...props }, ref) => {
44
- const { containerRef = container } = useContext(ActiveAnchorContext);
45
- const active = useActiveAnchor(props.href);
80
+ ({ onActiveChange, ...props }, ref) => {
81
+ const containerRef = useContext(ScrollContext);
82
+ const activeAnchor = useActiveAnchor();
46
83
  const anchorRef = useRef(null);
47
84
  const mergedRef = mergeRefs(anchorRef, ref);
48
- useEffect(() => {
85
+ const isActive = activeAnchor === props.href.split("#")[1];
86
+ useOnChange(isActive, (v) => {
49
87
  const element = anchorRef.current;
50
- if (active && element && containerRef) {
88
+ if (!element) return;
89
+ if (v && containerRef.current) {
51
90
  scrollIntoView(element, {
52
91
  behavior: "smooth",
53
92
  block: "center",
@@ -56,14 +95,15 @@ var TOCItem = forwardRef(
56
95
  boundary: containerRef.current
57
96
  });
58
97
  }
59
- }, [active, containerRef]);
60
- return /* @__PURE__ */ jsx("a", { ref: mergedRef, "data-active": active, ...props, children: props.children });
98
+ onActiveChange?.(v);
99
+ });
100
+ return /* @__PURE__ */ jsx("a", { ref: mergedRef, "data-active": isActive, ...props, children: props.children });
61
101
  }
62
102
  );
63
103
  TOCItem.displayName = "TOCItem";
64
104
  export {
105
+ AnchorProvider,
106
+ ScrollProvider,
65
107
  TOCItem,
66
- TOCProvider,
67
- TOCScrollProvider,
68
108
  useActiveAnchor
69
109
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fumadocs-core",
3
- "version": "12.5.6",
3
+ "version": "13.0.1",
4
4
  "description": "The library for building a documentation website in Next.js",
5
5
  "keywords": [
6
6
  "NextJs",
@@ -24,10 +24,6 @@
24
24
  "import": "./dist/toc.js",
25
25
  "types": "./dist/toc.d.ts"
26
26
  },
27
- "./toc-internal": {
28
- "import": "./dist/toc-internal.js",
29
- "types": "./dist/toc-internal.d.ts"
30
- },
31
27
  "./search/client": {
32
28
  "import": "./dist/search/client.js",
33
29
  "types": "./dist/search/client.d.ts"
@@ -84,9 +80,6 @@
84
80
  "toc": [
85
81
  "./dist/toc.d.ts"
86
82
  ],
87
- "toc-internal": [
88
- "./dist/toc-internal.d.ts"
89
- ],
90
83
  "search/client": [
91
84
  "./dist/search/client.d.ts"
92
85
  ],
@@ -127,8 +120,8 @@
127
120
  ],
128
121
  "dependencies": {
129
122
  "@formatjs/intl-localematcher": "^0.5.4",
130
- "@shikijs/rehype": "^1.11.0",
131
- "@shikijs/transformers": "^1.11.0",
123
+ "@shikijs/rehype": "^1.11.1",
124
+ "@shikijs/transformers": "^1.11.1",
132
125
  "flexsearch": "0.7.21",
133
126
  "github-slugger": "^2.0.0",
134
127
  "negotiator": "^0.6.3",
@@ -138,7 +131,7 @@
138
131
  "remark-gfm": "^4.0.0",
139
132
  "remark-mdx": "^3.0.1",
140
133
  "scroll-into-view-if-needed": "^3.1.0",
141
- "shiki": "^1.11.0",
134
+ "shiki": "^1.11.1",
142
135
  "swr": "^2.2.5",
143
136
  "unist-util-visit": "^5.0.0"
144
137
  },
@@ -150,7 +143,7 @@
150
143
  "@types/hast": "^3.0.4",
151
144
  "@types/mdast": "^4.0.3",
152
145
  "@types/negotiator": "^0.6.3",
153
- "@types/node": "20.14.11",
146
+ "@types/node": "20.14.12",
154
147
  "@types/react": "^18.3.3",
155
148
  "@types/react-dom": "^18.3.0",
156
149
  "algoliasearch": "^4.24.0",
@@ -1,50 +0,0 @@
1
- // src/utils/merge-refs.ts
2
- function mergeRefs(...refs) {
3
- return (value) => {
4
- refs.forEach((ref) => {
5
- if (typeof ref === "function") {
6
- ref(value);
7
- } else if (ref !== null) {
8
- ref.current = value;
9
- }
10
- });
11
- };
12
- }
13
-
14
- // src/utils/use-anchor-observer.ts
15
- import { useEffect, useState } from "react";
16
- function useAnchorObserver(watch) {
17
- const [activeAnchor, setActiveAnchor] = useState();
18
- useEffect(() => {
19
- const observer = new IntersectionObserver(
20
- (entries) => {
21
- setActiveAnchor((f) => {
22
- for (const entry of entries) {
23
- const aboveHalf = window.innerHeight / 2 > entry.boundingClientRect.y;
24
- const active = aboveHalf && entry.isIntersecting;
25
- if (active) {
26
- return entry.target.id;
27
- }
28
- }
29
- return f ?? watch[0];
30
- });
31
- },
32
- { rootMargin: `0% 0% -80% 0%` }
33
- );
34
- for (const heading of watch) {
35
- const element = document.getElementById(heading);
36
- if (element !== null) {
37
- observer.observe(element);
38
- }
39
- }
40
- return () => {
41
- observer.disconnect();
42
- };
43
- }, [watch]);
44
- return activeAnchor;
45
- }
46
-
47
- export {
48
- mergeRefs,
49
- useAnchorObserver
50
- };
@@ -1,28 +0,0 @@
1
- import * as react from 'react';
2
- import { ReactNode, RefObject, AnchorHTMLAttributes } from 'react';
3
- import { T as TableOfContents } from './get-toc-CM4X3hbw.js';
4
-
5
- /**
6
- * The id of active anchor (doesn't include hash)
7
- */
8
- declare function useActiveAnchor(): string | undefined;
9
- interface AnchorProviderProps {
10
- toc: TableOfContents;
11
- children?: ReactNode;
12
- }
13
- interface ScrollProviderProps {
14
- /**
15
- * Scroll into the view of container when active
16
- */
17
- containerRef: RefObject<HTMLElement>;
18
- children?: ReactNode;
19
- }
20
- declare function ScrollProvider({ containerRef, children, }: ScrollProviderProps): React.ReactElement;
21
- declare function AnchorProvider({ toc, children, }: AnchorProviderProps): React.ReactElement;
22
- interface TOCItemProps extends Omit<AnchorHTMLAttributes<HTMLAnchorElement>, 'href'> {
23
- href: string;
24
- onActiveChange?: (v: boolean) => void;
25
- }
26
- declare const TOCItem: react.ForwardRefExoticComponent<TOCItemProps & react.RefAttributes<HTMLAnchorElement>>;
27
-
28
- export { AnchorProvider, type AnchorProviderProps, ScrollProvider, type ScrollProviderProps, TOCItem, type TOCItemProps, useActiveAnchor };
@@ -1,65 +0,0 @@
1
- import {
2
- useOnChange
3
- } from "./chunk-KGMG4N3Y.js";
4
- import {
5
- mergeRefs,
6
- useAnchorObserver
7
- } from "./chunk-V6DBK6TW.js";
8
- import "./chunk-MLKGABMK.js";
9
-
10
- // src/toc-internal.tsx
11
- import { createContext, forwardRef, useContext, useMemo, useRef } from "react";
12
- import scrollIntoView from "scroll-into-view-if-needed";
13
- import { jsx } from "react/jsx-runtime";
14
- var ActiveAnchorContext = createContext(void 0);
15
- var ScrollContext = createContext({ current: null });
16
- function useActiveAnchor() {
17
- return useContext(ActiveAnchorContext);
18
- }
19
- function ScrollProvider({
20
- containerRef,
21
- children
22
- }) {
23
- return /* @__PURE__ */ jsx(ScrollContext.Provider, { value: containerRef, children });
24
- }
25
- function AnchorProvider({
26
- toc,
27
- children
28
- }) {
29
- const headings = useMemo(() => {
30
- return toc.map((item) => item.url.split("#")[1]);
31
- }, [toc]);
32
- const activeAnchor = useAnchorObserver(headings);
33
- return /* @__PURE__ */ jsx(ActiveAnchorContext.Provider, { value: activeAnchor, children });
34
- }
35
- var TOCItem = forwardRef(
36
- ({ onActiveChange, ...props }, ref) => {
37
- const containerRef = useContext(ScrollContext);
38
- const activeAnchor = useActiveAnchor();
39
- const anchorRef = useRef(null);
40
- const mergedRef = mergeRefs(anchorRef, ref);
41
- const isActive = activeAnchor === props.href.split("#")[1];
42
- useOnChange(isActive, (v) => {
43
- const element = anchorRef.current;
44
- if (!element) return;
45
- if (v && containerRef.current) {
46
- scrollIntoView(element, {
47
- behavior: "smooth",
48
- block: "center",
49
- inline: "center",
50
- scrollMode: "always",
51
- boundary: containerRef.current
52
- });
53
- }
54
- onActiveChange?.(v);
55
- });
56
- return /* @__PURE__ */ jsx("a", { ref: mergedRef, "data-active": isActive, ...props, children: props.children });
57
- }
58
- );
59
- TOCItem.displayName = "TOCItem";
60
- export {
61
- AnchorProvider,
62
- ScrollProvider,
63
- TOCItem,
64
- useActiveAnchor
65
- };