diff --git a/.eslintrc.json b/.eslintrc.json
new file mode 100644
index 0000000..0851bea
--- /dev/null
+++ b/.eslintrc.json
@@ -0,0 +1,19 @@
+{
+ "extends": [
+ "next/core-web-vitals",
+ "next/typescript",
+ "plugin:@typescript-eslint/recommended"
+ ],
+ "rules": {
+ "@typescript-eslint/no-explicit-any": "warn",
+ "@typescript-eslint/no-unused-vars": [
+ "warn",
+ {
+ "argsIgnorePattern": "^_",
+ "varsIgnorePattern": "^_",
+ "caughtErrorsIgnorePattern": "^_"
+ }
+ ],
+ "@typescript-eslint/no-empty-object-type": "off"
+ }
+}
diff --git a/app/docs/[[...slug]]/page.tsx b/app/docs/[[...slug]]/page.tsx
index e765173..c4f6f05 100644
--- a/app/docs/[[...slug]]/page.tsx
+++ b/app/docs/[[...slug]]/page.tsx
@@ -68,7 +68,7 @@ export default async function DocsPage({ params: { slug = [] } }: PageProps) {
if (!res) notFound();
- const { title, description, image, date } = res.frontmatter;
+ const { title, description, image: _image, date } = res.frontmatter;
// File path for edit link
const filePath = `contents/docs/${slug.join("/") || ""}/index.mdx`;
diff --git a/app/page.tsx b/app/page.tsx
index 2a1152d..9a0a5c8 100644
--- a/app/page.tsx
+++ b/app/page.tsx
@@ -25,7 +25,7 @@ export default function Home() {
)}
>
- 🚀 New Version - Release v1.13.6
+ 🚀 New Version - Release v1.13.9
diff --git a/components/Sponsor.tsx b/components/Sponsor.tsx
index 783192d..def5ce0 100644
--- a/components/Sponsor.tsx
+++ b/components/Sponsor.tsx
@@ -10,16 +10,76 @@ interface SponsorItem {
description?: string;
}
+interface NavbarConfig {
+ title?: string;
+ logo?: {
+ light?: string;
+ dark?: string;
+ };
+ links?: Array<{
+ title: string;
+ href: string;
+ external?: boolean;
+ }>;
+}
+
+interface FooterConfig {
+ text?: string;
+ links?: Array<{
+ title: string;
+ href: string;
+ external?: boolean;
+ }>;
+}
+
+interface MetaConfig {
+ title?: string;
+ description?: string;
+ favicon?: string;
+ socialBanner?: string;
+}
+
+interface RepositoryConfig {
+ url: string;
+ editUrl?: string;
+ branch?: string;
+ directory?: string;
+}
+
+interface RouteItem {
+ title: string;
+ href: string;
+ noLink?: boolean;
+ context?: {
+ icon: string;
+ description: string;
+ title: string;
+ };
+ items?: RouteItem[];
+}
+
+interface RouteConfig {
+ title: string;
+ href: string;
+ noLink?: boolean;
+ context?: {
+ icon: string;
+ description: string;
+ title: string;
+ };
+ items?: RouteItem[];
+}
+
interface DocuConfig {
sponsor?: {
title?: string;
item?: SponsorItem;
};
- navbar: any; // Anda bisa mendefinisikan tipe yang lebih spesifik jika diperlukan
- footer: any;
- meta: any;
- repository: any;
- routes: any[];
+ navbar: NavbarConfig;
+ footer: FooterConfig;
+ meta: MetaConfig;
+ repository: RepositoryConfig;
+ routes: RouteConfig[];
}
// Type assertion for docu.json
diff --git a/components/markdown/ButtonMdx.tsx b/components/markdown/ButtonMdx.tsx
index e0a5a72..eee7404 100644
--- a/components/markdown/ButtonMdx.tsx
+++ b/components/markdown/ButtonMdx.tsx
@@ -1,8 +1,6 @@
import React from "react";
import * as Icons from "lucide-react";
import Link from "next/link";
-
-type IconName = keyof typeof Icons;
type ButtonProps = {
icon?: keyof typeof Icons;
text?: string;
diff --git a/components/markdown/mdx-provider.tsx b/components/markdown/mdx-provider.tsx
index 8265b8f..b2e6e0d 100644
--- a/components/markdown/mdx-provider.tsx
+++ b/components/markdown/mdx-provider.tsx
@@ -1,6 +1,6 @@
'use client';
-import { MDXRemote, MDXRemoteProps } from 'next-mdx-remote/rsc';
+import { MDXRemote } from 'next-mdx-remote/rsc';
import { Kbd } from './KeyboardMdx';
// Define components mapping
diff --git a/components/mob-toc.tsx b/components/mob-toc.tsx
index 6a23a0a..625e5e6 100644
--- a/components/mob-toc.tsx
+++ b/components/mob-toc.tsx
@@ -7,7 +7,7 @@ import { useRef, useMemo } from "react";
import { usePathname } from "next/navigation";
import { Button } from "./ui/button";
import { motion, AnimatePresence } from "framer-motion";
-import { useScrollPosition, useActiveSection } from "@/hooks";
+import { useActiveSection } from "@/hooks";
import { TocItem } from "@/lib/toc";
interface MobTocProps {
diff --git a/components/sublink.tsx b/components/sublink.tsx
index 68f5897..eb5a425 100644
--- a/components/sublink.tsx
+++ b/components/sublink.tsx
@@ -32,9 +32,6 @@ export default function SubLink({
// Full path including parent's href
const fullHref = `${parentHref}${href}`;
- // Check if current path exactly matches this link's href
- const isExactActive = useMemo(() => path === fullHref, [path, fullHref]);
-
// Check if any child is active (for parent items)
const hasActiveChild = useMemo(() => {
if (!items) return false;
diff --git a/components/toc-observer.tsx b/components/toc-observer.tsx
index b0d8a4f..1d595db 100644
--- a/components/toc-observer.tsx
+++ b/components/toc-observer.tsx
@@ -1,6 +1,5 @@
"use client";
-import { getDocsTocs } from "@/lib/markdown";
import clsx from "clsx";
import Link from "next/link";
import { useState, useRef, useEffect, useCallback } from "react";
@@ -110,7 +109,6 @@ export default function TocObserver({
// Calculate scroll progress for the active section
const [scrollProgress, setScrollProgress] = useState(0);
- const [activeSectionIndex, setActiveSectionIndex] = useState(0);
useEffect(() => {
const handleScroll = () => {
@@ -137,15 +135,6 @@ export default function TocObserver({
return () => window.removeEventListener('scroll', handleScroll);
}, [activeId]);
- // Update active section index when activeId changes
- useEffect(() => {
- if (activeId) {
- const index = data.findIndex(item => item.href.slice(1) === activeId);
- if (index !== -1) {
- setActiveSectionIndex(index);
- }
- }
- }, [activeId, data]);
return (
@@ -155,8 +144,9 @@ export default function TocObserver({
const id = href.slice(1);
const isActive = activeId === id;
const indent = level > 1 ? (level - 1) * 20 : 0;
- const isParent = hasChildren(id, level);
- const isLastInLevel = index === data.length - 1 || data[index + 1].level <= level;
+ // Prefix with underscore to indicate intentionally unused
+ const _isParent = hasChildren(id, level);
+ const _isLastInLevel = index === data.length - 1 || data[index + 1].level <= level;
return (
diff --git a/components/ui/icon-cloud.tsx b/components/ui/icon-cloud.tsx
index c151d60..1f6136e 100644
--- a/components/ui/icon-cloud.tsx
+++ b/components/ui/icon-cloud.tsx
@@ -24,7 +24,7 @@ function easeOutCubic(t: number): number {
export function IconCloud({ icons, images }: IconCloudProps) {
const canvasRef = useRef(null);
const [iconPositions, setIconPositions] = useState([]);
- const [rotation, setRotation] = useState({ x: 0, y: 0 });
+ const [rotation] = useState({ x: 0, y: 0 });
const [isDragging, setIsDragging] = useState(false);
const [lastMousePos, setLastMousePos] = useState({ x: 0, y: 0 });
const [mousePos, setMousePos] = useState({ x: 0, y: 0 });
diff --git a/components/ui/input.tsx b/components/ui/input.tsx
index 677d05f..aba38dc 100644
--- a/components/ui/input.tsx
+++ b/components/ui/input.tsx
@@ -2,8 +2,7 @@ import * as React from "react"
import { cn } from "@/lib/utils"
-export interface InputProps
- extends React.InputHTMLAttributes {}
+export type InputProps = React.InputHTMLAttributes;
const Input = React.forwardRef(
({ className, type, ...props }, ref) => {
diff --git a/components/ui/interactive-hover-button.tsx b/components/ui/interactive-hover-button.tsx
index 46cf526..e150f87 100644
--- a/components/ui/interactive-hover-button.tsx
+++ b/components/ui/interactive-hover-button.tsx
@@ -2,8 +2,7 @@ import React from "react";
import { ArrowRight } from "lucide-react";
import { cn } from "@/lib/utils";
-interface InteractiveHoverButtonProps
- extends React.ButtonHTMLAttributes {}
+type InteractiveHoverButtonProps = React.ButtonHTMLAttributes;
export const InteractiveHoverButton = React.forwardRef<
HTMLButtonElement,
diff --git a/lib/markdown.ts b/lib/markdown.ts
index f4f4764..341bf23 100644
--- a/lib/markdown.ts
+++ b/lib/markdown.ts
@@ -8,8 +8,26 @@ 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 matter from "gray-matter";
+// Type definitions for unist-util-visit
+interface Element extends Node {
+ type: string;
+ tagName?: string;
+ properties?: Record & {
+ raw?: string;
+ };
+ children?: Node[];
+ value?: string;
+ raw?: string; // For internal use in processing
+}
+
+interface TextNode extends Node {
+ type: 'text';
+ value: string;
+}
+
// custom components imports
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import Pre from "@/components/markdown/PreMdx";
@@ -139,11 +157,11 @@ function justGetFrontmatterFromMD(rawMd: string): Frontmatter {
}
export async function getAllChilds(pathString: string) {
- const items = pathString.split("/").filter((it) => it != "");
+ const items = pathString.split("/").filter((it) => it !== "");
let page_routes_copy = ROUTES;
let prevHref = "";
- for (let it of items) {
+ for (const it of items) {
const found = page_routes_copy.find((innerIt) => innerIt.href == `/${it}`);
if (!found) break;
prevHref += found.href;
@@ -170,20 +188,28 @@ export async function getAllChilds(pathString: string) {
}
// for copying the code in pre
-const preProcess = () => (tree: any) => {
- visit(tree, (node) => {
- if (node?.type === "element" && node?.tagName === "pre") {
- const [codeEl] = node.children;
- if (codeEl.tagName !== "code") return;
- node.raw = codeEl.children?.[0].value;
+const preProcess = () => (tree: Node) => {
+ visit(tree, (node: Node) => {
+ const element = node as Element;
+ if (element?.type === "element" && element?.tagName === "pre" && element.children) {
+ const [codeEl] = element.children as Element[];
+ if (codeEl.tagName !== "code" || !codeEl.children?.[0]) return;
+
+ const textNode = codeEl.children[0] as TextNode;
+ if (textNode.type === 'text' && textNode.value) {
+ element.raw = textNode.value;
+ }
}
});
};
-const postProcess = () => (tree: any) => {
- visit(tree, "element", (node) => {
- if (node?.type === "element" && node?.tagName === "pre") {
- node.properties["raw"] = node.raw;
+const postProcess = () => (tree: Node) => {
+ visit(tree, "element", (node: Node) => {
+ const element = node as Element;
+ if (element?.type === "element" && element?.tagName === "pre") {
+ if (element.properties && element.raw) {
+ element.properties.raw = element.raw;
+ }
}
});
};
diff --git a/package.json b/package.json
index 4ba5e8d..67e142b 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "docubook",
- "version": "1.13.6",
+ "version": "1.13.9",
"private": true,
"scripts": {
"dev": "next dev",