docstra 1.4.0 → 1.4.6

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.
package/README.md CHANGED
@@ -25,19 +25,50 @@ npm install docstra
25
25
 
26
26
  ```ts
27
27
  // docstra.config.ts
28
+ import { defineDocstraConfig } from 'docstra/config';
29
+
28
30
  export default defineDocstraConfig({
29
- siteName: 'Docstra Site',
30
- githubRepo: 'https://github.com/sudhucodes/test',
31
+ siteName: 'Docstra',
32
+ githubRepo: 'https://github.com/sudhucodes/docstra',
31
33
  editOnGithub: true,
32
- formSyncFormID: 'FORM_ID',
34
+ feedback: {
35
+ enabled: true,
36
+ formSyncFormID: 'FORM_ID'
37
+ },
33
38
  navbar: {
34
39
  logo: {
35
- link: '/docs'
40
+ link: '/docs',
41
+ src: '/logo.svg',
42
+ alt: 'Logo',
43
+ className: 'h-9.5 w-auto'
36
44
  },
37
- links: [{ name: 'Guides', href: '/docs/guides' }]
45
+ links: [
46
+ { name: 'Guides', href: '/docs/guides' },
47
+ { name: 'Examples', href: '/docs/examples' }
48
+ ]
38
49
  },
39
50
  sidebar: {
40
- // sidebar links
51
+ links: [
52
+ {
53
+ section: 'Introduction',
54
+ items: [
55
+ {
56
+ name: 'Overview',
57
+ href: '/docs',
58
+ icon: 'NotebookPenIcon'
59
+ },
60
+ {
61
+ name: 'Quick Start',
62
+ href: '/docs/quick-start',
63
+ icon: 'RocketIcon'
64
+ }
65
+ ]
66
+ },
67
+ {
68
+ section: 'Tailwind Setup',
69
+ items: [{ name: 'Installation', href: '/docs/setup/installation' }]
70
+ }
71
+ ]
41
72
  }
42
73
  });
43
74
  ```
@@ -23,7 +23,6 @@ interface DocstraConfig {
23
23
  formSyncFormID?: string;
24
24
  watermark?: boolean;
25
25
  };
26
- formSyncFormID?: string;
27
26
  githubRepo?: string;
28
27
  navbar?: {
29
28
  logo?: {
@@ -71,10 +70,7 @@ interface Props {
71
70
  }
72
71
  declare function DocstraBody({ children }: Props): react_jsx_runtime.JSX.Element;
73
72
 
74
- declare function DocstraTOC({ mdxFilePath, rawMdxContent }: {
75
- mdxFilePath: string;
76
- rawMdxContent: string;
77
- }): react_jsx_runtime.JSX.Element;
73
+ declare function DocstraTOC(): react_jsx_runtime.JSX.Element;
78
74
 
79
75
  declare function DocstraCodeBlock(props: any): react_jsx_runtime.JSX.Element;
80
76
 
@@ -23,7 +23,6 @@ interface DocstraConfig {
23
23
  formSyncFormID?: string;
24
24
  watermark?: boolean;
25
25
  };
26
- formSyncFormID?: string;
27
26
  githubRepo?: string;
28
27
  navbar?: {
29
28
  logo?: {
@@ -71,10 +70,7 @@ interface Props {
71
70
  }
72
71
  declare function DocstraBody({ children }: Props): react_jsx_runtime.JSX.Element;
73
72
 
74
- declare function DocstraTOC({ mdxFilePath, rawMdxContent }: {
75
- mdxFilePath: string;
76
- rawMdxContent: string;
77
- }): react_jsx_runtime.JSX.Element;
73
+ declare function DocstraTOC(): react_jsx_runtime.JSX.Element;
78
74
 
79
75
  declare function DocstraCodeBlock(props: any): react_jsx_runtime.JSX.Element;
80
76
 
@@ -107,7 +107,7 @@ function DocstraSearchBox() {
107
107
  {
108
108
  className: "w-full bg-transparent h-full outline-none text-gray-400 placeholder:text-gray-400",
109
109
  type: "text",
110
- placeholder: "Search components",
110
+ placeholder: "Search docs...",
111
111
  spellCheck: "false",
112
112
  autoFocus: true,
113
113
  value: searchQuery,
@@ -587,7 +587,7 @@ function DocstraPagination() {
587
587
  import_link5.default,
588
588
  {
589
589
  href: prev.href,
590
- className: "flex flex-col items-start gap-2 hover:bg-gray-100 py-3 md:min-w-52 pl-4 pr-10 rounded-lg text-sm",
590
+ className: "flex flex-col items-start gap-2 border border-gray-200 hover:bg-gray-50 py-3 md:min-w-62 pl-4 pr-10 rounded-lg text-sm",
591
591
  children: [
592
592
  /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "text-gray-500", children: "Previous" }),
593
593
  /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("p", { className: "flex items-center font-medium", children: [
@@ -601,7 +601,7 @@ function DocstraPagination() {
601
601
  import_link5.default,
602
602
  {
603
603
  href: next.href,
604
- className: "flex flex-col items-end gap-2 hover:bg-gray-100 py-3 pr-4 md:min-w-52 pl-10 rounded-lg text-sm",
604
+ className: "flex flex-col items-end gap-2 border border-gray-200 hover:bg-gray-50 py-3 pr-4 md:min-w-62 pl-10 rounded-lg text-sm",
605
605
  children: [
606
606
  /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "text-gray-500", children: "Next" }),
607
607
  /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("p", { className: "flex items-center font-medium", children: [
@@ -663,13 +663,14 @@ function extractHeadingsFromMdx(raw) {
663
663
 
664
664
  // src/client/docstra-toc.tsx
665
665
  var import_jsx_runtime15 = require("react/jsx-runtime");
666
- function DocstraTOC({ mdxFilePath, rawMdxContent }) {
666
+ function DocstraTOC() {
667
667
  const [headings, setHeadings] = (0, import_react6.useState)([]);
668
668
  const [activeId, setActiveId] = (0, import_react6.useState)(null);
669
669
  const [scrollDir, setScrollDir] = (0, import_react6.useState)("down");
670
670
  const [isScrolled, setIsScrolled] = (0, import_react6.useState)(false);
671
671
  const [isManualClick, setIsManualClick] = (0, import_react6.useState)(false);
672
- const { docstraConfig } = useDocstra();
672
+ const { docstraConfig, mdxData } = useDocstra();
673
+ const { mdxFilePath, rawMdxContent } = mdxData;
673
674
  const lastScrollY = (0, import_react6.useRef)(0);
674
675
  const observerRef = (0, import_react6.useRef)(null);
675
676
  const pathname = (0, import_navigation4.usePathname)();
@@ -807,12 +808,8 @@ var import_lucide_react10 = require("lucide-react");
807
808
  var import_react_toast_msg3 = require("react-toast-msg");
808
809
  var import_jsx_runtime16 = require("react/jsx-runtime");
809
810
  function DocstraCodeBlock(props) {
810
- const { className, children } = props.children?.props || props;
811
- if (!className || !className.startsWith("language-")) {
812
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("code", { className: "px-1 py-0.5 rounded border border-gray-200 text-gray-800 text-sm", children });
813
- }
814
- const language = className.replace("language-", "") || "text";
815
- const code = typeof children === "string" ? children.trim() : Array.isArray(children) ? children.join("").trim() : "";
811
+ const { language, title, children } = props;
812
+ const code = typeof children === "string" ? children.trim() : children?.props?.children?.toString()?.trim() || "";
816
813
  const [copied, setCopied] = (0, import_react7.useState)(false);
817
814
  const handleCopy = () => {
818
815
  navigator.clipboard.writeText(code);
@@ -827,7 +824,7 @@ function DocstraCodeBlock(props) {
827
824
  }, [copied]);
828
825
  return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "max-w-2xl overflow-hidden rounded-lg text-sm text-gray-800 border border-gray-200/80 mt-4", children: [
829
826
  /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex items-center bg-gray-50 justify-between border-b border-gray-200/80", children: [
830
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "text-xs text-gray-400 p-4", children: language }),
827
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "text-xs text-gray-400 p-4", children: title || language }),
831
828
  /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
832
829
  "button",
833
830
  {
@@ -65,7 +65,7 @@ function DocstraSearchBox() {
65
65
  {
66
66
  className: "w-full bg-transparent h-full outline-none text-gray-400 placeholder:text-gray-400",
67
67
  type: "text",
68
- placeholder: "Search components",
68
+ placeholder: "Search docs...",
69
69
  spellCheck: "false",
70
70
  autoFocus: true,
71
71
  value: searchQuery,
@@ -545,7 +545,7 @@ function DocstraPagination() {
545
545
  Link2,
546
546
  {
547
547
  href: prev.href,
548
- className: "flex flex-col items-start gap-2 hover:bg-gray-100 py-3 md:min-w-52 pl-4 pr-10 rounded-lg text-sm",
548
+ className: "flex flex-col items-start gap-2 border border-gray-200 hover:bg-gray-50 py-3 md:min-w-62 pl-4 pr-10 rounded-lg text-sm",
549
549
  children: [
550
550
  /* @__PURE__ */ jsx13("span", { className: "text-gray-500", children: "Previous" }),
551
551
  /* @__PURE__ */ jsxs10("p", { className: "flex items-center font-medium", children: [
@@ -559,7 +559,7 @@ function DocstraPagination() {
559
559
  Link2,
560
560
  {
561
561
  href: next.href,
562
- className: "flex flex-col items-end gap-2 hover:bg-gray-100 py-3 pr-4 md:min-w-52 pl-10 rounded-lg text-sm",
562
+ className: "flex flex-col items-end gap-2 border border-gray-200 hover:bg-gray-50 py-3 pr-4 md:min-w-62 pl-10 rounded-lg text-sm",
563
563
  children: [
564
564
  /* @__PURE__ */ jsx13("span", { className: "text-gray-500", children: "Next" }),
565
565
  /* @__PURE__ */ jsxs10("p", { className: "flex items-center font-medium", children: [
@@ -621,13 +621,14 @@ function extractHeadingsFromMdx(raw) {
621
621
 
622
622
  // src/client/docstra-toc.tsx
623
623
  import { jsx as jsx15, jsxs as jsxs12 } from "react/jsx-runtime";
624
- function DocstraTOC({ mdxFilePath, rawMdxContent }) {
624
+ function DocstraTOC() {
625
625
  const [headings, setHeadings] = useState5([]);
626
626
  const [activeId, setActiveId] = useState5(null);
627
627
  const [scrollDir, setScrollDir] = useState5("down");
628
628
  const [isScrolled, setIsScrolled] = useState5(false);
629
629
  const [isManualClick, setIsManualClick] = useState5(false);
630
- const { docstraConfig } = useDocstra();
630
+ const { docstraConfig, mdxData } = useDocstra();
631
+ const { mdxFilePath, rawMdxContent } = mdxData;
631
632
  const lastScrollY = useRef(0);
632
633
  const observerRef = useRef(null);
633
634
  const pathname = usePathname4();
@@ -765,12 +766,8 @@ import { CheckIcon as CheckIcon2, CopyIcon as CopyIcon2 } from "lucide-react";
765
766
  import { toast as toast2 } from "react-toast-msg";
766
767
  import { jsx as jsx16, jsxs as jsxs13 } from "react/jsx-runtime";
767
768
  function DocstraCodeBlock(props) {
768
- const { className, children } = props.children?.props || props;
769
- if (!className || !className.startsWith("language-")) {
770
- return /* @__PURE__ */ jsx16("code", { className: "px-1 py-0.5 rounded border border-gray-200 text-gray-800 text-sm", children });
771
- }
772
- const language = className.replace("language-", "") || "text";
773
- const code = typeof children === "string" ? children.trim() : Array.isArray(children) ? children.join("").trim() : "";
769
+ const { language, title, children } = props;
770
+ const code = typeof children === "string" ? children.trim() : children?.props?.children?.toString()?.trim() || "";
774
771
  const [copied, setCopied] = useState6(false);
775
772
  const handleCopy = () => {
776
773
  navigator.clipboard.writeText(code);
@@ -785,7 +782,7 @@ function DocstraCodeBlock(props) {
785
782
  }, [copied]);
786
783
  return /* @__PURE__ */ jsxs13("div", { className: "max-w-2xl overflow-hidden rounded-lg text-sm text-gray-800 border border-gray-200/80 mt-4", children: [
787
784
  /* @__PURE__ */ jsxs13("div", { className: "flex items-center bg-gray-50 justify-between border-b border-gray-200/80", children: [
788
- /* @__PURE__ */ jsx16("div", { className: "text-xs text-gray-400 p-4", children: language }),
785
+ /* @__PURE__ */ jsx16("span", { className: "text-xs text-gray-400 p-4", children: title || language }),
789
786
  /* @__PURE__ */ jsx16(
790
787
  "button",
791
788
  {
@@ -8,7 +8,6 @@ interface DocstraConfig {
8
8
  formSyncFormID?: string;
9
9
  watermark?: boolean;
10
10
  };
11
- formSyncFormID?: string;
12
11
  githubRepo?: string;
13
12
  navbar?: {
14
13
  logo?: {
@@ -54,7 +53,7 @@ declare function getFileContents({ slug, CONTENT_DIR }: {
54
53
 
55
54
  declare function defineDocstraConfig<T extends DocstraConfig>(config: T): T;
56
55
 
57
- declare function DocstraMDXCompiler({ mdxContent, components }: {
56
+ declare function DocstraMDXCompiler({ mdxContent, components, }: {
58
57
  mdxContent: string;
59
58
  components?: Record<string, any>;
60
59
  }): react_jsx_runtime.JSX.Element;
@@ -8,7 +8,6 @@ interface DocstraConfig {
8
8
  formSyncFormID?: string;
9
9
  watermark?: boolean;
10
10
  };
11
- formSyncFormID?: string;
12
11
  githubRepo?: string;
13
12
  navbar?: {
14
13
  logo?: {
@@ -54,7 +53,7 @@ declare function getFileContents({ slug, CONTENT_DIR }: {
54
53
 
55
54
  declare function defineDocstraConfig<T extends DocstraConfig>(config: T): T;
56
55
 
57
- declare function DocstraMDXCompiler({ mdxContent, components }: {
56
+ declare function DocstraMDXCompiler({ mdxContent, components, }: {
58
57
  mdxContent: string;
59
58
  components?: Record<string, any>;
60
59
  }): react_jsx_runtime.JSX.Element;
@@ -81,9 +81,6 @@ function defineDocstraConfig(config) {
81
81
  // src/server/mdx-compiler.tsx
82
82
  var import_rsc = require("next-mdx-remote/rsc");
83
83
 
84
- // src/client/mdx-components.tsx
85
- var import_link = __toESM(require("next/link"));
86
-
87
84
  // src/client/create-heading.tsx
88
85
  var import_lucide_react = require("lucide-react");
89
86
 
@@ -134,39 +131,79 @@ function CreateHeading({ children, level }) {
134
131
  );
135
132
  }
136
133
 
137
- // src/client/mdx-components.tsx
134
+ // src/client/link.tsx
135
+ var import_link = __toESM(require("next/link"));
138
136
  var import_jsx_runtime2 = require("react/jsx-runtime");
137
+ function Link({ href, children, className, onNavigate, ...props }) {
138
+ if (href.startsWith("http")) {
139
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("a", { href, className, ...props, target: "_blank", rel: "noopener noreferrer", children });
140
+ }
141
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_link.default, { href, className, onNavigate, ...props, "aria-label": "Ns", children });
142
+ }
143
+
144
+ // src/client/mdx-components.tsx
145
+ var import_jsx_runtime3 = require("react/jsx-runtime");
139
146
  var defaultMdxComponents = {
140
- h1: (props) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h1", { className: "text-3xl font-bold text-gray-900 mb-4", children: props.children }),
141
- h2: (props) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(CreateHeading, { ...props, level: 2 }),
142
- h3: (props) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(CreateHeading, { ...props, level: 3 }),
143
- h4: (props) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(CreateHeading, { ...props, level: 4 }),
144
- h5: (props) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(CreateHeading, { ...props, level: 5 }),
145
- p: (props) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "my-5", children: props.children }),
146
- hr: () => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("hr", { className: "my-10 border-gray-200" }),
147
- a: (props) => props.href.startsWith("/") ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_link.default, { className: "underline underline-offset-4", href: props.href, children: props.children }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("a", { className: "underline underline-offset-4", href: props.href, children: props.children }),
148
- ul: (props) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("ul", { className: "list-['-'] pl-4 space-y-2", children: props.children }),
149
- li: (props) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("li", { className: "mb-2 pl-3 text-gray-700", children: props.children }),
150
- ol: (props) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("ol", { className: "list-decimal pl-4 space-y-2", children: props.children }),
151
- blockquote: (props) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("blockquote", { className: "border-l-4 border-gray-200 pl-4 my-8 text-gray-700", children: props.children })
147
+ h1: (props) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h1", { className: "text-3xl font-bold text-gray-900 mb-4", children: props.children }),
148
+ h2: (props) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(CreateHeading, { ...props, level: 2 }),
149
+ h3: (props) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(CreateHeading, { ...props, level: 3 }),
150
+ h4: (props) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(CreateHeading, { ...props, level: 4 }),
151
+ h5: (props) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(CreateHeading, { ...props, level: 5 }),
152
+ code: (props) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("code", { className: "px-1 py-0.5 rounded border border-gray-200 text-gray-800 text-sm", children: props.children }),
153
+ p: (props) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "my-5", children: props.children }),
154
+ hr: () => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("hr", { className: "my-10 border-gray-200" }),
155
+ a: (props) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Link, { href: props.href, children: props.children }),
156
+ ul: (props) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("ul", { className: "list-['-'] pl-4 space-y-2", children: props.children }),
157
+ li: (props) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("li", { className: "mb-2 pl-3 text-gray-700", children: props.children }),
158
+ ol: (props) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("ol", { className: "list-decimal pl-4 space-y-2", children: props.children }),
159
+ blockquote: (props) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("blockquote", { className: "border-l-4 border-gray-200 pl-4 my-8 text-gray-700", children: props.children })
152
160
  };
153
161
 
162
+ // src/plugins/rehype-code-meta.ts
163
+ var import_unist_util_visit = require("unist-util-visit");
164
+ function rehypeCodeMetaProps() {
165
+ return (tree) => {
166
+ (0, import_unist_util_visit.visit)(tree, "element", (node) => {
167
+ if (node.tagName !== "pre") return;
168
+ const code = node.children?.[0];
169
+ if (!code || code.tagName !== "code") return;
170
+ const className = code.properties?.className?.[0];
171
+ const language = className?.replace("language-", "");
172
+ const meta = code.data?.meta || "";
173
+ const metaProps = {};
174
+ meta.replace(
175
+ /(\w+)=["']?([^"'\s]+)["']?/g,
176
+ (_match, key, value) => {
177
+ metaProps[key] = value;
178
+ return "";
179
+ }
180
+ );
181
+ node.properties = { ...node.properties || {}, language, ...metaProps };
182
+ });
183
+ };
184
+ }
185
+
154
186
  // src/server/mdx-compiler.tsx
155
- var import_jsx_runtime3 = require("react/jsx-runtime");
187
+ var import_jsx_runtime4 = require("react/jsx-runtime");
156
188
  function DocstraMDXCompiler({
157
189
  mdxContent,
158
190
  components = {}
159
191
  }) {
160
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
192
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
161
193
  import_rsc.MDXRemote,
162
194
  {
163
195
  source: mdxContent,
164
196
  components: {
165
197
  ...defaultMdxComponents,
166
198
  ...components
199
+ },
200
+ options: {
201
+ mdxOptions: {
202
+ rehypePlugins: [rehypeCodeMetaProps]
203
+ }
167
204
  }
168
205
  }
169
- ) });
206
+ );
170
207
  }
171
208
  // Annotate the CommonJS export names for ESM import in node:
172
209
  0 && (module.exports = {
@@ -42,9 +42,6 @@ function defineDocstraConfig(config) {
42
42
  // src/server/mdx-compiler.tsx
43
43
  import { MDXRemote } from "next-mdx-remote/rsc";
44
44
 
45
- // src/client/mdx-components.tsx
46
- import Link from "next/link";
47
-
48
45
  // src/client/create-heading.tsx
49
46
  import { LinkIcon } from "lucide-react";
50
47
 
@@ -95,39 +92,79 @@ function CreateHeading({ children, level }) {
95
92
  );
96
93
  }
97
94
 
98
- // src/client/mdx-components.tsx
95
+ // src/client/link.tsx
96
+ import LinkComponent from "next/link";
99
97
  import { jsx as jsx2 } from "react/jsx-runtime";
98
+ function Link({ href, children, className, onNavigate, ...props }) {
99
+ if (href.startsWith("http")) {
100
+ return /* @__PURE__ */ jsx2("a", { href, className, ...props, target: "_blank", rel: "noopener noreferrer", children });
101
+ }
102
+ return /* @__PURE__ */ jsx2(LinkComponent, { href, className, onNavigate, ...props, "aria-label": "Ns", children });
103
+ }
104
+
105
+ // src/client/mdx-components.tsx
106
+ import { jsx as jsx3 } from "react/jsx-runtime";
100
107
  var defaultMdxComponents = {
101
- h1: (props) => /* @__PURE__ */ jsx2("h1", { className: "text-3xl font-bold text-gray-900 mb-4", children: props.children }),
102
- h2: (props) => /* @__PURE__ */ jsx2(CreateHeading, { ...props, level: 2 }),
103
- h3: (props) => /* @__PURE__ */ jsx2(CreateHeading, { ...props, level: 3 }),
104
- h4: (props) => /* @__PURE__ */ jsx2(CreateHeading, { ...props, level: 4 }),
105
- h5: (props) => /* @__PURE__ */ jsx2(CreateHeading, { ...props, level: 5 }),
106
- p: (props) => /* @__PURE__ */ jsx2("p", { className: "my-5", children: props.children }),
107
- hr: () => /* @__PURE__ */ jsx2("hr", { className: "my-10 border-gray-200" }),
108
- a: (props) => props.href.startsWith("/") ? /* @__PURE__ */ jsx2(Link, { className: "underline underline-offset-4", href: props.href, children: props.children }) : /* @__PURE__ */ jsx2("a", { className: "underline underline-offset-4", href: props.href, children: props.children }),
109
- ul: (props) => /* @__PURE__ */ jsx2("ul", { className: "list-['-'] pl-4 space-y-2", children: props.children }),
110
- li: (props) => /* @__PURE__ */ jsx2("li", { className: "mb-2 pl-3 text-gray-700", children: props.children }),
111
- ol: (props) => /* @__PURE__ */ jsx2("ol", { className: "list-decimal pl-4 space-y-2", children: props.children }),
112
- blockquote: (props) => /* @__PURE__ */ jsx2("blockquote", { className: "border-l-4 border-gray-200 pl-4 my-8 text-gray-700", children: props.children })
108
+ h1: (props) => /* @__PURE__ */ jsx3("h1", { className: "text-3xl font-bold text-gray-900 mb-4", children: props.children }),
109
+ h2: (props) => /* @__PURE__ */ jsx3(CreateHeading, { ...props, level: 2 }),
110
+ h3: (props) => /* @__PURE__ */ jsx3(CreateHeading, { ...props, level: 3 }),
111
+ h4: (props) => /* @__PURE__ */ jsx3(CreateHeading, { ...props, level: 4 }),
112
+ h5: (props) => /* @__PURE__ */ jsx3(CreateHeading, { ...props, level: 5 }),
113
+ code: (props) => /* @__PURE__ */ jsx3("code", { className: "px-1 py-0.5 rounded border border-gray-200 text-gray-800 text-sm", children: props.children }),
114
+ p: (props) => /* @__PURE__ */ jsx3("p", { className: "my-5", children: props.children }),
115
+ hr: () => /* @__PURE__ */ jsx3("hr", { className: "my-10 border-gray-200" }),
116
+ a: (props) => /* @__PURE__ */ jsx3(Link, { href: props.href, children: props.children }),
117
+ ul: (props) => /* @__PURE__ */ jsx3("ul", { className: "list-['-'] pl-4 space-y-2", children: props.children }),
118
+ li: (props) => /* @__PURE__ */ jsx3("li", { className: "mb-2 pl-3 text-gray-700", children: props.children }),
119
+ ol: (props) => /* @__PURE__ */ jsx3("ol", { className: "list-decimal pl-4 space-y-2", children: props.children }),
120
+ blockquote: (props) => /* @__PURE__ */ jsx3("blockquote", { className: "border-l-4 border-gray-200 pl-4 my-8 text-gray-700", children: props.children })
113
121
  };
114
122
 
123
+ // src/plugins/rehype-code-meta.ts
124
+ import { visit } from "unist-util-visit";
125
+ function rehypeCodeMetaProps() {
126
+ return (tree) => {
127
+ visit(tree, "element", (node) => {
128
+ if (node.tagName !== "pre") return;
129
+ const code = node.children?.[0];
130
+ if (!code || code.tagName !== "code") return;
131
+ const className = code.properties?.className?.[0];
132
+ const language = className?.replace("language-", "");
133
+ const meta = code.data?.meta || "";
134
+ const metaProps = {};
135
+ meta.replace(
136
+ /(\w+)=["']?([^"'\s]+)["']?/g,
137
+ (_match, key, value) => {
138
+ metaProps[key] = value;
139
+ return "";
140
+ }
141
+ );
142
+ node.properties = { ...node.properties || {}, language, ...metaProps };
143
+ });
144
+ };
145
+ }
146
+
115
147
  // src/server/mdx-compiler.tsx
116
- import { Fragment, jsx as jsx3 } from "react/jsx-runtime";
148
+ import { jsx as jsx4 } from "react/jsx-runtime";
117
149
  function DocstraMDXCompiler({
118
150
  mdxContent,
119
151
  components = {}
120
152
  }) {
121
- return /* @__PURE__ */ jsx3(Fragment, { children: /* @__PURE__ */ jsx3(
153
+ return /* @__PURE__ */ jsx4(
122
154
  MDXRemote,
123
155
  {
124
156
  source: mdxContent,
125
157
  components: {
126
158
  ...defaultMdxComponents,
127
159
  ...components
160
+ },
161
+ options: {
162
+ mdxOptions: {
163
+ rehypePlugins: [rehypeCodeMetaProps]
164
+ }
128
165
  }
129
166
  }
130
- ) });
167
+ );
131
168
  }
132
169
  export {
133
170
  DocstraMDXCompiler,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "docstra",
3
- "version": "1.4.0",
4
- "description": "A Modern Documentation Framework for Next.js",
3
+ "version": "1.4.6",
4
+ "description": "The Modern Documentation Framework for Next.js",
5
5
  "keywords": [
6
6
  "next",
7
7
  "nextjs",
@@ -15,17 +15,19 @@
15
15
  "files": [
16
16
  "dist"
17
17
  ],
18
- "types": "./dist/client/index.d.ts",
19
18
  "exports": {
20
19
  ".": {
20
+ "types": "./dist/client/index.d.ts",
21
21
  "import": "./dist/client/index.mjs",
22
22
  "require": "./dist/client/index.js"
23
23
  },
24
24
  "./server": {
25
+ "types": "./dist/server/index.d.ts",
25
26
  "import": "./dist/server/index.mjs",
26
27
  "require": "./dist/server/index.js"
27
28
  },
28
29
  "./config": {
30
+ "types": "./dist/server/index.d.ts",
29
31
  "import": "./dist/server/index.mjs",
30
32
  "require": "./dist/server/index.js"
31
33
  },
@@ -38,14 +40,14 @@
38
40
  "prettier": "prettier --write src"
39
41
  },
40
42
  "devDependencies": {
43
+ "@tailwindcss/cli": "^4.1.17",
41
44
  "@types/node": "^24.10.1",
42
45
  "@types/react": "^19.2.2",
43
46
  "@types/react-dom": "^19.2.2",
44
47
  "prettier": "^3.6.2",
45
- "tsup": "^8.5.0",
46
- "typescript": "^5.9.3",
47
48
  "tailwindcss": "^4.1.17",
48
- "@tailwindcss/cli": "^4.1.17"
49
+ "tsup": "^8.5.0",
50
+ "typescript": "^5.9.3"
49
51
  },
50
52
  "dependencies": {
51
53
  "clsx": "^2.1.1",
@@ -57,6 +59,7 @@
57
59
  "react": "^18 || ^19",
58
60
  "react-dom": "^18 || ^19",
59
61
  "react-toast-msg": "^2.2.6",
60
- "tailwind-merge": "^3.4.0"
62
+ "tailwind-merge": "^3.4.0",
63
+ "unist-util-visit": "^5.0.0"
61
64
  }
62
65
  }