docstra 1.5.2-next.1 → 1.6.0

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
@@ -30,6 +30,7 @@ import { defineDocstraConfig } from 'docstra/config';
30
30
  export default defineDocstraConfig({
31
31
  siteName: 'Docstra',
32
32
  githubRepo: 'https://github.com/sudhucodes/docstra',
33
+ contentDir: 'docs/content',
33
34
  editOnGithub: true,
34
35
  feedback: {
35
36
  enabled: true,
@@ -1,10 +1,11 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import React$1 from 'react';
3
- import { D as DocstraConfig, p as pageDataContent, a as DocstraContextType } from '../types-QIYN3ZUM.mjs';
3
+ import { D as DocstraConfig, p as pageDataContent, a as DocstraContextType } from '../types-BCr1htTq.mjs';
4
4
 
5
- declare function DocstraProvider({ children, docstraConfig, pageData }: {
5
+ declare function DocstraProvider({ children, docstraConfig, docs, pageData }: {
6
6
  children: React$1.ReactNode;
7
7
  docstraConfig: DocstraConfig;
8
+ docs: pageDataContent[];
8
9
  pageData: pageDataContent;
9
10
  }): react_jsx_runtime.JSX.Element;
10
11
  declare function useDocstra(): DocstraContextType;
@@ -1,10 +1,11 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import React$1 from 'react';
3
- import { D as DocstraConfig, p as pageDataContent, a as DocstraContextType } from '../types-QIYN3ZUM.js';
3
+ import { D as DocstraConfig, p as pageDataContent, a as DocstraContextType } from '../types-BCr1htTq.js';
4
4
 
5
- declare function DocstraProvider({ children, docstraConfig, pageData }: {
5
+ declare function DocstraProvider({ children, docstraConfig, docs, pageData }: {
6
6
  children: React$1.ReactNode;
7
7
  docstraConfig: DocstraConfig;
8
+ docs: pageDataContent[];
8
9
  pageData: pageDataContent;
9
10
  }): react_jsx_runtime.JSX.Element;
10
11
  declare function useDocstra(): DocstraContextType;
@@ -58,13 +58,26 @@ function cn(...inputs) {
58
58
 
59
59
  // src/client/search-box.tsx
60
60
  var import_react = require("react");
61
+ var import_fuse = __toESM(require("fuse.js"));
62
+
63
+ // src/client/link.tsx
64
+ var import_link = __toESM(require("next/link"));
61
65
  var import_jsx_runtime = require("react/jsx-runtime");
66
+ function Link({ href, children, className, onNavigate, ...props }) {
67
+ if (href.startsWith("http")) {
68
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { href, className, ...props, target: "_blank", rel: "noopener noreferrer", children });
69
+ }
70
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_link.default, { href, className, onNavigate, ...props, children });
71
+ }
72
+
73
+ // src/client/search-box.tsx
74
+ var import_navigation = require("next/navigation");
75
+ var import_jsx_runtime2 = require("react/jsx-runtime");
62
76
  function DocstraSearchBox() {
63
- const { openSearchBox, setOpenSearchBox } = useDocstra();
77
+ const { openSearchBox, setOpenSearchBox, docs } = useDocstra();
64
78
  const [searchQuery, setSearchQuery] = (0, import_react.useState)("");
65
- (0, import_react.useEffect)(() => {
66
- console.log(`Search query: ${searchQuery}`);
67
- }, [searchQuery]);
79
+ const [searchResults, setSearchResults] = (0, import_react.useState)([]);
80
+ const router = (0, import_navigation.useRouter)();
68
81
  (0, import_react.useEffect)(() => {
69
82
  const handleKeyDown = (event) => {
70
83
  if (event.ctrlKey && event.key === "k") {
@@ -77,7 +90,30 @@ function DocstraSearchBox() {
77
90
  window.removeEventListener("keydown", handleKeyDown);
78
91
  };
79
92
  }, []);
80
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
93
+ const fuse = (0, import_react.useMemo)(() => {
94
+ return new import_fuse.default(docs, {
95
+ keys: ["frontmatter.title", "frontmatter.description", "headings", "info.slug"],
96
+ threshold: 0.3
97
+ });
98
+ }, [docs]);
99
+ (0, import_react.useEffect)(() => {
100
+ if (searchQuery) {
101
+ const results = fuse.search(searchQuery);
102
+ setSearchResults(results.map((r) => r.item));
103
+ }
104
+ }, [searchQuery]);
105
+ const onSearchHandler = (e) => {
106
+ e.preventDefault();
107
+ if (searchQuery) {
108
+ const component = searchResults[0];
109
+ if (component) {
110
+ router.push(`/docs/${component.info.slug}`);
111
+ setSearchQuery("");
112
+ setOpenSearchBox(false);
113
+ }
114
+ }
115
+ };
116
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
81
117
  "div",
82
118
  {
83
119
  onClick: () => {
@@ -88,67 +124,59 @@ function DocstraSearchBox() {
88
124
  "fixed inset-0 z-25 flex items-start justify-center bg-white/40 backdrop-blur-md opacity-0 pointer-events-none transition-all duration-300",
89
125
  openSearchBox && "opacity-100 pointer-events-auto"
90
126
  ),
91
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
127
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
92
128
  "div",
93
129
  {
94
130
  onClick: (e) => e.stopPropagation(),
95
131
  className: "flex flex-col items-center mt-30 max-w-lg w-full max-md:px-4",
96
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
97
- "form",
98
- {
99
- className: cn(
100
- "relative flex items-center justify-between w-full bg-white border border-slate-200 text-gray-400 h-15 p-0.5 rounded-md"
101
- // searchQuery && "rounded-b-none border-b-0"
102
- ),
103
- children: openSearchBox && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
104
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.SearchIcon, { className: "size-5.5 mx-3 shrink-0" }),
105
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
106
- "input",
107
- {
108
- className: "w-full bg-transparent h-full outline-none text-gray-400 placeholder:text-gray-400",
109
- type: "text",
110
- placeholder: "Search docs...",
111
- spellCheck: "false",
112
- autoFocus: true,
113
- value: searchQuery,
114
- onChange: (e) => setSearchQuery(e.target.value),
115
- name: "searchQuery",
116
- required: true
117
- }
132
+ children: [
133
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
134
+ "form",
135
+ {
136
+ onSubmit: onSearchHandler,
137
+ className: cn(
138
+ "relative flex items-center justify-between w-full bg-white border border-slate-200 text-gray-400 h-15 p-0.5 rounded-md",
139
+ searchQuery && "rounded-b-none border-b-0"
118
140
  ),
119
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
120
- "svg",
121
- {
122
- className: "h-4.5 shrink-0 w-auto mr-3",
123
- width: "29",
124
- height: "18",
125
- viewBox: "0 0 29 18",
126
- fill: "none",
127
- xmlns: "http://www.w3.org/2000/svg",
128
- children: [
129
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
130
- "path",
131
- {
132
- d: "M13.5 2.25a2.25 2.25 0 0 0-2.25 2.25v9a2.25 2.25 0 1 0 2.25-2.25h-9a2.25 2.25 0 1 0 2.25 2.25v-9A2.25 2.25 0 1 0 4.5 6.75h9a2.25 2.25 0 0 0 0-4.5",
133
- stroke: "#99A1AF",
134
- strokeWidth: "1.5",
135
- strokeLinecap: "round",
136
- strokeLinejoin: "round"
137
- }
138
- ),
139
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
140
- "path",
141
- {
142
- d: "M25.986 14 21.45 8.89l4.438-4.69h2.058l-4.9 5.096v-.882L28.086 14zm-5.922 0V4.2h1.61V14z",
143
- fill: "#99A1AF"
144
- }
145
- )
146
- ]
147
- }
148
- )
149
- ] })
150
- }
151
- )
141
+ children: openSearchBox && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
142
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react.SearchIcon, { className: "size-5.5 mx-3 shrink-0" }),
143
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("input", { className: "w-full bg-transparent h-full outline-none text-gray-400 placeholder:text-gray-400", type: "text", placeholder: "Search docs...", spellCheck: "false", autoFocus: true, value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), name: "searchQuery", required: true }),
144
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { className: "h-4.5 shrink-0 w-auto mr-3", width: "29", height: "18", viewBox: "0 0 29 18", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
145
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M13.5 2.25a2.25 2.25 0 0 0-2.25 2.25v9a2.25 2.25 0 1 0 2.25-2.25h-9a2.25 2.25 0 1 0 2.25 2.25v-9A2.25 2.25 0 1 0 4.5 6.75h9a2.25 2.25 0 0 0 0-4.5", stroke: "#99A1AF", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }),
146
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M25.986 14 21.45 8.89l4.438-4.69h2.058l-4.9 5.096v-.882L28.086 14zm-5.922 0V4.2h1.61V14z", fill: "#99A1AF" })
147
+ ] })
148
+ ] })
149
+ }
150
+ ),
151
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
152
+ "div",
153
+ {
154
+ className: cn(
155
+ "max-h-70 overflow-x-hidden overflow-y-auto scrollbar-y w-full bg-white text-slate-700 flex flex-col",
156
+ searchQuery && "rounded-b-md border border-slate-200"
157
+ ),
158
+ children: [
159
+ searchResults.map((item) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
160
+ Link,
161
+ {
162
+ href: `/docs/${item.info.slug}`,
163
+ onNavigate: () => {
164
+ setOpenSearchBox(false);
165
+ setSearchQuery("");
166
+ },
167
+ className: "w-full hover:bg-gray-100/70 border-b border-slate-200 transition-all py-4 px-4 last:mb-2",
168
+ children: [
169
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h4", { className: "font-medium", children: item.frontmatter.title }),
170
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-sm mt-1 text-gray-500", children: item.frontmatter.description })
171
+ ]
172
+ },
173
+ item.info.slug
174
+ )),
175
+ searchQuery && searchResults.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "text-gray-500 text-center py-6", children: "No results found" })
176
+ ]
177
+ }
178
+ )
179
+ ]
152
180
  }
153
181
  )
154
182
  }
@@ -156,16 +184,17 @@ function DocstraSearchBox() {
156
184
  }
157
185
 
158
186
  // src/context/docstra-context.tsx
159
- var import_jsx_runtime2 = require("react/jsx-runtime");
187
+ var import_jsx_runtime3 = require("react/jsx-runtime");
160
188
  var DocstraContext = (0, import_react2.createContext)(null);
161
189
  function DocstraProvider({
162
190
  children,
163
191
  docstraConfig,
192
+ docs,
164
193
  pageData
165
194
  }) {
166
195
  const [openSidebar, setOpenSidebar] = (0, import_react2.useState)(false);
167
196
  const [openSearchBox, setOpenSearchBox] = (0, import_react2.useState)(false);
168
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
197
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
169
198
  DocstraContext.Provider,
170
199
  {
171
200
  value: {
@@ -174,11 +203,12 @@ function DocstraProvider({
174
203
  docstraConfig,
175
204
  openSearchBox,
176
205
  setOpenSearchBox,
177
- pageData
206
+ pageData,
207
+ docs
178
208
  },
179
209
  children: [
180
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_toast_msg.ToastContainer, {}),
181
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(DocstraSearchBox, {}),
210
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_toast_msg.ToastContainer, {}),
211
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(DocstraSearchBox, {}),
182
212
  children
183
213
  ]
184
214
  }
@@ -193,18 +223,6 @@ function useDocstra() {
193
223
  // src/client/header.tsx
194
224
  var import_lucide_react2 = require("lucide-react");
195
225
  var import_react3 = require("react");
196
-
197
- // src/client/link.tsx
198
- var import_link = __toESM(require("next/link"));
199
- var import_jsx_runtime3 = require("react/jsx-runtime");
200
- function Link({ href, children, className, onNavigate, ...props }) {
201
- if (href.startsWith("http")) {
202
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("a", { href, className, ...props, target: "_blank", rel: "noopener noreferrer", children });
203
- }
204
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_link.default, { href, className, onNavigate, ...props, children });
205
- }
206
-
207
- // src/client/header.tsx
208
226
  var import_jsx_runtime4 = require("react/jsx-runtime");
209
227
  function DocstraHeader() {
210
228
  const { openSidebar, setOpenSidebar, docstraConfig } = useDocstra();
@@ -241,7 +259,7 @@ function DocstraHeader() {
241
259
 
242
260
  // src/client/sidebar.tsx
243
261
  var import_lucide_react3 = require("lucide-react");
244
- var import_navigation = require("next/navigation");
262
+ var import_navigation2 = require("next/navigation");
245
263
 
246
264
  // src/utils/get-icon.ts
247
265
  var Icons = __toESM(require("lucide-react"));
@@ -251,11 +269,10 @@ function getIcon(name) {
251
269
  }
252
270
 
253
271
  // src/client/sidebar.tsx
254
- var import_react_toast_msg2 = require("react-toast-msg");
255
272
  var import_jsx_runtime5 = require("react/jsx-runtime");
256
273
  function DocstraSidebar() {
257
- const { openSidebar, setOpenSidebar, docstraConfig } = useDocstra();
258
- const pathname = (0, import_navigation.usePathname)();
274
+ const { openSidebar, setOpenSidebar, docstraConfig, setOpenSearchBox } = useDocstra();
275
+ const pathname = (0, import_navigation2.usePathname)();
259
276
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
260
277
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
261
278
  "div",
@@ -279,7 +296,10 @@ function DocstraSidebar() {
279
296
  "div",
280
297
  {
281
298
  className: "flex items-center gap-2 cursor-pointer mt-6 mb-4 p-2.5 text-gray-500 border border-gray-200 rounded-lg hover:bg-gray-50",
282
- onClick: () => import_react_toast_msg2.toast.warning("Search is not available yet!"),
299
+ onClick: () => {
300
+ setOpenSidebar(openSidebar && false);
301
+ setOpenSearchBox(true);
302
+ },
283
303
  children: [
284
304
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react3.SearchIcon, { className: "size-4.5" }),
285
305
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { children: "Search" }),
@@ -324,11 +344,11 @@ function DocstraPage({ children }) {
324
344
  }
325
345
 
326
346
  // src/client/breadcrumbs.tsx
327
- var import_navigation2 = require("next/navigation");
347
+ var import_navigation3 = require("next/navigation");
328
348
  var import_lucide_react4 = require("lucide-react");
329
349
  var import_jsx_runtime7 = require("react/jsx-runtime");
330
350
  function DocstraBreadcrumbs() {
331
- const pathname = (0, import_navigation2.usePathname)();
351
+ const pathname = (0, import_navigation3.usePathname)();
332
352
  const paths = pathname.split("/").filter(Boolean);
333
353
  const breadcrumbs = paths.map((segment, index) => {
334
354
  const href = "/" + paths.slice(0, index + 1).join("/");
@@ -573,12 +593,12 @@ function DocstraFeedback() {
573
593
  }
574
594
 
575
595
  // src/client/pagination.tsx
576
- var import_navigation3 = require("next/navigation");
577
- var import_link5 = __toESM(require("next/link"));
596
+ var import_navigation4 = require("next/navigation");
597
+ var import_link6 = __toESM(require("next/link"));
578
598
  var import_lucide_react8 = require("lucide-react");
579
599
  var import_jsx_runtime13 = require("react/jsx-runtime");
580
600
  function DocstraPagination() {
581
- const pathname = (0, import_navigation3.usePathname)();
601
+ const pathname = (0, import_navigation4.usePathname)();
582
602
  const { docstraConfig } = useDocstra();
583
603
  const flatLinks = docstraConfig?.sidebar?.links?.flatMap((section) => section.items);
584
604
  const currentIndex = flatLinks.findIndex((item) => item.href === pathname);
@@ -586,7 +606,7 @@ function DocstraPagination() {
586
606
  const next = currentIndex < flatLinks.length - 1 ? flatLinks[currentIndex + 1] : null;
587
607
  return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex flex-col md:flex-row gap-2 justify-between py-10 mt-10", children: [
588
608
  prev ? /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
589
- import_link5.default,
609
+ import_link6.default,
590
610
  {
591
611
  href: prev.href,
592
612
  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",
@@ -600,7 +620,7 @@ function DocstraPagination() {
600
620
  }
601
621
  ) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", {}),
602
622
  next ? /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
603
- import_link5.default,
623
+ import_link6.default,
604
624
  {
605
625
  href: next.href,
606
626
  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",
@@ -631,7 +651,7 @@ function DocstraBody({ children }) {
631
651
 
632
652
  // src/client/docstra-toc.tsx
633
653
  var import_lucide_react9 = require("lucide-react");
634
- var import_navigation4 = require("next/navigation");
654
+ var import_navigation5 = require("next/navigation");
635
655
  var import_react6 = require("react");
636
656
 
637
657
  // src/utils/generate-id-from-text.ts
@@ -676,7 +696,7 @@ function DocstraTOC() {
676
696
  const rawMdxContent = pageData?.content;
677
697
  const lastScrollY = (0, import_react6.useRef)(0);
678
698
  const observerRef = (0, import_react6.useRef)(null);
679
- const pathname = (0, import_navigation4.usePathname)();
699
+ const pathname = (0, import_navigation5.usePathname)();
680
700
  const baseUrlOfGithub = docstraConfig?.githubRepo || "https://github.com/sudhucodes/docstra";
681
701
  const githubLink = `${baseUrlOfGithub}/edit/main/${mdxFilePath}`;
682
702
  (0, import_react6.useEffect)(() => {
@@ -805,7 +825,7 @@ function TableOfContentsLink({ heading, activeId, handleClick, className }) {
805
825
  var import_react7 = require("react");
806
826
  var import_prism_react_renderer = require("prism-react-renderer");
807
827
  var import_lucide_react10 = require("lucide-react");
808
- var import_react_toast_msg3 = require("react-toast-msg");
828
+ var import_react_toast_msg2 = require("react-toast-msg");
809
829
  var import_jsx_runtime16 = require("react/jsx-runtime");
810
830
  function DocstraCodeBlock(props) {
811
831
  const { language, title, children } = props;
@@ -813,7 +833,7 @@ function DocstraCodeBlock(props) {
813
833
  const [copied, setCopied] = (0, import_react7.useState)(false);
814
834
  const handleCopy = () => {
815
835
  navigator.clipboard.writeText(code);
816
- import_react_toast_msg3.toast.success("Copied to clipboard!");
836
+ import_react_toast_msg2.toast.success("Copied to clipboard!");
817
837
  setCopied(true);
818
838
  };
819
839
  (0, import_react7.useEffect)(() => {