docstra 1.2.0 → 1.3.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
@@ -4,6 +4,8 @@ Docstra is a modern documentation framework for Next.js. It's built with Tailwin
4
4
 
5
5
  > Documentation of Docstra is coming soon. Stay tuned!
6
6
 
7
+ > For any questions, feel free to reach out us on [contact@sudhucodes.com](mailto:contact@sudhucodes.com)
8
+
7
9
  ## Features
8
10
 
9
11
  - MDX support
@@ -214,7 +214,7 @@ function DocstraHeader() {
214
214
  }
215
215
  }, [openSidebar]);
216
216
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("header", { className: "sticky top-0 z-10 text-sm flex items-center justify-between border-b border-gray-100 h-18 px-4 md:px-6 bg-white", children: [
217
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("a", { href: docstraConfig.navbar?.logo?.link || "/", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
217
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Link, { href: docstraConfig.navbar?.logo?.link || "/", className: "hover:opacity-80 transition", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
218
218
  "img",
219
219
  {
220
220
  src: docstraConfig.navbar?.logo?.src || "/logo.png",
@@ -347,17 +347,15 @@ function DocstraBreadcrumbs() {
347
347
 
348
348
  // src/client/page-buttons.tsx
349
349
  var import_lucide_react5 = require("lucide-react");
350
- var import_navigation3 = require("next/navigation");
351
350
  var import_react4 = require("react");
352
351
  var import_jsx_runtime8 = require("react/jsx-runtime");
353
352
  function DocstraPageButtons({ rawMdxContent }) {
354
353
  const [isCopied, setIsCopied] = (0, import_react4.useState)(false);
355
354
  const [href, setHref] = (0, import_react4.useState)(null);
356
- const pathname = (0, import_navigation3.usePathname)();
357
355
  (0, import_react4.useEffect)(() => {
358
356
  setHref(window.location.href);
359
357
  }, []);
360
- const prompt = `Read from this URL: ${href + pathname} and explain it to me.`;
358
+ const prompt = `Read from this URL: ${href} and explain it to me.`;
361
359
  const handleCopy = () => {
362
360
  navigator.clipboard.writeText(rawMdxContent);
363
361
  setIsCopied(true);
@@ -562,12 +560,12 @@ function DocstraFeedback() {
562
560
  }
563
561
 
564
562
  // src/client/pagination.tsx
565
- var import_navigation4 = require("next/navigation");
563
+ var import_navigation3 = require("next/navigation");
566
564
  var import_link5 = __toESM(require("next/link"));
567
565
  var import_lucide_react8 = require("lucide-react");
568
566
  var import_jsx_runtime13 = require("react/jsx-runtime");
569
567
  function DocstraPagination() {
570
- const pathname = (0, import_navigation4.usePathname)();
568
+ const pathname = (0, import_navigation3.usePathname)();
571
569
  const { docstraConfig } = useDocstra();
572
570
  const flatLinks = docstraConfig?.sidebar?.links?.flatMap((section) => section.items);
573
571
  const currentIndex = flatLinks.findIndex((item) => item.href === pathname);
@@ -619,7 +617,7 @@ function DocstraBody({ children, metadata, mdxContent }) {
619
617
 
620
618
  // src/client/docstra-toc.tsx
621
619
  var import_lucide_react9 = require("lucide-react");
622
- var import_navigation5 = require("next/navigation");
620
+ var import_navigation4 = require("next/navigation");
623
621
  var import_react6 = require("react");
624
622
 
625
623
  // src/utils/generate-id-from-text.ts
@@ -662,7 +660,7 @@ function DocstraTOC({ mdxFilePath, rawMdxContent }) {
662
660
  const { docstraConfig } = useDocstra();
663
661
  const lastScrollY = (0, import_react6.useRef)(0);
664
662
  const observerRef = (0, import_react6.useRef)(null);
665
- const pathname = (0, import_navigation5.usePathname)();
663
+ const pathname = (0, import_navigation4.usePathname)();
666
664
  const baseUrlOfGithub = docstraConfig?.githubRepo || "https://github.com/sudhucodes/docstra";
667
665
  const normalized = mdxFilePath.replace(/\\/g, "/");
668
666
  const match = normalized.match(/\/docs\/(.+)$/);
@@ -706,6 +704,22 @@ function DocstraTOC({ mdxFilePath, rawMdxContent }) {
706
704
  const scrolled = window.scrollY > 100;
707
705
  !scrolled && setActiveId(headings[0]?.id);
708
706
  }, [headings]);
707
+ (0, import_react6.useEffect)(() => {
708
+ if (!activeId) return;
709
+ const container = document.querySelector(".toc-scroll-container");
710
+ if (!container) return;
711
+ const activeLink = container.querySelector(`a[href="#${activeId}"]`);
712
+ if (!activeLink) return;
713
+ const containerRect = container.getBoundingClientRect();
714
+ const linkRect = activeLink.getBoundingClientRect();
715
+ const isOutOfView = linkRect.top < containerRect.top || linkRect.bottom > containerRect.bottom;
716
+ if (isOutOfView) {
717
+ activeLink.scrollIntoView({
718
+ behavior: "smooth",
719
+ block: "nearest"
720
+ });
721
+ }
722
+ }, [activeId]);
709
723
  (0, import_react6.useEffect)(() => {
710
724
  if (!isManualClick) return;
711
725
  const timer = setTimeout(() => setIsManualClick(false), 800);
@@ -720,7 +734,7 @@ function DocstraTOC({ mdxFilePath, rawMdxContent }) {
720
734
  /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react9.TextAlignStartIcon, { className: "size-4" }),
721
735
  "On this page"
722
736
  ] }),
723
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("ul", { children: headings.map((h2) => /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("li", { children: [
737
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("ul", { className: "toc-scroll-container max-h-3/4 overflow-y-auto scrollbar-none", children: headings.map((h2) => /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("li", { children: [
724
738
  /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(TableOfContentsLink, { heading: h2, activeId, handleClick }),
725
739
  h2.children.map((h3) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
726
740
  TableOfContentsLink,
@@ -172,7 +172,7 @@ function DocstraHeader() {
172
172
  }
173
173
  }, [openSidebar]);
174
174
  return /* @__PURE__ */ jsxs3("header", { className: "sticky top-0 z-10 text-sm flex items-center justify-between border-b border-gray-100 h-18 px-4 md:px-6 bg-white", children: [
175
- /* @__PURE__ */ jsx4("a", { href: docstraConfig.navbar?.logo?.link || "/", children: /* @__PURE__ */ jsx4(
175
+ /* @__PURE__ */ jsx4(Link, { href: docstraConfig.navbar?.logo?.link || "/", className: "hover:opacity-80 transition", children: /* @__PURE__ */ jsx4(
176
176
  "img",
177
177
  {
178
178
  src: docstraConfig.navbar?.logo?.src || "/logo.png",
@@ -305,17 +305,15 @@ function DocstraBreadcrumbs() {
305
305
 
306
306
  // src/client/page-buttons.tsx
307
307
  import { CheckIcon, CopyIcon } from "lucide-react";
308
- import { usePathname as usePathname3 } from "next/navigation";
309
308
  import { useEffect as useEffect3, useState as useState3 } from "react";
310
309
  import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
311
310
  function DocstraPageButtons({ rawMdxContent }) {
312
311
  const [isCopied, setIsCopied] = useState3(false);
313
312
  const [href, setHref] = useState3(null);
314
- const pathname = usePathname3();
315
313
  useEffect3(() => {
316
314
  setHref(window.location.href);
317
315
  }, []);
318
- const prompt = `Read from this URL: ${href + pathname} and explain it to me.`;
316
+ const prompt = `Read from this URL: ${href} and explain it to me.`;
319
317
  const handleCopy = () => {
320
318
  navigator.clipboard.writeText(rawMdxContent);
321
319
  setIsCopied(true);
@@ -520,12 +518,12 @@ function DocstraFeedback() {
520
518
  }
521
519
 
522
520
  // src/client/pagination.tsx
523
- import { usePathname as usePathname4 } from "next/navigation";
521
+ import { usePathname as usePathname3 } from "next/navigation";
524
522
  import Link2 from "next/link";
525
523
  import { ArrowLeftIcon, ArrowRightIcon } from "lucide-react";
526
524
  import { jsx as jsx13, jsxs as jsxs10 } from "react/jsx-runtime";
527
525
  function DocstraPagination() {
528
- const pathname = usePathname4();
526
+ const pathname = usePathname3();
529
527
  const { docstraConfig } = useDocstra();
530
528
  const flatLinks = docstraConfig?.sidebar?.links?.flatMap((section) => section.items);
531
529
  const currentIndex = flatLinks.findIndex((item) => item.href === pathname);
@@ -577,7 +575,7 @@ function DocstraBody({ children, metadata, mdxContent }) {
577
575
 
578
576
  // src/client/docstra-toc.tsx
579
577
  import { ArrowUpCircleIcon, SquareArrowOutUpRightIcon, TextAlignStartIcon } from "lucide-react";
580
- import { usePathname as usePathname5 } from "next/navigation";
578
+ import { usePathname as usePathname4 } from "next/navigation";
581
579
  import { useEffect as useEffect4, useRef, useState as useState5 } from "react";
582
580
 
583
581
  // src/utils/generate-id-from-text.ts
@@ -620,7 +618,7 @@ function DocstraTOC({ mdxFilePath, rawMdxContent }) {
620
618
  const { docstraConfig } = useDocstra();
621
619
  const lastScrollY = useRef(0);
622
620
  const observerRef = useRef(null);
623
- const pathname = usePathname5();
621
+ const pathname = usePathname4();
624
622
  const baseUrlOfGithub = docstraConfig?.githubRepo || "https://github.com/sudhucodes/docstra";
625
623
  const normalized = mdxFilePath.replace(/\\/g, "/");
626
624
  const match = normalized.match(/\/docs\/(.+)$/);
@@ -664,6 +662,22 @@ function DocstraTOC({ mdxFilePath, rawMdxContent }) {
664
662
  const scrolled = window.scrollY > 100;
665
663
  !scrolled && setActiveId(headings[0]?.id);
666
664
  }, [headings]);
665
+ useEffect4(() => {
666
+ if (!activeId) return;
667
+ const container = document.querySelector(".toc-scroll-container");
668
+ if (!container) return;
669
+ const activeLink = container.querySelector(`a[href="#${activeId}"]`);
670
+ if (!activeLink) return;
671
+ const containerRect = container.getBoundingClientRect();
672
+ const linkRect = activeLink.getBoundingClientRect();
673
+ const isOutOfView = linkRect.top < containerRect.top || linkRect.bottom > containerRect.bottom;
674
+ if (isOutOfView) {
675
+ activeLink.scrollIntoView({
676
+ behavior: "smooth",
677
+ block: "nearest"
678
+ });
679
+ }
680
+ }, [activeId]);
667
681
  useEffect4(() => {
668
682
  if (!isManualClick) return;
669
683
  const timer = setTimeout(() => setIsManualClick(false), 800);
@@ -678,7 +692,7 @@ function DocstraTOC({ mdxFilePath, rawMdxContent }) {
678
692
  /* @__PURE__ */ jsx15(TextAlignStartIcon, { className: "size-4" }),
679
693
  "On this page"
680
694
  ] }),
681
- /* @__PURE__ */ jsx15("ul", { children: headings.map((h2) => /* @__PURE__ */ jsxs12("li", { children: [
695
+ /* @__PURE__ */ jsx15("ul", { className: "toc-scroll-container max-h-3/4 overflow-y-auto scrollbar-none", children: headings.map((h2) => /* @__PURE__ */ jsxs12("li", { children: [
682
696
  /* @__PURE__ */ jsx15(TableOfContentsLink, { heading: h2, activeId, handleClick }),
683
697
  h2.children.map((h3) => /* @__PURE__ */ jsx15(
684
698
  TableOfContentsLink,
@@ -44,8 +44,7 @@ var import_gray_matter = __toESM(require("gray-matter"));
44
44
  var DEFAULT_CONTENT_DIR = import_path.default.join(process.cwd(), "app", "docs", "content");
45
45
  function getFilePath({ slug, CONTENT_DIR }) {
46
46
  const slugArray = Array.isArray(slug) && slug.length > 0 ? slug : ["index"];
47
- const USER_CONTENT_DIR = process.cwd() + CONTENT_DIR;
48
- const DIR = USER_CONTENT_DIR || DEFAULT_CONTENT_DIR;
47
+ const DIR = CONTENT_DIR ? import_path.default.join(process.cwd(), CONTENT_DIR) : DEFAULT_CONTENT_DIR;
49
48
  const possiblePaths = [
50
49
  import_path.default.join(DIR, ...slugArray) + ".mdx",
51
50
  import_path.default.join(DIR, ...slugArray) + ".md",
@@ -57,10 +56,13 @@ function getFilePath({ slug, CONTENT_DIR }) {
57
56
  return filePath;
58
57
  }
59
58
  }
60
- throw new Error(`\u274C MDX file not found in: ${DIR} `);
59
+ throw new Error(`\u274C MDX file not found in: ${DIR}`);
61
60
  }
62
61
  function getFileContents({ slug, CONTENT_DIR }) {
63
- const filePath = getFilePath({ slug, CONTENT_DIR: CONTENT_DIR || DEFAULT_CONTENT_DIR });
62
+ const filePath = getFilePath({
63
+ slug,
64
+ CONTENT_DIR
65
+ });
64
66
  const rawFile = import_fs.default.readFileSync(filePath, "utf-8");
65
67
  const { data, content } = (0, import_gray_matter.default)(rawFile);
66
68
  return {
@@ -5,8 +5,7 @@ import matter from "gray-matter";
5
5
  var DEFAULT_CONTENT_DIR = path.join(process.cwd(), "app", "docs", "content");
6
6
  function getFilePath({ slug, CONTENT_DIR }) {
7
7
  const slugArray = Array.isArray(slug) && slug.length > 0 ? slug : ["index"];
8
- const USER_CONTENT_DIR = process.cwd() + CONTENT_DIR;
9
- const DIR = USER_CONTENT_DIR || DEFAULT_CONTENT_DIR;
8
+ const DIR = CONTENT_DIR ? path.join(process.cwd(), CONTENT_DIR) : DEFAULT_CONTENT_DIR;
10
9
  const possiblePaths = [
11
10
  path.join(DIR, ...slugArray) + ".mdx",
12
11
  path.join(DIR, ...slugArray) + ".md",
@@ -18,10 +17,13 @@ function getFilePath({ slug, CONTENT_DIR }) {
18
17
  return filePath;
19
18
  }
20
19
  }
21
- throw new Error(`\u274C MDX file not found in: ${DIR} `);
20
+ throw new Error(`\u274C MDX file not found in: ${DIR}`);
22
21
  }
23
22
  function getFileContents({ slug, CONTENT_DIR }) {
24
- const filePath = getFilePath({ slug, CONTENT_DIR: CONTENT_DIR || DEFAULT_CONTENT_DIR });
23
+ const filePath = getFilePath({
24
+ slug,
25
+ CONTENT_DIR
26
+ });
25
27
  const rawFile = fs.readFileSync(filePath, "utf-8");
26
28
  const { data, content } = matter(rawFile);
27
29
  return {
package/dist/styles.css CHANGED
@@ -1 +1,43 @@
1
- @source ".";
1
+ @source ".";
2
+
3
+ .scrollbar-none::-webkit-scrollbar {
4
+ display: none;
5
+ }
6
+
7
+ .scrollbar-x::-webkit-scrollbar {
8
+ display: block;
9
+ height: 3.5px;
10
+ }
11
+
12
+ .scrollbar-x::-webkit-scrollbar-track {
13
+ background: var(--color-gray-100);
14
+ }
15
+
16
+ .scrollbar-x::-webkit-scrollbar-thumb {
17
+ background-color: var(--color-gray-300);
18
+ border-radius: 0px;
19
+ background-clip: padding-box;
20
+ }
21
+
22
+ .scrollbar-x::-webkit-scrollbar-thumb:hover {
23
+ background-color: var(--color-gray-400);
24
+ }
25
+
26
+ .scrollbar-y::-webkit-scrollbar {
27
+ display: block;
28
+ width: 3.5px;
29
+ }
30
+
31
+ .scrollbar-y::-webkit-scrollbar-track {
32
+ background: var(--color-gray-100);
33
+ }
34
+
35
+ .scrollbar-y::-webkit-scrollbar-thumb {
36
+ background-color: var(--color-gray-300);
37
+ border-radius: 0px;
38
+ background-clip: padding-box;
39
+ }
40
+
41
+ .scrollbar-y::-webkit-scrollbar-thumb:hover {
42
+ background-color: var(--color-gray-400);
43
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "docstra",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "description": "A Modern Documentation Framework for Next.js",
5
5
  "keywords": [
6
6
  "next",