mirror of
https://github.com/KazooTTT/kazoottt-blog-v2.git
synced 2025-06-23 18:51:30 +08:00
feat: enhancer toc
This commit is contained in:
@ -2,17 +2,25 @@
|
|||||||
import { generateToc } from "@/utils/generateToc";
|
import { generateToc } from "@/utils/generateToc";
|
||||||
import type { MarkdownHeading } from "astro";
|
import type { MarkdownHeading } from "astro";
|
||||||
import TOCHeading from "./TOCHeading.astro";
|
import TOCHeading from "./TOCHeading.astro";
|
||||||
|
import { cn } from "@/utils/tailwind";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
headings: MarkdownHeading[];
|
headings: MarkdownHeading[];
|
||||||
|
classname?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { headings } = Astro.props;
|
const { headings, classname } = Astro.props;
|
||||||
|
|
||||||
const toc = generateToc(headings);
|
const toc = generateToc(headings);
|
||||||
---
|
---
|
||||||
|
|
||||||
<details open class="lg:sticky lg:top-12 lg:order-2 lg:-me-32 lg:basis-64">
|
<details
|
||||||
|
open
|
||||||
|
class={cn(
|
||||||
|
"[&::-webkit-scrollbar-thumb]:bg-accent/20 hover:[&::-webkit-scrollbar-thumb]:bg-accent/30 h-[calc(100vh-20rem)] overflow-x-hidden pr-4 lg:sticky lg:top-12 lg:order-2 lg:-me-32 lg:basis-64 [&::-webkit-scrollbar]:w-2 [&::-webkit-scrollbar-thumb]:rounded-full [&::-webkit-scrollbar-track]:bg-transparent",
|
||||||
|
classname
|
||||||
|
)}
|
||||||
|
>
|
||||||
<summary class="title hover:marker:text-accent cursor-pointer text-lg">Table of Contents</summary>
|
<summary class="title hover:marker:text-accent cursor-pointer text-lg">Table of Contents</summary>
|
||||||
<nav class="ms-4 lg:w-full">
|
<nav class="ms-4 lg:w-full">
|
||||||
<ol class="mt-4">
|
<ol class="mt-4">
|
||||||
|
@ -1,26 +1,26 @@
|
|||||||
---
|
---
|
||||||
import type { MarkdownHeading } from 'astro'
|
import type { MarkdownHeading } from "astro";
|
||||||
import { generateToc } from '@/utils'
|
import { generateToc } from "@/utils";
|
||||||
|
|
||||||
import TOCHeading from './TOCHeading.astro'
|
import TOCHeading from "./TOCHeading.astro";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
headings: MarkdownHeading[]
|
headings: MarkdownHeading[];
|
||||||
}
|
}
|
||||||
|
|
||||||
const { headings } = Astro.props
|
const { headings } = Astro.props;
|
||||||
|
|
||||||
const toc = generateToc(headings)
|
const toc = generateToc(headings);
|
||||||
---
|
---
|
||||||
|
|
||||||
<aside
|
<aside
|
||||||
class='sticky top-20 order-2 -me-28 hidden h-[calc(100vh-6rem)] basis-60 lg:flex lg:flex-col'
|
class="sticky top-20 order-2 -me-28 hidden h-[calc(100vh-6rem)] basis-60 lg:flex lg:flex-col"
|
||||||
>
|
>
|
||||||
{
|
{
|
||||||
toc.length > 0 && (
|
toc.length > 0 && (
|
||||||
<>
|
<>
|
||||||
<h2 class='mb-4 font-semibold'>TABLE OF CONTENTS</h2>
|
<h2 class="mb-4 font-semibold">TABLE OF CONTENTS</h2>
|
||||||
<ul class='max-h-[calc(100vh-10rem)] overflow-y-auto pr-4 text-card-foreground'>
|
<ul class="text-card-foreground max-h-[calc(100vh-10rem)] overflow-y-auto pr-4">
|
||||||
{toc.map((heading) => (
|
{toc.map((heading) => (
|
||||||
<TOCHeading heading={heading} />
|
<TOCHeading heading={heading} />
|
||||||
))}
|
))}
|
||||||
|
@ -65,7 +65,7 @@ if (modifiedDate && modifiedDate.toDateString() === date.toDateString()) {
|
|||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
<div class="group w-full overflow-auto">
|
<div class="group w-full overflow-auto">
|
||||||
<div class="prose prose-sm prose-cactus mt-4 max-w-none [&>p:last-of-type]:mb-0">
|
<div class="prose prose-base prose-cactus mt-4 max-w-none [&>p:last-of-type]:mb-0">
|
||||||
<Content />
|
<Content />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -27,7 +27,7 @@ const {
|
|||||||
/>
|
/>
|
||||||
</head>
|
</head>
|
||||||
<body
|
<body
|
||||||
class="bg-global-bg text-global-text mx-auto flex min-h-screen max-w-3xl flex-col px-4 pt-16 font-mono text-sm font-normal antialiased sm:px-8"
|
class="bg-global-bg text-global-text mx-auto flex min-h-screen max-w-5xl flex-col px-4 pt-16 font-mono text-sm font-normal antialiased sm:px-8"
|
||||||
>
|
>
|
||||||
<ThemeProvider />
|
<ThemeProvider />
|
||||||
<SkipLink />
|
<SkipLink />
|
||||||
|
@ -38,14 +38,36 @@ const readingTime: string = remarkPluginFrontmatter.readingTime;
|
|||||||
tags: [category, ...tags].join(", "),
|
tags: [category, ...tags].join(", "),
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ArticleContainer className="grow break-words" dataPagefindBody={true}>
|
<div class="hidden flex-col gap-10 lg:flex lg:flex-row lg:items-start">
|
||||||
|
{!!headings.length && <TOC headings={headings} classname="lg:w-64 lg:flex-shrink-0" />}
|
||||||
|
|
||||||
|
<ArticleContainer className="grow break-words" dataPagefindBody={true}>
|
||||||
|
<div id="blog-hero" class="mb-12">
|
||||||
|
<Masthead content={post} readingTime={readingTime} ogImage={socialImage} />
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col gap-10 lg:flex-row lg:items-start">
|
||||||
|
<div
|
||||||
|
class="prose prose-base prose-headings:font-semibold prose-headings:text-accent-2 prose-headings:before:absolute prose-headings:before:-ms-4 prose-headings:before:text-gray-600 prose-headings:hover:before:text-accent sm:prose-headings:before:content-['#'] sm:prose-th:before:content-none lg:!max-w-none"
|
||||||
|
>
|
||||||
|
<slot />
|
||||||
|
<WebMentions />
|
||||||
|
<GiscusComment client:load />
|
||||||
|
<div class="mt-8 border-t pt-4">
|
||||||
|
<ShareButtons />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ArticleContainer>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ArticleContainer className="grow break-words lg:hidden" dataPagefindBody={true}>
|
||||||
<div id="blog-hero" class="mb-12">
|
<div id="blog-hero" class="mb-12">
|
||||||
<Masthead content={post} readingTime={readingTime} ogImage={socialImage} />
|
<Masthead content={post} readingTime={readingTime} ogImage={socialImage} />
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col gap-10 lg:flex-row lg:items-start">
|
<div class="flex flex-col gap-10 lg:flex-row lg:items-start">
|
||||||
{!!headings.length && <TOC headings={headings} />}
|
{!!headings.length && <TOC headings={headings} classname="lg:w-64 lg:flex-shrink-0" />}
|
||||||
<div
|
<div
|
||||||
class="prose prose-sm prose-headings:font-semibold prose-headings:text-accent-2 prose-headings:before:absolute prose-headings:before:-ms-4 prose-headings:before:text-gray-600 prose-headings:hover:before:text-accent sm:prose-headings:before:content-['#'] sm:prose-th:before:content-none"
|
class="prose prose-base prose-headings:font-semibold prose-headings:text-accent-2 prose-headings:before:absolute prose-headings:before:-ms-4 prose-headings:before:text-gray-600 prose-headings:hover:before:text-accent sm:prose-headings:before:content-['#'] sm:prose-th:before:content-none lg:!max-w-none"
|
||||||
>
|
>
|
||||||
<slot />
|
<slot />
|
||||||
<WebMentions />
|
<WebMentions />
|
||||||
|
@ -10,7 +10,7 @@ const meta = {
|
|||||||
|
|
||||||
<PageLayout meta={meta}>
|
<PageLayout meta={meta}>
|
||||||
<h1 class="title mb-6">About</h1>
|
<h1 class="title mb-6">About</h1>
|
||||||
<div class="prose prose-sm prose-cactus max-w-none">TODO ...</div>
|
<div class="prose prose-base prose-cactus max-w-none">TODO ...</div>
|
||||||
<div class="mt-2">
|
<div class="mt-2">
|
||||||
<a href="https://wakatime.com/@d3dc2570-e4bf-4469-b0c2-127b495e8b91"
|
<a href="https://wakatime.com/@d3dc2570-e4bf-4469-b0c2-127b495e8b91"
|
||||||
><img
|
><img
|
||||||
|
Reference in New Issue
Block a user