chore: Sync package version v1.16.1

This commit is contained in:
Bot DocuBook
2025-08-12 14:32:00 +00:00
parent 5060fd2154
commit 4a6d0da72a
6 changed files with 237 additions and 17 deletions

View File

@@ -25,7 +25,7 @@ export default function Home() {
)}
>
<AnimatedShinyText className="inline-flex items-center justify-center px-4 py-1 transition ease-out hover:text-neutral-100 hover:duration-300 hover:dark:text-neutral-200">
<span>🚀 New Version - Release v1.16.0</span>
<span>🚀 New Version - Release v1.16.1</span>
<ArrowRightIcon className="ml-1 size-3 transition-transform duration-300 ease-in-out group-hover:translate-x-0.5" />
</AnimatedShinyText>
</div>

View File

@@ -1,19 +1,109 @@
import { ComponentProps } from "react";
import { type ComponentProps } from "react";
import Copy from "./CopyMdx";
import {
SiJavascript,
SiTypescript,
SiReact,
SiPython,
SiGo,
SiPhp,
SiRuby,
SiSwift,
SiKotlin,
SiHtml5,
SiCss3,
SiSass,
SiPostgresql,
SiGraphql,
SiYaml,
SiToml,
SiDocker,
SiNginx,
SiGit,
SiGnubash,
SiMarkdown,
} from "react-icons/si";
import { FaJava, FaCode } from "react-icons/fa";
import { TbJson } from "react-icons/tb";
type PreProps = ComponentProps<"pre"> & {
raw?: string;
"data-title"?: string;
};
// Component to display an icon based on the programming language
const LanguageIcon = ({ lang }: { lang: string }) => {
const iconProps = { className: "w-4 h-4" };
const languageToIconMap: Record<string, JSX.Element> = {
gitignore: <SiGit {...iconProps} />,
docker: <SiDocker {...iconProps} />,
dockerfile: <SiDocker {...iconProps} />,
nginx: <SiNginx {...iconProps} />,
sql: <SiPostgresql {...iconProps} />,
graphql: <SiGraphql {...iconProps} />,
yaml: <SiYaml {...iconProps} />,
yml: <SiYaml {...iconProps} />,
toml: <SiToml {...iconProps} />,
json: <TbJson {...iconProps} />,
md: <SiMarkdown {...iconProps} />,
markdown: <SiMarkdown {...iconProps} />,
bash: <SiGnubash {...iconProps} />,
sh: <SiGnubash {...iconProps} />,
shell: <SiGnubash {...iconProps} />,
swift: <SiSwift {...iconProps} />,
kotlin: <SiKotlin {...iconProps} />,
kt: <SiKotlin {...iconProps} />,
kts: <SiKotlin {...iconProps} />,
rb: <SiRuby {...iconProps} />,
ruby: <SiRuby {...iconProps} />,
php: <SiPhp {...iconProps} />,
go: <SiGo {...iconProps} />,
py: <SiPython {...iconProps} />,
python: <SiPython {...iconProps} />,
java: <FaJava {...iconProps} />,
tsx: <SiReact {...iconProps} />,
typescript: <SiTypescript {...iconProps} />,
ts: <SiTypescript {...iconProps} />,
jsx: <SiReact {...iconProps} />,
js: <SiJavascript {...iconProps} />,
javascript: <SiJavascript {...iconProps} />,
html: <SiHtml5 {...iconProps} />,
css: <SiCss3 {...iconProps} />,
scss: <SiSass {...iconProps} />,
sass: <SiSass {...iconProps} />,
};
return languageToIconMap[lang] || <FaCode {...iconProps} />;
};
// Function to extract the language from className
function getLanguage(className: string = ""): string {
const match = className.match(/language-(\w+)/);
return match ? match[1] : "default";
}
export default function Pre({ children, raw, ...rest }: PreProps) {
const { "data-title": title, className, ...restProps } = rest;
const language = getLanguage(className);
const hasTitle = !!title;
export default function Pre({
children,
raw,
...rest
}: ComponentProps<"pre"> & { raw?: string }) {
return (
<div className="my-5 relative">
<div className="absolute top-3 right-2.5 z-10 sm:block hidden">
<Copy content={raw!} />
<div className="code-block-container">
<div className="code-block-actions">
{raw && <Copy content={raw} />}
</div>
<div className="relative">
<pre {...rest}>{children}</pre>
{hasTitle && (
<div className="code-block-header">
<div className="flex items-center gap-2">
<LanguageIcon lang={language} />
<span>{title}</span>
</div>
</div>
)}
<div className="code-block-body">
<pre className={className} {...restProps}>
{children}
</pre>
</div>
</div>
);
}
}

View File

@@ -8,7 +8,7 @@ import rehypeSlug from "rehype-slug";
import rehypeCodeTitles from "rehype-code-titles";
import { page_routes, ROUTES } from "./routes-config";
import { visit } from "unist-util-visit";
import type { Node } from "unist";
import type { Node, Parent } from "unist";
import matter from "gray-matter";
// Type definitions for unist-util-visit
@@ -16,6 +16,7 @@ interface Element extends Node {
type: string;
tagName?: string;
properties?: Record<string, unknown> & {
className?: string[];
raw?: string;
};
children?: Node[];
@@ -77,6 +78,49 @@ const components = {
AccordionGroup
};
// helper function to handle rehype code titles, since by default we can't inject into the className of rehype-code-titles
const handleCodeTitles = () => (tree: Node) => {
visit(tree, "element", (node: Element, index: number | null, parent: Parent | null) => {
// Ensure the visited node is valid
if (!parent || index === null || node.tagName !== 'div') {
return;
}
// Check if this is the title div from rehype-code-titles
const isTitleDiv = node.properties?.className?.includes('rehype-code-title');
if (!isTitleDiv) {
return;
}
// Find the next <pre> element, skipping over other nodes like whitespace text
let nextElement = null;
for (let i = index + 1; i < parent.children.length; i++) {
const sibling = parent.children[i];
if (sibling.type === 'element') {
nextElement = sibling as Element;
break;
}
}
// If the next element is a <pre>, move the title to it
if (nextElement && nextElement.tagName === 'pre') {
const titleNode = node.children?.[0] as TextNode;
if (titleNode && titleNode.type === 'text') {
if (!nextElement.properties) {
nextElement.properties = {};
}
nextElement.properties['data-title'] = titleNode.value;
// Remove the original title div
parent.children.splice(index, 1);
// Return the same index to continue visiting from the correct position
return index;
}
}
});
};
// can be used for other pages like blogs, Guides etc
async function parseMdx<Frontmatter>(rawMdx: string) {
return await compileMDX<Frontmatter>({
@@ -87,6 +131,7 @@ async function parseMdx<Frontmatter>(rawMdx: string) {
rehypePlugins: [
preProcess,
rehypeCodeTitles,
handleCodeTitles,
rehypePrism,
rehypeSlug,
rehypeAutolinkHeadings,

View File

@@ -1,6 +1,6 @@
{
"name": "docubook",
"version": "1.16.0",
"version": "1.16.1",
"private": true,
"scripts": {
"dev": "next dev",
@@ -30,13 +30,13 @@
"framer-motion": "^12.4.1",
"geist": "^1.3.1",
"gray-matter": "^4.0.3",
"install": "^0.13.0",
"lucide-react": "^0.511.0",
"next": "^14.2.6",
"next-mdx-remote": "^5.0.0",
"next-themes": "^0.3.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-icons": "^5.5.0",
"rehype-autolink-headings": "^7.1.0",
"rehype-code-titles": "^1.2.0",
"rehype-prism-plus": "^2.0.0",

View File

@@ -90,6 +90,7 @@ pre>code {
display: grid;
max-width: inherit !important;
padding: 14px 0 !important;
border: 0 !important;
}
.code-line {
@@ -138,4 +139,4 @@ pre>code {
background-position: 0% 0%;
}
}
}
}

View File

@@ -93,3 +93,87 @@
border: none;
border-radius: 8px; /* Sudut melengkung pada iframe */
}
/* ======================================================================== */
/* Custom styling for code blocks */
/* ======================================================================== */
.code-block-container {
position: relative;
margin: 1.5rem 0;
border: 1px solid hsl(var(--border));
overflow: hidden;
font-size: 0.875rem;
border-radius: 0.75rem;
}
.code-block-header {
display: flex;
align-items: center;
gap: 0.5rem;
background-color: hsl(var(--muted));
padding: 0.5rem 1rem;
border-bottom: 1px solid hsl(var(--border));
color: hsl(var(--muted-foreground));
font-family: monospace;
font-size: 0.8rem;
}
.code-block-actions {
position: absolute;
top: 0.5rem;
right: 0.75rem;
z-index: 10;
}
.code-block-actions button {
color: hsl(var(--muted-foreground));
transition: color 0.2s ease-in-out;
}
.code-block-actions button:hover {
color: hsl(var(--foreground));
}
.code-block-body pre[class*="language-"] {
margin: 0 !important;
padding: 0 !important;
background: transparent !important;
}
.line-numbers-wrapper {
position: absolute;
top: 0;
left: 0;
width: 3rem;
padding-top: 1rem;
text-align: right;
color: var(--line-number-color);
user-select: none;
}
.line-highlight {
position: absolute;
left: 0;
right: 0;
background: hsl(var(--primary) / 0.1);
border-left: 2px solid hsl(var(--primary));
pointer-events: none;
}
.code-block-body pre[data-line-numbers="true"] .line-highlight {
padding-left: 3.5rem;
}
.code-block-body::-webkit-scrollbar {
height: 8px;
}
.code-block-body::-webkit-scrollbar-track {
background: transparent;
}
.code-block-body::-webkit-scrollbar-thumb {
background: hsl(var(--border));
border-radius: 4px;
}
.code-block-body::-webkit-scrollbar-thumb:hover {
background: hsl(var(--muted));
}