From 856a8f27954c20b7130ed778162eb82ec10db8ab Mon Sep 17 00:00:00 2001 From: grassblock Date: Sat, 7 Jun 2025 17:53:46 +0800 Subject: [PATCH 1/4] feat: working table of contents --- astro.config.mjs | 5 +- package.json | 1 - pnpm-lock.yaml | 29 --------- src/components/TableOfContents.astro | 92 ++++++++++++++++++++++++++++ src/pages/post/[...slug].astro | 5 ++ 5 files changed, 98 insertions(+), 34 deletions(-) create mode 100644 src/components/TableOfContents.astro diff --git a/astro.config.mjs b/astro.config.mjs index ea1607a..5b7752d 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -3,7 +3,7 @@ import { defineConfig } from 'astro/config'; import sitemap from '@astrojs/sitemap'; import mdx from '@astrojs/mdx'; -import remarkToc from 'remark-toc'; + import cloudflare from '@astrojs/cloudflare'; @@ -21,9 +21,6 @@ export default defineConfig({ theme: 'nord', wrap: true }, - remarkPlugins: [ - [remarkToc, { heading: 'Contents', maxDepth: 3 }] - ] }, integrations: [sitemap(), mdx()], diff --git a/package.json b/package.json index c42ec2d..b409a5e 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,6 @@ "@fontsource-variable/jetbrains-mono": "^5.2.5", "astro": "^5.2.5", "ico-endec": "^0.1.6", - "remark-toc": "^9.0.0", "sharp": "^0.34.1", "ultrahtml": "^1.6.0" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 69bc3ba..320fe3a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -32,9 +32,6 @@ importers: ico-endec: specifier: ^0.1.6 version: 0.1.6 - remark-toc: - specifier: ^9.0.0 - version: 9.0.0 sharp: specifier: ^0.34.1 version: 0.34.1 @@ -1025,9 +1022,6 @@ packages: '@types/tmp@0.0.33': resolution: {integrity: sha512-gVC1InwyVrO326wbBZw+AO3u2vRXz/iRWq9jYhpG4W8LXyIgDv3ZmcLQ5Q4Gs+gFMyqx+viFoFT+l3p61QFCmQ==} - '@types/ungap__structured-clone@1.2.0': - resolution: {integrity: sha512-ZoaihZNLeZSxESbk9PUAPZOlSpcKx81I1+4emtULDVmBLkYutTcMlCj2K9VNlf9EWODxdO6gkAqEaLorXwZQVA==} - '@types/unist@2.0.11': resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==} @@ -2130,9 +2124,6 @@ packages: mdast-util-to-string@4.0.0: resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==} - mdast-util-toc@7.1.0: - resolution: {integrity: sha512-2TVKotOQzqdY7THOdn2gGzS9d1Sdd66bvxUyw3aNpWfcPXCLYSJCCgfPy30sEtuzkDraJgqF35dzgmz6xlvH/w==} - mdn-data@2.12.2: resolution: {integrity: sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==} @@ -2631,9 +2622,6 @@ packages: remark-stringify@11.0.0: resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==} - remark-toc@9.0.0: - resolution: {integrity: sha512-KJ9txbo33GjDAV1baHFze7ij4G8c7SGYoY8Kzsm2gzFpbhL/bSoVpMMzGa3vrNDSWASNd/3ppAqL7cP2zD6JIA==} - require-directory@2.1.1: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} @@ -4220,8 +4208,6 @@ snapshots: '@types/tmp@0.0.33': {} - '@types/ungap__structured-clone@1.2.0': {} - '@types/unist@2.0.11': {} '@types/unist@3.0.3': {} @@ -5620,16 +5606,6 @@ 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.3.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 - mdn-data@2.12.2: {} merge-stream@2.0.0: {} @@ -6351,11 +6327,6 @@ snapshots: mdast-util-to-markdown: 2.1.2 unified: 11.0.5 - remark-toc@9.0.0: - dependencies: - '@types/mdast': 4.0.4 - mdast-util-toc: 7.1.0 - require-directory@2.1.1: {} requires-port@1.0.0: {} diff --git a/src/components/TableOfContents.astro b/src/components/TableOfContents.astro new file mode 100644 index 0000000..6e91d7c --- /dev/null +++ b/src/components/TableOfContents.astro @@ -0,0 +1,92 @@ +--- +import type { MarkdownHeading } from 'astro'; + +interface Props { + headings: MarkdownHeading[]; +} + +const { headings } = Astro.props; + + +const filteredHeadings = headings.filter((heading) => heading.depth <= 3); + +// github.com/rezahedi/rezahedi.dev/blob/main/src/components/TOC.astro +function buildHierarchy(headings: MarkdownHeading[]) { + const toc: any[] = []; + const parentHeadings = new Map(); + + if (!headings) + return toc; + + headings.forEach((h: any) => { + const heading = { ...h, subheadings: [] }; + parentHeadings.set(heading.depth, heading); + // Change 2 to 1 if your markdown includes your

+ if (heading.depth === 2) { + toc.push(heading); + } else { + parentHeadings.get(heading.depth - 1)?.subheadings.push(heading); + } + }); + return toc; +} + +const toc = buildHierarchy(filteredHeadings); +--- +
+ Table of Contents +
    + { + toc.map((heading) => ( +
  • + {heading.text} + { + heading.subheadings.length > 0 && ( +
      + { + heading.subheadings.map((subheading) => ( +
    • + {subheading.text} + {subheading.subheadings.length > 0 && ( + + )} +
    • + )) + } +
    + ) + } +
  • + )) + } +
+
+ + + diff --git a/src/pages/post/[...slug].astro b/src/pages/post/[...slug].astro index da2b02a..9516bca 100644 --- a/src/pages/post/[...slug].astro +++ b/src/pages/post/[...slug].astro @@ -1,5 +1,6 @@ --- import Layout from '../../layouts/Layout.astro'; + import { getCollection, getEntry } from 'astro:content'; import Comments from "../../components/Comments.astro"; import {getImage} from "astro:assets"; @@ -7,6 +8,7 @@ import {siteConfig} from "../../config"; import ReplyViaEmail from "../../components/ReplyViaEmail.astro"; import { ExtractFirstImage } from '../../plugins/extract-images'; import AuthorInfo from "../../components/helper/authors/Info.astro"; +import TableOfContents from "../../components/TableOfContents.astro"; export async function getStaticPaths() { const blogEntries = await getCollection('posts'); @@ -17,6 +19,8 @@ export async function getStaticPaths() { const { entry } = Astro.props; const { Content } = await entry.render(); +const headings = await entry.render().then(rendered => rendered.headings); + const noscript = siteConfig.noClientJavaScript const slug = Astro.params.slug; const author = entry.data.author || {collection: 'authors', id: siteConfig.defaultAuthor.id}; @@ -48,6 +52,7 @@ const cover = customFeaturedImage || matchedImage_src?.src || firstImageURL || `

{entry.data.title}

{new Date(entry.data.pubDate).toISOString().split('T')[0]} + {headings.length !== 0 && }
From bce6cd4506491235a16e778bae9808a03fb2478e Mon Sep 17 00:00:00 2001 From: grassblock Date: Sat, 7 Jun 2025 17:54:31 +0800 Subject: [PATCH 2/4] feat: adjust margin between content and article info --- src/styles/global.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/styles/global.css b/src/styles/global.css index 476c9e7..40364c7 100644 --- a/src/styles/global.css +++ b/src/styles/global.css @@ -192,7 +192,7 @@ h1.title { margin-bottom: 0.5rem; } div.content { - margin-bottom: 2rem; + margin: 1rem auto; span.date { color: var(--secondary-text-color); font-size: 0.9rem; From 742c011f4ee62e04f2d2d8f7b2e9b76b08203655 Mon Sep 17 00:00:00 2001 From: grassblock Date: Sat, 7 Jun 2025 17:59:19 +0800 Subject: [PATCH 3/4] fix: callout info text color distinguishable when in light mode --- src/components/shortcodes/Callout.astro | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/components/shortcodes/Callout.astro b/src/components/shortcodes/Callout.astro index 51d1cc6..9617c89 100644 --- a/src/components/shortcodes/Callout.astro +++ b/src/components/shortcodes/Callout.astro @@ -40,4 +40,10 @@ const { icon, type = 'info'} = Astro.props; --callout-bg: var(--terminal-red); --callout-text: #111; } + + @media (prefers-color-scheme: light) { + :root:not([data-theme="dark"]) .callout-info { + --callout-text: #eee; + } + } \ No newline at end of file From 27201e2be8fb7c58ce159a12f25e4b3a3deffcd7 Mon Sep 17 00:00:00 2001 From: grassblock Date: Sat, 7 Jun 2025 18:21:09 +0800 Subject: [PATCH 4/4] feat: improve table and blockquote styling for content --- src/styles/global.css | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/styles/global.css b/src/styles/global.css index 40364c7..19555c0 100644 --- a/src/styles/global.css +++ b/src/styles/global.css @@ -230,11 +230,35 @@ div.content { background-color: #3b4252 !important; } + table { + border-collapse: collapse; + } + + table, + th, + td { + border: 1px dashed var(--secondary-text-color); + padding: 10px; + } + h1, h2, h3, h4 { margin: 0.5rem 0; line-height: 1.3; } + a { + text-decoration: underline 1px; + } + + blockquote { + border-left: 1px solid var(--accent-color); + color: var(--text-color); + padding: 20px; + font-style: italic; + margin-left: 0; + margin-right: 0; + } + /* Responsive Images */ img { max-width: 100%;