mirror of
https://github.com/Dokploy/website
synced 2025-06-26 18:16:01 +00:00
feat: add table of contents and improve blog post page layout
This commit is contained in:
parent
92f3a2117f
commit
064924316b
@ -0,0 +1,76 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
interface Heading {
|
||||
id: string;
|
||||
text: string;
|
||||
level: number;
|
||||
}
|
||||
|
||||
export function TableOfContents() {
|
||||
const [headings, setHeadings] = useState<Heading[]>([]);
|
||||
const [activeId, setActiveId] = useState<string>();
|
||||
|
||||
useEffect(() => {
|
||||
const elements = Array.from(document.querySelectorAll("h1, h2, h3"))
|
||||
.filter((element) => element.id)
|
||||
.map((element) => ({
|
||||
id: element.id,
|
||||
text: element.textContent || "",
|
||||
level: Number(element.tagName.charAt(1)),
|
||||
}));
|
||||
|
||||
setHeadings(elements);
|
||||
|
||||
const observer = new IntersectionObserver(
|
||||
(entries) => {
|
||||
for (const entry of entries) {
|
||||
if (entry.isIntersecting) {
|
||||
setActiveId(entry.target.id);
|
||||
}
|
||||
}
|
||||
},
|
||||
{ rootMargin: "-100px 0px -66%" },
|
||||
);
|
||||
|
||||
for (const { id } of elements) {
|
||||
const element = document.getElementById(id);
|
||||
if (element) {
|
||||
observer.observe(element);
|
||||
}
|
||||
}
|
||||
|
||||
return () => observer.disconnect();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<nav className="space-y-2 text-sm">
|
||||
<p className="font-medium mb-4">Table of Contents</p>
|
||||
<ul className="space-y-2">
|
||||
{headings.map((heading) => (
|
||||
<li
|
||||
key={heading.id}
|
||||
style={{ paddingLeft: `${(heading.level - 1) * 1}rem` }}
|
||||
>
|
||||
<a
|
||||
href={`#${heading.id}`}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
document.getElementById(heading.id)?.scrollIntoView({
|
||||
behavior: "smooth",
|
||||
});
|
||||
}}
|
||||
className={`hover:text-primary transition-colors block ${
|
||||
activeId === heading.id
|
||||
? "text-primary font-medium"
|
||||
: "text-muted-foreground"
|
||||
}`}
|
||||
>
|
||||
{heading.text}
|
||||
</a>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</nav>
|
||||
);
|
||||
}
|
@ -12,11 +12,14 @@ import ReactMarkdown from "react-markdown";
|
||||
import type { Components } from "react-markdown";
|
||||
import rehypeRaw from "rehype-raw";
|
||||
import remarkGfm from "remark-gfm";
|
||||
import remarkToc from "remark-toc";
|
||||
import { codeToHtml } from "shiki";
|
||||
import type { BundledLanguage } from "shiki/bundle/web";
|
||||
import slugify from "slugify";
|
||||
import TurndownService from "turndown";
|
||||
// @ts-ignore
|
||||
import * as turndownPluginGfm from "turndown-plugin-gfm";
|
||||
import { TableOfContents } from "./components/TableOfContents";
|
||||
import { ZoomableImage } from "./components/ZoomableImage";
|
||||
|
||||
type Props = {
|
||||
@ -158,7 +161,7 @@ export default async function BlogPostPage({ params }: Props) {
|
||||
const gfm = turndownPluginGfm.gfm;
|
||||
const tables = turndownPluginGfm.tables;
|
||||
const strikethrough = turndownPluginGfm.strikethrough;
|
||||
turndownService.use([tables, strikethrough, gfm]);
|
||||
turndownService.use([tables, strikethrough, gfm, remarkToc]);
|
||||
|
||||
const markdown = turndownService.turndown(post.html);
|
||||
|
||||
@ -169,18 +172,45 @@ export default async function BlogPostPage({ params }: Props) {
|
||||
});
|
||||
|
||||
const components: Partial<Components> = {
|
||||
h1: ({ node, ...props }) => (
|
||||
<h1
|
||||
className="text-xl md:text-2xl xl:text-3xl text-primary font-bold mt-8 mb-4"
|
||||
{...props}
|
||||
/>
|
||||
),
|
||||
h2: ({ node, ...props }) => (
|
||||
<h2 className="text-2xl text-primary/90 font-bold mt-6 mb-3" {...props} />
|
||||
),
|
||||
h3: ({ node, ...props }) => (
|
||||
<h3 className="text-xl text-primary/90 font-bold mt-4 mb-2" {...props} />
|
||||
),
|
||||
h1: ({ node, ...props }) => {
|
||||
const id = slugify(props.children?.toString() || "", {
|
||||
lower: true,
|
||||
strict: true,
|
||||
});
|
||||
return (
|
||||
<h1
|
||||
id={id}
|
||||
className="text-xl md:text-2xl xl:text-3xl text-primary font-bold mt-8 mb-4"
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
},
|
||||
h2: ({ node, ...props }) => {
|
||||
const id = slugify(props.children?.toString() || "", {
|
||||
lower: true,
|
||||
strict: true,
|
||||
});
|
||||
return (
|
||||
<h2
|
||||
id={id}
|
||||
className="text-2xl text-primary/90 font-semibold mt-6 mb-3"
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
},
|
||||
h3: ({ node, ...props }) => {
|
||||
const id = slugify(props.children?.toString() || "", {
|
||||
lower: true,
|
||||
strict: true,
|
||||
});
|
||||
return (
|
||||
<h3
|
||||
id={id}
|
||||
className="text-xl text-primary/90 font-semibold mt-4 mb-2"
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
},
|
||||
p: ({ node, children, ...props }) => {
|
||||
return (
|
||||
<p
|
||||
@ -254,7 +284,7 @@ export default async function BlogPostPage({ params }: Props) {
|
||||
};
|
||||
|
||||
return (
|
||||
<article className="container mx-auto px-4 pb-12 max-w-5xl">
|
||||
<article className="mx-auto px-4 sm:px-6 lg:px-8 pb-12 max-w-7xl w-full">
|
||||
<Link
|
||||
href="/blog"
|
||||
className="inline-flex items-center mb-8 text-primary hover:text-primary/80 transition-colors"
|
||||
@ -274,95 +304,106 @@ export default async function BlogPostPage({ params }: Props) {
|
||||
{t("backToBlog")}
|
||||
</Link>
|
||||
|
||||
<div className=" rounded-lg p-8 shadow-lg border border-border">
|
||||
<header className="mb-8">
|
||||
<h1 className="text-xl md:text-2xl xl:text-3xl font-bold mb-4">
|
||||
{post.title}
|
||||
</h1>
|
||||
<div className="flex items-center mb-6">
|
||||
{post.primary_author?.profile_image && (
|
||||
<div className="relative h-12 w-12 rounded-full overflow-hidden mr-4">
|
||||
{post.primary_author.twitter ? (
|
||||
<a
|
||||
href={`https://twitter.com/${post.primary_author.twitter}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="block cursor-pointer transition-opacity hover:opacity-90"
|
||||
>
|
||||
<div className="grid grid-cols-1 lg:grid-cols-[1fr_250px] gap-8">
|
||||
<div className="rounded-lg p-8 shadow-lg border border-border">
|
||||
<header className="mb-8">
|
||||
<h1 className="text-xl md:text-2xl xl:text-3xl font-bold mb-4">
|
||||
{post.title}
|
||||
</h1>
|
||||
<div className="flex items-center mb-6">
|
||||
{post.primary_author?.profile_image && (
|
||||
<div className="relative h-12 w-12 rounded-full overflow-hidden mr-4">
|
||||
{post.primary_author.twitter ? (
|
||||
<a
|
||||
href={`https://twitter.com/${post.primary_author.twitter}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="block cursor-pointer transition-opacity hover:opacity-90"
|
||||
>
|
||||
<Image
|
||||
src={post.primary_author.profile_image}
|
||||
alt={post.primary_author.name}
|
||||
fill
|
||||
className="object-cover"
|
||||
/>
|
||||
</a>
|
||||
) : (
|
||||
<Image
|
||||
src={post.primary_author.profile_image}
|
||||
alt={post.primary_author.name}
|
||||
fill
|
||||
className="object-cover"
|
||||
/>
|
||||
</a>
|
||||
) : (
|
||||
<Image
|
||||
src={post.primary_author.profile_image}
|
||||
alt={post.primary_author.name}
|
||||
fill
|
||||
className="object-cover"
|
||||
/>
|
||||
)}
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
<div>
|
||||
<p className="font-medium">
|
||||
{post.primary_author?.twitter ? (
|
||||
<a
|
||||
href={`https://twitter.com/${post.primary_author.twitter}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="hover:text-primary transition-colors"
|
||||
>
|
||||
{post.primary_author.name || "Unknown Author"}
|
||||
</a>
|
||||
) : (
|
||||
post.primary_author?.name || "Unknown Author"
|
||||
)}
|
||||
</p>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
{formattedDate} • {post.reading_time} min read
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
{post.feature_image && (
|
||||
<div className="relative w-full h-[400px] mb-8">
|
||||
<ZoomableImage
|
||||
src={post.feature_image}
|
||||
alt={post.title}
|
||||
className="rounded-lg h-full w-full object-cover"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<div>
|
||||
<p className="font-medium">
|
||||
{post.primary_author?.twitter ? (
|
||||
<a
|
||||
href={`https://twitter.com/${post.primary_author.twitter}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="hover:text-primary transition-colors"
|
||||
>
|
||||
{post.primary_author.name || "Unknown Author"}
|
||||
</a>
|
||||
) : (
|
||||
post.primary_author?.name || "Unknown Author"
|
||||
)}
|
||||
</p>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
{formattedDate} • {post.reading_time} min read
|
||||
</p>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div className="prose prose-lg max-w-none">
|
||||
<ReactMarkdown
|
||||
remarkPlugins={[
|
||||
remarkGfm,
|
||||
[remarkToc, { tight: true, maxDepth: 3 }],
|
||||
]}
|
||||
rehypePlugins={[rehypeRaw]}
|
||||
components={components}
|
||||
>
|
||||
{markdown}
|
||||
</ReactMarkdown>
|
||||
</div>
|
||||
{post.feature_image && (
|
||||
<div className="relative w-full h-[400px] mb-8">
|
||||
<ZoomableImage
|
||||
src={post.feature_image}
|
||||
alt={post.title}
|
||||
className="rounded-lg h-full w-full object-cover"
|
||||
/>
|
||||
|
||||
{post.tags && post.tags.length > 0 && (
|
||||
<div className="mt-12 pt-6 border-t border-border">
|
||||
<h2 className="text-xl font-semibold mb-4">{t("tags")}</h2>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{post.tags.map((tag) => (
|
||||
<Link
|
||||
key={tag.id}
|
||||
href={`/blog/tag/${tag.slug}`}
|
||||
className="px-4 py-2 bg-muted hover:bg-muted/80 rounded-full text-sm transition-colors"
|
||||
>
|
||||
{tag.name}
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</header>
|
||||
|
||||
<div className="prose prose-lg max-w-none">
|
||||
<ReactMarkdown
|
||||
remarkPlugins={[remarkGfm]}
|
||||
rehypePlugins={[rehypeRaw]}
|
||||
components={components}
|
||||
>
|
||||
{markdown}
|
||||
</ReactMarkdown>
|
||||
</div>
|
||||
|
||||
{post.tags && post.tags.length > 0 && (
|
||||
<div className="mt-12 pt-6 border-t border-border">
|
||||
<h2 className="text-xl font-semibold mb-4">{t("tags")}</h2>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{post.tags.map((tag) => (
|
||||
<Link
|
||||
key={tag.id}
|
||||
href={`/blog/tag/${tag.slug}`}
|
||||
className="px-4 py-2 bg-muted hover:bg-muted/80 rounded-full text-sm transition-colors"
|
||||
>
|
||||
{tag.name}
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
<div className="hidden lg:block max-w-[16rem]">
|
||||
<div className="sticky top-4">
|
||||
<TableOfContents />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{relatedPosts.length > 0 && (
|
||||
|
@ -37,20 +37,21 @@
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"react-ga4": "^2.1.0",
|
||||
"react-markdown": "^10.0.0",
|
||||
"react-photo-view": "^1.2.7",
|
||||
"rehype-raw": "^7.0.0",
|
||||
"remark-gfm": "^4.0.1",
|
||||
"remark-toc": "^9.0.0",
|
||||
"satori": "^0.12.1",
|
||||
"sharp": "^0.33.5",
|
||||
"shiki": "1.22.2",
|
||||
"slugify": "^1.6.6",
|
||||
"tailwind-merge": "^2.2.2",
|
||||
"tailwindcss": "^3.4.1",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"turndown": "^7.2.0",
|
||||
"turndown-plugin-gfm": "^1.0.2",
|
||||
"typescript": "5.1.6",
|
||||
"react-markdown": "^10.0.0",
|
||||
"rehype-raw": "^7.0.0",
|
||||
"remark-gfm": "^4.0.1",
|
||||
"@resvg/resvg-js": "^2.6.2",
|
||||
"satori": "^0.12.1",
|
||||
"sharp": "^0.33.5"
|
||||
"typescript": "5.1.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.26.9",
|
||||
|
168
pnpm-lock.yaml
168
pnpm-lock.yaml
@ -121,9 +121,6 @@ importers:
|
||||
'@radix-ui/react-tooltip':
|
||||
specifier: ^1.1.3
|
||||
version: 1.1.3(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
|
||||
'@resvg/resvg-js':
|
||||
specifier: ^2.6.2
|
||||
version: 2.6.2
|
||||
'@tabler/icons-react':
|
||||
specifier: 3.21.0
|
||||
version: 3.21.0(react@18.2.0)
|
||||
@ -181,6 +178,9 @@ importers:
|
||||
remark-gfm:
|
||||
specifier: ^4.0.1
|
||||
version: 4.0.1
|
||||
remark-toc:
|
||||
specifier: ^9.0.0
|
||||
version: 9.0.0
|
||||
satori:
|
||||
specifier: ^0.12.1
|
||||
version: 0.12.1
|
||||
@ -190,6 +190,9 @@ importers:
|
||||
shiki:
|
||||
specifier: 1.22.2
|
||||
version: 1.22.2
|
||||
slugify:
|
||||
specifier: ^1.6.6
|
||||
version: 1.6.6
|
||||
tailwind-merge:
|
||||
specifier: ^2.2.2
|
||||
version: 2.4.0
|
||||
@ -1620,82 +1623,6 @@ packages:
|
||||
peerDependencies:
|
||||
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
|
||||
|
||||
'@resvg/resvg-js-android-arm-eabi@2.6.2':
|
||||
resolution: {integrity: sha512-FrJibrAk6v29eabIPgcTUMPXiEz8ssrAk7TXxsiZzww9UTQ1Z5KAbFJs+Z0Ez+VZTYgnE5IQJqBcoSiMebtPHA==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm]
|
||||
os: [android]
|
||||
|
||||
'@resvg/resvg-js-android-arm64@2.6.2':
|
||||
resolution: {integrity: sha512-VcOKezEhm2VqzXpcIJoITuvUS/fcjIw5NA/w3tjzWyzmvoCdd+QXIqy3FBGulWdClvp4g+IfUemigrkLThSjAQ==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [android]
|
||||
|
||||
'@resvg/resvg-js-darwin-arm64@2.6.2':
|
||||
resolution: {integrity: sha512-nmok2LnAd6nLUKI16aEB9ydMC6Lidiiq2m1nEBDR1LaaP7FGs4AJ90qDraxX+CWlVuRlvNjyYJTNv8qFjtL9+A==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@resvg/resvg-js-darwin-x64@2.6.2':
|
||||
resolution: {integrity: sha512-GInyZLjgWDfsVT6+SHxQVRwNzV0AuA1uqGsOAW+0th56J7Nh6bHHKXHBWzUrihxMetcFDmQMAX1tZ1fZDYSRsw==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@resvg/resvg-js-linux-arm-gnueabihf@2.6.2':
|
||||
resolution: {integrity: sha512-YIV3u/R9zJbpqTTNwTZM5/ocWetDKGsro0SWp70eGEM9eV2MerWyBRZnQIgzU3YBnSBQ1RcxRZvY/UxwESfZIw==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
|
||||
'@resvg/resvg-js-linux-arm64-gnu@2.6.2':
|
||||
resolution: {integrity: sha512-zc2BlJSim7YR4FZDQ8OUoJg5holYzdiYMeobb9pJuGDidGL9KZUv7SbiD4E8oZogtYY42UZEap7dqkkYuA91pg==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@resvg/resvg-js-linux-arm64-musl@2.6.2':
|
||||
resolution: {integrity: sha512-3h3dLPWNgSsD4lQBJPb4f+kvdOSJHa5PjTYVsWHxLUzH4IFTJUAnmuWpw4KqyQ3NA5QCyhw4TWgxk3jRkQxEKg==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@resvg/resvg-js-linux-x64-gnu@2.6.2':
|
||||
resolution: {integrity: sha512-IVUe+ckIerA7xMZ50duAZzwf1U7khQe2E0QpUxu5MBJNao5RqC0zwV/Zm965vw6D3gGFUl7j4m+oJjubBVoftw==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@resvg/resvg-js-linux-x64-musl@2.6.2':
|
||||
resolution: {integrity: sha512-UOf83vqTzoYQO9SZ0fPl2ZIFtNIz/Rr/y+7X8XRX1ZnBYsQ/tTb+cj9TE+KHOdmlTFBxhYzVkP2lRByCzqi4jQ==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@resvg/resvg-js-win32-arm64-msvc@2.6.2':
|
||||
resolution: {integrity: sha512-7C/RSgCa+7vqZ7qAbItfiaAWhyRSoD4l4BQAbVDqRRsRgY+S+hgS3in0Rxr7IorKUpGE69X48q6/nOAuTJQxeQ==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
'@resvg/resvg-js-win32-ia32-msvc@2.6.2':
|
||||
resolution: {integrity: sha512-har4aPAlvjnLcil40AC77YDIk6loMawuJwFINEM7n0pZviwMkMvjb2W5ZirsNOZY4aDbo5tLx0wNMREp5Brk+w==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [ia32]
|
||||
os: [win32]
|
||||
|
||||
'@resvg/resvg-js-win32-x64-msvc@2.6.2':
|
||||
resolution: {integrity: sha512-ZXtYhtUr5SSaBrUDq7DiyjOFJqBVL/dOBN7N/qmi/pO0IgiWW/f/ue3nbvu9joWE5aAKDoIzy/CxsY0suwGosQ==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@resvg/resvg-js@2.6.2':
|
||||
resolution: {integrity: sha512-xBaJish5OeGmniDj9cW5PRa/PtmuVU3ziqrbr5xJj901ZDN4TosrVaNZpEiLZAxdfnhAe7uQ7QFWfjPe9d9K2Q==}
|
||||
engines: {node: '>= 10'}
|
||||
|
||||
'@shikijs/core@1.22.2':
|
||||
resolution: {integrity: sha512-bvIQcd8BEeR1yFvOYv6HDiyta2FFVePbzeowf5pPS1avczrPK+cjmaxxh0nx5QzbON7+Sv0sQfQVciO7bN72sg==}
|
||||
|
||||
@ -1804,6 +1731,9 @@ packages:
|
||||
'@types/turndown@5.0.5':
|
||||
resolution: {integrity: sha512-TL2IgGgc7B5j78rIccBtlYAnkuv8nUQqhQc+DSYV5j9Be9XOcm/SKOVRuA47xAVI3680Tk9B1d8flK2GWT2+4w==}
|
||||
|
||||
'@types/ungap__structured-clone@1.2.0':
|
||||
resolution: {integrity: sha512-ZoaihZNLeZSxESbk9PUAPZOlSpcKx81I1+4emtULDVmBLkYutTcMlCj2K9VNlf9EWODxdO6gkAqEaLorXwZQVA==}
|
||||
|
||||
'@types/unist@2.0.10':
|
||||
resolution: {integrity: sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==}
|
||||
|
||||
@ -2856,6 +2786,9 @@ packages:
|
||||
mdast-util-to-string@4.0.0:
|
||||
resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==}
|
||||
|
||||
mdast-util-toc@7.1.0:
|
||||
resolution: {integrity: sha512-2TVKotOQzqdY7THOdn2gGzS9d1Sdd66bvxUyw3aNpWfcPXCLYSJCCgfPy30sEtuzkDraJgqF35dzgmz6xlvH/w==}
|
||||
|
||||
meow@12.1.1:
|
||||
resolution: {integrity: sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==}
|
||||
engines: {node: '>=16.10'}
|
||||
@ -3448,6 +3381,9 @@ packages:
|
||||
remark-stringify@11.0.0:
|
||||
resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==}
|
||||
|
||||
remark-toc@9.0.0:
|
||||
resolution: {integrity: sha512-KJ9txbo33GjDAV1baHFze7ij4G8c7SGYoY8Kzsm2gzFpbhL/bSoVpMMzGa3vrNDSWASNd/3ppAqL7cP2zD6JIA==}
|
||||
|
||||
remark@15.0.1:
|
||||
resolution: {integrity: sha512-Eht5w30ruCXgFmxVUSlNWQ9iiimq07URKeFS3hNc8cUWy1llX4KDWfyEDZRycMc+znsN9Ux5/tJ/BFdgdOwA3A==}
|
||||
|
||||
@ -3541,6 +3477,10 @@ packages:
|
||||
resolution: {integrity: sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
slugify@1.6.6:
|
||||
resolution: {integrity: sha512-h+z7HKHYXj6wJU+AnS/+IH8Uh9fdcX1Lrhg1/VMdf9PwoBQXFcXiAdsy2tSK0P6gKwJLXp02r90ahUCqHk9rrw==}
|
||||
engines: {node: '>=8.0.0'}
|
||||
|
||||
source-map-js@1.2.1:
|
||||
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@ -5401,57 +5341,6 @@ snapshots:
|
||||
dependencies:
|
||||
react: 18.2.0
|
||||
|
||||
'@resvg/resvg-js-android-arm-eabi@2.6.2':
|
||||
optional: true
|
||||
|
||||
'@resvg/resvg-js-android-arm64@2.6.2':
|
||||
optional: true
|
||||
|
||||
'@resvg/resvg-js-darwin-arm64@2.6.2':
|
||||
optional: true
|
||||
|
||||
'@resvg/resvg-js-darwin-x64@2.6.2':
|
||||
optional: true
|
||||
|
||||
'@resvg/resvg-js-linux-arm-gnueabihf@2.6.2':
|
||||
optional: true
|
||||
|
||||
'@resvg/resvg-js-linux-arm64-gnu@2.6.2':
|
||||
optional: true
|
||||
|
||||
'@resvg/resvg-js-linux-arm64-musl@2.6.2':
|
||||
optional: true
|
||||
|
||||
'@resvg/resvg-js-linux-x64-gnu@2.6.2':
|
||||
optional: true
|
||||
|
||||
'@resvg/resvg-js-linux-x64-musl@2.6.2':
|
||||
optional: true
|
||||
|
||||
'@resvg/resvg-js-win32-arm64-msvc@2.6.2':
|
||||
optional: true
|
||||
|
||||
'@resvg/resvg-js-win32-ia32-msvc@2.6.2':
|
||||
optional: true
|
||||
|
||||
'@resvg/resvg-js-win32-x64-msvc@2.6.2':
|
||||
optional: true
|
||||
|
||||
'@resvg/resvg-js@2.6.2':
|
||||
optionalDependencies:
|
||||
'@resvg/resvg-js-android-arm-eabi': 2.6.2
|
||||
'@resvg/resvg-js-android-arm64': 2.6.2
|
||||
'@resvg/resvg-js-darwin-arm64': 2.6.2
|
||||
'@resvg/resvg-js-darwin-x64': 2.6.2
|
||||
'@resvg/resvg-js-linux-arm-gnueabihf': 2.6.2
|
||||
'@resvg/resvg-js-linux-arm64-gnu': 2.6.2
|
||||
'@resvg/resvg-js-linux-arm64-musl': 2.6.2
|
||||
'@resvg/resvg-js-linux-x64-gnu': 2.6.2
|
||||
'@resvg/resvg-js-linux-x64-musl': 2.6.2
|
||||
'@resvg/resvg-js-win32-arm64-msvc': 2.6.2
|
||||
'@resvg/resvg-js-win32-ia32-msvc': 2.6.2
|
||||
'@resvg/resvg-js-win32-x64-msvc': 2.6.2
|
||||
|
||||
'@shikijs/core@1.22.2':
|
||||
dependencies:
|
||||
'@shikijs/engine-javascript': 1.22.2
|
||||
@ -5587,6 +5476,8 @@ snapshots:
|
||||
|
||||
'@types/turndown@5.0.5': {}
|
||||
|
||||
'@types/ungap__structured-clone@1.2.0': {}
|
||||
|
||||
'@types/unist@2.0.10': {}
|
||||
|
||||
'@types/unist@3.0.2': {}
|
||||
@ -6854,6 +6745,16 @@ snapshots:
|
||||
dependencies:
|
||||
'@types/mdast': 4.0.4
|
||||
|
||||
mdast-util-toc@7.1.0:
|
||||
dependencies:
|
||||
'@types/mdast': 4.0.4
|
||||
'@types/ungap__structured-clone': 1.2.0
|
||||
'@ungap/structured-clone': 1.2.0
|
||||
github-slugger: 2.0.0
|
||||
mdast-util-to-string: 4.0.0
|
||||
unist-util-is: 6.0.0
|
||||
unist-util-visit: 5.0.0
|
||||
|
||||
meow@12.1.1: {}
|
||||
|
||||
merge-stream@2.0.0: {}
|
||||
@ -7614,6 +7515,11 @@ snapshots:
|
||||
mdast-util-to-markdown: 2.1.0
|
||||
unified: 11.0.5
|
||||
|
||||
remark-toc@9.0.0:
|
||||
dependencies:
|
||||
'@types/mdast': 4.0.4
|
||||
mdast-util-toc: 7.1.0
|
||||
|
||||
remark@15.0.1:
|
||||
dependencies:
|
||||
'@types/mdast': 4.0.4
|
||||
@ -7740,6 +7646,8 @@ snapshots:
|
||||
ansi-styles: 6.2.1
|
||||
is-fullwidth-code-point: 5.0.0
|
||||
|
||||
slugify@1.6.6: {}
|
||||
|
||||
source-map-js@1.2.1: {}
|
||||
|
||||
source-map@0.7.4: {}
|
||||
|
Loading…
Reference in New Issue
Block a user