From 9426e948841ab804cd880d9f3e367b98343b81d7 Mon Sep 17 00:00:00 2001 From: gitfromwildan <> Date: Sun, 1 Jun 2025 22:19:56 +0700 Subject: [PATCH] push docu version 1.13.6 --- CHANGELOG.md | 357 -- README.md | 2 +- components/context-popover.tsx | 133 + components/docs-menu.tsx | 60 +- components/footer.tsx | 6 +- components/leftbar.tsx | 18 +- components/markdown/CardGroupMdx.tsx | 2 +- components/markdown/CardMdx.tsx | 9 +- components/markdown/FileTreeMdx.tsx | 138 + components/markdown/KeyboardMdx.tsx | 2 +- components/markdown/NoteMdx.tsx | 2 +- components/markdown/StepperMdx.tsx | 4 +- components/markdown/TooltipsMdx.tsx | 9 +- components/navbar.tsx | 6 +- components/pagination.tsx | 2 +- components/search.tsx | 44 +- components/sublink.tsx | 13 +- components/theme-toggle.tsx | 20 +- components/toc-observer.tsx | 18 +- docu.json | 10 + lib/changelog.ts | 76 - lib/markdown.ts | 67 +- lib/routes-config.ts | 9 +- package-lock.json | 8628 -------------------------- package.json | 4 +- styles/editor.css | 57 - styles/globals.css | 1 - tailwind.config.ts | 1 - 28 files changed, 437 insertions(+), 9261 deletions(-) delete mode 100644 CHANGELOG.md create mode 100644 components/context-popover.tsx create mode 100644 components/markdown/FileTreeMdx.tsx delete mode 100644 lib/changelog.ts delete mode 100644 package-lock.json delete mode 100644 styles/editor.css diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index 3b71425..0000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,357 +0,0 @@ -## [1.8.5] - 2025-05-10 - -> Add sponsor card on single docs page - -### Added - -- Expandables Leftbar -- sponsor badges or ads -- boolean show/hide `edit on github` -- with the same code run anywhere (bun or nodejs) -- add fronmatter (metadata) to playground editor - -### Improved - -- adjusment docu.json -- adjustment navbar, footer and components - -### Fixed - -- bun compability rename .js to common js -- cli manage packageManager on package.json -- inconsistent design moved to better UI/UX -- error handle render footer.social - -### Removed - -- remove confused and verbose cli on installer - -## [1.8.0] - 2025-03-01 - -> Now looks more modern and clean which is a big change in layout and design - -### Added - -- Social footer -- Toggle group -- Site description {meta.description} in footer -- Site title {meta.title} in footer - -### Improved - -- Header design changes -- Footer design changes -- New functions in theme provider -- Object changes in docu.json - -### Fixed - -- Updates to path structure components -- Groups to organize components - -## [1.7.0] - 2025-02-23 - -> Remove the old function in the search dialog and replace it with a new and more optimal feature - -### Added - -- Up and down navigation : search dialog.tsx -- Enter (return) to select : search dialog.tsx -- Escape to close the dialog : search dialog.tsx - -### Improved - -- Maintenance for anchor components -- Anchor.tsx adjustments for all elements that use it - -### Removed - -- Remove suboptimal search features - -## [1.6.0] - 2025-02-21 - -> New Feature Card Groups with arrays for more Flexible Content - -### Added - -- Card Groups Components -- Props : href to url link -- Props : horizontal boolean - -### Improved - -- Card props styling -- Compability for Cards components -- {children} support for card content - -### Removed - -- remove unused props cards components - -## [1.5.0] - 2025-02-18 - -> Minor Update - improved features and responsiveness on all devices - -### Added - -- New dialog footer on searchbox above @media 768px -- Icon X for close dialog on searcbox as esc on medium screen - -### Improved - -- Responsive Leftbar components on large screen -- Menu Trigger on medium screen -- Responsive Navbar components on medium screen -- Better UX for searchbox dialog -- tooltips components can be written together with regular paragraphs - -### Fixed - -- Responsive issue -- Compatibility for Bun -- Changes postcss.config.js to .cjs for Bun -- all CLI installer and updater not working -- adjustments for package managers npm, pnpm, bun, yarn - -## [1.4.2] - 2025-02-16 - -> Complex Content for Accordion Component props {children} - -### Added - -- New Props with {children} in accordion -- Compatibility for markdown in accordion -- Nested components inside an accordion -- New icon on note components -- add CLI npx @docubook/create@latest -- add CLI npx @docubook/update@latest - -### Improved - -- Better UI design for accordion -- Styling Note components on markdown -- Change accordion output on playground -- Change accordion output on snippet - -### Removed - -- Remove depcreated props on accordion -- Remove CLI npx update_docu -- Remove CLI npx create_docu - -## [1.4.0] - 2025-02-11 - -> Floating Button Version with Dynamic Tag {version} on Changelog page - -### Added - -- New components / changelog floating-version.tsx -- Button popover to open version-toc below @media 1024px -- Dynamic tag by section ID #version -- Dynamic url tag #version -- Dynamic version indicator on floating version when scrolling section by ID - -### Improved - -- change icon version history -- responsive version-toc -- improvement components to changelog page - -## [1.3.8] - 2025-02-08 - -> Responsive Table of Content - -### Added - -- Components terminal MagicUI -- Components card Shadcn -- New mob-toc for a better experience on mobile devices -- New Components scroll to top button -- Scroll to top :blog-post -- Scroll to top :docs-post - -### Improved - -- lib/markdown for generated dynamic toc on markdown -- Responsive Table of Content below @media 1024px -- Improve docs page - -## [1.3.6] - 2025-02-01 - -> Appears more modern editor for Docu Play - -![version 1.3.6 - Playground](https://docubook.pro/images/new-editor.png) - -### Added - -- Line Number for editor -- editor.css - -### Improved - -- Better Design for Editor -- Similar to Github Editor -- Moved Handler Element (copy, download, reset and fullscreen) on Header - -## [1.3.5] - 2025-01-30 - -> it's Easy to Write Markdown with Playground - -![version 1.3.5 - Playground](https://docubook.pro/images/img-playground.png) - -### Added - -- New Playground Page -- New Playground Layout -- Toolbar for Markdown Components -- Fullscreen Mode to Focus Editing Your Content -- Copy to Clipboard Your Content -- Download Your Content as index.mdx -- Reset Your Content without refresh the Browser -- Only Large Screen for Better Experience - -## [1.3.1] - 2025-01-20 - -> Snippet Feature to Easily Write Markdown and Call DocuBook Components - -![version 1.3.1 - Snippet Features](https://docubook.pro/images/snippet.png) - -### Added - -- New Feature Snippet for Markdown Components -- Support Snippet for Visual Studio Code - -### Removed - -- remove props icon and props description for accordion components - -## [1.3.0] - 2024-12-31 - -> Release Note Feature to Make it Easier to Write Changelogs - -### Added - -- New Release Note Feature -- New Layout for Changelog page -- New Changelog page -- Add Release Note Component -- Easily write release notes directly from the CHANGELOG.md file -- TOC for versioning -- Write with the markdown tag -- Add lib / changelog.ts - -### Improved - -- Improvement Responsive feature image for Version Entry -- Improvement Layout for changelog page -- Improvement Padding on mobile devices -- Only use containers of md size -- Improvement syntax.css for ul>li classes - -### Fixed - -- Fix og:image not showing on Page.tsx -- Fix text-indent on class li - -### Removed - -- Remove excessive padding -- Remove Logo on Footer - -## [1.2.0] - 2024-12-22 - -> New Accordion Component : Support content plain text, html and all markdown component - -### Added - -- add New Accordion - -### Improved - -- Props Improvement -- Support Dynamic Content for Accordion - -## [1.1.0] - 2024-12-15 - -> Minor Update : Easily manage set up with docu.json - -### Added - -- add docu.json file -- add openGraph (title, description, image) -- add Dynamic metadata -- Generate metadata as openGraph -- openGraph support for .mdx - -### Improved - -- routes-config from json -- Frontmatter improvement -- Edit the content of footer.tsx simply via the docu.json file -- Edit the content of navbar.tsx simply via the docu.json file - -## [1.0.7] - 2024-12-14 - -> Easily updates your DocuBook Version with CLI npx update_docu - -### Added - -- CLI npx update_docu (update features into docubook existing directory) -- Playground (easily to written content) -- New Button component -- Navbar external link conditions -- CLI npx create_docu - -### Improved - -- Searchbar Improvement -- Navigation Improvement -- Edit on Github Improvement - -### Removed -- Remove CLI npx create-docu (on this version not usage dash `-`) - -## [1.0.6] - 2024-11-24 - -> New Components, Fix and Improvement - -### Added - -- New Card component -- New Tooltips component - -### Fixed - -- change root folder - -### Improved - -- logo on navbar & footer -- easily change logo - -## [1.0.5] - 2024-11-16 - -> Add New Features and Improvement for this version - -### Added - -- New Youtube component -- edit this page - easily manage directory content via the github repo -- support installation via cli commant npx create-docu - -### Improved - -- keyboard shortcut command + k or ctrl + k to open search dialog - -## [1.0.0] - 2024-11-10 - -> Initial release of DocuBook to create interactive nested docs with MDX - -### Added - -- Initial release of DocuBook -- Basic documentation structure -- Markdown support with MDX -- Responsive design -- Search functionality -- Dark mode support diff --git a/README.md b/README.md index 68f4d02..67ddb8e 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ **DocuBook** is a documentation web project designed to provide a simple and user-friendly interface for accessing various types of documentation. This site is crafted for developers and teams who need quick access to references, guides, and essential documents. [![Deploy with -Vercel](https://vercel.com/button)](https://vercel.com/import/project?template=https://github.com/gitfromwildan/docubook) +Vercel](https://vercel.com/button)](https://vercel.com/import/project?template=https://github.com/DocuBook/docubook) ## Features diff --git a/components/context-popover.tsx b/components/context-popover.tsx new file mode 100644 index 0000000..bbc454a --- /dev/null +++ b/components/context-popover.tsx @@ -0,0 +1,133 @@ +"use client"; + +import { usePathname, useRouter } from "next/navigation"; +import { useState, useEffect } from "react"; +import { ROUTES, EachRoute } from "@/lib/routes-config"; +import { cn } from "@/lib/utils"; +import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"; +import { Button } from "@/components/ui/button"; +import * as LucideIcons from "lucide-react"; +import { ChevronsUpDown, Check, type LucideIcon } from "lucide-react"; + +interface ContextPopoverProps { + className?: string; +} + +// Get all root-level routes with context +function getContextRoutes(): EachRoute[] { + return ROUTES.filter(route => route.context); +} + +// Get the first item's href from a route +function getFirstItemHref(route: EachRoute): string { + return route.items?.[0]?.href ? `${route.href}${route.items[0].href}` : route.href; +} + +// Get the active context route from the current path +function getActiveContextRoute(path: string): EachRoute | undefined { + if (!path.startsWith('/docs')) return undefined; + const docPath = path.replace(/^\/docs/, ''); + return getContextRoutes().find(route => docPath.startsWith(route.href)); +} + +// Get icon component by name +function getIcon(name: string) { + const Icon = LucideIcons[name as keyof typeof LucideIcons] as LucideIcon | undefined; + if (!Icon) return ; + return ; +} + +export default function ContextPopover({ className }: ContextPopoverProps) { + const pathname = usePathname(); + const router = useRouter(); + const [activeRoute, setActiveRoute] = useState(); + const contextRoutes = getContextRoutes(); + + useEffect(() => { + if (pathname.startsWith("/docs")) { + setActiveRoute(getActiveContextRoute(pathname)); + } else { + setActiveRoute(undefined); + } + }, [pathname]); + + if (!pathname.startsWith("/docs") || contextRoutes.length === 0) { + return null; + } + + return ( + + + + + +
+ {contextRoutes.map((route) => { + const isActive = activeRoute?.href === route.href; + const firstItemPath = getFirstItemHref(route); + const contextPath = `/docs${firstItemPath}`; + + return ( + + ); + })} +
+
+
+ ); +} diff --git a/components/docs-menu.tsx b/components/docs-menu.tsx index 2ef1d9a..4df580c 100644 --- a/components/docs-menu.tsx +++ b/components/docs-menu.tsx @@ -1,44 +1,62 @@ "use client"; -import { ROUTES } from "@/lib/routes-config"; +import { ROUTES, EachRoute } from "@/lib/routes-config"; import SubLink from "./sublink"; import { usePathname } from "next/navigation"; +import { cn } from "@/lib/utils"; interface DocsMenuProps { isSheet?: boolean; className?: string; } +// Get the current context from the path +function getCurrentContext(path: string): string | undefined { + if (!path.startsWith('/docs')) return undefined; + + // Extract the first segment after /docs/ + const match = path.match(/^\/docs\/([^\/]+)/); + return match ? match[1] : undefined; +} + +// Get the route that matches the current context +function getContextRoute(contextPath: string): EachRoute | undefined { + return ROUTES.find(route => { + const normalizedHref = route.href.replace(/^\/+|\/+$/g, ''); + return normalizedHref === contextPath; + }); +} + export default function DocsMenu({ isSheet = false, className = "" }: DocsMenuProps) { const pathname = usePathname(); // Skip rendering if not on a docs page if (!pathname.startsWith("/docs")) return null; + // Get the current context + const currentContext = getCurrentContext(pathname); + + // Get the route for the current context + const contextRoute = currentContext ? getContextRoute(currentContext) : undefined; + + // If no context route is found, don't render anything + if (!contextRoute) return null; + return ( ); diff --git a/components/footer.tsx b/components/footer.tsx index fe71929..953cb48 100644 --- a/components/footer.tsx +++ b/components/footer.tsx @@ -63,8 +63,9 @@ export function FooterButtons() { target="_blank" rel="noopener noreferrer" aria-label={item.name} + className="text-muted-foreground hover:text-foreground transition-colors" > - + ); })} @@ -79,7 +80,8 @@ export function MadeWith() { DocuBook - + + ); } diff --git a/components/leftbar.tsx b/components/leftbar.tsx index e0de122..2264751 100644 --- a/components/leftbar.tsx +++ b/components/leftbar.tsx @@ -9,12 +9,12 @@ import { } from "@/components/ui/sheet"; import { Logo, NavMenu } from "@/components/navbar"; import { Button } from "@/components/ui/button"; -import { AlignLeftIcon, PanelLeftClose, PanelLeftOpen } from "lucide-react"; -import { FooterButtons } from "@/components/footer"; +import { LayoutGrid, PanelLeftClose, PanelLeftOpen } from "lucide-react"; import { DialogTitle, DialogDescription } from "@/components/ui/dialog"; import { ScrollArea } from "@/components/ui/scroll-area"; import DocsMenu from "@/components/docs-menu"; import { ModeToggle } from "@/components/theme-toggle"; +import ContextPopover from "@/components/context-popover"; // Toggle Button Component export function ToggleButton({ @@ -52,9 +52,14 @@ export function Leftbar() { ${collapsed ? "w-[24px]" : "w-[280px]"} flex flex-col pr-2`} > - {/* Scrollable DocsMenu */} + {/* Scrollable Content */} - {!collapsed && } + {!collapsed && ( +
+ + +
+ )}
); @@ -65,7 +70,7 @@ export function SheetLeftbar() { @@ -82,7 +87,8 @@ export function SheetLeftbar() {
-
+
+
diff --git a/components/markdown/CardGroupMdx.tsx b/components/markdown/CardGroupMdx.tsx index f1f6771..a1423b8 100644 --- a/components/markdown/CardGroupMdx.tsx +++ b/components/markdown/CardGroupMdx.tsx @@ -13,7 +13,7 @@ const CardGroup: React.FC = ({ children, cols = 2, className }) return (
= ({ title, icon, href, horizontal, children, cl const content = (
= ({ title, icon, href, horizontal, children, cl > {Icon && }
- {title} -
{children}
+ {title} +
{children}
); diff --git a/components/markdown/FileTreeMdx.tsx b/components/markdown/FileTreeMdx.tsx new file mode 100644 index 0000000..6abdd3b --- /dev/null +++ b/components/markdown/FileTreeMdx.tsx @@ -0,0 +1,138 @@ +'use client'; + +import React, { useState, ReactNode, Children, isValidElement, cloneElement } from 'react'; +import { ChevronRight, File as FileIcon, Folder as FolderIcon, FolderOpen } from 'lucide-react'; + +interface FileProps { + name: string; + children?: ReactNode; +} + +const FileComponent = ({ name }: FileProps) => { + const [isHovered, setIsHovered] = useState(false); + const fileExtension = name.split('.').pop()?.toUpperCase(); + + return ( +
setIsHovered(true)} + onMouseLeave={() => setIsHovered(false)} + tabIndex={-1} + > + + {name} + {isHovered && fileExtension && ( + + {fileExtension} + + )} +
+ ); +}; + +const FolderComponent = ({ name, children }: FileProps) => { + const [isOpen, setIsOpen] = useState(true); // Set to true by default + const [isHovered, setIsHovered] = useState(false); + const hasChildren = React.Children.count(children) > 0; + + return ( +
+
hasChildren && setIsOpen(!isOpen)} + onMouseEnter={() => setIsHovered(true)} + onMouseLeave={() => setIsHovered(false)} + tabIndex={-1} + onKeyDown={(e) => e.preventDefault()} + > + {hasChildren ? ( + + ) : ( +
+ )} + {isOpen ? ( + + ) : ( + + )} + + {name} + +
+ {isOpen && hasChildren && ( +
+ {children} +
+ )} +
+ ); +}; + +export const Files = ({ children }: { children: ReactNode }) => { + return ( +
e.preventDefault()} + > +
+ {Children.map(children, (child, index) => { + if (isValidElement(child)) { + return cloneElement(child, { key: index }); + } + return null; + })} +
+
+ ); +}; + +export const Folder = ({ name, children }: FileProps) => { + return {children}; +}; + +export const File = ({ name }: FileProps) => { + return ; +}; + +// MDX Components +export const FileTreeMdx = { + Files, + File, + Folder, +}; + +export default FileTreeMdx; diff --git a/components/markdown/KeyboardMdx.tsx b/components/markdown/KeyboardMdx.tsx index aede1a5..18c9625 100644 --- a/components/markdown/KeyboardMdx.tsx +++ b/components/markdown/KeyboardMdx.tsx @@ -88,7 +88,7 @@ const KbdComponent: React.FC = ({ return ( {renderContent()} diff --git a/components/markdown/NoteMdx.tsx b/components/markdown/NoteMdx.tsx index 49ee7b9..2627737 100644 --- a/components/markdown/NoteMdx.tsx +++ b/components/markdown/NoteMdx.tsx @@ -29,7 +29,7 @@ export default function Note({ "dark:bg-stone-950/25 bg-stone-50": type === "note", "dark:bg-red-950 bg-red-100 border-red-200 dark:border-red-900": type === "danger", - "dark:bg-orange-950 bg-orange-100 border-orange-200 dark:border-orange-900": + "bg-orange-50 border-orange-200 dark:border-orange-900 dark:bg-orange-900/50": type === "warning", "dark:bg-green-950 bg-green-100 border-green-200 dark:border-green-900": type === "success", diff --git a/components/markdown/StepperMdx.tsx b/components/markdown/StepperMdx.tsx index 297bfad..c63f0ee 100644 --- a/components/markdown/StepperMdx.tsx +++ b/components/markdown/StepperMdx.tsx @@ -11,13 +11,13 @@ export function Stepper({ children }: PropsWithChildren) { return (
-
+
{index + 1}
{child} diff --git a/components/markdown/TooltipsMdx.tsx b/components/markdown/TooltipsMdx.tsx index 6459348..43c6ab4 100644 --- a/components/markdown/TooltipsMdx.tsx +++ b/components/markdown/TooltipsMdx.tsx @@ -11,14 +11,17 @@ const Tooltip: React.FC = ({ text, tip }) => { return ( setVisible(true)} onMouseLeave={() => setVisible(false)} > - {text} + + {text} + {visible && ( - + {tip} + )} diff --git a/components/navbar.tsx b/components/navbar.tsx index cc00b89..1613c31 100644 --- a/components/navbar.tsx +++ b/components/navbar.tsx @@ -63,15 +63,15 @@ export function NavMenu({ isSheet = false }) { const Comp = ( {item.title} - {isExternal && } + {isExternal && } ); return isSheet ? ( diff --git a/components/pagination.tsx b/components/pagination.tsx index f73a831..9da486d 100644 --- a/components/pagination.tsx +++ b/components/pagination.tsx @@ -1,7 +1,7 @@ import { getPreviousNext } from "@/lib/markdown"; import { ChevronLeftIcon, ChevronRightIcon } from "lucide-react"; import Link from "next/link"; -import { buttonVariants } from "./ui/button"; +import { buttonVariants } from "@/components/ui/button"; export default function Pagination({ pathname }: { pathname: string }) { const res = getPreviousNext(pathname); diff --git a/components/search.tsx b/components/search.tsx index 49bd70b..7509d88 100644 --- a/components/search.tsx +++ b/components/search.tsx @@ -17,6 +17,23 @@ import { import Anchor from "./anchor"; import { advanceSearch, cn } from "@/lib/utils"; import { ScrollArea } from "@/components/ui/scroll-area"; +import { page_routes } from "@/lib/routes-config"; + +// Define the ContextInfo type to match the one in routes-config +type ContextInfo = { + icon: string; + description: string; + title?: string; +}; + +type SearchResult = { + title: string; + href: string; + noLink?: boolean; + items?: undefined; + score?: number; + context?: ContextInfo; +}; export default function Search() { const router = useRouter(); @@ -39,10 +56,25 @@ export default function Search() { }; }, []); - const filteredResults = useMemo( - () => advanceSearch(searchedInput.trim()), - [searchedInput] - ); + const filteredResults = useMemo(() => { + const trimmedInput = searchedInput.trim(); + + // If search input is empty or less than 3 characters, show initial suggestions + if (trimmedInput.length < 3) { + return page_routes + .filter((route: { href: string }) => !route.href.endsWith('/')) // Filter out directory routes + .slice(0, 6) // Limit to 6 posts + .map((route: { title: string; href: string; noLink?: boolean; context?: ContextInfo }) => ({ + title: route.title, + href: route.href, + noLink: route.noLink, + context: route.context + })); + } + + // For search with 3 or more characters, use the advance search + return advanceSearch(trimmedInput) as unknown as SearchResult[]; + }, [searchedInput]); useEffect(() => { setSelectedIndex(0); @@ -100,10 +132,10 @@ export default function Search() {
- +
- + ( @@ -72,8 +73,8 @@ export default function SubLink({ ) ) : (

{title}

@@ -93,7 +94,7 @@ export default function SubLink({ >
{titleOrLink} - + {!isOpen ? (