fumadocs-core 12.0.1 → 12.0.3

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.
@@ -1,4 +1,4 @@
1
- import "./chunk-UWTMEZUM.js";
1
+ import "./chunk-CWMXXUWU.js";
2
2
 
3
3
  // src/breadcrumb.tsx
4
4
  import { useMemo } from "react";
@@ -0,0 +1,50 @@
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 != null ? 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
+ };
@@ -2,7 +2,7 @@ import {
2
2
  __objRest,
3
3
  __spreadProps,
4
4
  __spreadValues
5
- } from "./chunk-UWTMEZUM.js";
5
+ } from "./chunk-CWMXXUWU.js";
6
6
 
7
7
  // src/link.tsx
8
8
  import Original from "next/link";
@@ -1,11 +1,11 @@
1
1
  "use client";
2
2
  import {
3
3
  Link
4
- } from "./chunk-2BP57A6C.js";
4
+ } from "./chunk-XB7CNOKH.js";
5
5
  import {
6
6
  __objRest,
7
7
  __spreadValues
8
- } from "./chunk-UWTMEZUM.js";
8
+ } from "./chunk-CWMXXUWU.js";
9
9
 
10
10
  // src/dynamic-link.tsx
11
11
  import { useParams } from "next/navigation";
package/dist/link.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  Link
3
- } from "./chunk-2BP57A6C.js";
4
- import "./chunk-UWTMEZUM.js";
3
+ } from "./chunk-XB7CNOKH.js";
4
+ import "./chunk-CWMXXUWU.js";
5
5
  export {
6
6
  Link as default
7
7
  };
@@ -27,6 +27,7 @@ type RehypeCodeOptions = RehypeShikiOptions & {
27
27
  * Default language
28
28
  *
29
29
  * @defaultValue plaintext
30
+ * @deprecated Use `defaultLanguage` instead
30
31
  */
31
32
  defaultLang?: string;
32
33
  /**
@@ -6,9 +6,8 @@ import {
6
6
  slash
7
7
  } from "../chunk-UWEEHUJV.js";
8
8
  import {
9
- __async,
10
9
  __spreadValues
11
- } from "../chunk-UWTMEZUM.js";
10
+ } from "../chunk-CWMXXUWU.js";
12
11
 
13
12
  // src/mdx-plugins/index.ts
14
13
  import {
@@ -22,20 +21,6 @@ import {
22
21
  transformerNotationWordHighlight
23
22
  } from "@shikijs/transformers";
24
23
 
25
- // src/mdx-plugins/hast-utils.ts
26
- function visit(node, tagNames, handler) {
27
- if (node.type === "element") {
28
- if (tagNames.includes(node.tagName)) {
29
- handler(node);
30
- return;
31
- }
32
- }
33
- if ("children" in node)
34
- node.children.forEach((n) => {
35
- visit(n, tagNames, handler);
36
- });
37
- }
38
-
39
24
  // src/mdx-plugins/transformer-icon.ts
40
25
  import { toEstree } from "hast-util-to-estree";
41
26
  var defaultShortcuts = {
@@ -287,7 +272,7 @@ var rehypeCodeDefaultOptions = {
287
272
  light: "github-light",
288
273
  dark: "github-dark"
289
274
  },
290
- defaultLang: "plaintext",
275
+ defaultLanguage: "plaintext",
291
276
  defaultColor: false,
292
277
  transformers: [
293
278
  transformerNotationHighlight(),
@@ -316,7 +301,7 @@ function rehypeCode(options = {}) {
316
301
  codeOptions.transformers || (codeOptions.transformers = []);
317
302
  codeOptions.transformers = [
318
303
  {
319
- name: "rehype-code:filter-meta",
304
+ name: "rehype-code:pre-process",
320
305
  preprocess(code, { meta }) {
321
306
  var _a;
322
307
  if (meta && codeOptions.filterMetaString) {
@@ -341,33 +326,16 @@ function rehypeCode(options = {}) {
341
326
  transformerIcon(codeOptions.icon)
342
327
  ];
343
328
  }
344
- const prefix = "language-";
345
- const transformer = rehypeShiki.call(this, codeOptions);
346
- return (root, file) => __async(this, null, function* () {
347
- visit(root, ["pre"], (element) => {
348
- var _a;
349
- const head = element.children[0];
350
- if (element.children.length === 0 || head.type !== "element" || head.tagName !== "code")
351
- return;
352
- (_a = head.properties).className || (_a.className = []);
353
- const classes = head.properties.className;
354
- if (!Array.isArray(classes)) return;
355
- const hasLanguage = classes.some(
356
- (d) => typeof d === "string" && d.startsWith(prefix)
357
- );
358
- if (!hasLanguage && codeOptions.defaultLang)
359
- classes.push(`${prefix}${codeOptions.defaultLang}`);
360
- });
361
- if (transformer)
362
- yield transformer.call(this, root, file, () => {
363
- });
364
- });
329
+ if (codeOptions.defaultLang) {
330
+ codeOptions.defaultLanguage = codeOptions.defaultLang;
331
+ }
332
+ return rehypeShiki.call(this, codeOptions);
365
333
  }
366
334
 
367
335
  // src/mdx-plugins/remark-image.ts
368
336
  import { existsSync } from "fs";
369
337
  import path from "path";
370
- import { visit as visit2 } from "unist-util-visit";
338
+ import { visit } from "unist-util-visit";
371
339
  var VALID_BLUR_EXT = [".jpeg", ".png", ".webp", ".avif", ".jpg"];
372
340
  var EXTERNAL_URL_REGEX = /^https?:\/\//;
373
341
  var PUBLIC_DIR = path.join(process.cwd(), "public");
@@ -376,7 +344,7 @@ function remarkImage({
376
344
  } = {}) {
377
345
  return (tree, _file, done) => {
378
346
  const importsToInject = [];
379
- visit2(tree, "image", (node) => {
347
+ visit(tree, "image", (node) => {
380
348
  var _a;
381
349
  let url = decodeURI(node.url);
382
350
  if (!url || EXTERNAL_URL_REGEX.test(url)) {
@@ -460,7 +428,7 @@ import Slugger from "github-slugger";
460
428
  import { remark } from "remark";
461
429
  import remarkGfm from "remark-gfm";
462
430
  import remarkMdx from "remark-mdx";
463
- import { visit as visit3 } from "unist-util-visit";
431
+ import { visit as visit2 } from "unist-util-visit";
464
432
  var slugger = new Slugger();
465
433
  function remarkStructure({
466
434
  types = ["paragraph", "blockquote", "heading"]
@@ -469,7 +437,7 @@ function remarkStructure({
469
437
  slugger.reset();
470
438
  const data = { contents: [], headings: [] };
471
439
  let lastHeading = "";
472
- visit3(node, types, (element) => {
440
+ visit2(node, types, (element) => {
473
441
  var _a, _b;
474
442
  if (element.type === "root") return;
475
443
  const content = flattenNode(element).trim();
@@ -1,4 +1,4 @@
1
- import "./chunk-UWTMEZUM.js";
1
+ import "./chunk-CWMXXUWU.js";
2
2
 
3
3
  // src/middleware.ts
4
4
  import { match as matchLocale } from "@formatjs/intl-localematcher";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  __async
3
- } from "../chunk-UWTMEZUM.js";
3
+ } from "../chunk-CWMXXUWU.js";
4
4
 
5
5
  // src/search/client.ts
6
6
  import { useEffect, useState } from "react";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  __spreadProps,
3
3
  __spreadValues
4
- } from "../chunk-UWTMEZUM.js";
4
+ } from "../chunk-CWMXXUWU.js";
5
5
 
6
6
  // src/search/server.ts
7
7
  import { Document } from "flexsearch";
@@ -2,7 +2,7 @@ import {
2
2
  __async,
3
3
  __objRest,
4
4
  __spreadValues
5
- } from "../chunk-UWTMEZUM.js";
5
+ } from "../chunk-CWMXXUWU.js";
6
6
 
7
7
  // src/search-algolia/client.ts
8
8
  import { useState } from "react";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  __async,
3
3
  __spreadValues
4
- } from "../chunk-UWTMEZUM.js";
4
+ } from "../chunk-CWMXXUWU.js";
5
5
 
6
6
  // src/search-algolia/server.ts
7
7
  import { randomUUID } from "crypto";
@@ -3,7 +3,7 @@ import {
3
3
  } from "../chunk-QRNTLL6S.js";
4
4
  import {
5
5
  __async
6
- } from "../chunk-UWTMEZUM.js";
6
+ } from "../chunk-CWMXXUWU.js";
7
7
 
8
8
  // src/server/get-toc.ts
9
9
  import { remark } from "remark";
package/dist/sidebar.js CHANGED
@@ -2,7 +2,7 @@ import {
2
2
  __objRest,
3
3
  __spreadProps,
4
4
  __spreadValues
5
- } from "./chunk-UWTMEZUM.js";
5
+ } from "./chunk-CWMXXUWU.js";
6
6
 
7
7
  // src/sidebar.tsx
8
8
  import {
@@ -5,7 +5,7 @@ import {
5
5
  __export,
6
6
  __objRest,
7
7
  __spreadValues
8
- } from "../chunk-UWTMEZUM.js";
8
+ } from "../chunk-CWMXXUWU.js";
9
9
 
10
10
  // src/source/path.ts
11
11
  import { parse } from "path";
@@ -0,0 +1,28 @@
1
+ import * as react from 'react';
2
+ import { ReactNode, RefObject, AnchorHTMLAttributes } from 'react';
3
+ import { T as TableOfContents } from './get-toc-B-AMfFKT.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 };
@@ -0,0 +1,79 @@
1
+ import {
2
+ mergeRefs,
3
+ useAnchorObserver
4
+ } from "./chunk-EP2HYVJS.js";
5
+ import {
6
+ __objRest,
7
+ __spreadProps,
8
+ __spreadValues
9
+ } from "./chunk-CWMXXUWU.js";
10
+
11
+ // src/toc-internal.tsx
12
+ import {
13
+ createContext,
14
+ forwardRef,
15
+ useContext,
16
+ useEffect,
17
+ useMemo,
18
+ useRef
19
+ } from "react";
20
+ import scrollIntoView from "scroll-into-view-if-needed";
21
+ import { jsx } from "react/jsx-runtime";
22
+ var ActiveAnchorContext = createContext(void 0);
23
+ var ScrollContext = createContext({ current: null });
24
+ function useActiveAnchor() {
25
+ return useContext(ActiveAnchorContext);
26
+ }
27
+ function ScrollProvider({
28
+ containerRef,
29
+ children
30
+ }) {
31
+ return /* @__PURE__ */ jsx(ScrollContext.Provider, { value: containerRef, children });
32
+ }
33
+ function AnchorProvider({
34
+ toc,
35
+ children
36
+ }) {
37
+ const headings = useMemo(() => {
38
+ return toc.map((item) => item.url.split("#")[1]);
39
+ }, [toc]);
40
+ const activeAnchor = useAnchorObserver(headings);
41
+ return /* @__PURE__ */ jsx(ActiveAnchorContext.Provider, { value: activeAnchor, children });
42
+ }
43
+ var TOCItem = forwardRef(
44
+ (_a, ref) => {
45
+ var _b = _a, { onActiveChange } = _b, props = __objRest(_b, ["onActiveChange"]);
46
+ const containerRef = useContext(ScrollContext);
47
+ const activeAnchor = useActiveAnchor();
48
+ const anchorRef = useRef(null);
49
+ const mergedRef = mergeRefs(anchorRef, ref);
50
+ const isActive = activeAnchor === props.href.split("#")[1];
51
+ const onActiveRef = useRef();
52
+ onActiveRef.current = (active) => {
53
+ const element = anchorRef.current;
54
+ if (!element) return;
55
+ if (active && containerRef.current) {
56
+ scrollIntoView(element, {
57
+ behavior: "smooth",
58
+ block: "center",
59
+ inline: "center",
60
+ scrollMode: "always",
61
+ boundary: containerRef.current
62
+ });
63
+ }
64
+ onActiveChange == null ? void 0 : onActiveChange(active);
65
+ };
66
+ useEffect(() => {
67
+ var _a2;
68
+ (_a2 = onActiveRef.current) == null ? void 0 : _a2.call(onActiveRef, isActive);
69
+ }, [isActive]);
70
+ return /* @__PURE__ */ jsx("a", __spreadProps(__spreadValues({ ref: mergedRef, "data-active": isActive }, props), { children: props.children }));
71
+ }
72
+ );
73
+ TOCItem.displayName = "TOCItem";
74
+ export {
75
+ AnchorProvider,
76
+ ScrollProvider,
77
+ TOCItem,
78
+ useActiveAnchor
79
+ };
package/dist/toc.d.ts CHANGED
@@ -8,13 +8,20 @@ interface TOCProviderProps extends HTMLAttributes<HTMLDivElement> {
8
8
  }
9
9
  declare const TOCProvider: react.ForwardRefExoticComponent<TOCProviderProps & react.RefAttributes<HTMLDivElement>>;
10
10
  interface TOCScrollProvider {
11
- containerRef: RefObject<HTMLElement>;
11
+ /**
12
+ * Scroll into the view of container when active
13
+ */
14
+ containerRef?: RefObject<HTMLElement>;
12
15
  toc: TableOfContents;
13
16
  children: ReactNode;
14
17
  }
15
18
  declare function TOCScrollProvider({ toc, containerRef, children, }: TOCScrollProvider): React.ReactElement;
16
19
  interface TOCItemProps extends AnchorHTMLAttributes<HTMLAnchorElement> {
17
20
  href: string;
21
+ /**
22
+ * Scroll into the view of container when active
23
+ */
24
+ containerRef?: RefObject<HTMLElement>;
18
25
  }
19
26
  declare const TOCItem: react.ForwardRefExoticComponent<TOCItemProps & react.RefAttributes<HTMLAnchorElement>>;
20
27
 
package/dist/toc.js CHANGED
@@ -1,72 +1,25 @@
1
+ import {
2
+ mergeRefs,
3
+ useAnchorObserver
4
+ } from "./chunk-EP2HYVJS.js";
1
5
  import {
2
6
  __objRest,
3
7
  __spreadProps,
4
8
  __spreadValues
5
- } from "./chunk-UWTMEZUM.js";
9
+ } from "./chunk-CWMXXUWU.js";
6
10
 
7
11
  // src/toc.tsx
8
12
  import {
9
13
  createContext,
10
14
  forwardRef,
11
15
  useContext,
12
- useEffect as useEffect2,
16
+ useEffect,
13
17
  useMemo,
14
18
  useRef
15
19
  } from "react";
16
20
  import scrollIntoView from "scroll-into-view-if-needed";
17
-
18
- // src/utils/merge-refs.ts
19
- function mergeRefs(...refs) {
20
- return (value) => {
21
- refs.forEach((ref) => {
22
- if (typeof ref === "function") {
23
- ref(value);
24
- } else if (ref !== null) {
25
- ref.current = value;
26
- }
27
- });
28
- };
29
- }
30
-
31
- // src/utils/use-anchor-observer.ts
32
- import { useEffect, useState } from "react";
33
- function useAnchorObserver(watch) {
34
- const [activeAnchor, setActiveAnchor] = useState();
35
- useEffect(() => {
36
- const observer = new IntersectionObserver(
37
- (entries) => {
38
- setActiveAnchor((f) => {
39
- for (const entry of entries) {
40
- const aboveHalf = window.innerHeight / 2 > entry.boundingClientRect.y;
41
- const active = aboveHalf && entry.isIntersecting;
42
- if (active) {
43
- return entry.target.id;
44
- }
45
- }
46
- return f != null ? f : watch[0];
47
- });
48
- },
49
- { rootMargin: `0% 0% -80% 0%` }
50
- );
51
- for (const heading of watch) {
52
- const element = document.getElementById(heading);
53
- if (element !== null) {
54
- observer.observe(element);
55
- }
56
- }
57
- return () => {
58
- observer.disconnect();
59
- };
60
- }, [watch]);
61
- return activeAnchor;
62
- }
63
-
64
- // src/toc.tsx
65
21
  import { jsx } from "react/jsx-runtime";
66
- var ActiveAnchorContext = createContext({
67
- activeAnchor: void 0,
68
- containerRef: { current: null }
69
- });
22
+ var ActiveAnchorContext = createContext({});
70
23
  var useActiveAnchor = (url) => {
71
24
  const { activeAnchor } = useContext(ActiveAnchorContext);
72
25
  return activeAnchor === url.split("#")[1];
@@ -92,14 +45,15 @@ function TOCScrollProvider({
92
45
  return /* @__PURE__ */ jsx(ActiveAnchorContext.Provider, { value: { containerRef, activeAnchor }, children });
93
46
  }
94
47
  var TOCItem = forwardRef(
95
- (props, ref) => {
96
- const { containerRef } = useContext(ActiveAnchorContext);
48
+ (_a, ref) => {
49
+ var _b = _a, { containerRef: container } = _b, props = __objRest(_b, ["containerRef"]);
50
+ const { containerRef = container } = useContext(ActiveAnchorContext);
97
51
  const active = useActiveAnchor(props.href);
98
52
  const anchorRef = useRef(null);
99
53
  const mergedRef = mergeRefs(anchorRef, ref);
100
- useEffect2(() => {
54
+ useEffect(() => {
101
55
  const element = anchorRef.current;
102
- if (active && element) {
56
+ if (active && element && containerRef) {
103
57
  scrollIntoView(element, {
104
58
  behavior: "smooth",
105
59
  block: "center",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fumadocs-core",
3
- "version": "12.0.1",
3
+ "version": "12.0.3",
4
4
  "description": "The library for building a documentation website in Next.js",
5
5
  "keywords": [
6
6
  "NextJs",
@@ -24,6 +24,10 @@
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
+ },
27
31
  "./search/client": {
28
32
  "import": "./dist/search/client.js",
29
33
  "types": "./dist/search/client.d.ts"
@@ -76,6 +80,9 @@
76
80
  "toc": [
77
81
  "./dist/toc.d.ts"
78
82
  ],
83
+ "toc-internal": [
84
+ "./dist/toc-internal.d.ts"
85
+ ],
79
86
  "search/client": [
80
87
  "./dist/search/client.d.ts"
81
88
  ],
@@ -113,8 +120,8 @@
113
120
  ],
114
121
  "dependencies": {
115
122
  "@formatjs/intl-localematcher": "^0.5.4",
116
- "@shikijs/rehype": "^1.6.3",
117
- "@shikijs/transformers": "^1.6.3",
123
+ "@shikijs/rehype": "^1.6.4",
124
+ "@shikijs/transformers": "^1.6.4",
118
125
  "flexsearch": "0.7.21",
119
126
  "github-slugger": "^2.0.0",
120
127
  "hast-util-to-estree": "^3.1.0",
@@ -125,7 +132,7 @@
125
132
  "remark-gfm": "^4.0.0",
126
133
  "remark-mdx": "^3.0.1",
127
134
  "scroll-into-view-if-needed": "^3.1.0",
128
- "shiki": "^1.6.3",
135
+ "shiki": "^1.6.4",
129
136
  "swr": "^2.2.5",
130
137
  "unist-util-visit": "^5.0.0"
131
138
  },
@@ -141,7 +148,7 @@
141
148
  "@types/react": "^18.3.3",
142
149
  "@types/react-dom": "^18.3.0",
143
150
  "algoliasearch": "^4.23.3",
144
- "next": "^14.2.3",
151
+ "next": "^14.2.4",
145
152
  "unified": "^11.0.4",
146
153
  "eslint-config-custom": "0.0.0",
147
154
  "tsconfig": "0.0.0"
File without changes