Compare commits

..

3 commits

Author SHA1 Message Date
grassblock
1cf002b8b8 feat: add full text RSS & mdx support (for real) 2025-05-02 21:20:53 +08:00
grassblock
fcde96f0ab chore: remove lab 2025-05-02 09:37:22 +08:00
grassblock
53d5c01777 fix: footer svg not appear on multi-level pages 2025-05-02 09:37:10 +08:00
6 changed files with 605 additions and 465 deletions

View file

@ -11,9 +11,14 @@
"astro": "astro"
},
"dependencies": {
"astro": "^5.2.5",
"@astrojs/mdx": "^4.2.6",
"@astrojs/rss": "^4.0.1",
"fuse.js": "^7.0.0"
"astro": "^5.2.5",
"fuse.js": "^7.0.0",
"ultrahtml": "^1.6.0"
},
"packageManager": "pnpm@10.7.1+sha512.2d92c86b7928dc8284f53494fb4201f983da65f0fb4f0d40baafa5cf628fa31dae3e5968f12466f17df7e97310e30f343a648baea1b9b350685dafafffdf5808"
"packageManager": "pnpm@10.7.1+sha512.2d92c86b7928dc8284f53494fb4201f983da65f0fb4f0d40baafa5cf628fa31dae3e5968f12466f17df7e97310e30f343a648baea1b9b350685dafafffdf5808",
"devDependencies": {
"@types/node": "^22.15.3"
}
}

543
pnpm-lock.yaml generated
View file

@ -8,15 +8,25 @@ importers:
.:
dependencies:
'@astrojs/mdx':
specifier: ^4.2.6
version: 4.2.6(astro@5.7.10(@types/node@22.15.3)(rollup@4.40.1)(typescript@5.8.3))
'@astrojs/rss':
specifier: ^4.0.1
version: 4.0.11
astro:
specifier: ^5.2.5
version: 5.7.10(rollup@4.40.1)(typescript@5.8.3)
version: 5.7.10(@types/node@22.15.3)(rollup@4.40.1)(typescript@5.8.3)
fuse.js:
specifier: ^7.0.0
version: 7.1.0
ultrahtml:
specifier: ^1.6.0
version: 1.6.0
devDependencies:
'@types/node':
specifier: ^22.15.3
version: 22.15.3
packages:
@ -29,6 +39,12 @@ packages:
'@astrojs/markdown-remark@6.3.1':
resolution: {integrity: sha512-c5F5gGrkczUaTVgmMW9g1YMJGzOtRvjjhw6IfGuxarM6ct09MpwysP10US729dy07gg8y+ofVifezvP3BNsWZg==}
'@astrojs/mdx@4.2.6':
resolution: {integrity: sha512-0i/GmOm6d0qq1/SCfcUgY/IjDc/bS0i42u7h85TkPFBmlFOcBZfkYhR5iyz6hZLwidvJOEq5yGfzt9B1Azku4w==}
engines: {node: ^18.17.1 || ^20.3.0 || >=22.0.0}
peerDependencies:
astro: ^5.0.0
'@astrojs/prism@3.2.0':
resolution: {integrity: sha512-GilTHKGCW6HMq7y3BUv9Ac7GMe/MO9gi9GW62GzKtth0SwukCu/qp2wLiGpEujhY+VVhaG9v7kv/5vFzvf4NYw==}
engines: {node: ^18.17.1 || ^20.3.0 || >=22.0.0}
@ -321,6 +337,9 @@ packages:
'@jridgewell/sourcemap-codec@1.5.0':
resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==}
'@mdx-js/mdx@3.1.0':
resolution: {integrity: sha512-/QxEhPAvGwbQmy1Px8F899L5Uc2KZ6JtXwlCgJmjSTBedwOZkByYcBG4GceIGPXRDsmfxhHazuS+hlOShRLeDw==}
'@oslojs/encoding@1.1.0':
resolution: {integrity: sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==}
@ -460,6 +479,9 @@ packages:
'@types/debug@4.1.12':
resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==}
'@types/estree-jsx@1.0.5':
resolution: {integrity: sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==}
'@types/estree@1.0.7':
resolution: {integrity: sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==}
@ -469,18 +491,32 @@ packages:
'@types/mdast@4.0.4':
resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==}
'@types/mdx@2.0.13':
resolution: {integrity: sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==}
'@types/ms@2.1.0':
resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==}
'@types/nlcst@2.0.3':
resolution: {integrity: sha512-vSYNSDe6Ix3q+6Z7ri9lyWqgGhJTmzRjZRqyq15N0Z/1/UnVsno9G/N40NBijoYx2seFDIl0+B2mgAb9mezUCA==}
'@types/node@22.15.3':
resolution: {integrity: sha512-lX7HFZeHf4QG/J7tBZqrCAXwz9J5RD56Y6MpP0eJkka8p+K0RY/yBTW7CYFJ4VGCclxqOLKmiGP5juQc6MKgcw==}
'@types/unist@2.0.11':
resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==}
'@types/unist@3.0.3':
resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==}
'@ungap/structured-clone@1.3.0':
resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==}
acorn-jsx@5.3.2:
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
peerDependencies:
acorn: ^6.0.0 || ^7.0.0 || ^8.0.0
acorn@8.14.1:
resolution: {integrity: sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==}
engines: {node: '>=0.4.0'}
@ -515,6 +551,10 @@ packages:
array-iterate@2.0.1:
resolution: {integrity: sha512-I1jXZMjAgCMmxT4qxXfPXa6SthSoE8h6gkSI9BGGNv8mP8G/v0blc+qFnZu6K42vTOiuME596QaLO0TP3Lk0xg==}
astring@1.9.0:
resolution: {integrity: sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==}
hasBin: true
astro@5.7.10:
resolution: {integrity: sha512-9TQcFZqP2w6//JXXUHfw8/5PX7KUx9EkG5O3m+hISuyeUztvjY1q5+p7+C5HiXyg24Zs3KkpieoL5BGRXGCAGA==}
engines: {node: ^18.17.1 || ^20.3.0 || >=22.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0'}
@ -563,6 +603,9 @@ packages:
character-entities@2.0.2:
resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==}
character-reference-invalid@2.0.1:
resolution: {integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==}
chokidar@4.0.3:
resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==}
engines: {node: '>= 14.16.0'}
@ -583,6 +626,9 @@ packages:
resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==}
engines: {node: '>=6'}
collapse-white-space@2.1.0:
resolution: {integrity: sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw==}
color-convert@2.0.1:
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
engines: {node: '>=7.0.0'}
@ -688,6 +734,12 @@ packages:
es-module-lexer@1.7.0:
resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==}
esast-util-from-estree@2.0.0:
resolution: {integrity: sha512-4CyanoAudUSBAn5K13H4JhsMH6L9ZP7XbLVe/dKybkxMO7eDyLsT8UHl9TRNrU2Gr9nz+FovfSIjuXWJ81uVwQ==}
esast-util-from-js@2.0.1:
resolution: {integrity: sha512-8Ja+rNJ0Lt56Pcf3TAmpBZjmx8ZcK5Ts4cAzIOjsjevg9oSXJnl6SUQ2EevU8tv3h6ZLWmoKL5H4fgWvdvfETw==}
esbuild@0.25.3:
resolution: {integrity: sha512-qKA6Pvai73+M2FtftpNKRxJ78GIjmFXFxd/1DVBqGo/qNhLSfv+G12n9pNoWdytJC8U00TrViOwpjT0zgqQS8Q==}
engines: {node: '>=18'}
@ -697,6 +749,24 @@ packages:
resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==}
engines: {node: '>=12'}
estree-util-attach-comments@3.0.0:
resolution: {integrity: sha512-cKUwm/HUcTDsYh/9FgnuFqpfquUbwIqwKM26BVCGDPVgvaCl/nDCCjUfiLlx6lsEZ3Z4RFxNbOQ60pkaEwFxGw==}
estree-util-build-jsx@3.0.1:
resolution: {integrity: sha512-8U5eiL6BTrPxp/CHbs2yMgP8ftMhR5ww1eIKoWRMlqvltHF8fZn5LRDvTKuxD3DUn+shRbLGqXemcP51oFCsGQ==}
estree-util-is-identifier-name@3.0.0:
resolution: {integrity: sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==}
estree-util-scope@1.0.0:
resolution: {integrity: sha512-2CAASclonf+JFWBNJPndcOpA8EMJwa0Q8LUFJEKqXLW6+qBvbFZuF5gItbQOs/umBUkjviCSDCbBwU2cXbmrhQ==}
estree-util-to-js@2.0.0:
resolution: {integrity: sha512-WDF+xj5rRWmD5tj6bIqRi6CkLIXbbNQUcxQHzGysQzvHmdYG2G7p/Tf0J0gpxGgkeMZNTIjT/AoSvC9Xehcgdg==}
estree-util-visit@2.0.0:
resolution: {integrity: sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww==}
estree-walker@2.0.2:
resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
@ -765,9 +835,15 @@ packages:
hast-util-raw@9.1.0:
resolution: {integrity: sha512-Y8/SBAHkZGoNkpzqqfCldijcuUKh7/su31kEBp67cFY09Wy0mTRgtsLYsiIxMJxlu0f6AA5SUTbDR8K0rxnbUw==}
hast-util-to-estree@3.1.3:
resolution: {integrity: sha512-48+B/rJWAp0jamNbAAf9M7Uf//UVqAoMmgXhBdxTDJLGKY+LRnZ99qcG+Qjl5HfMpYNzS5v4EAwVEF34LeAj7w==}
hast-util-to-html@9.0.5:
resolution: {integrity: sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==}
hast-util-to-jsx-runtime@2.3.6:
resolution: {integrity: sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==}
hast-util-to-parse5@8.0.0:
resolution: {integrity: sha512-3KKrV5ZVI8if87DVSi1vDeByYrkGzg4mEfeu4alwgmmIeARiBLKCZS2uw5Gb6nU9x9Yufyj3iudm6i7nl52PFw==}
@ -792,12 +868,24 @@ packages:
import-meta-resolve@4.1.0:
resolution: {integrity: sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==}
inline-style-parser@0.2.4:
resolution: {integrity: sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==}
iron-webcrypto@1.2.1:
resolution: {integrity: sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==}
is-alphabetical@2.0.1:
resolution: {integrity: sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==}
is-alphanumerical@2.0.1:
resolution: {integrity: sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==}
is-arrayish@0.3.2:
resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==}
is-decimal@2.0.1:
resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==}
is-docker@3.0.0:
resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
@ -807,6 +895,9 @@ packages:
resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
engines: {node: '>=8'}
is-hexadecimal@2.0.1:
resolution: {integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==}
is-inside-container@1.0.0:
resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==}
engines: {node: '>=14.16'}
@ -844,6 +935,10 @@ packages:
magicast@0.3.5:
resolution: {integrity: sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==}
markdown-extensions@2.0.0:
resolution: {integrity: sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q==}
engines: {node: '>=16'}
markdown-table@3.0.4:
resolution: {integrity: sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==}
@ -874,6 +969,18 @@ packages:
mdast-util-gfm@3.1.0:
resolution: {integrity: sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==}
mdast-util-mdx-expression@2.0.1:
resolution: {integrity: sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==}
mdast-util-mdx-jsx@3.2.0:
resolution: {integrity: sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==}
mdast-util-mdx@3.0.0:
resolution: {integrity: sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w==}
mdast-util-mdxjs-esm@2.0.1:
resolution: {integrity: sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==}
mdast-util-phrasing@4.1.0:
resolution: {integrity: sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==}
@ -913,12 +1020,30 @@ packages:
micromark-extension-gfm@3.0.0:
resolution: {integrity: sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==}
micromark-extension-mdx-expression@3.0.1:
resolution: {integrity: sha512-dD/ADLJ1AeMvSAKBwO22zG22N4ybhe7kFIZ3LsDI0GlsNr2A3KYxb0LdC1u5rj4Nw+CHKY0RVdnHX8vj8ejm4Q==}
micromark-extension-mdx-jsx@3.0.2:
resolution: {integrity: sha512-e5+q1DjMh62LZAJOnDraSSbDMvGJ8x3cbjygy2qFEi7HCeUT4BDKCvMozPozcD6WmOt6sVvYDNBKhFSz3kjOVQ==}
micromark-extension-mdx-md@2.0.0:
resolution: {integrity: sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ==}
micromark-extension-mdxjs-esm@3.0.0:
resolution: {integrity: sha512-DJFl4ZqkErRpq/dAPyeWp15tGrcrrJho1hKK5uBS70BCtfrIFg81sqcTVu3Ta+KD1Tk5vAtBNElWxtAa+m8K9A==}
micromark-extension-mdxjs@3.0.0:
resolution: {integrity: sha512-A873fJfhnJ2siZyUrJ31l34Uqwy4xIFmvPY1oj+Ean5PHcPBYzEsvqvWGaWcfEIr11O5Dlw3p2y0tZWpKHDejQ==}
micromark-factory-destination@2.0.1:
resolution: {integrity: sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==}
micromark-factory-label@2.0.1:
resolution: {integrity: sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==}
micromark-factory-mdx-expression@2.0.3:
resolution: {integrity: sha512-kQnEtA3vzucU2BkrIa8/VaSAsP+EJ3CKOvhMuJgOEGg9KDC6OAY6nSnNDVRiVNRqj7Y4SlSzcStaH/5jge8JdQ==}
micromark-factory-space@2.0.1:
resolution: {integrity: sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==}
@ -949,6 +1074,9 @@ packages:
micromark-util-encode@2.0.1:
resolution: {integrity: sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==}
micromark-util-events-to-acorn@2.0.3:
resolution: {integrity: sha512-jmsiEIiZ1n7X1Rr5k8wVExBQCg5jy4UXVADItHmNk1zkwEVhBuIUKRu3fqv+hs4nxLISi2DQGlqIOGiFxgbfHg==}
micromark-util-html-tag-name@2.0.1:
resolution: {integrity: sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==}
@ -1041,6 +1169,9 @@ packages:
pako@0.2.9:
resolution: {integrity: sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==}
parse-entities@4.0.2:
resolution: {integrity: sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==}
parse-latin@7.0.0:
resolution: {integrity: sha512-mhHgobPPua5kZ98EF4HWiH167JWBfl4pvAIXXdbaVohtK7a6YBOy56kvhCqduqyo/f3yrHFWmqmiMg/BkBkYYQ==}
@ -1083,6 +1214,18 @@ packages:
resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==}
engines: {node: '>= 14.18.0'}
recma-build-jsx@1.0.0:
resolution: {integrity: sha512-8GtdyqaBcDfva+GUKDr3nev3VpKAhup1+RvkMvUxURHpW7QyIvk9F5wz7Vzo06CEMSilw6uArgRqhpiUcWp8ew==}
recma-jsx@1.0.0:
resolution: {integrity: sha512-5vwkv65qWwYxg+Atz95acp8DMu1JDSqdGkA2Of1j6rCreyFUE/gp15fC8MnGEuG1W68UKjM6x6+YTWIh7hZM/Q==}
recma-parse@1.0.0:
resolution: {integrity: sha512-OYLsIGBB5Y5wjnSnQW6t3Xg7q3fQ7FWbw/vcXtORTnyaSFscOtABg+7Pnz6YZ6c27fG1/aN8CjfwoUEUIdwqWQ==}
recma-stringify@1.0.0:
resolution: {integrity: sha512-cjwII1MdIIVloKvC9ErQ+OgAtwHBmcZ0Bg4ciz78FtbT8In39aAYbaA7zvxQ61xVMSPE8WxhLwLbhif4Js2C+g==}
regex-recursion@6.0.2:
resolution: {integrity: sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==}
@ -1098,6 +1241,9 @@ packages:
rehype-raw@7.0.0:
resolution: {integrity: sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==}
rehype-recma@1.0.0:
resolution: {integrity: sha512-lqA4rGUf1JmacCNWWZx0Wv1dHqMwxzsDWYMTowuplHF3xH0N/MmrZ/G3BDZnzAkRmxDadujCjaKM2hqYdCBOGw==}
rehype-stringify@10.0.1:
resolution: {integrity: sha512-k9ecfXHmIPuFVI61B9DeLPN0qFHfawM6RsuX48hoqlaKSF61RskNjSm1lI8PhBEM0MRdLxVVm4WmTqJQccH9mA==}
@ -1107,6 +1253,9 @@ packages:
remark-gfm@4.0.1:
resolution: {integrity: sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==}
remark-mdx@3.1.0:
resolution: {integrity: sha512-Ngl/H3YXyBV9RcRNdlYsZujAmhsxwzxpDzpDEhFBVAGthS4GDgnctpDjgFl/ULx5UEDzqtW1cyBSNKqYYrqLBA==}
remark-parse@11.0.0:
resolution: {integrity: sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==}
@ -1166,6 +1315,10 @@ packages:
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
engines: {node: '>=0.10.0'}
source-map@0.7.4:
resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==}
engines: {node: '>= 8'}
space-separated-tokens@2.0.2:
resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==}
@ -1191,6 +1344,12 @@ packages:
strnum@1.1.2:
resolution: {integrity: sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==}
style-to-js@1.1.16:
resolution: {integrity: sha512-/Q6ld50hKYPH3d/r6nr117TZkHR0w0kGGIVfpG9N6D8NymRPM9RqCUv4pRpJ62E5DqOYx2AFpbZMyCPnjQCnOw==}
style-to-object@1.0.8:
resolution: {integrity: sha512-xT47I/Eo0rwJmaXC4oilDGDWLohVhR6o/xAQcPQN8q6QBuZVL8qMYL85kLmST5cPjAorwvqIA4qXTRQoYHaL6g==}
tiny-inflate@1.0.3:
resolution: {integrity: sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==}
@ -1241,6 +1400,9 @@ packages:
uncrypto@0.1.3:
resolution: {integrity: sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==}
undici-types@6.21.0:
resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}
unicode-properties@1.4.1:
resolution: {integrity: sha512-CLjCCLQ6UuMxWnbIylkisbRj31qxHPAurvena/0iwSVbQ2G1VY5/HjV0IRabOEbDHlzZlRdCrD4NhB0JtU40Pg==}
@ -1262,6 +1424,9 @@ packages:
unist-util-modify-children@4.0.0:
resolution: {integrity: sha512-+tdN5fGNddvsQdIzUF3Xx82CU9sMM+fA0dLgR9vOmT0oPT2jH+P1nd5lSqfCfXAw+93NhcXNY2qqvTUtE4cQkw==}
unist-util-position-from-estree@2.0.0:
resolution: {integrity: sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ==}
unist-util-position@5.0.0:
resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==}
@ -1485,6 +1650,25 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@astrojs/mdx@4.2.6(astro@5.7.10(@types/node@22.15.3)(rollup@4.40.1)(typescript@5.8.3))':
dependencies:
'@astrojs/markdown-remark': 6.3.1
'@mdx-js/mdx': 3.1.0(acorn@8.14.1)
acorn: 8.14.1
astro: 5.7.10(@types/node@22.15.3)(rollup@4.40.1)(typescript@5.8.3)
es-module-lexer: 1.7.0
estree-util-visit: 2.0.0
hast-util-to-html: 9.0.5
kleur: 4.1.5
rehype-raw: 7.0.0
remark-gfm: 4.0.1
remark-smartypants: 3.0.2
source-map: 0.7.4
unist-util-visit: 5.0.0
vfile: 6.0.3
transitivePeerDependencies:
- supports-color
'@astrojs/prism@3.2.0':
dependencies:
prismjs: 1.30.0
@ -1684,6 +1868,36 @@ snapshots:
'@jridgewell/sourcemap-codec@1.5.0': {}
'@mdx-js/mdx@3.1.0(acorn@8.14.1)':
dependencies:
'@types/estree': 1.0.7
'@types/estree-jsx': 1.0.5
'@types/hast': 3.0.4
'@types/mdx': 2.0.13
collapse-white-space: 2.1.0
devlop: 1.1.0
estree-util-is-identifier-name: 3.0.0
estree-util-scope: 1.0.0
estree-walker: 3.0.3
hast-util-to-jsx-runtime: 2.3.6
markdown-extensions: 2.0.0
recma-build-jsx: 1.0.0
recma-jsx: 1.0.0(acorn@8.14.1)
recma-stringify: 1.0.0
rehype-recma: 1.0.0
remark-mdx: 3.1.0
remark-parse: 11.0.0
remark-rehype: 11.1.2
source-map: 0.7.4
unified: 11.0.5
unist-util-position-from-estree: 2.0.0
unist-util-stringify-position: 4.0.0
unist-util-visit: 5.0.0
vfile: 6.0.3
transitivePeerDependencies:
- acorn
- supports-color
'@oslojs/encoding@1.1.0': {}
'@rollup/pluginutils@5.1.4(rollup@4.40.1)':
@ -1795,6 +2009,10 @@ snapshots:
dependencies:
'@types/ms': 2.1.0
'@types/estree-jsx@1.0.5':
dependencies:
'@types/estree': 1.0.7
'@types/estree@1.0.7': {}
'@types/hast@3.0.4':
@ -1805,16 +2023,28 @@ snapshots:
dependencies:
'@types/unist': 3.0.3
'@types/mdx@2.0.13': {}
'@types/ms@2.1.0': {}
'@types/nlcst@2.0.3':
dependencies:
'@types/unist': 3.0.3
'@types/node@22.15.3':
dependencies:
undici-types: 6.21.0
'@types/unist@2.0.11': {}
'@types/unist@3.0.3': {}
'@ungap/structured-clone@1.3.0': {}
acorn-jsx@5.3.2(acorn@8.14.1):
dependencies:
acorn: 8.14.1
acorn@8.14.1: {}
ansi-align@3.0.1:
@ -1838,7 +2068,9 @@ snapshots:
array-iterate@2.0.1: {}
astro@5.7.10(rollup@4.40.1)(typescript@5.8.3):
astring@1.9.0: {}
astro@5.7.10(@types/node@22.15.3)(rollup@4.40.1)(typescript@5.8.3):
dependencies:
'@astrojs/compiler': 2.11.0
'@astrojs/internal-helpers': 0.6.1
@ -1891,8 +2123,8 @@ snapshots:
unist-util-visit: 5.0.0
unstorage: 1.16.0
vfile: 6.0.3
vite: 6.3.4
vitefu: 1.0.6(vite@6.3.4)
vite: 6.3.4(@types/node@22.15.3)
vitefu: 1.0.6(vite@6.3.4(@types/node@22.15.3))
xxhash-wasm: 1.1.0
yargs-parser: 21.1.1
yocto-spinner: 0.2.2
@ -1973,6 +2205,8 @@ snapshots:
character-entities@2.0.2: {}
character-reference-invalid@2.0.1: {}
chokidar@4.0.3:
dependencies:
readdirp: 4.1.2
@ -1985,6 +2219,8 @@ snapshots:
clsx@2.1.1: {}
collapse-white-space@2.1.0: {}
color-convert@2.0.1:
dependencies:
color-name: 1.1.4
@ -2073,6 +2309,20 @@ snapshots:
es-module-lexer@1.7.0: {}
esast-util-from-estree@2.0.0:
dependencies:
'@types/estree-jsx': 1.0.5
devlop: 1.1.0
estree-util-visit: 2.0.0
unist-util-position-from-estree: 2.0.0
esast-util-from-js@2.0.1:
dependencies:
'@types/estree-jsx': 1.0.5
acorn: 8.14.1
esast-util-from-estree: 2.0.0
vfile-message: 4.0.2
esbuild@0.25.3:
optionalDependencies:
'@esbuild/aix-ppc64': 0.25.3
@ -2103,6 +2353,35 @@ snapshots:
escape-string-regexp@5.0.0: {}
estree-util-attach-comments@3.0.0:
dependencies:
'@types/estree': 1.0.7
estree-util-build-jsx@3.0.1:
dependencies:
'@types/estree-jsx': 1.0.5
devlop: 1.1.0
estree-util-is-identifier-name: 3.0.0
estree-walker: 3.0.3
estree-util-is-identifier-name@3.0.0: {}
estree-util-scope@1.0.0:
dependencies:
'@types/estree': 1.0.7
devlop: 1.1.0
estree-util-to-js@2.0.0:
dependencies:
'@types/estree-jsx': 1.0.5
astring: 1.9.0
source-map: 0.7.4
estree-util-visit@2.0.0:
dependencies:
'@types/estree-jsx': 1.0.5
'@types/unist': 3.0.3
estree-walker@2.0.2: {}
estree-walker@3.0.3:
@ -2202,6 +2481,27 @@ snapshots:
web-namespaces: 2.0.1
zwitch: 2.0.4
hast-util-to-estree@3.1.3:
dependencies:
'@types/estree': 1.0.7
'@types/estree-jsx': 1.0.5
'@types/hast': 3.0.4
comma-separated-tokens: 2.0.3
devlop: 1.1.0
estree-util-attach-comments: 3.0.0
estree-util-is-identifier-name: 3.0.0
hast-util-whitespace: 3.0.0
mdast-util-mdx-expression: 2.0.1
mdast-util-mdx-jsx: 3.2.0
mdast-util-mdxjs-esm: 2.0.1
property-information: 7.0.0
space-separated-tokens: 2.0.2
style-to-js: 1.1.16
unist-util-position: 5.0.0
zwitch: 2.0.4
transitivePeerDependencies:
- supports-color
hast-util-to-html@9.0.5:
dependencies:
'@types/hast': 3.0.4
@ -2216,6 +2516,26 @@ snapshots:
stringify-entities: 4.0.4
zwitch: 2.0.4
hast-util-to-jsx-runtime@2.3.6:
dependencies:
'@types/estree': 1.0.7
'@types/hast': 3.0.4
'@types/unist': 3.0.3
comma-separated-tokens: 2.0.3
devlop: 1.1.0
estree-util-is-identifier-name: 3.0.0
hast-util-whitespace: 3.0.0
mdast-util-mdx-expression: 2.0.1
mdast-util-mdx-jsx: 3.2.0
mdast-util-mdxjs-esm: 2.0.1
property-information: 7.0.0
space-separated-tokens: 2.0.2
style-to-js: 1.1.16
unist-util-position: 5.0.0
vfile-message: 4.0.2
transitivePeerDependencies:
- supports-color
hast-util-to-parse5@8.0.0:
dependencies:
'@types/hast': 3.0.4
@ -2253,15 +2573,28 @@ snapshots:
import-meta-resolve@4.1.0: {}
inline-style-parser@0.2.4: {}
iron-webcrypto@1.2.1: {}
is-alphabetical@2.0.1: {}
is-alphanumerical@2.0.1:
dependencies:
is-alphabetical: 2.0.1
is-decimal: 2.0.1
is-arrayish@0.3.2:
optional: true
is-decimal@2.0.1: {}
is-docker@3.0.0: {}
is-fullwidth-code-point@3.0.0: {}
is-hexadecimal@2.0.1: {}
is-inside-container@1.0.0:
dependencies:
is-docker: 3.0.0
@ -2294,6 +2627,8 @@ snapshots:
'@babel/types': 7.27.1
source-map-js: 1.2.1
markdown-extensions@2.0.0: {}
markdown-table@3.0.4: {}
mdast-util-definitions@6.0.0:
@ -2383,6 +2718,55 @@ snapshots:
transitivePeerDependencies:
- supports-color
mdast-util-mdx-expression@2.0.1:
dependencies:
'@types/estree-jsx': 1.0.5
'@types/hast': 3.0.4
'@types/mdast': 4.0.4
devlop: 1.1.0
mdast-util-from-markdown: 2.0.2
mdast-util-to-markdown: 2.1.2
transitivePeerDependencies:
- supports-color
mdast-util-mdx-jsx@3.2.0:
dependencies:
'@types/estree-jsx': 1.0.5
'@types/hast': 3.0.4
'@types/mdast': 4.0.4
'@types/unist': 3.0.3
ccount: 2.0.1
devlop: 1.1.0
mdast-util-from-markdown: 2.0.2
mdast-util-to-markdown: 2.1.2
parse-entities: 4.0.2
stringify-entities: 4.0.4
unist-util-stringify-position: 4.0.0
vfile-message: 4.0.2
transitivePeerDependencies:
- supports-color
mdast-util-mdx@3.0.0:
dependencies:
mdast-util-from-markdown: 2.0.2
mdast-util-mdx-expression: 2.0.1
mdast-util-mdx-jsx: 3.2.0
mdast-util-mdxjs-esm: 2.0.1
mdast-util-to-markdown: 2.1.2
transitivePeerDependencies:
- supports-color
mdast-util-mdxjs-esm@2.0.1:
dependencies:
'@types/estree-jsx': 1.0.5
'@types/hast': 3.0.4
'@types/mdast': 4.0.4
devlop: 1.1.0
mdast-util-from-markdown: 2.0.2
mdast-util-to-markdown: 2.1.2
transitivePeerDependencies:
- supports-color
mdast-util-phrasing@4.1.0:
dependencies:
'@types/mdast': 4.0.4
@ -2495,6 +2879,57 @@ snapshots:
micromark-util-combine-extensions: 2.0.1
micromark-util-types: 2.0.2
micromark-extension-mdx-expression@3.0.1:
dependencies:
'@types/estree': 1.0.7
devlop: 1.1.0
micromark-factory-mdx-expression: 2.0.3
micromark-factory-space: 2.0.1
micromark-util-character: 2.1.1
micromark-util-events-to-acorn: 2.0.3
micromark-util-symbol: 2.0.1
micromark-util-types: 2.0.2
micromark-extension-mdx-jsx@3.0.2:
dependencies:
'@types/estree': 1.0.7
devlop: 1.1.0
estree-util-is-identifier-name: 3.0.0
micromark-factory-mdx-expression: 2.0.3
micromark-factory-space: 2.0.1
micromark-util-character: 2.1.1
micromark-util-events-to-acorn: 2.0.3
micromark-util-symbol: 2.0.1
micromark-util-types: 2.0.2
vfile-message: 4.0.2
micromark-extension-mdx-md@2.0.0:
dependencies:
micromark-util-types: 2.0.2
micromark-extension-mdxjs-esm@3.0.0:
dependencies:
'@types/estree': 1.0.7
devlop: 1.1.0
micromark-core-commonmark: 2.0.3
micromark-util-character: 2.1.1
micromark-util-events-to-acorn: 2.0.3
micromark-util-symbol: 2.0.1
micromark-util-types: 2.0.2
unist-util-position-from-estree: 2.0.0
vfile-message: 4.0.2
micromark-extension-mdxjs@3.0.0:
dependencies:
acorn: 8.14.1
acorn-jsx: 5.3.2(acorn@8.14.1)
micromark-extension-mdx-expression: 3.0.1
micromark-extension-mdx-jsx: 3.0.2
micromark-extension-mdx-md: 2.0.0
micromark-extension-mdxjs-esm: 3.0.0
micromark-util-combine-extensions: 2.0.1
micromark-util-types: 2.0.2
micromark-factory-destination@2.0.1:
dependencies:
micromark-util-character: 2.1.1
@ -2508,6 +2943,18 @@ snapshots:
micromark-util-symbol: 2.0.1
micromark-util-types: 2.0.2
micromark-factory-mdx-expression@2.0.3:
dependencies:
'@types/estree': 1.0.7
devlop: 1.1.0
micromark-factory-space: 2.0.1
micromark-util-character: 2.1.1
micromark-util-events-to-acorn: 2.0.3
micromark-util-symbol: 2.0.1
micromark-util-types: 2.0.2
unist-util-position-from-estree: 2.0.0
vfile-message: 4.0.2
micromark-factory-space@2.0.1:
dependencies:
micromark-util-character: 2.1.1
@ -2560,6 +3007,16 @@ snapshots:
micromark-util-encode@2.0.1: {}
micromark-util-events-to-acorn@2.0.3:
dependencies:
'@types/estree': 1.0.7
'@types/unist': 3.0.3
devlop: 1.1.0
estree-util-visit: 2.0.0
micromark-util-symbol: 2.0.1
micromark-util-types: 2.0.2
vfile-message: 4.0.2
micromark-util-html-tag-name@2.0.1: {}
micromark-util-normalize-identifier@2.0.1:
@ -2662,6 +3119,16 @@ snapshots:
pako@0.2.9: {}
parse-entities@4.0.2:
dependencies:
'@types/unist': 2.0.11
character-entities-legacy: 3.0.0
character-reference-invalid: 2.0.1
decode-named-character-reference: 1.1.0
is-alphanumerical: 2.0.1
is-decimal: 2.0.1
is-hexadecimal: 2.0.1
parse-latin@7.0.0:
dependencies:
'@types/nlcst': 2.0.3
@ -2702,6 +3169,36 @@ snapshots:
readdirp@4.1.2: {}
recma-build-jsx@1.0.0:
dependencies:
'@types/estree': 1.0.7
estree-util-build-jsx: 3.0.1
vfile: 6.0.3
recma-jsx@1.0.0(acorn@8.14.1):
dependencies:
acorn-jsx: 5.3.2(acorn@8.14.1)
estree-util-to-js: 2.0.0
recma-parse: 1.0.0
recma-stringify: 1.0.0
unified: 11.0.5
transitivePeerDependencies:
- acorn
recma-parse@1.0.0:
dependencies:
'@types/estree': 1.0.7
esast-util-from-js: 2.0.1
unified: 11.0.5
vfile: 6.0.3
recma-stringify@1.0.0:
dependencies:
'@types/estree': 1.0.7
estree-util-to-js: 2.0.0
unified: 11.0.5
vfile: 6.0.3
regex-recursion@6.0.2:
dependencies:
regex-utilities: 2.3.0
@ -2724,6 +3221,14 @@ snapshots:
hast-util-raw: 9.1.0
vfile: 6.0.3
rehype-recma@1.0.0:
dependencies:
'@types/estree': 1.0.7
'@types/hast': 3.0.4
hast-util-to-estree: 3.1.3
transitivePeerDependencies:
- supports-color
rehype-stringify@10.0.1:
dependencies:
'@types/hast': 3.0.4
@ -2748,6 +3253,13 @@ snapshots:
transitivePeerDependencies:
- supports-color
remark-mdx@3.1.0:
dependencies:
mdast-util-mdx: 3.0.0
micromark-extension-mdxjs: 3.0.0
transitivePeerDependencies:
- supports-color
remark-parse@11.0.0:
dependencies:
'@types/mdast': 4.0.4
@ -2882,6 +3394,8 @@ snapshots:
source-map-js@1.2.1: {}
source-map@0.7.4: {}
space-separated-tokens@2.0.2: {}
string-width@4.2.3:
@ -2911,6 +3425,14 @@ snapshots:
strnum@1.1.2: {}
style-to-js@1.1.16:
dependencies:
style-to-object: 1.0.8
style-to-object@1.0.8:
dependencies:
inline-style-parser: 0.2.4
tiny-inflate@1.0.3: {}
tinyexec@0.3.2: {}
@ -2942,6 +3464,8 @@ snapshots:
uncrypto@0.1.3: {}
undici-types@6.21.0: {}
unicode-properties@1.4.1:
dependencies:
base64-js: 1.5.1
@ -2981,6 +3505,10 @@ snapshots:
'@types/unist': 3.0.3
array-iterate: 2.0.1
unist-util-position-from-estree@2.0.0:
dependencies:
'@types/unist': 3.0.3
unist-util-position@5.0.0:
dependencies:
'@types/unist': 3.0.3
@ -3035,7 +3563,7 @@ snapshots:
'@types/unist': 3.0.3
vfile-message: 4.0.2
vite@6.3.4:
vite@6.3.4(@types/node@22.15.3):
dependencies:
esbuild: 0.25.3
fdir: 6.4.4(picomatch@4.0.2)
@ -3044,11 +3572,12 @@ snapshots:
rollup: 4.40.1
tinyglobby: 0.2.13
optionalDependencies:
'@types/node': 22.15.3
fsevents: 2.3.3
vitefu@1.0.6(vite@6.3.4):
vitefu@1.0.6(vite@6.3.4(@types/node@22.15.3)):
optionalDependencies:
vite: 6.3.4
vite: 6.3.4(@types/node@22.15.3)
web-namespaces@2.0.1: {}

View file

@ -36,7 +36,6 @@ const { title, path = formattedPath } = Astro.props;
<nav class="nav">
<a href="/">Home</a>
<a href="/blog">Blog</a>
<a href="/lab">Lab</a>
</nav>
<Search />
@ -49,7 +48,7 @@ const { title, path = formattedPath } = Astro.props;
<footer class="footer">
<div class="container">
Powered by <a href="https://git.gb0.dev/gb/mercury"><img src="mercury.svg" width="16px" alt="mercury logo" /> mercury</a>
Powered by <a href="https://git.gb0.dev/gb/mercury"><img src="/mercury.svg" width="16px" alt="mercury logo" /> mercury</a>
</div>
</footer>
</body>

View file

@ -1,30 +0,0 @@
---
import Layout from '../layouts/Layout.astro';
---
<Layout title="Lab | Terminal Blog" >
<h1 class="post-title">~/lab</h1>
<div class="post-content">
<p class="typewriter">This is where experiments happen.</p>
<div style="margin-top: 2rem;">
<span class="command">ls -la experiments/</span>
<div style="margin-top: 1rem; margin-left: 1rem;">
<p><a href="/lab/experiment-1">Terminal Text Effects</a></p>
<p><a href="/lab/experiment-2">ASCII Art Generator</a></p>
<p><a href="/lab/experiment-3">Command Line Games</a></p>
</div>
</div>
<div style="margin-top: 2rem;">
<span class="command">cat README.md</span>
<div style="margin-top: 0.5rem; margin-left: 1rem;">
<p>
The lab is a space for experimental projects and ideas.
Feel free to explore, but be cautious as things might break.
</p>
</div>
</div>
</div>
</Layout>

View file

@ -1,410 +0,0 @@
---
import Layout from '../../layouts/Layout.astro';
export function getStaticPaths() {
return [
{ params: { slug: 'experiment-1' } },
{ params: { slug: 'experiment-2' } },
{ params: { slug: 'experiment-3' } }
];
}
const { slug } = Astro.params;
const experiments = {
'experiment-1': {
title: 'Terminal Text Effects',
content: `
<p class="typewriter">This is a demonstration of terminal-like text effects.</p>
<div style="margin-top: 2rem;">
<p id="rainbow-text">This text will change colors like a rainbow.</p>
</div>
<div style="margin-top: 2rem;">
<p id="glitch-text">This text will occasionally glitch.</p>
</div>
`,
script: `
// Rainbow text effect
const rainbowText = document.getElementById('rainbow-text');
if (rainbowText) {
const colors = ['#ff5555', '#ffb86c', '#f1fa8c', '#50fa7b', '#8be9fd', '#bd93f9', '#ff79c6'];
let colorIndex = 0;
setInterval(() => {
rainbowText.style.color = colors[colorIndex];
colorIndex = (colorIndex + 1) % colors.length;
}, 1000);
}
// Glitch text effect
const glitchText = document.getElementById('glitch-text');
if (glitchText) {
const originalText = glitchText.textContent;
const glitchChars = '!@#$%^&*()_+-=[]{}|;:,.<>?/\\\\';
setInterval(() => {
if (Math.random() > 0.9) {
let glitchedText = '';
for (let i = 0; i < originalText.length; i++) {
if (Math.random() > 0.9) {
glitchedText += glitchChars[Math.floor(Math.random() * glitchChars.length)];
} else {
glitchedText += originalText[i];
}
}
glitchText.textContent = glitchedText;
setTimeout(() => {
glitchText.textContent = originalText;
}, 100);
}
}, 2000);
}
`
},
'experiment-2': {
title: 'ASCII Art Generator',
content: `
<p class="typewriter">Generate ASCII art from text.</p>
<div style="margin-top: 2rem;">
<input type="text" id="ascii-input" placeholder="Enter text" class="terminal-input" />
<button id="generate-btn" class="terminal-btn">Generate</button>
</div>
<div style="margin-top: 1rem; white-space: pre; font-family: monospace; overflow-x: auto;" id="ascii-output">
</div>
`,
script: `
const generateBtn = document.getElementById('generate-btn');
const asciiInput = document.getElementById('ascii-input');
const asciiOutput = document.getElementById('ascii-output');
if (generateBtn && asciiInput && asciiOutput) {
generateBtn.addEventListener('click', () => {
const text = asciiInput.value.trim();
if (!text) return;
const fontStyles = [
generateSimpleAscii,
generateBlockAscii,
generateShadowAscii
];
const style = fontStyles[Math.floor(Math.random() * fontStyles.length)];
asciiOutput.textContent = style(text);
});
}
function generateSimpleAscii(text) {
return \`
_____ _____ _____ _____ _____ _____
|_____||_____||_____||_____||_____||_____|
| ${text.split('').join(' | ')} |
|_____|_____|_____|_____|_____|_____|
\`;
}
function generateBlockAscii(text) {
return \`
██████╗ ${text.split('').map(() => '██████╗ ').join('')}
██╔════╝ ${text.split('').map(() => '██╔══██╗').join('')}
██║ ███╗${text.split('').map(() => '██████╔╝').join('')}
██║ ██║${text.split('').map(() => '██╔══██╗').join('')}
╚██████╔╝${text.split('').map(() => '██████╔╝').join('')}
╚═════╝ ${text.split('').map(() => '╚═════╝ ').join('')}
\`;
}
function generateShadowAscii(text) {
return \`
░░░░░░${text.split('').map(() => '░░░░░░').join('')}
▒░ ▒░${text.split('').map(() => '▒░ ▒░').join('')}
▒▒ ▒▒${text.split('').map(() => '▒▒ ▒▒').join('')}
▓▒ ▒▓${text.split('').map(() => '▓▒ ▒▓').join('')}
▓▓▓▓▓▓ ${text.split('').map(() => '▓▓▓▓▓▓ ').join('')}
\`;
}
`,
style: `
.terminal-input {
background-color: var(--bg-color);
border: 1px solid var(--border-color);
color: var(--text-color);
padding: 0.5rem;
font-family: var(--font-mono);
margin-right: 0.5rem;
}
.terminal-btn {
background-color: var(--border-color);
border: none;
color: var(--text-color);
padding: 0.5rem 1rem;
font-family: var(--font-mono);
cursor: pointer;
transition: background-color 0.2s;
}
.terminal-btn:hover {
background-color: var(--accent-color);
color: var(--bg-color);
}
`
},
'experiment-3': {
title: 'Command Line Games',
content: `
<p class="typewriter">Try a simple command line game.</p>
<div style="margin-top: 2rem;">
<p>Enter a command:</p>
<div style="display: flex; margin-top: 0.5rem;">
<span class="command" style="margin-right: 0;">play</span>
<input type="text" id="game-input" class="terminal-input" style="flex-grow: 1;" />
</div>
<div id="game-output" style="margin-top: 1rem; white-space: pre-wrap; font-family: monospace;">
Available games: number-guess, rock-paper-scissors, hangman
</div>
</div>
`,
script: `
const gameInput = document.getElementById('game-input');
const gameOutput = document.getElementById('game-output');
let currentGame = null;
let gameState = {};
if (gameInput && gameOutput) {
gameInput.addEventListener('keydown', (e) => {
if (e.key === 'Enter') {
const command = gameInput.value.trim().toLowerCase();
gameInput.value = '';
processCommand(command);
}
});
}
function processCommand(command) {
if (!currentGame) {
// Starting a new game
if (command === 'number-guess') {
currentGame = 'number-guess';
gameState = {
target: Math.floor(Math.random() * 100) + 1,
attempts: 0
};
appendOutput('I\'m thinking of a number between 1 and 100.');
appendOutput('Enter your guess:');
} else if (command === 'rock-paper-scissors') {
currentGame = 'rock-paper-scissors';
appendOutput('Let\'s play Rock, Paper, Scissors!');
appendOutput('Enter rock, paper, or scissors:');
} else if (command === 'hangman') {
currentGame = 'hangman';
const words = ['javascript', 'terminal', 'computer', 'keyboard', 'program'];
gameState = {
word: words[Math.floor(Math.random() * words.length)],
guessed: [],
attempts: 0
};
appendOutput('Let\'s play Hangman!');
appendOutput(\`The word has \${gameState.word.length} letters.\`);
appendOutput(getHangmanDisplay());
} else {
appendOutput(\`Unknown game: \${command}\`);
appendOutput('Available games: number-guess, rock-paper-scissors, hangman');
}
} else if (currentGame === 'number-guess') {
const guess = parseInt(command);
if (isNaN(guess)) {
appendOutput('Please enter a valid number.');
return;
}
gameState.attempts++;
if (guess === gameState.target) {
appendOutput(\`Congratulations! You guessed it in \${gameState.attempts} attempts.\`);
currentGame = null;
appendOutput('\\nAvailable games: number-guess, rock-paper-scissors, hangman');
} else if (guess < gameState.target) {
appendOutput('Too low! Try again:');
} else {
appendOutput('Too high! Try again:');
}
} else if (currentGame === 'rock-paper-scissors') {
const choices = ['rock', 'paper', 'scissors'];
if (!choices.includes(command)) {
appendOutput('Please enter rock, paper, or scissors.');
return;
}
const computerChoice = choices[Math.floor(Math.random() * choices.length)];
appendOutput(\`You chose \${command}. Computer chose \${computerChoice}.\`);
if (command === computerChoice) {
appendOutput('It\'s a tie!');
} else if (
(command === 'rock' && computerChoice === 'scissors') ||
(command === 'paper' && computerChoice === 'rock') ||
(command === 'scissors' && computerChoice === 'paper')
) {
appendOutput('You win!');
} else {
appendOutput('Computer wins!');
}
appendOutput('Play again? Enter rock, paper, or scissors, or type "exit" to quit:');
if (command === 'exit') {
currentGame = null;
appendOutput('\\nAvailable games: number-guess, rock-paper-scissors, hangman');
}
} else if (currentGame === 'hangman') {
if (command === 'exit') {
currentGame = null;
appendOutput(\`The word was: \${gameState.word}\`);
appendOutput('\\nAvailable games: number-guess, rock-paper-scissors, hangman');
return;
}
if (command.length !== 1) {
appendOutput('Please enter a single letter.');
return;
}
const letter = command.toLowerCase();
if (gameState.guessed.includes(letter)) {
appendOutput('You already guessed that letter!');
return;
}
gameState.guessed.push(letter);
if (!gameState.word.includes(letter)) {
gameState.attempts++;
}
appendOutput(getHangmanDisplay());
const wordDisplay = gameState.word
.split('')
.map(char => gameState.guessed.includes(char) ? char : '_')
.join(' ');
appendOutput(\`Word: \${wordDisplay}\`);
appendOutput(\`Guessed: \${gameState.guessed.join(', ')}\`);
if (!wordDisplay.includes('_')) {
appendOutput('Congratulations! You guessed the word!');
currentGame = null;
appendOutput('\\nAvailable games: number-guess, rock-paper-scissors, hangman');
} else if (gameState.attempts >= 6) {
appendOutput(\`Game over! The word was: \${gameState.word}\`);
currentGame = null;
appendOutput('\\nAvailable games: number-guess, rock-paper-scissors, hangman');
}
}
}
function getHangmanDisplay() {
const hangmanStages = [
\`
+---+
| |
|
|
|
|
=========\`,
\`
+---+
| |
O |
|
|
|
=========\`,
\`
+---+
| |
O |
| |
|
|
=========\`,
\`
+---+
| |
O |
/| |
|
|
=========\`,
\`
+---+
| |
O |
/|\\ |
|
|
=========\`,
\`
+---+
| |
O |
/|\\ |
/ |
|
=========\`,
\`
+---+
| |
O |
/|\\ |
/ \\ |
|
=========\`
];
return hangmanStages[Math.min(gameState.attempts, 6)];
}
function appendOutput(text) {
gameOutput.textContent += '\\n' + text;
gameOutput.scrollTop = gameOutput.scrollHeight;
}
`,
style: `
.terminal-input {
background-color: var(--bg-color);
border: 1px solid var(--border-color);
color: var(--text-color);
padding: 0.5rem;
font-family: var(--font-mono);
}
`
}
};
---
<Layout title={`Lab | ${experiments[slug]?.title}`} path={`~/grassblock/micr0blog/lab/${slug}`}>
<h1 class="post-title">{experiments[slug]?.title}</h1>
<div class="post-content">
<div set:html={experiments[slug]?.content}></div>
</div>
<div style="margin-top: 2rem; border-top: 1px solid var(--border-color); padding-top: 1rem;">
<a href="/lab">&larr; Back to lab</a>
</div>
{experiments[slug]?.style && (
<style set:html={experiments[slug]?.style}></style>
)}
{experiments[slug]?.script && (
<script set:html={experiments[slug]?.script}></script>
)}
</Layout>

View file

@ -1,18 +1,65 @@
import rss from '@astrojs/rss';
import { getCollection } from 'astro:content';
import { getContainerRenderer as getMDXRenderer } from "@astrojs/mdx";
import rss from "@astrojs/rss";
import { experimental_AstroContainer as AstroContainer } from "astro/container";
import { loadRenderers } from "astro:container";
import { getCollection } from "astro:content";
import { transform, walk } from "ultrahtml";
import sanitize from "ultrahtml/transformers/sanitize";
import { siteConfig } from "../config.js"
// code from https://github.com/delucis/astro-blog-full-text-rss
export async function GET(context) {
const posts = await getCollection('blog');
// Get the URL to prepend to relative site links. Based on `site` in `astro.config.mjs`.
let baseUrl = context.site?.href || "https://terminal-blog.example.com";
if (baseUrl.at(-1) === "/") baseUrl = baseUrl.slice(0, -1);
// Load MDX renderer. Other renderers for UI frameworks (e.g. React, Vue, etc.) would need adding here if you were using those.
const renderers = await loadRenderers([getMDXRenderer()]);
// Create a new Astro container that we can render components with.
// See https://docs.astro.build/en/reference/container-reference/
const container = await AstroContainer.create({ renderers });
// Load the content collection entries to add to our RSS feed.
const posts = (await getCollection("blog")).sort((a, b) =>
// Sort by publication date descending.
a.data.pubDate > b.data.pubDate ? -1 : 1
);
// Loop over blog posts to create feed items for each, including full content.
const feedItems = [];
for (const post of posts) {
// Get the `<Content/>` component for the current post.
const { Content } = await post.render();
// Use the Astro container to render the content to a string.
const rawContent = await container.renderToString(Content);
// Process and sanitize the raw content:
// - Removes `<!DOCTYPE html>` preamble
// - Makes link `href` and image `src` attributes absolute instead of relative
// - Strips any `<script>` and `<style>` tags
// Thanks @Princesseuh — https://github.com/Princesseuh/erika.florist/blob/1827288c14681490fa301400bfd815acb53463e9/src/middleware.ts
const content = await transform(rawContent.replace(/^<!DOCTYPE html>/, ''), [
async (node) => {
await walk(node, (node) => {
if (node.name === "a" && node.attributes.href?.startsWith("/")) {
node.attributes.href = baseUrl + node.attributes.href;
}
if (node.name === "img" && node.attributes.src?.startsWith("/")) {
node.attributes.src = baseUrl + node.attributes.src;
}
});
return node;
},
sanitize({ dropElements: ["script", "style"] }),
]);
feedItems.push({ ...post.data, link: `/blog/${post.slug}/`, content });
}
// Return our RSS feed XML response.
return rss({
title: 'Terminal Blog',
description: 'A random grassblock do some some writing work.',
title: siteConfig.title,
description: siteConfig.description,
site: context.site,
items: posts.map((post) => ({
title: post.data.title,
description: post.data.description,
pubDate: post.data.pubDate,
link: `/blog/${post.slug}/`,
content: post.body,
})),
items: feedItems,
});
}
}