docstra 1.5.2-next.2 → 1.6.2

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-BpWZQq13.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-BpWZQq13.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,44 @@ 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
+ (0, import_react.useEffect)(() => {
117
+ const handleEscape = (e) => {
118
+ if (e.key === "Escape") {
119
+ setOpenSearchBox(false);
120
+ setSearchQuery("");
121
+ }
122
+ };
123
+ if (openSearchBox) {
124
+ window.addEventListener("keydown", handleEscape);
125
+ }
126
+ return () => {
127
+ window.removeEventListener("keydown", handleEscape);
128
+ };
129
+ }, [openSearchBox]);
130
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
81
131
  "div",
82
132
  {
83
133
  onClick: () => {
@@ -88,67 +138,56 @@ function DocstraSearchBox() {
88
138
  "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
139
  openSearchBox && "opacity-100 pointer-events-auto"
90
140
  ),
91
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
141
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
92
142
  "div",
93
143
  {
94
144
  onClick: (e) => e.stopPropagation(),
95
145
  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
- }
146
+ children: [
147
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
148
+ "form",
149
+ {
150
+ onSubmit: onSearchHandler,
151
+ className: cn(
152
+ "relative flex items-center justify-between w-full bg-white border border-slate-200 text-gray-400 h-15 p-0.5 rounded-md",
153
+ searchQuery && "rounded-b-none border-b-0"
118
154
  ),
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
- )
155
+ children: openSearchBox && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
156
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react.SearchIcon, { className: "size-5.5 mx-3 shrink-0" }),
157
+ /* @__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 }),
158
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "border border-gray-200 px-2 mr-3 py-1 rounded text-xs", children: "Esc" })
159
+ ] })
160
+ }
161
+ ),
162
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
163
+ "div",
164
+ {
165
+ className: cn(
166
+ "max-h-70 overflow-x-hidden overflow-y-auto scrollbar-y w-full bg-white text-slate-700 flex flex-col",
167
+ searchQuery && "rounded-b-md border border-slate-200"
168
+ ),
169
+ children: [
170
+ searchResults.map((item) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
171
+ Link,
172
+ {
173
+ href: `/docs/${item.info.slug.replace("index", "")}`,
174
+ onNavigate: () => {
175
+ setOpenSearchBox(false);
176
+ setSearchQuery("");
177
+ },
178
+ className: "w-full hover:bg-gray-100/70 border-b border-slate-200 transition-all py-4 px-4 last:mb-2",
179
+ children: [
180
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h4", { className: "font-medium", children: item.frontmatter.title }),
181
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-sm mt-1 text-gray-500", children: item.frontmatter.description })
182
+ ]
183
+ },
184
+ item.info.slug
185
+ )),
186
+ searchQuery && searchResults.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "text-gray-500 text-center py-20", children: "No results found" })
187
+ ]
188
+ }
189
+ )
190
+ ]
152
191
  }
153
192
  )
154
193
  }
@@ -156,16 +195,17 @@ function DocstraSearchBox() {
156
195
  }
157
196
 
158
197
  // src/context/docstra-context.tsx
159
- var import_jsx_runtime2 = require("react/jsx-runtime");
198
+ var import_jsx_runtime3 = require("react/jsx-runtime");
160
199
  var DocstraContext = (0, import_react2.createContext)(null);
161
200
  function DocstraProvider({
162
201
  children,
163
202
  docstraConfig,
203
+ docs,
164
204
  pageData
165
205
  }) {
166
206
  const [openSidebar, setOpenSidebar] = (0, import_react2.useState)(false);
167
207
  const [openSearchBox, setOpenSearchBox] = (0, import_react2.useState)(false);
168
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
208
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
169
209
  DocstraContext.Provider,
170
210
  {
171
211
  value: {
@@ -174,11 +214,12 @@ function DocstraProvider({
174
214
  docstraConfig,
175
215
  openSearchBox,
176
216
  setOpenSearchBox,
177
- pageData
217
+ pageData,
218
+ docs
178
219
  },
179
220
  children: [
180
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_toast_msg.ToastContainer, {}),
181
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(DocstraSearchBox, {}),
221
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_toast_msg.ToastContainer, {}),
222
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(DocstraSearchBox, {}),
182
223
  children
183
224
  ]
184
225
  }
@@ -193,18 +234,6 @@ function useDocstra() {
193
234
  // src/client/header.tsx
194
235
  var import_lucide_react2 = require("lucide-react");
195
236
  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
237
  var import_jsx_runtime4 = require("react/jsx-runtime");
209
238
  function DocstraHeader() {
210
239
  const { openSidebar, setOpenSidebar, docstraConfig } = useDocstra();
@@ -241,7 +270,7 @@ function DocstraHeader() {
241
270
 
242
271
  // src/client/sidebar.tsx
243
272
  var import_lucide_react3 = require("lucide-react");
244
- var import_navigation = require("next/navigation");
273
+ var import_navigation2 = require("next/navigation");
245
274
 
246
275
  // src/utils/get-icon.ts
247
276
  var Icons = __toESM(require("lucide-react"));
@@ -251,11 +280,10 @@ function getIcon(name) {
251
280
  }
252
281
 
253
282
  // src/client/sidebar.tsx
254
- var import_react_toast_msg2 = require("react-toast-msg");
255
283
  var import_jsx_runtime5 = require("react/jsx-runtime");
256
284
  function DocstraSidebar() {
257
- const { openSidebar, setOpenSidebar, docstraConfig } = useDocstra();
258
- const pathname = (0, import_navigation.usePathname)();
285
+ const { openSidebar, setOpenSidebar, docstraConfig, setOpenSearchBox } = useDocstra();
286
+ const pathname = (0, import_navigation2.usePathname)();
259
287
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
260
288
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
261
289
  "div",
@@ -278,8 +306,11 @@ function DocstraSidebar() {
278
306
  /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
279
307
  "div",
280
308
  {
281
- 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!"),
309
+ className: "flex items-center select-none gap-2 cursor-pointer mt-6 mb-4 p-2.5 text-gray-500 border border-gray-200 rounded-lg hover:bg-gray-50",
310
+ onClick: () => {
311
+ setOpenSidebar(openSidebar && false);
312
+ setOpenSearchBox(true);
313
+ },
283
314
  children: [
284
315
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react3.SearchIcon, { className: "size-4.5" }),
285
316
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { children: "Search" }),
@@ -324,11 +355,11 @@ function DocstraPage({ children }) {
324
355
  }
325
356
 
326
357
  // src/client/breadcrumbs.tsx
327
- var import_navigation2 = require("next/navigation");
358
+ var import_navigation3 = require("next/navigation");
328
359
  var import_lucide_react4 = require("lucide-react");
329
360
  var import_jsx_runtime7 = require("react/jsx-runtime");
330
361
  function DocstraBreadcrumbs() {
331
- const pathname = (0, import_navigation2.usePathname)();
362
+ const pathname = (0, import_navigation3.usePathname)();
332
363
  const paths = pathname.split("/").filter(Boolean);
333
364
  const breadcrumbs = paths.map((segment, index) => {
334
365
  const href = "/" + paths.slice(0, index + 1).join("/");
@@ -573,12 +604,12 @@ function DocstraFeedback() {
573
604
  }
574
605
 
575
606
  // src/client/pagination.tsx
576
- var import_navigation3 = require("next/navigation");
577
- var import_link5 = __toESM(require("next/link"));
607
+ var import_navigation4 = require("next/navigation");
608
+ var import_link6 = __toESM(require("next/link"));
578
609
  var import_lucide_react8 = require("lucide-react");
579
610
  var import_jsx_runtime13 = require("react/jsx-runtime");
580
611
  function DocstraPagination() {
581
- const pathname = (0, import_navigation3.usePathname)();
612
+ const pathname = (0, import_navigation4.usePathname)();
582
613
  const { docstraConfig } = useDocstra();
583
614
  const flatLinks = docstraConfig?.sidebar?.links?.flatMap((section) => section.items);
584
615
  const currentIndex = flatLinks.findIndex((item) => item.href === pathname);
@@ -586,7 +617,7 @@ function DocstraPagination() {
586
617
  const next = currentIndex < flatLinks.length - 1 ? flatLinks[currentIndex + 1] : null;
587
618
  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
619
  prev ? /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
589
- import_link5.default,
620
+ import_link6.default,
590
621
  {
591
622
  href: prev.href,
592
623
  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 +631,7 @@ function DocstraPagination() {
600
631
  }
601
632
  ) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", {}),
602
633
  next ? /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
603
- import_link5.default,
634
+ import_link6.default,
604
635
  {
605
636
  href: next.href,
606
637
  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 +662,7 @@ function DocstraBody({ children }) {
631
662
 
632
663
  // src/client/docstra-toc.tsx
633
664
  var import_lucide_react9 = require("lucide-react");
634
- var import_navigation4 = require("next/navigation");
665
+ var import_navigation5 = require("next/navigation");
635
666
  var import_react6 = require("react");
636
667
 
637
668
  // src/utils/generate-id-from-text.ts
@@ -676,7 +707,7 @@ function DocstraTOC() {
676
707
  const rawMdxContent = pageData?.content;
677
708
  const lastScrollY = (0, import_react6.useRef)(0);
678
709
  const observerRef = (0, import_react6.useRef)(null);
679
- const pathname = (0, import_navigation4.usePathname)();
710
+ const pathname = (0, import_navigation5.usePathname)();
680
711
  const baseUrlOfGithub = docstraConfig?.githubRepo || "https://github.com/sudhucodes/docstra";
681
712
  const githubLink = `${baseUrlOfGithub}/edit/main/${mdxFilePath}`;
682
713
  (0, import_react6.useEffect)(() => {
@@ -805,7 +836,7 @@ function TableOfContentsLink({ heading, activeId, handleClick, className }) {
805
836
  var import_react7 = require("react");
806
837
  var import_prism_react_renderer = require("prism-react-renderer");
807
838
  var import_lucide_react10 = require("lucide-react");
808
- var import_react_toast_msg3 = require("react-toast-msg");
839
+ var import_react_toast_msg2 = require("react-toast-msg");
809
840
  var import_jsx_runtime16 = require("react/jsx-runtime");
810
841
  function DocstraCodeBlock(props) {
811
842
  const { language, title, children } = props;
@@ -813,7 +844,7 @@ function DocstraCodeBlock(props) {
813
844
  const [copied, setCopied] = (0, import_react7.useState)(false);
814
845
  const handleCopy = () => {
815
846
  navigator.clipboard.writeText(code);
816
- import_react_toast_msg3.toast.success("Copied to clipboard!");
847
+ import_react_toast_msg2.toast.success("Copied to clipboard!");
817
848
  setCopied(true);
818
849
  };
819
850
  (0, import_react7.useEffect)(() => {