fumadocs-core 15.3.1 → 15.3.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.
@@ -112,7 +112,15 @@ interface RehypeTocOptions {
112
112
  }
113
113
  declare function rehypeToc(this: Processor, { exportToc }?: RehypeTocOptions): Transformer<Root, Root>;
114
114
 
115
- declare function remarkCodeTab(): Transformer<Root$1, Root$1>;
115
+ interface RemarkCodeTabOptions {
116
+ /**
117
+ * Parse MDX in tab values
118
+ *
119
+ * @defaultValue false
120
+ */
121
+ parseMdx?: boolean;
122
+ }
123
+ declare function remarkCodeTab(this: Processor, options?: RemarkCodeTabOptions): Transformer<Root$1, Root$1>;
116
124
 
117
125
  interface RemarkStepsOptions {
118
126
  /**
@@ -133,4 +141,4 @@ interface RemarkStepsOptions {
133
141
  */
134
142
  declare function remarkSteps({ steps, step, }?: RemarkStepsOptions): Transformer<Root$1, Root$1>;
135
143
 
136
- export { type CodeBlockIcon, type RehypeCodeOptions, type RehypeTocOptions, type RemarkAdmonitionOptions, type RemarkImageOptions, type RemarkStepsOptions, rehypeCode, rehypeCodeDefaultOptions, rehypeToc, remarkAdmonition, remarkCodeTab, remarkImage, remarkSteps, transformerIcon, transformerTab };
144
+ export { type CodeBlockIcon, type RehypeCodeOptions, type RehypeTocOptions, type RemarkAdmonitionOptions, type RemarkCodeTabOptions, type RemarkImageOptions, type RemarkStepsOptions, rehypeCode, rehypeCodeDefaultOptions, rehypeToc, remarkAdmonition, remarkCodeTab, remarkImage, remarkSteps, transformerIcon, transformerTab };
@@ -21,6 +21,7 @@ import {
21
21
  import rehypeShikiFromHighlighter from "@shikijs/rehype/core";
22
22
  import {
23
23
  transformerNotationDiff,
24
+ transformerNotationFocus,
24
25
  transformerNotationHighlight,
25
26
  transformerNotationWordHighlight
26
27
  } from "@shikijs/transformers";
@@ -209,6 +210,9 @@ var rehypeCodeDefaultOptions = {
209
210
  }),
210
211
  transformerNotationDiff({
211
212
  matchAlgorithm: "v3"
213
+ }),
214
+ transformerNotationFocus({
215
+ matchAlgorithm: "v3"
212
216
  })
213
217
  ],
214
218
  parseMetaString(meta) {
@@ -297,7 +301,7 @@ function transformerTab() {
297
301
  }
298
302
 
299
303
  // src/mdx-plugins/remark-image.ts
300
- import * as path from "node:path";
304
+ import * as path from "path";
301
305
  import { visit } from "unist-util-visit";
302
306
  import { imageSize } from "image-size";
303
307
  import { imageSizeFromFile } from "image-size/fromFile";
@@ -757,8 +761,40 @@ function rehypeToc({ exportToc = true } = {}) {
757
761
  // src/mdx-plugins/remark-code-tab.ts
758
762
  import { visit as visit5 } from "unist-util-visit";
759
763
  var TabRegex = /tab="(.+?)"/;
760
- function toTab(nodes) {
761
- const names = nodes.map((node, i) => {
764
+ function remarkCodeTab(options = {}) {
765
+ return (tree) => {
766
+ visit5(tree, (node) => {
767
+ if (!("children" in node)) return;
768
+ if (node.type === "mdxJsxFlowElement" && node.name === "Tabs") return;
769
+ let start = -1;
770
+ let i = 0;
771
+ while (i < node.children.length) {
772
+ const child = node.children[i];
773
+ const isSwitcher = child.type === "code" && child.meta && child.meta.match(TabRegex);
774
+ if (isSwitcher && start === -1) {
775
+ start = i;
776
+ }
777
+ const isLast = i === node.children.length - 1;
778
+ if (start !== -1 && (isLast || !isSwitcher)) {
779
+ const end = isSwitcher ? i + 1 : i;
780
+ const targets = node.children.slice(start, end);
781
+ node.children.splice(
782
+ start,
783
+ end - start,
784
+ options.parseMdx ? toTabMdx(this, targets) : toTab(targets)
785
+ );
786
+ if (isLast) break;
787
+ i = start + 1;
788
+ start = -1;
789
+ } else {
790
+ i++;
791
+ }
792
+ }
793
+ });
794
+ };
795
+ }
796
+ function processTabValue(nodes) {
797
+ return nodes.map((node, i) => {
762
798
  let title = `Tab ${i + 1}`;
763
799
  node.meta = node.meta?.replace(TabRegex, (_, value) => {
764
800
  title = value;
@@ -766,16 +802,9 @@ function toTab(nodes) {
766
802
  });
767
803
  return title;
768
804
  });
769
- const itemsArr = {
770
- type: "ExpressionStatement",
771
- expression: {
772
- type: "ArrayExpression",
773
- elements: names.map((name) => ({
774
- type: "Literal",
775
- value: name
776
- }))
777
- }
778
- };
805
+ }
806
+ function toTab(nodes) {
807
+ const names = processTabValue(nodes);
779
808
  return {
780
809
  type: "mdxJsxFlowElement",
781
810
  name: "Tabs",
@@ -785,12 +814,24 @@ function toTab(nodes) {
785
814
  name: "items",
786
815
  value: {
787
816
  type: "mdxJsxAttributeValueExpression",
817
+ value: names.join(", "),
788
818
  data: {
789
819
  estree: {
790
820
  type: "Program",
791
821
  sourceType: "module",
792
822
  comments: [],
793
- body: [itemsArr]
823
+ body: [
824
+ {
825
+ type: "ExpressionStatement",
826
+ expression: {
827
+ type: "ArrayExpression",
828
+ elements: names.map((name) => ({
829
+ type: "Literal",
830
+ value: name
831
+ }))
832
+ }
833
+ }
834
+ ]
794
835
  }
795
836
  }
796
837
  }
@@ -812,35 +853,63 @@ function toTab(nodes) {
812
853
  })
813
854
  };
814
855
  }
815
- function remarkCodeTab() {
816
- return (tree) => {
817
- visit5(tree, (node) => {
818
- if (!("children" in node)) return;
819
- if (node.type === "mdxJsxFlowElement" && node.name === "Tabs") return;
820
- let start = -1;
821
- let i = 0;
822
- while (i < node.children.length) {
823
- const child = node.children[i];
824
- const isSwitcher = child.type === "code" && child.meta && child.meta.match(TabRegex);
825
- if (isSwitcher && start === -1) {
826
- start = i;
827
- }
828
- const isLast = i === node.children.length - 1;
829
- if (start !== -1 && (isLast || !isSwitcher)) {
830
- const end = isSwitcher ? i + 1 : i;
831
- const targets = node.children.slice(start, end);
832
- node.children.splice(
833
- start,
834
- end - start,
835
- toTab(targets)
836
- );
837
- if (isLast) break;
838
- i = start;
839
- start = -1;
840
- }
841
- i++;
856
+ function toTabMdx(processor, nodes) {
857
+ const names = processTabValue(nodes);
858
+ function inline(node) {
859
+ if (node.type === "root") {
860
+ node.children = node.children.flatMap((child) => {
861
+ if (child.type === "paragraph") return child.children;
862
+ return child;
863
+ });
864
+ }
865
+ return node;
866
+ }
867
+ return {
868
+ type: "mdxJsxFlowElement",
869
+ name: "Tabs",
870
+ attributes: [
871
+ {
872
+ type: "mdxJsxAttribute",
873
+ name: "defaultValue",
874
+ value: names[0]
842
875
  }
843
- });
876
+ ],
877
+ children: [
878
+ {
879
+ type: "mdxJsxFlowElement",
880
+ name: "TabsList",
881
+ attributes: [],
882
+ children: names.map((name) => ({
883
+ type: "mdxJsxFlowElement",
884
+ name: "TabsTrigger",
885
+ attributes: [
886
+ {
887
+ type: "mdxJsxAttribute",
888
+ name: "value",
889
+ value: name
890
+ }
891
+ ],
892
+ children: [
893
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- needed
894
+ inline(processor.parse(name))
895
+ ]
896
+ }))
897
+ },
898
+ ...nodes.map(
899
+ (node, i) => ({
900
+ type: "mdxJsxFlowElement",
901
+ name: "TabsContent",
902
+ attributes: [
903
+ {
904
+ type: "mdxJsxAttribute",
905
+ name: "value",
906
+ value: names[i]
907
+ }
908
+ ],
909
+ children: [node]
910
+ })
911
+ )
912
+ ]
844
913
  };
845
914
  }
846
915
 
package/dist/toc.js CHANGED
@@ -46,8 +46,9 @@ function useAnchorObserver(watch, single) {
46
46
  function onScroll() {
47
47
  const element = document.scrollingElement;
48
48
  if (!element) return;
49
- if (element.scrollTop === 0 && single) setActiveAnchor(watch.slice(0, 1));
50
- else if (element.scrollTop + element.clientHeight >= element.scrollHeight - 6) {
49
+ const top = element.scrollTop;
50
+ if (top <= 0 && single) setActiveAnchor(watch.slice(0, 1));
51
+ else if (top + element.clientHeight >= element.scrollHeight - 6) {
51
52
  setActiveAnchor((active) => {
52
53
  return active.length > 0 && !single ? watch.slice(watch.indexOf(active[0])) : watch.slice(-1);
53
54
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fumadocs-core",
3
- "version": "15.3.1",
3
+ "version": "15.3.3",
4
4
  "description": "The library for building a documentation website in Next.js",
5
5
  "keywords": [
6
6
  "NextJs",
@@ -79,8 +79,8 @@
79
79
  "dependencies": {
80
80
  "@formatjs/intl-localematcher": "^0.6.1",
81
81
  "@orama/orama": "^3.1.6",
82
- "@shikijs/rehype": "^3.4.0",
83
- "@shikijs/transformers": "^3.4.0",
82
+ "@shikijs/rehype": "^3.4.2",
83
+ "@shikijs/transformers": "^3.4.2",
84
84
  "github-slugger": "^2.0.0",
85
85
  "hast-util-to-estree": "^3.1.3",
86
86
  "hast-util-to-jsx-runtime": "^2.3.6",
@@ -90,26 +90,26 @@
90
90
  "remark": "^15.0.0",
91
91
  "remark-gfm": "^4.0.1",
92
92
  "scroll-into-view-if-needed": "^3.1.0",
93
- "shiki": "^3.4.0",
93
+ "shiki": "^3.4.2",
94
94
  "unist-util-visit": "^5.0.0"
95
95
  },
96
96
  "devDependencies": {
97
97
  "@algolia/client-search": "4.24.0",
98
98
  "@mdx-js/mdx": "^3.1.0",
99
99
  "@oramacloud/client": "^2.1.4",
100
- "@tanstack/react-router": "^1.119.0",
100
+ "@tanstack/react-router": "^1.120.3",
101
101
  "@types/estree-jsx": "^1.0.5",
102
102
  "@types/hast": "^3.0.4",
103
103
  "@types/mdast": "^4.0.3",
104
104
  "@types/negotiator": "^0.6.3",
105
- "@types/node": "22.15.12",
106
- "@types/react": "^19.1.3",
107
- "@types/react-dom": "^19.1.3",
105
+ "@types/node": "22.15.18",
106
+ "@types/react": "^19.1.4",
107
+ "@types/react-dom": "^19.1.5",
108
108
  "algoliasearch": "4.24.0",
109
109
  "mdast-util-mdx-jsx": "^3.2.0",
110
110
  "mdast-util-mdxjs-esm": "^2.0.1",
111
- "next": "^15.3.1",
112
- "react-router": "^7.5.3",
111
+ "next": "^15.3.2",
112
+ "react-router": "^7.6.0",
113
113
  "remark-mdx": "^3.1.0",
114
114
  "remark-rehype": "^11.1.2",
115
115
  "typescript": "^5.8.3",