feat: personalize blog and update configurations

This commit is contained in:
KazooTTT
2025-02-05 20:35:05 +08:00
parent 4f55d62fb6
commit f22b2529e8
20 changed files with 314 additions and 50 deletions

2
.github/FUNDING.yml vendored
View File

@ -1,2 +1,2 @@
# These are supported funding model platforms
buy_me_a_coffee: chris.williams
buy_me_a_coffee: kazoottt

View File

@ -1,6 +1,6 @@
{
"[javascript]": { "editor.defaultFormatter": "biomejs.biome" },
"[typescript]": { "editor.defaultFormatter": "biomejs.biome" },
"[typescript]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
"[javascriptreact]": { "editor.defaultFormatter": "biomejs.biome" },
"[typescriptreact]": { "editor.defaultFormatter": "biomejs.biome" },
"[json]": { "editor.defaultFormatter": "biomejs.biome" },

View File

@ -36,7 +36,7 @@ export default defineConfig({
webmanifest({
// See: https://github.com/alextim/astro-lib/blob/main/packages/astro-webmanifest/README.md
name: siteConfig.title,
short_name: "Astro_Cactus", // optional
short_name: "kazoottt blog", // optional
description: siteConfig.description,
lang: siteConfig.lang,
icon: "public/icon.svg", // the source for generating favicon & icons

View File

@ -27,6 +27,7 @@
"astro-webmanifest": "^1.0.0",
"cssnano": "^7.0.6",
"hastscript": "^9.0.0",
"markdown-it": "^14.1.0",
"mdast-util-directive": "^3.0.0",
"mdast-util-to-markdown": "^2.1.2",
"mdast-util-to-string": "^4.0.0",
@ -34,6 +35,7 @@
"rehype-external-links": "^3.0.0",
"rehype-unwrap-images": "^1.0.0",
"remark-directive": "^3.0.0",
"sanitize-html": "^2.14.0",
"satori": "0.12.1",
"satori-html": "^0.3.2",
"sharp": "^0.33.5",
@ -48,7 +50,9 @@
"@resvg/resvg-js": "^2.6.2",
"@tailwindcss/typography": "^0.5.16",
"@types/hast": "^3.0.4",
"@types/markdown-it": "^14.1.2",
"@types/mdast": "^4.0.4",
"@types/sanitize-html": "^2.13.0",
"autoprefixer": "^10.4.20",
"pagefind": "^1.3.0",
"prettier": "^3.4.2",

156
pnpm-lock.yaml generated
View File

@ -44,6 +44,9 @@ importers:
hastscript:
specifier: ^9.0.0
version: 9.0.0
markdown-it:
specifier: ^14.1.0
version: 14.1.0
mdast-util-directive:
specifier: ^3.0.0
version: 3.0.0
@ -65,6 +68,9 @@ importers:
remark-directive:
specifier: ^3.0.0
version: 3.0.0
sanitize-html:
specifier: ^2.14.0
version: 2.14.0
satori:
specifier: 0.12.1
version: 0.12.1
@ -102,9 +108,15 @@ importers:
'@types/hast':
specifier: ^3.0.4
version: 3.0.4
'@types/markdown-it':
specifier: ^14.1.2
version: 14.1.2
'@types/mdast':
specifier: ^4.0.4
version: 4.0.4
'@types/sanitize-html':
specifier: ^2.13.0
version: 2.13.0
autoprefixer:
specifier: ^10.4.20
version: 10.4.20(postcss@8.4.49)
@ -233,24 +245,28 @@ packages:
engines: {node: '>=14.21.3'}
cpu: [arm64]
os: [linux]
libc: [musl]
'@biomejs/cli-linux-arm64@1.9.4':
resolution: {integrity: sha512-fJIW0+LYujdjUgJJuwesP4EjIBl/N/TcOX3IvIHJQNsAqvV2CHIogsmA94BPG6jZATS4Hi+xv4SkBBQSt1N4/g==}
engines: {node: '>=14.21.3'}
cpu: [arm64]
os: [linux]
libc: [glibc]
'@biomejs/cli-linux-x64-musl@1.9.4':
resolution: {integrity: sha512-gEhi/jSBhZ2m6wjV530Yy8+fNqG8PAinM3oV7CyO+6c3CEh16Eizm21uHVsyVBEB6RIM8JHIl6AGYCv6Q6Q9Tg==}
engines: {node: '>=14.21.3'}
cpu: [x64]
os: [linux]
libc: [musl]
'@biomejs/cli-linux-x64@1.9.4':
resolution: {integrity: sha512-lRCJv/Vi3Vlwmbd6K+oQ0KhLHMAysN8lXoCI7XeHlxaajk06u7G+UsFSO01NAs5iYuWKmVZjmiOzJ0OJmGsMwg==}
engines: {node: '>=14.21.3'}
cpu: [x64]
os: [linux]
libc: [glibc]
'@biomejs/cli-win32-arm64@1.9.4':
resolution: {integrity: sha512-tlbhLk+WXZmgwoIKwHIHEBZUwxml7bRJgk0X2sPyNR3S93cdRq6XulAZRQJ17FYGGzWne0fgrXBKpl7l4M87Hg==}
@ -630,67 +646,79 @@ packages:
resolution: {integrity: sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==}
cpu: [arm64]
os: [linux]
libc: [glibc]
'@img/sharp-libvips-linux-arm@1.0.5':
resolution: {integrity: sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==}
cpu: [arm]
os: [linux]
libc: [glibc]
'@img/sharp-libvips-linux-s390x@1.0.4':
resolution: {integrity: sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==}
cpu: [s390x]
os: [linux]
libc: [glibc]
'@img/sharp-libvips-linux-x64@1.0.4':
resolution: {integrity: sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==}
cpu: [x64]
os: [linux]
libc: [glibc]
'@img/sharp-libvips-linuxmusl-arm64@1.0.4':
resolution: {integrity: sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==}
cpu: [arm64]
os: [linux]
libc: [musl]
'@img/sharp-libvips-linuxmusl-x64@1.0.4':
resolution: {integrity: sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==}
cpu: [x64]
os: [linux]
libc: [musl]
'@img/sharp-linux-arm64@0.33.5':
resolution: {integrity: sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [arm64]
os: [linux]
libc: [glibc]
'@img/sharp-linux-arm@0.33.5':
resolution: {integrity: sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [arm]
os: [linux]
libc: [glibc]
'@img/sharp-linux-s390x@0.33.5':
resolution: {integrity: sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [s390x]
os: [linux]
libc: [glibc]
'@img/sharp-linux-x64@0.33.5':
resolution: {integrity: sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [x64]
os: [linux]
libc: [glibc]
'@img/sharp-linuxmusl-arm64@0.33.5':
resolution: {integrity: sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [arm64]
os: [linux]
libc: [musl]
'@img/sharp-linuxmusl-x64@0.33.5':
resolution: {integrity: sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [x64]
os: [linux]
libc: [musl]
'@img/sharp-wasm32@0.33.5':
resolution: {integrity: sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==}
@ -793,24 +821,28 @@ packages:
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
libc: [glibc]
'@resvg/resvg-js-linux-arm64-musl@2.6.2':
resolution: {integrity: sha512-3h3dLPWNgSsD4lQBJPb4f+kvdOSJHa5PjTYVsWHxLUzH4IFTJUAnmuWpw4KqyQ3NA5QCyhw4TWgxk3jRkQxEKg==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
libc: [musl]
'@resvg/resvg-js-linux-x64-gnu@2.6.2':
resolution: {integrity: sha512-IVUe+ckIerA7xMZ50duAZzwf1U7khQe2E0QpUxu5MBJNao5RqC0zwV/Zm965vw6D3gGFUl7j4m+oJjubBVoftw==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
libc: [glibc]
'@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]
libc: [musl]
'@resvg/resvg-js-win32-arm64-msvc@2.6.2':
resolution: {integrity: sha512-7C/RSgCa+7vqZ7qAbItfiaAWhyRSoD4l4BQAbVDqRRsRgY+S+hgS3in0Rxr7IorKUpGE69X48q6/nOAuTJQxeQ==}
@ -877,51 +909,61 @@ packages:
resolution: {integrity: sha512-PaMRNBSqCx7K3Wc9QZkFx5+CX27WFpAMxJNiYGAXfmMIKC7jstlr32UhTgK6T07OtqR+wYlWm9IxzennjnvdJg==}
cpu: [arm]
os: [linux]
libc: [glibc]
'@rollup/rollup-linux-arm-musleabihf@4.30.1':
resolution: {integrity: sha512-B8Rcyj9AV7ZlEFqvB5BubG5iO6ANDsRKlhIxySXcF1axXYUyqwBok+XZPgIYGBgs7LDXfWfifxhw0Ik57T0Yug==}
cpu: [arm]
os: [linux]
libc: [musl]
'@rollup/rollup-linux-arm64-gnu@4.30.1':
resolution: {integrity: sha512-hqVyueGxAj3cBKrAI4aFHLV+h0Lv5VgWZs9CUGqr1z0fZtlADVV1YPOij6AhcK5An33EXaxnDLmJdQikcn5NEw==}
cpu: [arm64]
os: [linux]
libc: [glibc]
'@rollup/rollup-linux-arm64-musl@4.30.1':
resolution: {integrity: sha512-i4Ab2vnvS1AE1PyOIGp2kXni69gU2DAUVt6FSXeIqUCPIR3ZlheMW3oP2JkukDfu3PsexYRbOiJrY+yVNSk9oA==}
cpu: [arm64]
os: [linux]
libc: [musl]
'@rollup/rollup-linux-loongarch64-gnu@4.30.1':
resolution: {integrity: sha512-fARcF5g296snX0oLGkVxPmysetwUk2zmHcca+e9ObOovBR++9ZPOhqFUM61UUZ2EYpXVPN1redgqVoBB34nTpQ==}
cpu: [loong64]
os: [linux]
libc: [glibc]
'@rollup/rollup-linux-powerpc64le-gnu@4.30.1':
resolution: {integrity: sha512-GLrZraoO3wVT4uFXh67ElpwQY0DIygxdv0BNW9Hkm3X34wu+BkqrDrkcsIapAY+N2ATEbvak0XQ9gxZtCIA5Rw==}
cpu: [ppc64]
os: [linux]
libc: [glibc]
'@rollup/rollup-linux-riscv64-gnu@4.30.1':
resolution: {integrity: sha512-0WKLaAUUHKBtll0wvOmh6yh3S0wSU9+yas923JIChfxOaaBarmb/lBKPF0w/+jTVozFnOXJeRGZ8NvOxvk/jcw==}
cpu: [riscv64]
os: [linux]
libc: [glibc]
'@rollup/rollup-linux-s390x-gnu@4.30.1':
resolution: {integrity: sha512-GWFs97Ruxo5Bt+cvVTQkOJ6TIx0xJDD/bMAOXWJg8TCSTEK8RnFeOeiFTxKniTc4vMIaWvCplMAFBt9miGxgkA==}
cpu: [s390x]
os: [linux]
libc: [glibc]
'@rollup/rollup-linux-x64-gnu@4.30.1':
resolution: {integrity: sha512-UtgGb7QGgXDIO+tqqJ5oZRGHsDLO8SlpE4MhqpY9Llpzi5rJMvrK6ZGhsRCST2abZdBqIBeXW6WPD5fGK5SDwg==}
cpu: [x64]
os: [linux]
libc: [glibc]
'@rollup/rollup-linux-x64-musl@4.30.1':
resolution: {integrity: sha512-V9U8Ey2UqmQsBT+xTOeMzPzwDzyXmnAoO4edZhL7INkwQcaW1Ckv3WJX3qrrp/VHaDkEWIBWhRwP47r8cdrOow==}
cpu: [x64]
os: [linux]
libc: [musl]
'@rollup/rollup-win32-arm64-msvc@4.30.1':
resolution: {integrity: sha512-WabtHWiPaFF47W3PkHnjbmWawnX/aE57K47ZDT1BXTS5GgrBUEpvOzq0FI0V/UYzQJgdb8XlhVNH8/fwV8xDjw==}
@ -1020,24 +1062,28 @@ packages:
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
libc: [glibc]
'@tailwindcss/oxide-linux-arm64-musl@4.0.0-beta.8':
resolution: {integrity: sha512-P+apWSDGGgCGbTHfyNxUe4+n3lIH6kV+7Y4QGCkBUx5o3L2RzZ2I2/kQNA5z60Moac0tUqX9mKF8AyCmGpBFCg==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
libc: [musl]
'@tailwindcss/oxide-linux-x64-gnu@4.0.0-beta.8':
resolution: {integrity: sha512-6Xj+lHcW0WrsrtRtiHbBFFoJYfHDhscNKumYFyv6THFP9AMwrB/9jp3xPfx9q7Pp3OJf3l0VP8KhdI5MPEMBpw==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
libc: [glibc]
'@tailwindcss/oxide-linux-x64-musl@4.0.0-beta.8':
resolution: {integrity: sha512-RWeMlHrcS0Rj3tFhbwxkhnsLmsw8E6g0nHjDawNY0lTYi6PP5RZF7ghgzUbzMkjw6QcBJthycpXYXUCKPIZlpA==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
libc: [musl]
'@tailwindcss/oxide-win32-arm64-msvc@4.0.0-beta.8':
resolution: {integrity: sha512-+FQFS2XjsHGlh+U/paIcUULLfkSmcBp9QzXkTu8UsEH6Ygp7L8RmMZshAr5dQDjXFKBvKHKJX4oIg/SP+VThgA==}
@ -1087,9 +1133,18 @@ packages:
'@types/hast@3.0.4':
resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==}
'@types/linkify-it@5.0.0':
resolution: {integrity: sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==}
'@types/markdown-it@14.1.2':
resolution: {integrity: sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==}
'@types/mdast@4.0.4':
resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==}
'@types/mdurl@2.0.0':
resolution: {integrity: sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==}
'@types/mdx@2.0.13':
resolution: {integrity: sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==}
@ -1108,6 +1163,9 @@ packages:
'@types/node@22.7.5':
resolution: {integrity: sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==}
'@types/sanitize-html@2.13.0':
resolution: {integrity: sha512-X31WxbvW9TjIhZZNyNBZ/p5ax4ti7qsNDBDEnH4zAgmEh35YnFD1UiS6z9Cd34kKm0LslFW0KPmTQzu/oGtsqQ==}
'@types/sax@1.2.7':
resolution: {integrity: sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==}
@ -1537,6 +1595,10 @@ packages:
resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==}
engines: {node: '>=4.0.0'}
deepmerge@4.3.1:
resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==}
engines: {node: '>=0.10.0'}
defu@6.1.4:
resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==}
@ -1660,6 +1722,10 @@ packages:
escape-html@1.0.3:
resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==}
escape-string-regexp@4.0.0:
resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
engines: {node: '>=10'}
escape-string-regexp@5.0.0:
resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==}
engines: {node: '>=12'}
@ -1881,6 +1947,9 @@ packages:
html-void-elements@3.0.0:
resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==}
htmlparser2@8.0.2:
resolution: {integrity: sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==}
htmlparser2@9.1.0:
resolution: {integrity: sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==}
@ -1962,6 +2031,10 @@ packages:
resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==}
engines: {node: '>=12'}
is-plain-object@5.0.0:
resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==}
engines: {node: '>=0.10.0'}
is-wsl@3.1.0:
resolution: {integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==}
engines: {node: '>=16'}
@ -2027,24 +2100,28 @@ packages:
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [linux]
libc: [glibc]
lightningcss-linux-arm64-musl@1.28.2:
resolution: {integrity: sha512-1SPG1ZTNnphWvAv8RVOymlZ8BDtAg69Hbo7n4QxARvkFVCJAt0cgjAw1Fox0WEhf4PwnyoOBaVH0Z5YNgzt4dA==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [linux]
libc: [musl]
lightningcss-linux-x64-gnu@1.28.2:
resolution: {integrity: sha512-ZhQy0FcO//INWUdo/iEdbefntTdpPVQ0XJwwtdbBuMQe+uxqZoytm9M+iqR9O5noWFaxK+nbS2iR/I80Q2Ofpg==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [linux]
libc: [glibc]
lightningcss-linux-x64-musl@1.28.2:
resolution: {integrity: sha512-alb/j1NMrgQmSFyzTbN1/pvMPM+gdDw7YBuQ5VSgcFDypN3Ah0BzC2dTZbzwzaMdUVDszX6zH5MzjfVN1oGuww==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [linux]
libc: [musl]
lightningcss-win32-arm64-msvc@1.28.2:
resolution: {integrity: sha512-WnwcjcBeAt0jGdjlgbT9ANf30pF0C/QMb1XnLnH272DQU8QXh+kmpi24R55wmWBwaTtNAETZ+m35ohyeMiNt+g==}
@ -2069,6 +2146,9 @@ packages:
linebreak@1.1.0:
resolution: {integrity: sha512-MHp03UImeVhB7XZtjd0E4n6+3xr5Dq/9xI/5FptGk5FrbDR3zagPa2DS6U8ks/3HjbKWG9Q1M2ufOzxV2qLYSQ==}
linkify-it@5.0.0:
resolution: {integrity: sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==}
load-yaml-file@0.2.0:
resolution: {integrity: sha512-OfCBkGEw4nN6JLtgRidPX6QxjBQGQf72q3si2uvqyFEMbycSFFHwAZeXx6cJgFM9wmLrf9zBwCP3Ivqa+LLZPw==}
engines: {node: '>=6'}
@ -2115,6 +2195,10 @@ packages:
resolution: {integrity: sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q==}
engines: {node: '>=16'}
markdown-it@14.1.0:
resolution: {integrity: sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==}
hasBin: true
markdown-table@3.0.4:
resolution: {integrity: sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==}
@ -2181,6 +2265,9 @@ packages:
mdn-data@2.0.30:
resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==}
mdurl@2.0.0:
resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==}
merge2@1.4.1:
resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
engines: {node: '>= 8'}
@ -2493,6 +2580,9 @@ packages:
parse-latin@7.0.0:
resolution: {integrity: sha512-mhHgobPPua5kZ98EF4HWiH167JWBfl4pvAIXXdbaVohtK7a6YBOy56kvhCqduqyo/f3yrHFWmqmiMg/BkBkYYQ==}
parse-srcset@1.0.2:
resolution: {integrity: sha512-/2qh0lav6CmI15FzA3i/2Bzk2zCgQhGMkvhOhKNcBVQ1ldgpbfiNTVslmooUmWJcADi1f1kIeynbDRVzNlfR6Q==}
parse5-htmlparser2-tree-adapter@7.1.0:
resolution: {integrity: sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==}
@ -2818,6 +2908,10 @@ packages:
pump@3.0.2:
resolution: {integrity: sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==}
punycode.js@2.3.1:
resolution: {integrity: sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==}
engines: {node: '>=6'}
queue-microtask@1.2.3:
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
@ -2963,6 +3057,9 @@ packages:
safer-buffer@2.1.2:
resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
sanitize-html@2.14.0:
resolution: {integrity: sha512-CafX+IUPxZshXqqRaG9ZClSlfPVjSxI0td7n07hk8QO2oO+9JDnlcL8iM8TWeOXOIBFgIOx6zioTzM53AOMn3g==}
sass-formatter@0.7.9:
resolution: {integrity: sha512-CWZ8XiSim+fJVG0cFLStwDvft1VI7uvXdCNJYXhDvowiv+DsbD1nXLiQ4zrE5UBvj5DWZJ93cwN0NX5PMsr1Pw==}
@ -3162,6 +3259,9 @@ packages:
engines: {node: '>=14.17'}
hasBin: true
uc.micro@2.1.0:
resolution: {integrity: sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==}
ufo@1.5.4:
resolution: {integrity: sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==}
@ -4424,10 +4524,19 @@ snapshots:
dependencies:
'@types/unist': 3.0.3
'@types/linkify-it@5.0.0': {}
'@types/markdown-it@14.1.2':
dependencies:
'@types/linkify-it': 5.0.0
'@types/mdurl': 2.0.0
'@types/mdast@4.0.4':
dependencies:
'@types/unist': 3.0.3
'@types/mdurl@2.0.0': {}
'@types/mdx@2.0.13': {}
'@types/ms@0.7.34': {}
@ -4446,6 +4555,10 @@ snapshots:
dependencies:
undici-types: 6.19.8
'@types/sanitize-html@2.13.0':
dependencies:
htmlparser2: 8.0.2
'@types/sax@1.2.7':
dependencies:
'@types/node': 22.7.5
@ -5023,6 +5136,8 @@ snapshots:
deep-extend@0.6.0: {}
deepmerge@4.3.1: {}
defu@6.1.4: {}
delayed-stream@1.0.0: {}
@ -5178,6 +5293,8 @@ snapshots:
escape-html@1.0.3: {}
escape-string-regexp@4.0.0: {}
escape-string-regexp@5.0.0: {}
esprima@4.0.1: {}
@ -5509,6 +5626,13 @@ snapshots:
html-void-elements@3.0.0: {}
htmlparser2@8.0.2:
dependencies:
domelementtype: 2.3.0
domhandler: 5.0.3
domutils: 3.2.2
entities: 4.5.0
htmlparser2@9.1.0:
dependencies:
domelementtype: 2.3.0
@ -5571,6 +5695,8 @@ snapshots:
is-plain-obj@4.1.0: {}
is-plain-object@5.0.0: {}
is-wsl@3.1.0:
dependencies:
is-inside-container: 1.0.0
@ -5650,6 +5776,10 @@ snapshots:
base64-js: 0.0.8
unicode-trie: 2.0.0
linkify-it@5.0.0:
dependencies:
uc.micro: 2.1.0
load-yaml-file@0.2.0:
dependencies:
graceful-fs: 4.2.11
@ -5694,6 +5824,15 @@ snapshots:
markdown-extensions@2.0.0: {}
markdown-it@14.1.0:
dependencies:
argparse: 2.0.1
entities: 4.5.0
linkify-it: 5.0.0
mdurl: 2.0.0
punycode.js: 2.3.1
uc.micro: 2.1.0
markdown-table@3.0.4: {}
mdast-util-definitions@6.0.0:
@ -5899,6 +6038,8 @@ snapshots:
mdn-data@2.0.30: {}
mdurl@2.0.0: {}
merge2@1.4.1: {}
micromark-core-commonmark@2.0.1:
@ -6434,6 +6575,8 @@ snapshots:
unist-util-visit-children: 3.0.0
vfile: 6.0.3
parse-srcset@1.0.2: {}
parse5-htmlparser2-tree-adapter@7.1.0:
dependencies:
domhandler: 5.0.3
@ -6701,6 +6844,8 @@ snapshots:
end-of-stream: 1.4.4
once: 1.4.0
punycode.js@2.3.1: {}
queue-microtask@1.2.3: {}
queue-tick@1.0.1: {}
@ -6958,6 +7103,15 @@ snapshots:
safer-buffer@2.1.2: {}
sanitize-html@2.14.0:
dependencies:
deepmerge: 4.3.1
escape-string-regexp: 4.0.0
htmlparser2: 8.0.2
is-plain-object: 5.0.0
parse-srcset: 1.0.2
postcss: 8.4.49
sass-formatter@0.7.9:
dependencies:
suf-log: 2.5.3
@ -7228,6 +7382,8 @@ snapshots:
typescript@5.7.3: {}
uc.micro@2.1.0: {}
ufo@1.5.4: {}
ultrahtml@1.2.0: {}

View File

@ -6,7 +6,7 @@ import "@/styles/global.css";
type Props = SiteMeta;
const { articleDate, description, ogImage, title } = Astro.props;
const { articleDate, description, ogImage, title, tags } = Astro.props;
const titleSeparator = "•";
const siteTitle = `${title} ${titleSeparator} ${siteConfig.title}`;
@ -39,6 +39,7 @@ const socialImageURL = new URL(ogImage ? ogImage : "/social-card.png", Astro.url
<meta content={siteTitle} name="title" />
<meta content={description} name="description" />
<meta content={siteConfig.author} name="author" />
{tags && <meta content={tags} name="tags" />}
{/* Open Graph / Facebook */}
<meta content={articleDate ? "article" : "website"} property="og:type" />

View File

@ -13,10 +13,20 @@ const socialLinks: {
name: string;
}[] = [
{
friendlyName: "Github",
link: "https://github.com/chrismwilliams/astro-cactus",
friendlyName: "Email",
link: "mailto:work@kazoottt.top",
name: "mdi:email",
},
{
friendlyName: "GitHub",
link: "https://github.com/kazoottt",
name: "mdi:github",
},
{
friendlyName: "Twitter",
link: "https://x.com/kazoottt",
name: "mdi:twitter",
},
];
---
@ -32,7 +42,7 @@ const socialLinks: {
rel={`noreferrer ${isWebmention ? "me authn" : ""}`}
target="_blank"
>
<Icon aria-hidden="true" class="h-8 w-8" focusable="false" name={name} />
<Icon aria-hidden="true" class="h-6 w-6" focusable="false" name={name} />
<span class="sr-only">{friendlyName}</span>
</a>
</li>

View File

@ -9,7 +9,7 @@ const year = new Date().getFullYear();
>
<div class="me-0 sm:me-4">
&copy; {siteConfig.author}
{year}.<span class="inline-block">&nbsp;🚀&nbsp;Astro Cactus</span>
{year}.<span class="inline-block">&nbsp;🚀&nbsp;{siteConfig.title}</span>
</div>
<nav
aria-labelledby="footer_links"

View File

@ -1,7 +1,7 @@
---
import Search from "@/components/Search.astro";
import ThemeToggle from "@/components/ThemeToggle.astro";
import { menuLinks } from "@/site.config";
import { menuLinks, siteConfig } from "@/site.config";
---
<header class="group relative mb-28 flex items-center sm:ps-18" id="main-header">
@ -31,7 +31,7 @@ import { menuLinks } from "@/site.config";
fill="#53C68C"></path>
<path d="M45.334 240 0 213.334v120L45.334 360V240Z" fill="#B04304"></path>
</svg>
<span class="text-xl font-bold sm:text-2xl">Astro Cactus</span>
<span class="text-xl font-bold sm:text-2xl">{siteConfig.title}</span>
</a>
<nav
aria-label="Main menu"

View File

@ -28,6 +28,7 @@ const note = defineCollection({
schema: baseSchema.extend({
description: z.string().optional().nullable(),
date: z.union([z.string(), z.date()]).transform((val) => new Date(val)),
tags: z.array(z.string()).default([]).transform(removeDupsAndLowerCase),
}),
});

View File

@ -1,3 +1,4 @@
import { collectionDateSort } from "@/utils/date";
import { type CollectionEntry, getCollection } from "astro:content";
/** filter out draft posts based on the environment */
@ -7,6 +8,14 @@ export async function getAllPosts(): Promise<CollectionEntry<"post">[]> {
});
}
export async function getAllCollectionPosts() {
const posts = await getAllPosts();
const notes = await getCollection("note");
const allPosts = [...posts, ...notes];
const allPostsSortedByDate = allPosts.sort(collectionDateSort);
return allPostsSortedByDate;
}
/** groups posts by year (based on option siteConfig.sortPostsByUpdatedDate), using the year as the key
* Note: This function doesn't filter draft posts, pass it the result of getAllPosts above to do so.
*/

View File

@ -12,13 +12,19 @@ interface Props {
}
const {
meta: { articleDate, description = siteConfig.description, ogImage, title },
meta: { articleDate, description = siteConfig.description, ogImage, title, tags },
} = Astro.props;
---
<html class="scroll-smooth" lang={siteConfig.lang}>
<head>
<BaseHead articleDate={articleDate} description={description} ogImage={ogImage} title={title} />
<BaseHead
articleDate={articleDate}
description={description}
ogImage={ogImage}
title={title}
tags={tags}
/>
</head>
<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"

View File

@ -18,6 +18,7 @@ const {
description,
date_modified: updatedDate,
date: publishDate,
tags,
} = post.data;
const socialImage = ogImage ?? `/og-image/${post.id}.png`;
const articleDate = updatedDate?.toISOString() ?? publishDate.toISOString();
@ -28,9 +29,10 @@ const readingTime: string = remarkPluginFrontmatter.readingTime;
<BaseLayout
meta={{
articleDate,
description,
description: description ?? "",
ogImage: socialImage,
title,
tags: tags.join(", "),
}}
>
<article class="grow break-words" data-pagefind-body>

View File

@ -9,28 +9,5 @@ const meta = {
<PageLayout meta={meta}>
<h1 class="title mb-6">About</h1>
<div class="prose prose-sm prose-cactus max-w-none">
<p>
Hi, Im a starter Astro. Im particularly great for getting you started with your own blogging
website.
</p>
<p>Here are my some of my awesome built in features:</p>
<ul class="list-inside list-disc" role="list">
<li>I'm ultra fast as I'm a static site</li>
<li>I'm fully responsive</li>
<li>I come with a light and dark mode</li>
<li>I'm easy to customise and add additional content</li>
<li>I have Tailwind CSS styling</li>
<li>Shiki code syntax highlighting</li>
<li>Satori for auto generating OG images for blog posts</li>
</ul>
<p>
Clone or fork my <a
class="cactus-link inline-block"
href="https://github.com/chrismwilliams/astro-cactus"
rel="noreferrer"
target="_blank">repo</a
> if you like me!
</p>
</div>
<div class="prose prose-sm prose-cactus max-w-none">TODO ...</div>
</PageLayout>

78
src/pages/friends.astro Normal file
View File

@ -0,0 +1,78 @@
---
import BaseLayout from "@/layouts/Base.astro";
const friends: { name: string; url: string; description?: string }[] = [
{
name: "Yuang's Blog",
url: "https://yuuuuang.com/",
},
{
name: "huaiying",
url: "https://blog.csdn.net/huaiyingdetective",
},
{
name: "Sorry404 Wang",
url: "http://40404.site/",
},
{
name: "lijinghua",
url: "www.lijinghua.club",
},
{
name: "思无道",
url: "https://siwudao.github.io/",
},
{
name: "Kai",
url: "https://kaiyi.cool/",
},
{
name: "buyfakett",
url: "https://www.tteam.icu/",
},
{
name: "poivre",
url: "https://blog.poivrehxx.site/",
},
{
name: `Roi's Blog`,
url: "https://roi.moe/",
},
];
---
<BaseLayout
meta={{
title: `Friends`,
description: "my friends ",
}}
>
<div class="container mx-auto px-4 py-8">
<h1 class="title mb-6">Friends</h1>
<div class="grid grid-cols-1 gap-6 md:grid-cols-2">
{
friends.map((friend) => (
<a
href={friend.url.startsWith("http") ? friend.url : `https://${friend.url}`}
target="_blank"
rel="noopener noreferrer"
class="block rounded-lg bg-white p-6 shadow-md transition-shadow duration-300 hover:shadow-lg dark:bg-gray-800"
>
<h2 class="text-xl font-semibold">{friend.name}</h2>
{friend.description && (
<p class="mt-2 truncate text-sm text-gray-600 dark:text-gray-400">
{friend.description}
</p>
)}
</a>
))
}
</div>
</div>
</BaseLayout>
<style>
.container {
max-width: 1200px;
}
</style>

View File

@ -23,11 +23,7 @@ const latestNotes = allNotes.sort(collectionDateSort).slice(0, MAX_NOTES);
<PageLayout meta={{ title: "Home" }}>
<section>
<h1 class="title mb-6">Hello World!</h1>
<p class="mb-4">
Hi, Im a theme for Astro, a simple starter that you can use to create your website or blog.
If you want to know more about how you can customise me, add more posts, and make it your own,
click on the GitHub icon link below and it will take you to my repo.
</p>
<p class="mb-4">TODO ...</p>
<SocialList />
</section>
<section class="mt-16">

View File

@ -22,6 +22,7 @@ const meta = {
description:
note.data.description || `Read about my note posted on: ${note.data.date.toLocaleDateString()}`,
title: note.data.title,
tags: note.data.tags.join(", "),
};
---

View File

@ -1,19 +1,37 @@
import { getAllPosts } from "@/data/post";
import { siteConfig } from "@/site.config";
import { collectionDateSort } from "@/utils/date";
import rss from "@astrojs/rss";
import MarkdownIt from "markdown-it";
import sanitizeHtml from "sanitize-html";
export const GET = async () => {
const posts = await getAllPosts();
const sortedPosts = posts.sort(collectionDateSort);
const parser = new MarkdownIt();
return rss({
customData: `<follow_challenge>
<feedId>75113012474671104</feedId>
<userId>62156866798228480</userId>
</follow_challenge>`,
title: siteConfig.title,
description: siteConfig.description,
site: import.meta.env.SITE,
items: posts.map((post) => ({
items: sortedPosts.map((post) => ({
title: post.data.title,
description: post.data.description ?? "",
pubDate: post.data.date,
link: `posts/${post.id}/`,
content: post.body
? sanitizeHtml(parser.render(post.body), {
allowedTags: sanitizeHtml.defaults.allowedTags.concat(["img"]),
textFilter: function (text: string) {
return text.replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x9F\uFFF0-\uFFFF]/g, "");
},
})
: "",
author: siteConfig.author,
})),
});
};

View File

@ -3,10 +3,10 @@ import type { AstroExpressiveCodeOptions } from "astro-expressive-code";
export const siteConfig: SiteConfig = {
// Used as both a meta property (src/components/BaseHead.astro L:31 + L:49) & the generated satori png (src/pages/og-image/[slug].png.ts)
author: "Chris Williams",
author: "KazooTTT",
// Date.prototype.toLocaleDateString() parameters, found in src/utils/date.ts.
date: {
locale: "en-GB",
locale: "zh-CN",
options: {
day: "numeric",
month: "short",
@ -14,15 +14,15 @@ export const siteConfig: SiteConfig = {
},
},
// Used as the default description meta property and webmanifest description
description: "An opinionated starter theme for Astro",
description: "记录技术分享、学习笔记、生活日常、碎碎念的地方。",
// HTML lang property, found in src/layouts/Base.astro L:18 & astro.config.ts L:48
lang: "en-GB",
lang: "zh-CN",
// Meta property, found in src/components/BaseHead.astro L:42
ogLocale: "en_GB",
ogLocale: "zh_CN",
// Used to construct the meta title property found in src/components/BaseHead.astro L:11, and webmanifest name found in astro.config.ts L:42
title: "Astro Theme Cactus",
title: "声控烤箱的博客",
// ! Please remember to replace the following site property with your own domain, used in astro.config.ts
url: "https://astro-cactus.chriswilliams.dev/",
url: "https://blog.kazoottt.top/",
};
// Used to generate links in both the Header & Footer.
@ -43,6 +43,10 @@ export const menuLinks: { path: string; title: string }[] = [
path: "/notes/",
title: "Notes",
},
{
path: "/friends/",
title: "Friends",
},
];
// https://expressive-code.com/reference/configuration/

View File

@ -22,6 +22,7 @@ export interface SiteMeta {
description?: string;
ogImage?: string | undefined;
title: string;
tags?: string | undefined;
}
/** Webmentions */