fix: image relative path in rss feed, modify the path of the local images
-
12
README.md
|
@ -1,5 +1,5 @@
|
|||
<img alt="Cover Image" src="assets/retypeset-en-desktop.webp"/>
|
||||
<img alt="Cover Image" src="assets/retypeset-en-mobile.webp"/>
|
||||
<img alt="Cover Image" src="images/retypeset-en-desktop.webp"/>
|
||||
<img alt="Cover Image" src="images/retypeset-en-mobile.webp"/>
|
||||
|
||||
<div align="center">
|
||||
<picture>
|
||||
|
@ -44,8 +44,8 @@ Retypeset is a static blog theme based on the [Astro](https://astro.build/) fram
|
|||
<br>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://pagespeed.web.dev/analysis?url=https%3A%2F%2Fretypeset.radishzz.cc%2F">
|
||||
<img width="710" alt="Retypeset Lighthouse Score" src="assets/retypeset-lighthouse-score.svg">
|
||||
<a href="https://pagespeed.web.dev/analysis?url=https%3A%2F%2Fretypeset.radishzz.cc%2Fen%2F">
|
||||
<img width="710" alt="Retypeset Lighthouse Score" src="images/retypeset-lighthouse-score.svg">
|
||||
<a>
|
||||
</p>
|
||||
|
||||
|
@ -78,8 +78,8 @@ Retypeset is a static blog theme based on the [Astro](https://astro.build/) fram
|
|||
|
||||
5. Refer to the [Astro Deployment Guides](https://docs.astro.build/en/guides/deploy/) to deploy your blog to Netlify, Vercel, or other platforms.
|
||||
|
||||
 [](https://app.netlify.com/start)
|
||||
[](https://vercel.com/new)
|
||||
 [](https://app.netlify.com/start)
|
||||
[](https://vercel.com/new)
|
||||
|
||||
## Updates
|
||||
|
||||
|
|
10
README.zh.md
|
@ -1,5 +1,5 @@
|
|||
<img alt="Cover Image" src="assets/retypeset-zh-desktop.webp"/>
|
||||
<img alt="Cover Image" src="assets/retypeset-zh-mobile.webp"/>
|
||||
<img alt="Cover Image" src="images/retypeset-zh-desktop.webp"/>
|
||||
<img alt="Cover Image" src="images/retypeset-zh-mobile.webp"/>
|
||||
|
||||
<div align="center">
|
||||
<a title="en" href="README.md">
|
||||
|
@ -45,7 +45,7 @@ Retypeset 是一款基于 [Astro](https://astro.build/) 框架的静态博客主
|
|||
|
||||
<p align="center">
|
||||
<a href="https://pagespeed.web.dev/analysis?url=https%3A%2F%2Fretypeset.radishzz.cc%2F">
|
||||
<img width="710" alt="Retypeset Lighthouse Score" src="assets/retypeset-lighthouse-score.svg">
|
||||
<img width="710" alt="Retypeset Lighthouse Score" src="images/retypeset-lighthouse-score.svg">
|
||||
<a>
|
||||
</p>
|
||||
|
||||
|
@ -78,8 +78,8 @@ Retypeset 是一款基于 [Astro](https://astro.build/) 框架的静态博客主
|
|||
|
||||
5. 参考 [Astro 部署指南](https://docs.astro.build/zh-cn/guides/deploy/),将博客部署至 Netlify、Vercel 等平台。
|
||||
|
||||
 [](https://app.netlify.com/start)
|
||||
[](https://vercel.com/new)
|
||||
 [](https://app.netlify.com/start)
|
||||
[](https://vercel.com/new)
|
||||
|
||||
## 更新
|
||||
|
||||
|
|
Before Width: | Height: | Size: 4.6 KiB After Width: | Height: | Size: 4.6 KiB |
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 158 KiB After Width: | Height: | Size: 158 KiB |
Before Width: | Height: | Size: 240 KiB After Width: | Height: | Size: 240 KiB |
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 6.1 KiB |
Before Width: | Height: | Size: 171 KiB After Width: | Height: | Size: 171 KiB |
Before Width: | Height: | Size: 227 KiB After Width: | Height: | Size: 227 KiB |
|
@ -25,6 +25,7 @@
|
|||
"katex": "^0.16.22",
|
||||
"markdown-it": "^14.1.0",
|
||||
"mdast-util-to-string": "^4.0.0",
|
||||
"node-html-parser": "^7.0.1",
|
||||
"overlayscrollbars": "^2.11.2",
|
||||
"photoswipe": "^5.4.4",
|
||||
"reading-time": "^1.5.0",
|
||||
|
@ -48,7 +49,7 @@
|
|||
"astro-eslint-parser": "^1.2.2",
|
||||
"eslint": "^9.26.0",
|
||||
"eslint-plugin-astro": "^1.3.1",
|
||||
"lint-staged": "^15.5.2",
|
||||
"lint-staged": "^16.0.0",
|
||||
"sharp": "^0.34.1",
|
||||
"typescript": "~5.8.3",
|
||||
"unocss": "66.1.1",
|
||||
|
|
135
pnpm-lock.yaml
generated
|
@ -44,6 +44,9 @@ importers:
|
|||
mdast-util-to-string:
|
||||
specifier: ^4.0.0
|
||||
version: 4.0.0
|
||||
node-html-parser:
|
||||
specifier: ^7.0.1
|
||||
version: 7.0.1
|
||||
overlayscrollbars:
|
||||
specifier: ^2.11.2
|
||||
version: 2.11.2
|
||||
|
@ -109,8 +112,8 @@ importers:
|
|||
specifier: ^1.3.1
|
||||
version: 1.3.1(eslint@9.26.0(jiti@2.4.2))
|
||||
lint-staged:
|
||||
specifier: ^15.5.2
|
||||
version: 15.5.2
|
||||
specifier: ^16.0.0
|
||||
version: 16.0.0
|
||||
sharp:
|
||||
specifier: ^0.34.1
|
||||
version: 0.34.1
|
||||
|
@ -1741,10 +1744,17 @@ packages:
|
|||
crossws@0.3.5:
|
||||
resolution: {integrity: sha512-ojKiDvcmByhwa8YYqbQI/hg7MEU0NC03+pSdEq4ZUnZR9xXpwk7E43SMNGkn+JxJGPFtNvQ48+vV2p+P1ml5PA==}
|
||||
|
||||
css-select@5.1.0:
|
||||
resolution: {integrity: sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==}
|
||||
|
||||
css-tree@3.1.0:
|
||||
resolution: {integrity: sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==}
|
||||
engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0}
|
||||
|
||||
css-what@6.1.0:
|
||||
resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==}
|
||||
engines: {node: '>= 6'}
|
||||
|
||||
cssesc@3.0.0:
|
||||
resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==}
|
||||
engines: {node: '>=4'}
|
||||
|
@ -1997,8 +2007,8 @@ packages:
|
|||
peerDependencies:
|
||||
eslint: ^8.57.0 || ^9.0.0
|
||||
|
||||
eslint-plugin-jsdoc@50.6.11:
|
||||
resolution: {integrity: sha512-k4+MnBCGR8cuIB5MZ++FGd4gbXxjob2rX1Nq0q3nWFF4xSGZENTgTLZSjb+u9B8SAnP6lpGV2FJrBjllV3pVSg==}
|
||||
eslint-plugin-jsdoc@50.6.14:
|
||||
resolution: {integrity: sha512-JUudvooQbUx3iB8n/MzXMOV/VtaXq7xL4CeXhYryinr8osck7nV6fE2/xUXTiH3epPXcvq6TE3HQfGQuRHErTQ==}
|
||||
engines: {node: '>=18'}
|
||||
peerDependencies:
|
||||
eslint: ^7.0.0 || ^8.0.0 || ^9.0.0
|
||||
|
@ -2161,10 +2171,6 @@ packages:
|
|||
resolution: {integrity: sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==}
|
||||
engines: {node: '>=18.0.0'}
|
||||
|
||||
execa@8.0.1:
|
||||
resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==}
|
||||
engines: {node: '>=16.17'}
|
||||
|
||||
expect-type@1.2.1:
|
||||
resolution: {integrity: sha512-/kP8CAwxzLVEeFrMm4kMmy4CCDlpipyA7MYLVrdJIkV0fYF0UaigQHRsxHiuY/GEea+bh4KSv3TIlgr+2UL6bw==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
|
@ -2296,10 +2302,6 @@ packages:
|
|||
resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
get-stream@8.0.1:
|
||||
resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==}
|
||||
engines: {node: '>=16'}
|
||||
|
||||
get-tsconfig@4.10.0:
|
||||
resolution: {integrity: sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==}
|
||||
|
||||
|
@ -2403,6 +2405,10 @@ packages:
|
|||
hastscript@9.0.1:
|
||||
resolution: {integrity: sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w==}
|
||||
|
||||
he@1.2.0:
|
||||
resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==}
|
||||
hasBin: true
|
||||
|
||||
html-escaper@3.0.3:
|
||||
resolution: {integrity: sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ==}
|
||||
|
||||
|
@ -2419,10 +2425,6 @@ packages:
|
|||
resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==}
|
||||
engines: {node: '>= 0.8'}
|
||||
|
||||
human-signals@5.0.0:
|
||||
resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==}
|
||||
engines: {node: '>=16.17.0'}
|
||||
|
||||
iconv-lite@0.6.3:
|
||||
resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
@ -2535,10 +2537,6 @@ packages:
|
|||
is-promise@4.0.0:
|
||||
resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==}
|
||||
|
||||
is-stream@3.0.0:
|
||||
resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==}
|
||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||
|
||||
is-wsl@3.1.0:
|
||||
resolution: {integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==}
|
||||
engines: {node: '>=16'}
|
||||
|
@ -2683,9 +2681,9 @@ packages:
|
|||
linkify-it@5.0.0:
|
||||
resolution: {integrity: sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==}
|
||||
|
||||
lint-staged@15.5.2:
|
||||
resolution: {integrity: sha512-YUSOLq9VeRNAo/CTaVmhGDKG+LBtA8KF1X4K5+ykMSwWST1vDxJRB2kv2COgLb1fvpCo+A/y9A0G0znNVmdx4w==}
|
||||
engines: {node: '>=18.12.0'}
|
||||
lint-staged@16.0.0:
|
||||
resolution: {integrity: sha512-sUCprePs6/rbx4vKC60Hez6X10HPkpDJaGcy3D1NdwR7g1RcNkWL8q9mJMreOqmHBTs+1sNFp+wOiX9fr+hoOQ==}
|
||||
engines: {node: '>=20.18'}
|
||||
hasBin: true
|
||||
|
||||
listr2@8.3.3:
|
||||
|
@ -2824,9 +2822,6 @@ packages:
|
|||
resolution: {integrity: sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
merge-stream@2.0.0:
|
||||
resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==}
|
||||
|
||||
merge2@1.4.1:
|
||||
resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
|
||||
engines: {node: '>= 8'}
|
||||
|
@ -2957,10 +2952,6 @@ packages:
|
|||
resolution: {integrity: sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==}
|
||||
engines: {node: '>= 0.6'}
|
||||
|
||||
mimic-fn@4.0.0:
|
||||
resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
mimic-function@5.0.1:
|
||||
resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==}
|
||||
engines: {node: '>=18'}
|
||||
|
@ -2993,6 +2984,10 @@ packages:
|
|||
muggle-string@0.4.1:
|
||||
resolution: {integrity: sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==}
|
||||
|
||||
nano-spawn@1.0.1:
|
||||
resolution: {integrity: sha512-BfcvzBlUTxSDWfT+oH7vd6CbUV+rThLLHCIym/QO6GGLBsyVXleZs00fto2i2jzC/wPiBYk5jyOmpXWg4YopiA==}
|
||||
engines: {node: '>=20.18'}
|
||||
|
||||
nanoid@3.3.11:
|
||||
resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==}
|
||||
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
|
||||
|
@ -3033,6 +3028,9 @@ packages:
|
|||
encoding:
|
||||
optional: true
|
||||
|
||||
node-html-parser@7.0.1:
|
||||
resolution: {integrity: sha512-KGtmPY2kS0thCWGK0VuPyOS+pBKhhe8gXztzA2ilAOhbUbxa9homF1bOyKvhGzMLXUoRds9IOmr/v5lr/lqNmA==}
|
||||
|
||||
node-mock-http@1.0.0:
|
||||
resolution: {integrity: sha512-0uGYQ1WQL1M5kKvGRXWQ3uZCHtLTO8hln3oBjIusM75WoesZ909uQJs/Hb946i2SS+Gsrhkaa6iAO17jRIv6DQ==}
|
||||
|
||||
|
@ -3043,10 +3041,6 @@ packages:
|
|||
resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
npm-run-path@5.3.0:
|
||||
resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==}
|
||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||
|
||||
nth-check@2.1.1:
|
||||
resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==}
|
||||
|
||||
|
@ -3071,10 +3065,6 @@ packages:
|
|||
once@1.4.0:
|
||||
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
|
||||
|
||||
onetime@6.0.0:
|
||||
resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
onetime@7.0.0:
|
||||
resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==}
|
||||
engines: {node: '>=18'}
|
||||
|
@ -3159,10 +3149,6 @@ packages:
|
|||
resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
path-key@4.0.0:
|
||||
resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
path-parse@1.0.7:
|
||||
resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
|
||||
|
||||
|
@ -3616,10 +3602,6 @@ packages:
|
|||
resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
strip-final-newline@3.0.0:
|
||||
resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
strip-indent@4.0.0:
|
||||
resolution: {integrity: sha512-mnVSV2l+Zv6BLpSD/8V87CW/y9EmmbYzGCIavsnsI6/nwn26DwffM/yztm30Z/I2DY9wdS3vXVCMnHDgZaVNoA==}
|
||||
engines: {node: '>=12'}
|
||||
|
@ -4281,7 +4263,7 @@ snapshots:
|
|||
eslint-plugin-antfu: 3.1.1(eslint@9.26.0(jiti@2.4.2))
|
||||
eslint-plugin-command: 3.2.0(eslint@9.26.0(jiti@2.4.2))
|
||||
eslint-plugin-import-x: 4.11.1(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)
|
||||
eslint-plugin-jsdoc: 50.6.11(eslint@9.26.0(jiti@2.4.2))
|
||||
eslint-plugin-jsdoc: 50.6.14(eslint@9.26.0(jiti@2.4.2))
|
||||
eslint-plugin-jsonc: 2.20.0(eslint@9.26.0(jiti@2.4.2))
|
||||
eslint-plugin-n: 17.18.0(eslint@9.26.0(jiti@2.4.2))
|
||||
eslint-plugin-no-only-tests: 3.3.0
|
||||
|
@ -6086,11 +6068,21 @@ snapshots:
|
|||
dependencies:
|
||||
uncrypto: 0.1.3
|
||||
|
||||
css-select@5.1.0:
|
||||
dependencies:
|
||||
boolbase: 1.0.0
|
||||
css-what: 6.1.0
|
||||
domhandler: 5.0.3
|
||||
domutils: 3.2.2
|
||||
nth-check: 2.1.1
|
||||
|
||||
css-tree@3.1.0:
|
||||
dependencies:
|
||||
mdn-data: 2.12.2
|
||||
source-map-js: 1.2.1
|
||||
|
||||
css-what@6.1.0: {}
|
||||
|
||||
cssesc@3.0.0: {}
|
||||
|
||||
csstype@3.1.3: {}
|
||||
|
@ -6343,7 +6335,7 @@ snapshots:
|
|||
- supports-color
|
||||
- typescript
|
||||
|
||||
eslint-plugin-jsdoc@50.6.11(eslint@9.26.0(jiti@2.4.2)):
|
||||
eslint-plugin-jsdoc@50.6.14(eslint@9.26.0(jiti@2.4.2)):
|
||||
dependencies:
|
||||
'@es-joy/jsdoccomment': 0.49.0
|
||||
are-docs-informative: 0.0.2
|
||||
|
@ -6604,18 +6596,6 @@ snapshots:
|
|||
dependencies:
|
||||
eventsource-parser: 3.0.1
|
||||
|
||||
execa@8.0.1:
|
||||
dependencies:
|
||||
cross-spawn: 7.0.6
|
||||
get-stream: 8.0.1
|
||||
human-signals: 5.0.0
|
||||
is-stream: 3.0.0
|
||||
merge-stream: 2.0.0
|
||||
npm-run-path: 5.3.0
|
||||
onetime: 6.0.0
|
||||
signal-exit: 4.1.0
|
||||
strip-final-newline: 3.0.0
|
||||
|
||||
expect-type@1.2.1:
|
||||
optional: true
|
||||
|
||||
|
@ -6778,8 +6758,6 @@ snapshots:
|
|||
dunder-proto: 1.0.1
|
||||
es-object-atoms: 1.1.1
|
||||
|
||||
get-stream@8.0.1: {}
|
||||
|
||||
get-tsconfig@4.10.0:
|
||||
dependencies:
|
||||
resolve-pkg-maps: 1.0.0
|
||||
|
@ -6979,6 +6957,8 @@ snapshots:
|
|||
property-information: 7.1.0
|
||||
space-separated-tokens: 2.0.2
|
||||
|
||||
he@1.2.0: {}
|
||||
|
||||
html-escaper@3.0.3: {}
|
||||
|
||||
html-void-elements@3.0.0: {}
|
||||
|
@ -7000,8 +6980,6 @@ snapshots:
|
|||
statuses: 2.0.1
|
||||
toidentifier: 1.0.1
|
||||
|
||||
human-signals@5.0.0: {}
|
||||
|
||||
iconv-lite@0.6.3:
|
||||
dependencies:
|
||||
safer-buffer: 2.1.2
|
||||
|
@ -7082,8 +7060,6 @@ snapshots:
|
|||
|
||||
is-promise@4.0.0: {}
|
||||
|
||||
is-stream@3.0.0: {}
|
||||
|
||||
is-wsl@3.1.0:
|
||||
dependencies:
|
||||
is-inside-container: 1.0.0
|
||||
|
@ -7192,15 +7168,15 @@ snapshots:
|
|||
dependencies:
|
||||
uc.micro: 2.1.0
|
||||
|
||||
lint-staged@15.5.2:
|
||||
lint-staged@16.0.0:
|
||||
dependencies:
|
||||
chalk: 5.4.1
|
||||
commander: 13.1.0
|
||||
debug: 4.4.0
|
||||
execa: 8.0.1
|
||||
lilconfig: 3.1.3
|
||||
listr2: 8.3.3
|
||||
micromatch: 4.0.8
|
||||
nano-spawn: 1.0.1
|
||||
pidtree: 0.6.0
|
||||
string-argv: 0.3.2
|
||||
yaml: 2.7.1
|
||||
|
@ -7490,8 +7466,6 @@ snapshots:
|
|||
|
||||
merge-descriptors@2.0.0: {}
|
||||
|
||||
merge-stream@2.0.0: {}
|
||||
|
||||
merge2@1.4.1: {}
|
||||
|
||||
micromark-core-commonmark@2.0.3:
|
||||
|
@ -7796,8 +7770,6 @@ snapshots:
|
|||
dependencies:
|
||||
mime-db: 1.54.0
|
||||
|
||||
mimic-fn@4.0.0: {}
|
||||
|
||||
mimic-function@5.0.1: {}
|
||||
|
||||
min-indent@1.0.1: {}
|
||||
|
@ -7827,6 +7799,8 @@ snapshots:
|
|||
|
||||
muggle-string@0.4.1: {}
|
||||
|
||||
nano-spawn@1.0.1: {}
|
||||
|
||||
nanoid@3.3.11: {}
|
||||
|
||||
napi-postinstall@0.2.3: {}
|
||||
|
@ -7849,16 +7823,17 @@ snapshots:
|
|||
dependencies:
|
||||
whatwg-url: 5.0.0
|
||||
|
||||
node-html-parser@7.0.1:
|
||||
dependencies:
|
||||
css-select: 5.1.0
|
||||
he: 1.2.0
|
||||
|
||||
node-mock-http@1.0.0: {}
|
||||
|
||||
node-releases@2.0.19: {}
|
||||
|
||||
normalize-path@3.0.0: {}
|
||||
|
||||
npm-run-path@5.3.0:
|
||||
dependencies:
|
||||
path-key: 4.0.0
|
||||
|
||||
nth-check@2.1.1:
|
||||
dependencies:
|
||||
boolbase: 1.0.0
|
||||
|
@ -7883,10 +7858,6 @@ snapshots:
|
|||
dependencies:
|
||||
wrappy: 1.0.2
|
||||
|
||||
onetime@6.0.0:
|
||||
dependencies:
|
||||
mimic-fn: 4.0.0
|
||||
|
||||
onetime@7.0.0:
|
||||
dependencies:
|
||||
mimic-function: 5.0.1
|
||||
|
@ -7978,8 +7949,6 @@ snapshots:
|
|||
|
||||
path-key@3.1.1: {}
|
||||
|
||||
path-key@4.0.0: {}
|
||||
|
||||
path-parse@1.0.7: {}
|
||||
|
||||
path-to-regexp@8.2.0: {}
|
||||
|
@ -8614,8 +8583,6 @@ snapshots:
|
|||
dependencies:
|
||||
ansi-regex: 6.1.0
|
||||
|
||||
strip-final-newline@3.0.0: {}
|
||||
|
||||
strip-indent@4.0.0:
|
||||
dependencies:
|
||||
min-indent: 1.0.1
|
||||
|
|
Before Width: | Height: | Size: 1,005 KiB After Width: | Height: | Size: 1,005 KiB |
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 1.1 MiB |
Before Width: | Height: | Size: 999 KiB After Width: | Height: | Size: 999 KiB |
Before Width: | Height: | Size: 1 MiB After Width: | Height: | Size: 1 MiB |
Before Width: | Height: | Size: 1 MiB After Width: | Height: | Size: 1 MiB |
Before Width: | Height: | Size: 1 MiB After Width: | Height: | Size: 1 MiB |
Before Width: | Height: | Size: 1,016 KiB After Width: | Height: | Size: 1,016 KiB |
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 1.1 MiB |
|
@ -14,8 +14,8 @@ To meet personalization needs, I've created several color schemes for the theme.
|
|||
|
||||
## Scallion White
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
```
|
||||
light: {
|
||||
|
@ -32,8 +32,8 @@ dark: {
|
|||
|
||||
## Raven Teal
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
```
|
||||
light: {
|
||||
|
@ -50,8 +50,8 @@ dark: {
|
|||
|
||||
## Ink Blue
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
```
|
||||
light: {
|
||||
|
@ -68,8 +68,8 @@ dark: {
|
|||
|
||||
## Ecru
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
```
|
||||
light: {
|
||||
|
|
|
@ -14,8 +14,8 @@ Para satisfacer las necesidades de personalización, he creado varios esquemas d
|
|||
|
||||
## Blanco Cebollino
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
```
|
||||
light: {
|
||||
|
@ -32,8 +32,8 @@ dark: {
|
|||
|
||||
## Azul Cuervo
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
```
|
||||
light: {
|
||||
|
@ -50,8 +50,8 @@ dark: {
|
|||
|
||||
## Azul Tinta
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
```
|
||||
light: {
|
||||
|
@ -68,8 +68,8 @@ dark: {
|
|||
|
||||
## Beige
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
```
|
||||
light: {
|
||||
|
|
|
@ -14,8 +14,8 @@ Retypesetは、[OKLCH](https://oklch.com/)カラースペースに基づいて
|
|||
|
||||
## 葱白色
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
```
|
||||
light: {
|
||||
|
@ -32,8 +32,8 @@ dark: {
|
|||
|
||||
## 烏青
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
```
|
||||
light: {
|
||||
|
@ -50,8 +50,8 @@ dark: {
|
|||
|
||||
## 墨藍
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
```
|
||||
light: {
|
||||
|
@ -68,8 +68,8 @@ dark: {
|
|||
|
||||
## 米色
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
```
|
||||
light: {
|
||||
|
|
|
@ -14,8 +14,8 @@ Retypeset определяет цветовые схемы темы на осн
|
|||
|
||||
## Бледно-зелёный
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
```
|
||||
light: {
|
||||
|
@ -32,8 +32,8 @@ dark: {
|
|||
|
||||
## Воронёный
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
```
|
||||
light: {
|
||||
|
@ -50,8 +50,8 @@ dark: {
|
|||
|
||||
## Чернильно-синий
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
```
|
||||
light: {
|
||||
|
@ -68,8 +68,8 @@ dark: {
|
|||
|
||||
## Кремовый
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
```
|
||||
light: {
|
||||
|
|
|
@ -14,8 +14,8 @@ Retypeset 基於 [OKLCH](https://oklch.com/) 顏色空間來定義主題配色
|
|||
|
||||
## 蔥白
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
```
|
||||
light: {
|
||||
|
@ -32,8 +32,8 @@ dark: {
|
|||
|
||||
## 鴉青
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
```
|
||||
light: {
|
||||
|
@ -50,8 +50,8 @@ dark: {
|
|||
|
||||
## 墨藍
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
```
|
||||
light: {
|
||||
|
@ -68,8 +68,8 @@ dark: {
|
|||
|
||||
## 米黃
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
```
|
||||
light: {
|
||||
|
|
|
@ -14,8 +14,8 @@ Retypeset 基于 [OKLCH](https://oklch.com/) 颜色空间来定义主题配色
|
|||
|
||||
## 葱白
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
```
|
||||
light: {
|
||||
|
@ -32,8 +32,8 @@ dark: {
|
|||
|
||||
## 鸦青
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
```
|
||||
light: {
|
||||
|
@ -50,8 +50,8 @@ dark: {
|
|||
|
||||
## 墨蓝
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
```
|
||||
light: {
|
||||
|
@ -68,8 +68,8 @@ dark: {
|
|||
|
||||
## 米黄
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
```
|
||||
light: {
|
||||
|
@ -82,4 +82,4 @@ dark: {
|
|||
secondary: 'oklch(0.80 0.017 59.39)',
|
||||
background: 'oklch(0.23 0 0)',
|
||||
},
|
||||
```
|
||||
```
|
||||
|
|
|
@ -1,24 +1,100 @@
|
|||
import type { APIContext } from 'astro'
|
||||
import type { APIContext, ImageMetadata } from 'astro'
|
||||
import type { CollectionEntry } from 'astro:content'
|
||||
import type { Author } from 'feed'
|
||||
import { defaultLocale, themeConfig } from '@/config'
|
||||
import { ui } from '@/i18n/ui'
|
||||
import { memoize } from '@/utils/cache'
|
||||
import { generateDescription } from '@/utils/description'
|
||||
import { getImage } from 'astro:assets'
|
||||
import { getCollection } from 'astro:content'
|
||||
import { Feed } from 'feed'
|
||||
import MarkdownIt from 'markdown-it'
|
||||
import { parse as htmlParser } from 'node-html-parser'
|
||||
import sanitizeHtml from 'sanitize-html'
|
||||
|
||||
const markdownParser = new MarkdownIt()
|
||||
const { title, description, url, author: siteAuthor } = themeConfig.site
|
||||
const followConfig = themeConfig.seo?.follow
|
||||
|
||||
interface GenerateFeedOptions {
|
||||
lang?: string
|
||||
}
|
||||
|
||||
const markdownParser = new MarkdownIt()
|
||||
const { title, description, url, author: siteAuthor } = themeConfig.site
|
||||
const followConfig = themeConfig.seo?.follow
|
||||
|
||||
// Dynamically import all images from /src/content/posts/_images
|
||||
const imagesGlob = import.meta.glob<{ default: ImageMetadata }>(
|
||||
'/src/content/posts/_images/**/*.{jpeg,jpg,png,gif,webp}',
|
||||
)
|
||||
|
||||
/**
|
||||
* Optimize image URLs
|
||||
*
|
||||
* @param srcPath Source relative path of the image
|
||||
* @param baseUrl Base URL of the site
|
||||
* @returns Optimized full image URL or null
|
||||
*/
|
||||
const getOptimizedImageUrl = memoize(async (srcPath: string, baseUrl: string) => {
|
||||
const prefixRemoved = srcPath.replace(/^\.\.\/|^\.\//g, '')
|
||||
const rawImagePath = `/src/content/posts/${prefixRemoved}`
|
||||
const rawImageMetadata = await imagesGlob[rawImagePath]?.()?.then(res => res.default)
|
||||
|
||||
if (rawImageMetadata) {
|
||||
const processedImageData = await getImage({ src: rawImageMetadata })
|
||||
return new URL(processedImageData.src, baseUrl).toString()
|
||||
}
|
||||
|
||||
return null
|
||||
})
|
||||
|
||||
/**
|
||||
* Fix relative image paths in HTML content
|
||||
*
|
||||
* @param htmlContent HTML content string
|
||||
* @param baseUrl Base URL of the site
|
||||
* @returns Processed HTML string with all image paths converted to absolute URLs
|
||||
*/
|
||||
async function fixRelativeImagePaths(htmlContent: string, baseUrl: string): Promise<string> {
|
||||
const htmlDoc = htmlParser(htmlContent)
|
||||
const images = htmlDoc.querySelectorAll('img')
|
||||
const imagePromises = []
|
||||
|
||||
for (const img of images) {
|
||||
const src = img.getAttribute('src')
|
||||
|
||||
if (!src)
|
||||
continue
|
||||
|
||||
imagePromises.push((async () => {
|
||||
try {
|
||||
// Process images from src/content/posts/_images directory
|
||||
if (src.startsWith('./') || src.startsWith('../')) {
|
||||
const optimizedImageUrl = await getOptimizedImageUrl(src, baseUrl)
|
||||
|
||||
if (optimizedImageUrl) {
|
||||
img.setAttribute('src', optimizedImageUrl)
|
||||
}
|
||||
}
|
||||
// Process images from public/images directory
|
||||
else if (src.startsWith('/images')) {
|
||||
const publicImageUrl = new URL(src, baseUrl).toString()
|
||||
img.setAttribute('src', publicImageUrl)
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
console.warn(`Failed to process image in RSS feed: ${src}`, error)
|
||||
}
|
||||
})())
|
||||
}
|
||||
|
||||
await Promise.all(imagePromises)
|
||||
return htmlDoc.toString()
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate post URL with language prefix and abbrlink/slug
|
||||
*
|
||||
* @param post The post collection entry
|
||||
* @param baseUrl Base URL of the site
|
||||
* @returns The fully formed URL for the post
|
||||
*/
|
||||
function generatePostUrl(post: CollectionEntry<'posts'>, baseUrl: string): string {
|
||||
const needsLangPrefix = post.data.lang !== defaultLocale && post.data.lang !== ''
|
||||
|
@ -30,6 +106,10 @@ function generatePostUrl(post: CollectionEntry<'posts'>, baseUrl: string): strin
|
|||
|
||||
/**
|
||||
* Generate a feed object supporting both RSS and Atom formats
|
||||
*
|
||||
* @param options Feed generation options
|
||||
* @param options.lang Optional language code
|
||||
* @returns A Feed instance ready for RSS or Atom output
|
||||
*/
|
||||
export async function generateFeed({ lang }: GenerateFeedOptions = {}) {
|
||||
const currentUI = ui[lang as keyof typeof ui] || ui[defaultLocale as keyof typeof ui]
|
||||
|
@ -66,24 +146,28 @@ export async function generateFeed({ lang }: GenerateFeedOptions = {}) {
|
|||
(!data.draft && (data.lang === lang || data.lang === '' || (lang === undefined && data.lang === defaultLocale))),
|
||||
)
|
||||
|
||||
// Sort posts by published date in descending order
|
||||
const sortedPosts = [...posts].sort((a, b) =>
|
||||
new Date(b.data.published).getTime() - new Date(a.data.published).getTime(),
|
||||
)
|
||||
|
||||
// Limit to the latest 25 posts
|
||||
const limitedPosts = sortedPosts.slice(0, 25)
|
||||
// Sort posts by published date in descending order and limit to the latest 25
|
||||
const limitedPosts = [...posts]
|
||||
.sort((a, b) => new Date(b.data.published).getTime() - new Date(a.data.published).getTime())
|
||||
.slice(0, 25)
|
||||
|
||||
// Add posts to feed
|
||||
for (const post of limitedPosts) {
|
||||
const postLink = generatePostUrl(post, url)
|
||||
|
||||
// Optimize content processing
|
||||
const postContent = post.body
|
||||
? sanitizeHtml(markdownParser.render(post.body), {
|
||||
allowedTags: sanitizeHtml.defaults.allowedTags.concat(['img']),
|
||||
})
|
||||
? sanitizeHtml(
|
||||
await fixRelativeImagePaths(markdownParser.render(post.body), url),
|
||||
{ allowedTags: sanitizeHtml.defaults.allowedTags.concat(['img']) },
|
||||
)
|
||||
: ''
|
||||
|
||||
// publishDate -> Atom:<published>, RSS:<pubDate>
|
||||
const publishDate = new Date(post.data.published)
|
||||
// updateDate -> Atom:<updated>, RSS has no update tag
|
||||
const updateDate = post.data.updated ? new Date(post.data.updated) : publishDate
|
||||
|
||||
feed.addItem({
|
||||
title: post.data.title,
|
||||
id: postLink,
|
||||
|
@ -91,10 +175,8 @@ export async function generateFeed({ lang }: GenerateFeedOptions = {}) {
|
|||
description: generateDescription(post, 'feed'),
|
||||
content: postContent,
|
||||
author: [author],
|
||||
// published -> Atom:<published>, RSS:<pubDate>
|
||||
published: new Date(post.data.published),
|
||||
// date -> Atom:<updated>, RSS has no update tag
|
||||
date: post.data.updated ? new Date(post.data.updated) : new Date(post.data.published),
|
||||
published: publishDate,
|
||||
date: updateDate,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -114,6 +196,9 @@ export async function generateFeed({ lang }: GenerateFeedOptions = {}) {
|
|||
|
||||
/**
|
||||
* Generate RSS 2.0 format feed
|
||||
*
|
||||
* @param context Astro API context containing request params
|
||||
* @returns Response object with RSS XML content
|
||||
*/
|
||||
export async function generateRSS(context: APIContext) {
|
||||
const feed = await generateFeed({
|
||||
|
@ -135,6 +220,9 @@ export async function generateRSS(context: APIContext) {
|
|||
|
||||
/**
|
||||
* Generate Atom 1.0 format feed
|
||||
*
|
||||
* @param context Astro API context containing request params
|
||||
* @returns Response object with Atom XML content
|
||||
*/
|
||||
export async function generateAtom(context: APIContext) {
|
||||
const feed = await generateFeed({
|
||||
|
|