diff --git a/astro.config.ts b/astro.config.ts index a38cc4c..7b76f18 100644 --- a/astro.config.ts +++ b/astro.config.ts @@ -13,14 +13,14 @@ import rehypePrettyCode from 'rehype-pretty-code' import remarkEmoji from 'remark-emoji' import remarkMath from 'remark-math' import remarkSectionize from 'remark-sectionize' -import remarkToc from 'remark-toc' -import remarkCallout from "@r4ai/remark-callout"; +import rehypeDocument from 'rehype-document' +import remarkCallout from "@r4ai/remark-callout" import { pluginCollapsibleSections } from '@expressive-code/plugin-collapsible-sections' import { pluginLineNumbers } from '@expressive-code/plugin-line-numbers' import tailwindcss from '@tailwindcss/vite' -import umami from "@yeskunall/astro-umami"; +import umami from "@yeskunall/astro-umami" export default defineConfig({ site: 'https://blog.z0x.ca', @@ -87,6 +87,12 @@ export default defineConfig({ markdown: { syntaxHighlight: false, rehypePlugins: [ + [ + rehypeDocument, + { + css: 'https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/katex.min.css', + }, + ], [ rehypeExternalLinks, { @@ -106,6 +112,6 @@ export default defineConfig({ }, ], ], - remarkPlugins: [remarkToc, remarkMath, remarkEmoji, remarkSectionize, remarkCallout,], + remarkPlugins: [remarkMath, remarkEmoji, remarkSectionize, remarkCallout,], }, }) diff --git a/bun.lock b/bun.lock index 4a5dd6b..2719ca7 100644 --- a/bun.lock +++ b/bun.lock @@ -22,7 +22,6 @@ "@radix-ui/react-scroll-area": "^1.2.4", "@radix-ui/react-separator": "^1.1.3", "@radix-ui/react-slot": "^1.2.0", - "@rehype-pretty/transformers": "^0.13.2", "@tailwindcss/vite": "^4.1.3", "@types/react": "19.0.0", "@types/react-dom": "19.0.0", @@ -30,13 +29,13 @@ "astro": "^5.6.1", "astro-expressive-code": "^0.40.2", "astro-icon": "^1.1.5", - "bootstrap-icons": "^1.11.3", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "lucide-react": "^0.469.0", "patch-package": "^8.0.0", "react": "19.0.0", "react-dom": "19.0.0", + "rehype-document": "^7.0.3", "rehype-external-links": "^3.0.0", "rehype-katex": "^7.0.1", "rehype-pretty-code": "^0.14.1", @@ -319,8 +318,6 @@ "@radix-ui/rect": ["@radix-ui/rect@1.1.1", "", {}, "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw=="], - "@rehype-pretty/transformers": ["@rehype-pretty/transformers@0.13.2", "", {}, "sha512-p2ciQSwqy5Ip8aNUa9q6rdS/hJZXrxHYYfDVOHvKOsBu3t9HDmQ65YX6r9Qbl19vi160OAxmGF7MIoCRDJrRhg=="], - "@rollup/pluginutils": ["@rollup/pluginutils@5.1.4", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-walker": "^2.0.2", "picomatch": "^4.0.2" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ=="], "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.37.0", "", { "os": "android", "cpu": "arm" }, "sha512-l7StVw6WAa8l3vA1ov80jyetOAEo1FtHvZDbzXDO/02Sq/QVvqlHkYoFwDJPIMj0GKiistsBudfx5tGFnwYWDQ=="], @@ -513,8 +510,6 @@ "boolbase": ["boolbase@1.0.0", "", {}, "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="], - "bootstrap-icons": ["bootstrap-icons@1.11.3", "", {}, "sha512-+3lpHrCw/it2/7lBL15VR0HEumaBss0+f/Lb6ZvHISn1mlK83jjFpooTLsMWbIjJMDjDjOExMsTxnXSIT4k4ww=="], - "boxen": ["boxen@8.0.1", "", { "dependencies": { "ansi-align": "^3.0.1", "camelcase": "^8.0.0", "chalk": "^5.3.0", "cli-boxes": "^3.0.0", "string-width": "^7.2.0", "type-fest": "^4.21.0", "widest-line": "^5.0.0", "wrap-ansi": "^9.0.0" } }, "sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw=="], "brace-expansion": ["brace-expansion@1.1.11", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA=="], @@ -809,7 +804,7 @@ "hast-util-whitespace": ["hast-util-whitespace@3.0.0", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw=="], - "hastscript": ["hastscript@9.0.1", "", { "dependencies": { "@types/hast": "^3.0.0", "comma-separated-tokens": "^2.0.0", "hast-util-parse-selector": "^4.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0" } }, "sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w=="], + "hastscript": ["hastscript@8.0.0", "", { "dependencies": { "@types/hast": "^3.0.0", "comma-separated-tokens": "^2.0.0", "hast-util-parse-selector": "^4.0.0", "property-information": "^6.0.0", "space-separated-tokens": "^2.0.0" } }, "sha512-dMOtzCEd3ABUeSIISmrETiKuyydk1w0pa+gE/uormcTpSYuaNJPbX1NU3JLyscSLjwAQM8bWMhhIlnCqnRvDTw=="], "html-escaper": ["html-escaper@3.0.3", "", {}, "sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ=="], @@ -1185,6 +1180,8 @@ "rehype": ["rehype@13.0.2", "", { "dependencies": { "@types/hast": "^3.0.0", "rehype-parse": "^9.0.0", "rehype-stringify": "^10.0.0", "unified": "^11.0.0" } }, "sha512-j31mdaRFrwFRUIlxGeuPXXKWQxet52RBQRvCmzl5eCefn/KGbomK5GMHNMsOJf55fgo3qw5tST5neDuarDYR2A=="], + "rehype-document": ["rehype-document@7.0.3", "", { "dependencies": { "@types/hast": "^3.0.0", "hastscript": "^8.0.0", "unified": "^11.0.0", "vfile": "^6.0.0" } }, "sha512-g5zq6i2FwWVBVdyVi0Jw/5MRvsHj3wuJCn+QeyOjm29QBpTG4r1iUElyH9GhfWx5fB27ZEApA53RdAiYGBb4zQ=="], + "rehype-expressive-code": ["rehype-expressive-code@0.40.2", "", { "dependencies": { "expressive-code": "^0.40.2" } }, "sha512-+kn+AMGCrGzvtH8Q5lC6Y5lnmTV/r33fdmi5QU/IH1KPHKobKr5UnLwJuqHv5jBTSN/0v2wLDS7RTM73FVzqmQ=="], "rehype-external-links": ["rehype-external-links@3.0.0", "", { "dependencies": { "@types/hast": "^3.0.0", "@ungap/structured-clone": "^1.0.0", "hast-util-is-element": "^3.0.0", "is-absolute-url": "^4.0.0", "space-separated-tokens": "^2.0.0", "unist-util-visit": "^5.0.0" } }, "sha512-yp+e5N9V3C6bwBeAC4n796kc86M4gJCdlVhiMTxIrJG5UHDMh+PJANf9heqORJbt1nrCbDwIlAZKjANIaVBbvw=="], @@ -1429,6 +1426,8 @@ "@babel/traverse/globals": ["globals@11.12.0", "", {}, "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="], + "@expressive-code/core/hastscript": ["hastscript@9.0.1", "", { "dependencies": { "@types/hast": "^3.0.0", "comma-separated-tokens": "^2.0.0", "hast-util-parse-selector": "^4.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0" } }, "sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w=="], + "@expressive-code/plugin-shiki/shiki": ["shiki@1.29.2", "", { "dependencies": { "@shikijs/core": "1.29.2", "@shikijs/engine-javascript": "1.29.2", "@shikijs/engine-oniguruma": "1.29.2", "@shikijs/langs": "1.29.2", "@shikijs/themes": "1.29.2", "@shikijs/types": "1.29.2", "@shikijs/vscode-textmate": "^10.0.1", "@types/hast": "^3.0.4" } }, "sha512-njXuliz/cP+67jU2hukkxCNuH1yUi4QfdZZY+sMr5PPrIyXSu5iTb/qYC4BiWWB0vZ+7TbdvYUCeL23zpwCfbg=="], "@iconify/utils/local-pkg": ["local-pkg@1.1.1", "", { "dependencies": { "mlly": "^1.7.4", "pkg-types": "^2.0.1", "quansync": "^0.2.8" } }, "sha512-WunYko2W1NcdfAFpuLUoucsgULmgDBRkdxHxWQ7mK0cQqwPiy8E1enjuRBrhLtZkB5iScJ1XIPdhVEFK8aOLSg=="], @@ -1453,10 +1452,16 @@ "fs-minipass/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], + "hast-util-from-dom/hastscript": ["hastscript@9.0.1", "", { "dependencies": { "@types/hast": "^3.0.0", "comma-separated-tokens": "^2.0.0", "hast-util-parse-selector": "^4.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0" } }, "sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w=="], + + "hast-util-from-parse5/hastscript": ["hastscript@9.0.1", "", { "dependencies": { "@types/hast": "^3.0.0", "comma-separated-tokens": "^2.0.0", "hast-util-parse-selector": "^4.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0" } }, "sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w=="], + "hast-util-to-parse5/property-information": ["property-information@6.5.0", "", {}, "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig=="], "hast-util-to-text/unist-util-find-after": ["unist-util-find-after@5.0.0", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0" } }, "sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ=="], + "hastscript/property-information": ["property-information@6.5.0", "", {}, "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig=="], + "micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], "minizlib/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], diff --git a/package.json b/package.json index 8a7c50c..10ce722 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,6 @@ "@radix-ui/react-scroll-area": "^1.2.4", "@radix-ui/react-separator": "^1.1.3", "@radix-ui/react-slot": "^1.2.0", - "@rehype-pretty/transformers": "^0.13.2", "@tailwindcss/vite": "^4.1.3", "@types/react": "19.0.0", "@types/react-dom": "19.0.0", @@ -39,13 +38,13 @@ "astro": "^5.6.1", "astro-expressive-code": "^0.40.2", "astro-icon": "^1.1.5", - "bootstrap-icons": "^1.11.3", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "lucide-react": "^0.469.0", "patch-package": "^8.0.0", "react": "19.0.0", "react-dom": "19.0.0", + "rehype-document": "^7.0.3", "rehype-external-links": "^3.0.0", "rehype-katex": "^7.0.1", "rehype-pretty-code": "^0.14.1", diff --git a/src/components/TableOfContents.astro b/src/components/TableOfContents.astro index 0aa8eee..0c18c0f 100644 --- a/src/components/TableOfContents.astro +++ b/src/components/TableOfContents.astro @@ -1,86 +1,71 @@ --- import { ScrollArea } from '@/components/ui/scroll-area' +import { cn } from '@/lib/utils' +import type { MarkdownHeading } from 'astro' import { Icon } from 'astro-icon/components' -import TableOfContentsHeading from './TableOfContentsHeading.astro' -export interface Heading { - depth: number - slug: string - text: string - subheadings: Heading[] +type Props = { + headings: MarkdownHeading[] } const { headings } = Astro.props -const toc = buildToc(headings) -function buildToc(headings: Heading[]): Heading[] { - const toc: Heading[] = [] - const stack: Heading[] = [] - - // biome-ignore lint/complexity/noForEach: - headings.forEach((h) => { - const heading = { ...h, subheadings: [] } - - while (stack.length > 0 && stack[stack.length - 1].depth >= heading.depth) { - stack.pop() - } - - if (stack.length === 0) { - toc.push(heading) - } else { - stack[stack.length - 1].subheadings.push(heading) - } - - stack.push(heading) - }) - - return toc +function getHeadingMargin(depth: number): string { + const margins: Record = { + 3: 'ml-4', + 4: 'ml-8', + 5: 'ml-12', + 6: 'ml-16', + } + return margins[depth] || '' } ---
- Table of Contents + Table of Contents + - +
- - + \ No newline at end of file diff --git a/src/styles/global.css b/src/styles/global.css index f4f2623..3f27863 100644 --- a/src/styles/global.css +++ b/src/styles/global.css @@ -1,4 +1,3 @@ -@import 'https://cdn.jsdelivr.net/npm/katex@0.12.0/dist/katex.min.css'; @import 'tailwindcss'; @custom-variant dark (&:is(.dark *));