@docubook/create 2.3.0 → 2.5.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.
Files changed (84) hide show
  1. package/package.json +1 -1
  2. package/src/dist/app/docs/[[...slug]]/page.tsx +56 -63
  3. package/src/dist/app/docs/layout.tsx +11 -4
  4. package/src/dist/app/layout.tsx +10 -9
  5. package/src/dist/app/page.tsx +3 -22
  6. package/src/dist/components/{context-popover.tsx → ContextPopover.tsx} +4 -3
  7. package/src/dist/components/{docs-breadcrumb.tsx → DocsBreadcrumb.tsx} +1 -1
  8. package/src/dist/components/{docs-menu.tsx → DocsMenu.tsx} +2 -2
  9. package/src/dist/components/DocsNavbar.tsx +46 -0
  10. package/src/dist/components/DocsSidebar.tsx +196 -0
  11. package/src/dist/components/Github.tsx +26 -0
  12. package/src/dist/components/{scroll-to-top.tsx → ScrollToTop.tsx} +16 -9
  13. package/src/dist/components/SearchBox.tsx +37 -0
  14. package/src/dist/components/SearchContext.tsx +47 -0
  15. package/src/dist/components/SearchModal.tsx +2 -2
  16. package/src/dist/components/SearchTrigger.tsx +5 -5
  17. package/src/dist/components/Sponsor.tsx +2 -2
  18. package/src/dist/components/{theme-toggle.tsx → ThemeToggle.tsx} +10 -10
  19. package/src/dist/components/TocObserver.tsx +197 -0
  20. package/src/dist/components/footer.tsx +16 -12
  21. package/src/dist/components/leftbar.tsx +45 -73
  22. package/src/dist/components/markdown/AccordionGroupMdx.tsx +1 -1
  23. package/src/dist/components/markdown/AccordionMdx.tsx +4 -4
  24. package/src/dist/components/markdown/CardMdx.tsx +4 -4
  25. package/src/dist/components/markdown/FileTreeMdx.tsx +4 -4
  26. package/src/dist/components/markdown/ImageMdx.tsx +1 -1
  27. package/src/dist/components/markdown/ReleaseMdx.tsx +1 -1
  28. package/src/dist/components/markdown/TooltipsMdx.tsx +1 -1
  29. package/src/dist/components/navbar.tsx +130 -53
  30. package/src/dist/components/sublink.tsx +1 -1
  31. package/src/dist/components/toc.tsx +16 -14
  32. package/src/dist/components/typography.tsx +1 -1
  33. package/src/dist/components/ui/icon-cloud.tsx +353 -0
  34. package/src/dist/components/ui/scroll-area.tsx +2 -2
  35. package/src/dist/components/ui/sheet.tsx +4 -4
  36. package/src/dist/components/ui/toggle.tsx +3 -3
  37. package/src/dist/docs/components/accordion-group.mdx +68 -0
  38. package/src/dist/docs/components/accordion.mdx +59 -0
  39. package/src/dist/docs/components/button.mdx +40 -0
  40. package/src/dist/docs/components/card-group.mdx +47 -0
  41. package/src/dist/docs/components/card.mdx +68 -0
  42. package/src/dist/docs/components/code-block.mdx +67 -0
  43. package/src/dist/docs/components/custom.mdx +38 -0
  44. package/src/dist/docs/components/file-tree.mdx +109 -0
  45. package/src/dist/docs/components/image.mdx +37 -0
  46. package/src/dist/docs/components/index.mdx +9 -0
  47. package/src/dist/docs/components/keyboard.mdx +117 -0
  48. package/src/dist/docs/components/link.mdx +34 -0
  49. package/src/dist/docs/components/note.mdx +44 -0
  50. package/src/dist/docs/components/release-note.mdx +114 -0
  51. package/src/dist/docs/components/stepper.mdx +45 -0
  52. package/src/dist/docs/components/tables.mdx +35 -0
  53. package/src/dist/docs/components/tabs.mdx +72 -0
  54. package/src/dist/docs/components/tooltips.mdx +22 -0
  55. package/src/dist/docs/components/youtube.mdx +23 -0
  56. package/src/dist/docs/getting-started/introduction.mdx +18 -0
  57. package/src/dist/docs/getting-started/quick-start-guide.mdx +60 -0
  58. package/src/dist/docu.json +36 -33
  59. package/src/dist/eslint.config.mjs +17 -30
  60. package/src/dist/hooks/useActiveSection.ts +34 -32
  61. package/src/dist/hooks/useScrollPosition.ts +16 -14
  62. package/src/dist/lib/markdown.ts +32 -17
  63. package/src/dist/lib/utils.ts +1 -1
  64. package/src/dist/next.config.mjs +10 -11
  65. package/src/dist/package.json +1 -1
  66. package/src/dist/styles/algolia.css +11 -9
  67. package/src/dist/styles/{syntax.css → override.css} +82 -39
  68. package/src/dist/tailwind.config.ts +11 -110
  69. package/src/dist/components/GithubStart.tsx +0 -44
  70. package/src/dist/components/mob-toc.tsx +0 -134
  71. package/src/dist/components/search.tsx +0 -55
  72. package/src/dist/components/toc-observer.tsx +0 -254
  73. package/src/dist/docs/api-reference/delete/index.mdx +0 -63
  74. package/src/dist/docs/api-reference/fetch/index.mdx +0 -63
  75. package/src/dist/docs/api-reference/get/index.mdx +0 -63
  76. package/src/dist/docs/api-reference/post/index.mdx +0 -63
  77. package/src/dist/docs/changelog/index.mdx +0 -49
  78. package/src/dist/docs/getting-started/development/index.mdx +0 -92
  79. package/src/dist/docs/getting-started/introduction/index.mdx +0 -92
  80. package/src/dist/docs/getting-started/quick-start-guide/index.mdx +0 -92
  81. /package/src/dist/components/{edit-on-github.tsx → EditWithGithub.tsx} +0 -0
  82. /package/src/dist/components/{contexts/theme-provider.tsx → ThemeProvider.tsx} +0 -0
  83. /package/src/dist/{components/contexts/AccordionContext.ts → lib/accordion-context.ts} +0 -0
  84. /package/src/dist/lib/{routes-config.ts → routes.ts} +0 -0
@@ -0,0 +1,35 @@
1
+ ---
2
+ title: Tables
3
+ description: Organize your data in style with GitHub-flavored tables.
4
+ date: 08-02-2026
5
+ ---
6
+
7
+ Tables are a powerful way to organize and present data. With full support for GitHub Flavored Markdown, you can easily create clean, responsive grids to display properties, comparisons, or datasets. Control column alignment and headers with simple syntax, ensuring your information looks professional and is easy to read.
8
+
9
+ ## Basic Table
10
+
11
+ | Property | Description | Type | Default |
12
+ | --- | --- | --- | --- |
13
+ | `title` | The title of the table | `string` | - |
14
+ | `description` | The description of the table | `string` | - |
15
+
16
+ ## Alignment
17
+
18
+ | Left | Center | Right |
19
+ | :--- | :---: | ---: |
20
+ | Left-aligned text | Center-aligned text | Right-aligned text |
21
+ | Left-aligned text | Center-aligned text | Right-aligned text |
22
+
23
+ ## Output Markdown
24
+
25
+ ```markdown:index.mdx
26
+ | Property | Description | Type | Default |
27
+ | --- | --- | --- | --- |
28
+ | `title` | The title of the table | `string` | - |
29
+ | `description` | The description of the table | `string` | - |
30
+
31
+ | Left | Center | Right |
32
+ | :--- | :---: | ---: |
33
+ | Left-aligned text | Center-aligned text | Right-aligned text |
34
+ | Left-aligned text | Center-aligned text | Right-aligned text |
35
+ ```
@@ -0,0 +1,72 @@
1
+ ---
2
+ title: Tabs
3
+ description: Organize content into multiple sections with switchable tabs.
4
+ date: 14-12-2024
5
+ ---
6
+
7
+ The `Tabs` component allows you to organize content into multiple sections, enabling users to switch between them easily. This is particularly useful for displaying related content in a compact manner.
8
+
9
+ ## Preview
10
+
11
+ <Tabs defaultValue="java" className="pt-5 pb-1">
12
+ <TabsList>
13
+ <TabsTrigger value="java">Java</TabsTrigger>
14
+ <TabsTrigger value="typescript">TypeScript</TabsTrigger>
15
+ </TabsList>
16
+ <TabsContent value="java">
17
+ ```java:HelloWorld.java
18
+ // HelloWorld.java
19
+ public class HelloWorld {
20
+ public static void main(String[] args) {
21
+ System.out.println("Hello, World!");
22
+ }
23
+ }
24
+ ```
25
+ </TabsContent>
26
+ <TabsContent value="typescript">
27
+ ```typescript:helloWorld.ts
28
+ // helloWorld.ts
29
+ function helloWorld(): void {
30
+ console.log("Hello, World!");
31
+ }
32
+ helloWorld();
33
+ ```
34
+ </TabsContent>
35
+ </Tabs>
36
+
37
+ ## Props
38
+
39
+ | Prop | Type | Default | Description |
40
+ | -------------- | -------- | ------- | ------------------------------------------------------ |
41
+ | `defaultValue` | string | null | The value of the tab that is selected by default. |
42
+ | `className` | string | null | Additional CSS classes for styling the Tabs component. |
43
+
44
+ ## Output Markdown
45
+
46
+ ````plaintext
47
+ <Tabs defaultValue="java" className="pt-5 pb-1">
48
+ <TabsList>
49
+ <TabsTrigger value="java">Java</TabsTrigger>
50
+ <TabsTrigger value="typescript">TypeScript</TabsTrigger>
51
+ </TabsList>
52
+ <TabsContent value="java">
53
+ ```java:HelloWorld.java
54
+ // HelloWorld.java
55
+ public class HelloWorld {
56
+ public static void main(String[] args) {
57
+ System.out.println("Hello, World!");
58
+ }
59
+ }
60
+ ```
61
+ </TabsContent>
62
+ <TabsContent value="typescript">
63
+ ```typescript:helloWorld.ts
64
+ // helloWorld.ts
65
+ function helloWorld(): void {
66
+ console.log("Hello, World!");
67
+ }
68
+ helloWorld();
69
+ ```
70
+ </TabsContent>
71
+ </Tabs>
72
+ ````
@@ -0,0 +1,22 @@
1
+ ---
2
+ title: Tooltips
3
+ description: A component used to display additional information when hovering over a word or phrase.
4
+ date: 19-02-2025
5
+ ---
6
+
7
+ I have implemented the `tooltips` component into markdown which allows you to add additional information to a word or phrase when hovering. This feature is useful for providing definitions, explanations, or any other additional information that can enhance the user experience.
8
+
9
+ ## Usage
10
+ You can use tooltips in your Markdown content to provide additional information when hovering over a word or phrase.
11
+
12
+ ### Preview
13
+
14
+ What do you know about <Tooltip text="DocuBook" tip="npx @docubook/create@latest" /> ? Create interactive nested documentations using MDX.
15
+
16
+ ### Output Markdown
17
+
18
+ The above Markdown is converted to:
19
+
20
+ ```markdown:index.mdx
21
+ What do you know about <Tooltip text="DocuBook" tip="npx @docubook/create@latest" /> ? Create interactive nested documentations using MDX.
22
+ ```
@@ -0,0 +1,23 @@
1
+ ---
2
+ title: Youtube
3
+ description: A component used to embed YouTube videos directly into your documentation.
4
+ date: 14-12-2024
5
+ ---
6
+
7
+ I have implemented a `YouTube` component for your documentation. This component allows you to easily embed YouTube videos directly into your documentation by simply inputting the video's ID.
8
+
9
+ ## Preview
10
+
11
+ <Youtube videoId="OPM2t54T-Vo" />
12
+
13
+ ## Output Markdown
14
+
15
+ ```markdown
16
+ <Youtube videoId="OPM2t54T-Vo" />
17
+ ```
18
+
19
+ ## Usage
20
+
21
+ <Note type="note" title="Usage">
22
+ for example the youtube URL show this https://www.youtube.com/watch?v=OPM2t54T-Vo the ID `OPM2t54T-Vo`
23
+ </Note>
@@ -0,0 +1,18 @@
1
+ ---
2
+ title : Introduction
3
+ description : overview or synopsis of a project
4
+ date : 10-12-2024
5
+ ---
6
+
7
+ ## Hello World
8
+
9
+ Welcome to the documentation!
10
+
11
+ <CardGroup cols={2}>
12
+ <Card title="Quickstart" icon="Zap" href="/docs/getting-started/quick-start-guide">
13
+ Get started with DocuBook in minutes.
14
+ </Card>
15
+ <Card title="Components" icon="Layers" href="/docs/components">
16
+ Explore the available library of components.
17
+ </Card>
18
+ </CardGroup>
@@ -0,0 +1,60 @@
1
+ ---
2
+ title : Quick Start Guide
3
+ description : a quick way to understand how to use it
4
+ date : 10-12-2024
5
+ ---
6
+
7
+ ## Adding a Route
8
+
9
+ To add a new page to your documentation, you need to register it in the `docu.json` file.
10
+
11
+ <Stepper>
12
+ <StepperItem title="Create the MDX file">
13
+ Create a new `.mdx` file in the `docs` directory. For example, `docs/my-new-page.mdx`.
14
+ </StepperItem>
15
+ <StepperItem title="Register in docu.json">
16
+ Open `docu.json` and add an entry to the `routes` array.
17
+
18
+ ```json
19
+ {
20
+ "title": "My New Page",
21
+ "href": "/my-new-page"
22
+ }
23
+ ```
24
+ </StepperItem>
25
+ </Stepper>
26
+
27
+ ## Writing Content
28
+
29
+ DocuBook supports standard Markdown and a variety of custom components to make your documentation more interactive.
30
+
31
+ ### Using Components
32
+
33
+ Here are some common components you can use:
34
+
35
+ #### Cards
36
+
37
+ Use cards to highlight important links or features.
38
+
39
+ <CardGroup cols={2}>
40
+ <Card title="Installation" icon="Download" href="#">
41
+ Learn how to install DocuBook.
42
+ </Card>
43
+ <Card title="Configuration" icon="Settings" href="#">
44
+ Configure your documentation site.
45
+ </Card>
46
+ </CardGroup>
47
+
48
+ #### Notes
49
+
50
+ Use notes to provide additional context or warnings.
51
+
52
+ <Note type="warning" title="Warning">
53
+ Always remember to back up your configuration files.
54
+ </Note>
55
+
56
+ <Note type="note" title="Pro Tip">
57
+ You can use Lucide icons in your cards by specifying the `icon` prop.
58
+ </Note>
59
+
60
+ For more details on available components, check out the [Components](/docs/components) section.
@@ -21,7 +21,7 @@
21
21
  "repository": {
22
22
  "url": "https://github.com/DocuBook/docubook",
23
23
  "editPathTemplate": "/blob/main/{filePath}",
24
- "editLink": true
24
+ "editLink": false
25
25
  },
26
26
  "sponsor": {
27
27
  "title": "Hosted on",
@@ -63,41 +63,44 @@
63
63
  "href": "/getting-started",
64
64
  "noLink": true,
65
65
  "context": {
66
- "icon": "Book",
67
- "description": "Set up your Documentation",
68
- "title": "Guides"
69
- },
70
- "items": [
71
- { "title": "Introduction", "href": "/introduction" },
72
- { "title": "Quick Start Guide", "href": "/quick-start-guide" },
73
- { "title": "Development", "href": "/development" }
74
- ]
66
+ "icon": "Book",
67
+ "description": "Set up your Documentation",
68
+ "title": "Guides"
75
69
  },
76
- {
77
- "title": "Api Reference",
78
- "href": "/api-reference",
70
+ "items": [
71
+ { "title": "Introduction", "href": "/introduction" },
72
+ { "title": "Quick Start Guide", "href": "/quick-start-guide" }
73
+ ]
74
+ },
75
+ {
76
+ "title": "Components",
77
+ "href": "/components",
79
78
  "noLink": true,
80
79
  "context": {
81
- "icon": "Terminal",
82
- "description": "reference for using the API",
83
- "title": "API Reference"
84
- },
85
- "items": [
86
- { "title": "Get", "href": "/get" },
87
- { "title": "Fetch", "href": "/fetch" },
88
- { "title": "Post", "href": "/post" },
89
- { "title": "Delete", "href": "/delete" }
90
- ]
80
+ "icon": "Layers",
81
+ "description": "Write with Markdown",
82
+ "title": "Markdown"
91
83
  },
92
- {
93
- "title": "Changelog",
94
- "href": "/changelog",
95
- "noLink": true,
96
- "context": {
97
- "icon": "History",
98
- "description": "Update and Changes",
99
- "title": "Release"
100
- }
101
- }
84
+ "items": [
85
+ { "title": "Accordion", "href": "/accordion" },
86
+ { "title": "Accordion Group", "href": "/accordion-group" },
87
+ { "title": "Button", "href": "/button" },
88
+ { "title": "Card", "href": "/card" },
89
+ { "title": "Card Group", "href": "/card-group" },
90
+ { "title": "Code Block", "href": "/code-block" },
91
+ { "title": "File Tree", "href": "/file-tree" },
92
+ { "title": "Image", "href": "/image" },
93
+ { "title": "Keyboard", "href": "/keyboard" },
94
+ { "title": "Link", "href": "/link" },
95
+ { "title": "Note", "href": "/note" },
96
+ { "title": "Release Note", "href": "/release-note" },
97
+ { "title": "Stepper", "href": "/stepper" },
98
+ { "title": "Tabs", "href": "/tabs" },
99
+ { "title": "Tooltips", "href": "/tooltips" },
100
+ { "title": "Tables", "href": "/tables" },
101
+ { "title": "Youtube", "href": "/youtube" },
102
+ { "title": "Custom", "href": "/custom" }
103
+ ]
104
+ }
102
105
  ]
103
106
  }
@@ -1,35 +1,22 @@
1
- import { defineConfig } from "eslint/config";
2
1
  import nextCoreWebVitals from "eslint-config-next/core-web-vitals";
3
2
  import nextTypescript from "eslint-config-next/typescript";
4
- import path from "node:path";
5
- import { fileURLToPath } from "node:url";
6
3
  import js from "@eslint/js";
7
- import { FlatCompat } from "@eslint/eslintrc";
4
+ import tseslint from "typescript-eslint";
8
5
 
9
- const __filename = fileURLToPath(import.meta.url);
10
- const __dirname = path.dirname(__filename);
11
- const compat = new FlatCompat({
12
- baseDirectory: __dirname,
13
- recommendedConfig: js.configs.recommended,
14
- allConfig: js.configs.all
15
- });
16
-
17
- export default defineConfig([{
18
- extends: [
19
- ...nextCoreWebVitals,
20
- ...nextTypescript,
21
- ...compat.extends("plugin:@typescript-eslint/recommended")
22
- ],
23
-
24
- rules: {
25
- "@typescript-eslint/no-explicit-any": "warn",
26
-
27
- "@typescript-eslint/no-unused-vars": ["warn", {
28
- argsIgnorePattern: "^_",
29
- varsIgnorePattern: "^_",
30
- caughtErrorsIgnorePattern: "^_",
31
- }],
32
-
33
- "@typescript-eslint/no-empty-object-type": "off",
6
+ export default tseslint.config(
7
+ js.configs.recommended,
8
+ ...nextCoreWebVitals,
9
+ ...nextTypescript,
10
+ ...tseslint.configs["recommended"],
11
+ {
12
+ rules: {
13
+ "@typescript-eslint/no-explicit-any": "warn",
14
+ "@typescript-eslint/no-unused-vars": ["warn", {
15
+ argsIgnorePattern: "^_",
16
+ varsIgnorePattern: "^_",
17
+ caughtErrorsIgnorePattern: "^_",
18
+ }],
19
+ "@typescript-eslint/no-empty-object-type": "off",
20
+ },
34
21
  },
35
- }]);
22
+ );
@@ -1,68 +1,70 @@
1
- import { useState, useCallback, useEffect, useRef } from 'react';
2
- import { TocItem } from '@/lib/toc';
1
+ "use client"
2
+
3
+ import { useState, useCallback, useEffect, useRef } from "react"
4
+ import { TocItem } from "@/lib/toc"
3
5
 
4
6
  export function useActiveSection(tocs: TocItem[]) {
5
- const [activeId, setActiveId] = useState<string | null>(null);
6
- const observerRef = useRef<IntersectionObserver | null>(null);
7
- const clickedIdRef = useRef<string | null>(null);
7
+ const [activeId, setActiveId] = useState<string | null>(null)
8
+ const observerRef = useRef<IntersectionObserver | null>(null)
9
+ const clickedIdRef = useRef<string | null>(null)
8
10
 
9
11
  // Handle intersection observer for active section
10
12
  useEffect(() => {
11
- if (typeof document === 'undefined' || !tocs.length) return;
13
+ if (typeof document === "undefined" || !tocs.length) return
12
14
 
13
15
  const handleIntersect = (entries: IntersectionObserverEntry[]) => {
14
- if (clickedIdRef.current) return;
16
+ if (clickedIdRef.current) return
15
17
 
16
- const visibleEntries = entries.filter(entry => entry.isIntersecting);
17
- if (!visibleEntries.length) return;
18
+ const visibleEntries = entries.filter((entry) => entry.isIntersecting)
19
+ if (!visibleEntries.length) return
18
20
 
19
21
  // Find the most visible entry
20
22
  const mostVisibleEntry = visibleEntries.reduce((prev, current) => {
21
- return current.intersectionRatio > prev.intersectionRatio ? current : prev;
22
- }, visibleEntries[0]);
23
+ return current.intersectionRatio > prev.intersectionRatio ? current : prev
24
+ }, visibleEntries[0])
23
25
 
24
- const newActiveId = mostVisibleEntry.target.id;
26
+ const newActiveId = mostVisibleEntry.target.id
25
27
  if (newActiveId !== activeId) {
26
- setActiveId(newActiveId);
28
+ setActiveId(newActiveId)
27
29
  }
28
- };
30
+ }
29
31
 
30
32
  // Initialize intersection observer
31
33
  observerRef.current = new IntersectionObserver(handleIntersect, {
32
- root: null,
33
- rootMargin: '0px 0px -80% 0px',
34
- threshold: 0.1,
35
- });
34
+ root: document.getElementById("scroll-container"),
35
+ rootMargin: "0px 0px -60% 0px",
36
+ threshold: 0,
37
+ })
36
38
 
37
39
  // Observe all headings
38
- tocs.forEach(toc => {
39
- const element = document.getElementById(toc.href.slice(1));
40
+ tocs.forEach((toc) => {
41
+ const element = document.getElementById(toc.href.slice(1))
40
42
  if (element) {
41
- observerRef.current?.observe(element);
43
+ observerRef.current?.observe(element)
42
44
  }
43
- });
45
+ })
44
46
 
45
47
  // Cleanup
46
48
  return () => {
47
- observerRef.current?.disconnect();
48
- };
49
- }, [tocs, activeId]);
49
+ observerRef.current?.disconnect()
50
+ }
51
+ }, [tocs, activeId])
50
52
 
51
53
  const handleLinkClick = useCallback((id: string) => {
52
- clickedIdRef.current = id;
53
- setActiveId(id);
54
+ clickedIdRef.current = id
55
+ setActiveId(id)
54
56
 
55
57
  // Reset clicked state after scroll completes
56
58
  const timer = setTimeout(() => {
57
- clickedIdRef.current = null;
58
- }, 1000);
59
+ clickedIdRef.current = null
60
+ }, 1000)
59
61
 
60
- return () => clearTimeout(timer);
61
- }, []);
62
+ return () => clearTimeout(timer)
63
+ }, [])
62
64
 
63
65
  return {
64
66
  activeId,
65
67
  setActiveId,
66
68
  handleLinkClick,
67
- };
69
+ }
68
70
  }
@@ -1,29 +1,31 @@
1
- import { useState, useCallback, useEffect } from 'react';
1
+ "use client"
2
+
3
+ import { useState, useCallback, useEffect } from "react"
2
4
 
3
5
  export function useScrollPosition(threshold = 0.5) {
4
- const [isScrolled, setIsScrolled] = useState(false);
6
+ const [isScrolled, setIsScrolled] = useState(false)
5
7
 
6
8
  const handleScroll = useCallback(() => {
7
- if (typeof window === 'undefined') return;
9
+ if (typeof window === "undefined") return
8
10
 
9
- const scrollPosition = window.scrollY;
10
- const viewportHeight = window.innerHeight;
11
- const shouldBeSticky = scrollPosition > viewportHeight * threshold;
11
+ const scrollPosition = window.scrollY
12
+ const viewportHeight = window.innerHeight
13
+ const shouldBeSticky = scrollPosition > viewportHeight * threshold
12
14
 
13
- setIsScrolled(prev => shouldBeSticky !== prev ? shouldBeSticky : prev);
14
- }, [threshold]);
15
+ setIsScrolled((prev) => (shouldBeSticky !== prev ? shouldBeSticky : prev))
16
+ }, [threshold])
15
17
 
16
18
  // Add scroll event listener
17
19
  useEffect(() => {
18
20
  // Initial check
19
21
  // eslint-disable-next-line react-hooks/set-state-in-effect
20
- handleScroll();
22
+ handleScroll()
21
23
 
22
- window.addEventListener('scroll', handleScroll, { passive: true });
24
+ window.addEventListener("scroll", handleScroll, { passive: true })
23
25
  return () => {
24
- window.removeEventListener('scroll', handleScroll);
25
- };
26
- }, [handleScroll]);
26
+ window.removeEventListener("scroll", handleScroll)
27
+ }
28
+ }, [handleScroll])
27
29
 
28
- return isScrolled;
30
+ return isScrolled
29
31
  }
@@ -6,7 +6,7 @@ import rehypePrism from "rehype-prism-plus";
6
6
  import rehypeAutolinkHeadings from "rehype-autolink-headings";
7
7
  import rehypeSlug from "rehype-slug";
8
8
  import rehypeCodeTitles from "rehype-code-titles";
9
- import { page_routes, ROUTES } from "./routes-config";
9
+ import { page_routes, ROUTES } from "./routes";
10
10
  import { visit } from "unist-util-visit";
11
11
  import type { Node, Parent } from "unist";
12
12
  import matter from "gray-matter";
@@ -163,17 +163,20 @@ export type BaseMdxFrontmatter = {
163
163
 
164
164
  export async function getDocsForSlug(slug: string) {
165
165
  try {
166
- const contentPath = getDocsContentPath(slug);
167
- const rawMdx = await fs.readFile(contentPath, "utf-8");
168
- return await parseMdx<BaseMdxFrontmatter>(rawMdx);
166
+ const { content, filePath } = await getRawMdx(slug);
167
+ const mdx = await parseMdx<BaseMdxFrontmatter>(content);
168
+ return {
169
+ ...mdx,
170
+ filePath,
171
+ };
169
172
  } catch (err) {
170
173
  console.log(err);
171
174
  }
172
175
  }
173
176
 
174
177
  export async function getDocsTocs(slug: string) {
175
- const contentPath = getDocsContentPath(slug);
176
- const rawMdx = await fs.readFile(contentPath, "utf-8");
178
+ const { content } = await getRawMdx(slug);
179
+ const rawMdx = content;
177
180
 
178
181
  // Regex to match code blocks (```...```), standard markdown headings (##), and <Release> tags
179
182
  const combinedRegex = /(```[\s\S]*?```)|^(#{2,4})\s(.+)$|<Release[^>]*version="([^"]+)"/gm;
@@ -222,8 +225,26 @@ function sluggify(text: string) {
222
225
  return slug.replace(/[^a-z0-9-]/g, "");
223
226
  }
224
227
 
225
- function getDocsContentPath(slug: string) {
226
- return path.join(process.cwd(), "/docs/", `${slug}/index.mdx`);
228
+ async function getRawMdx(slug: string) {
229
+ const commonPath = path.join(process.cwd(), "/docs/");
230
+ const paths = [
231
+ path.join(commonPath, `${slug}.mdx`),
232
+ path.join(commonPath, slug, "index.mdx"),
233
+ ];
234
+
235
+ for (const p of paths) {
236
+ try {
237
+ const content = await fs.readFile(p, "utf-8");
238
+ return {
239
+ content,
240
+ filePath: `docs/${path.relative(commonPath, p)}`,
241
+ };
242
+ } catch {
243
+ // ignore and try next
244
+ }
245
+ }
246
+
247
+ throw new Error(`Could not find mdx file for slug: ${slug}`);
227
248
  }
228
249
 
229
250
  function justGetFrontmatterFromMD<Frontmatter>(rawMd: string): Frontmatter {
@@ -245,16 +266,10 @@ export async function getAllChilds(pathString: string) {
245
266
 
246
267
  return await Promise.all(
247
268
  page_routes_copy.map(async (it) => {
248
- const totalPath = path.join(
249
- process.cwd(),
250
- "/docs/",
251
- prevHref,
252
- it.href,
253
- "index.mdx"
254
- );
255
- const raw = await fs.readFile(totalPath, "utf-8");
269
+ const slug = path.join(prevHref, it.href);
270
+ const { content } = await getRawMdx(slug);
256
271
  return {
257
- ...justGetFrontmatterFromMD<BaseMdxFrontmatter>(raw),
272
+ ...justGetFrontmatterFromMD<BaseMdxFrontmatter>(content),
258
273
  href: `/docs${prevHref}${it.href}`,
259
274
  };
260
275
  })
@@ -1,6 +1,6 @@
1
1
  import { type ClassValue, clsx } from "clsx";
2
2
  import { twMerge } from "tailwind-merge";
3
- import { EachRoute, ROUTES } from "./routes-config";
3
+ import { EachRoute, ROUTES } from "./routes";
4
4
 
5
5
  export function cn(...inputs: ClassValue[]) {
6
6
  return twMerge(clsx(inputs));
@@ -1,14 +1,13 @@
1
1
  /** @type {import('next').NextConfig} */
2
2
  const nextConfig = {
3
- images: {
4
- remotePatterns: [
5
- {
6
- protocol: "https",
7
- hostname: "**",
8
- },
9
- ],
10
- },
11
- };
12
-
13
- export default nextConfig;
3
+ images: {
4
+ remotePatterns: [
5
+ {
6
+ protocol: "https",
7
+ hostname: "**",
8
+ },
9
+ ],
10
+ },
11
+ }
14
12
 
13
+ export default nextConfig
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "docubook",
3
- "version": "2.3.0",
3
+ "version": "2.5.0",
4
4
  "private": true,
5
5
  "scripts": {
6
6
  "dev": "next dev",