fumadocs-core 14.7.7 → 15.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.
@@ -90,7 +90,6 @@ declare function remarkImage({ placeholder, external, useImport, publicDir, }?:
90
90
 
91
91
  interface RemarkAdmonitionOptions {
92
92
  tag?: string;
93
- types?: string[];
94
93
  /**
95
94
  * Map type to another type
96
95
  */
@@ -113,4 +112,6 @@ interface RehypeTocOptions {
113
112
  }
114
113
  declare function rehypeToc(this: Processor, { exportToc }?: RehypeTocOptions): Transformer<Root, Root>;
115
114
 
116
- export { type CodeBlockIcon, type RehypeCodeOptions, type RehypeTocOptions, type RemarkAdmonitionOptions, type RemarkImageOptions, rehypeCode, rehypeCodeDefaultOptions, rehypeToc, remarkAdmonition, remarkImage, transformerIcon, transformerTab };
115
+ declare function remarkCodeTab(): Transformer<Root$1, Root$1>;
116
+
117
+ export { type CodeBlockIcon, type RehypeCodeOptions, type RehypeTocOptions, type RemarkAdmonitionOptions, type RemarkImageOptions, rehypeCode, rehypeCodeDefaultOptions, rehypeToc, remarkAdmonition, remarkCodeTab, remarkImage, transformerIcon, transformerTab };
@@ -492,63 +492,65 @@ function structure(content, remarkPlugins = [], options = {}) {
492
492
  // src/mdx-plugins/remark-admonition.ts
493
493
  import { visit as visit3 } from "unist-util-visit";
494
494
  function remarkAdmonition(options = {}) {
495
- const types = options.types ?? ["warn", "info", "error"];
496
495
  const tag = options.tag ?? ":::";
497
496
  const typeMap = options.typeMap ?? {
497
+ info: "info",
498
+ warn: "warn",
498
499
  note: "info",
499
500
  tip: "info",
500
501
  warning: "warn",
501
502
  danger: "error"
502
503
  };
503
504
  function replaceNodes(nodes) {
504
- if (nodes.length === 0) return nodes;
505
- let open = -1, end = -1;
506
- const attributes = [];
505
+ if (nodes.length === 0) return;
506
+ let open = -1;
507
+ let attributes = [];
508
+ let hasIntercept = false;
507
509
  for (let i = 0; i < nodes.length; i++) {
508
510
  if (nodes[i].type !== "paragraph") continue;
509
511
  const text = flattenNode(nodes[i]);
510
- const start = types.find((type) => text.startsWith(`${tag}${type}`));
511
- if (start) {
512
- if (open !== -1) throw new Error("Nested callout is not supported");
512
+ const typeName = Object.keys(typeMap).find(
513
+ (type) => text.startsWith(`${tag}${type}`)
514
+ );
515
+ if (typeName) {
516
+ if (open !== -1) {
517
+ hasIntercept = true;
518
+ continue;
519
+ }
513
520
  open = i;
514
521
  attributes.push({
515
522
  type: "mdxJsxAttribute",
516
523
  name: "type",
517
- value: start in typeMap ? typeMap[start] : start
524
+ value: typeMap[typeName]
518
525
  });
519
- const rest = text.slice(`${tag}${start}`.length);
520
- if (rest.startsWith("[") && rest.endsWith("]")) {
526
+ const meta = text.slice(`${tag}${typeName}`.length);
527
+ if (meta.startsWith("[") && meta.endsWith("]")) {
521
528
  attributes.push({
522
529
  type: "mdxJsxAttribute",
523
530
  name: "title",
524
- value: rest.slice(1, -1)
531
+ value: meta.slice(1, -1)
525
532
  });
526
533
  }
527
534
  }
528
535
  if (open !== -1 && text === tag) {
529
- end = i;
530
- break;
536
+ const children = nodes.slice(open + 1, i);
537
+ nodes.splice(open, i - open + 1, {
538
+ type: "mdxJsxFlowElement",
539
+ name: "Callout",
540
+ attributes,
541
+ children: hasIntercept ? replaceNodes(children) : children
542
+ });
543
+ open = -1;
544
+ hasIntercept = false;
545
+ attributes = [];
546
+ i = open;
531
547
  }
532
548
  }
533
- if (open === -1 || end === -1) return nodes;
534
- return [
535
- ...nodes.slice(0, open),
536
- {
537
- type: "mdxJsxFlowElement",
538
- name: "Callout",
539
- attributes,
540
- children: nodes.slice(open + 1, end)
541
- },
542
- ...replaceNodes(nodes.slice(end + 1))
543
- ];
544
549
  }
545
550
  return (tree) => {
546
551
  visit3(tree, (node) => {
547
- if (!("children" in node)) return "skip";
548
- const result = replaceNodes(node.children);
549
- if (result === node.children) return;
550
- node.children = result;
551
- return "skip";
552
+ if (!("children" in node)) return;
553
+ replaceNodes(node.children);
552
554
  });
553
555
  };
554
556
  }
@@ -675,11 +677,103 @@ function rehypeToc({ exportToc = true } = {}) {
675
677
  });
676
678
  };
677
679
  }
680
+
681
+ // src/mdx-plugins/remark-code-tab.ts
682
+ import { visit as visit5 } from "unist-util-visit";
683
+ var TabRegex = /tab="(.+?)"/;
684
+ function toTab(nodes) {
685
+ const names = nodes.map((node, i) => {
686
+ let title = `Tab ${i + 1}`;
687
+ node.meta = node.meta?.replace(TabRegex, (_, value) => {
688
+ title = value;
689
+ return "";
690
+ });
691
+ return title;
692
+ });
693
+ const itemsArr = {
694
+ type: "ExpressionStatement",
695
+ expression: {
696
+ type: "ArrayExpression",
697
+ elements: names.map((name) => ({
698
+ type: "Literal",
699
+ value: name
700
+ }))
701
+ }
702
+ };
703
+ return {
704
+ type: "mdxJsxFlowElement",
705
+ name: "Tabs",
706
+ attributes: [
707
+ {
708
+ type: "mdxJsxAttribute",
709
+ name: "items",
710
+ value: {
711
+ type: "mdxJsxAttributeValueExpression",
712
+ data: {
713
+ estree: {
714
+ type: "Program",
715
+ sourceType: "module",
716
+ comments: [],
717
+ body: [itemsArr]
718
+ }
719
+ }
720
+ }
721
+ }
722
+ ],
723
+ children: nodes.map((node, i) => {
724
+ return {
725
+ type: "mdxJsxFlowElement",
726
+ name: "Tab",
727
+ attributes: [
728
+ {
729
+ type: "mdxJsxAttribute",
730
+ name: "value",
731
+ value: names[i]
732
+ }
733
+ ],
734
+ children: [node]
735
+ };
736
+ })
737
+ };
738
+ }
739
+ function remarkCodeTab() {
740
+ return (tree) => {
741
+ visit5(tree, (node) => {
742
+ if (node.type === "mdxJsxFlowElement" && node.name === "Tabs") return;
743
+ if ("children" in node) {
744
+ let start = -1;
745
+ let i = 0;
746
+ while (i < node.children.length) {
747
+ const child = node.children[i];
748
+ const isSwitcher = child.type === "code" && child.meta && child.meta.match(TabRegex);
749
+ if (isSwitcher && start === -1) {
750
+ start = i;
751
+ }
752
+ const isLast = i === node.children.length - 1;
753
+ if (start !== -1 && (isLast || !isSwitcher)) {
754
+ const end = isSwitcher ? i + 1 : i;
755
+ const targets = node.children.slice(start, end);
756
+ node.children.splice(
757
+ start,
758
+ end - start,
759
+ toTab(targets)
760
+ );
761
+ if (isLast) break;
762
+ i = start;
763
+ start = -1;
764
+ }
765
+ i++;
766
+ }
767
+ }
768
+ });
769
+ };
770
+ }
678
771
  export {
679
772
  rehypeCode,
680
773
  rehypeCodeDefaultOptions,
681
774
  rehypeToc,
682
775
  remarkAdmonition,
776
+ remarkCodeTab,
683
777
  default2 as remarkGfm,
684
778
  remarkHeading,
685
779
  remarkImage,
@@ -15,6 +15,7 @@ var group = /^\((?<name>.+)\)$/;
15
15
  var link = /^(?:\[(?<icon>[^\]]+)])?\[(?<name>[^\]]+)]\((?<url>[^)]+)\)$/;
16
16
  var separator = /^---(?<name>.*?)---$/;
17
17
  var rest = "...";
18
+ var restReversed = "z...a";
18
19
  var extractPrefix = "...";
19
20
  var excludePrefix = "!";
20
21
  function isPageFile(node) {
@@ -46,7 +47,7 @@ function buildAll(nodes, ctx, skipIndex) {
46
47
  return output;
47
48
  }
48
49
  function resolveFolderItem(folder, item, ctx, addedNodePaths) {
49
- if (item === rest) return "...";
50
+ if (item === rest || item === restReversed) return item;
50
51
  let match = separator.exec(item);
51
52
  if (match?.groups) {
52
53
  const node = {
@@ -111,8 +112,10 @@ function buildFolderNode(folder, isGlobalRoot, ctx) {
111
112
  !isRoot
112
113
  );
113
114
  const nodes = resolved?.flatMap((item) => {
114
- if (item === "...") {
115
+ if (item === rest) {
115
116
  return restNodes;
117
+ } else if (item === restReversed) {
118
+ return restNodes.reverse();
116
119
  }
117
120
  return item;
118
121
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fumadocs-core",
3
- "version": "14.7.7",
3
+ "version": "15.0.1",
4
4
  "description": "The library for building a documentation website in Next.js",
5
5
  "keywords": [
6
6
  "NextJs",
@@ -79,18 +79,18 @@
79
79
  "dependencies": {
80
80
  "@formatjs/intl-localematcher": "^0.5.10",
81
81
  "@orama/orama": "^2.1.1",
82
- "@shikijs/rehype": "^2.0.3",
83
- "@shikijs/transformers": "^2.0.3",
82
+ "@shikijs/rehype": "^2.2.0",
83
+ "@shikijs/transformers": "^2.2.0",
84
84
  "github-slugger": "^2.0.0",
85
85
  "hast-util-to-estree": "^3.1.1",
86
86
  "hast-util-to-jsx-runtime": "^2.3.2",
87
87
  "image-size": "^1.2.0",
88
88
  "negotiator": "^1.0.0",
89
- "react-remove-scroll": "^2.6.2",
89
+ "react-remove-scroll": "^2.6.3",
90
90
  "remark": "^15.0.0",
91
91
  "remark-gfm": "^4.0.0",
92
92
  "scroll-into-view-if-needed": "^3.1.0",
93
- "shiki": "^2.0.3",
93
+ "shiki": "^2.2.0",
94
94
  "unist-util-visit": "^5.0.0"
95
95
  },
96
96
  "devDependencies": {
@@ -102,13 +102,13 @@
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.10.7",
106
- "@types/react": "^19.0.7",
105
+ "@types/node": "22.13.0",
106
+ "@types/react": "^19.0.8",
107
107
  "@types/react-dom": "^19.0.3",
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.1.5",
111
+ "next": "^15.1.6",
112
112
  "remark-mdx": "^3.1.0",
113
113
  "remark-rehype": "^11.1.1",
114
114
  "typescript": "^5.7.3",