diff --git a/astro.config.mjs b/astro.config.mjs index 1e42894..c95248b 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -2,14 +2,10 @@ import { defineConfig } from 'astro/config' import node from '@astrojs/node' - import svelte from '@astrojs/svelte' - -import vue from '@astrojs/vue'; - -import react from '@astrojs/react'; - -import icon from 'astro-icon'; +import vue from '@astrojs/vue' +import react from '@astrojs/react' +import icon from 'astro-icon' // https://astro.build/config export default defineConfig({ @@ -18,4 +14,5 @@ export default defineConfig({ }), integrations: [svelte(), vue(), react(), icon()], -}) \ No newline at end of file + site: 'https://passthem.top', +}) diff --git a/package-lock.json b/package-lock.json index bbae52a..9842e5e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "dependencies": { "@astrojs/node": "^10.0.4", "@astrojs/react": "^5.0.2", + "@astrojs/rss": "^4.0.18", "@astrojs/svelte": "^8.0.4", "@astrojs/vue": "^6.0.1", "@iconify-json/mdi": "^1.2.3", @@ -155,6 +156,17 @@ "react-dom": "^17.0.2 || ^18.0.0 || ^19.0.0" } }, + "node_modules/@astrojs/rss": { + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/@astrojs/rss/-/rss-4.0.18.tgz", + "integrity": "sha512-wc5DwKlbTEdgVAWnHy8krFTeQ42t1v/DJqeq5HtulYK3FYHE4krtRGjoyhS3eXXgfdV6Raoz2RU3wrMTFAitRg==", + "license": "MIT", + "dependencies": { + "fast-xml-parser": "^5.5.7", + "piccolore": "^0.1.3", + "zod": "^4.3.6" + } + }, "node_modules/@astrojs/svelte": { "version": "8.0.4", "resolved": "https://registry.npmjs.org/@astrojs/svelte/-/svelte-8.0.4.tgz", @@ -4752,6 +4764,41 @@ "dev": true, "license": "MIT" }, + "node_modules/fast-xml-builder": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/fast-xml-builder/-/fast-xml-builder-1.1.4.tgz", + "integrity": "sha512-f2jhpN4Eccy0/Uz9csxh3Nu6q4ErKxf0XIsasomfOihuSUa3/xw6w8dnOtCDgEItQFJG8KyXPzQXzcODDrrbOg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "dependencies": { + "path-expression-matcher": "^1.1.3" + } + }, + "node_modules/fast-xml-parser": { + "version": "5.5.9", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.5.9.tgz", + "integrity": "sha512-jldvxr1MC6rtiZKgrFnDSvT8xuH+eJqxqOBThUVjYrxssYTo1avZLGql5l0a0BAERR01CadYzZ83kVEkbyDg+g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "dependencies": { + "fast-xml-builder": "^1.1.4", + "path-expression-matcher": "^1.2.0", + "strnum": "^2.2.2" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, "node_modules/fastq": { "version": "1.20.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", @@ -7085,6 +7132,21 @@ "node": ">=8" } }, + "node_modules/path-expression-matcher": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/path-expression-matcher/-/path-expression-matcher-1.2.0.tgz", + "integrity": "sha512-DwmPWeFn+tq7TiyJ2CxezCAirXjFxvaiD03npak3cRjlP9+OjTmSy1EpIrEbh+l6JgUundniloMLDQ/6VTdhLQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -7960,6 +8022,18 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/strnum": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.2.2.tgz", + "integrity": "sha512-DnR90I+jtXNSTXWdwrEy9FakW7UX+qUZg28gj5fk2vxxl7uS/3bpI4fjFYVmdK9etptYBPNkpahuQnEwhwECqA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT" + }, "node_modules/suf-log": { "version": "2.5.3", "resolved": "https://registry.npmjs.org/suf-log/-/suf-log-2.5.3.tgz", diff --git a/package.json b/package.json index 2ded07c..01c04a5 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "dependencies": { "@astrojs/node": "^10.0.4", "@astrojs/react": "^5.0.2", + "@astrojs/rss": "^4.0.18", "@astrojs/svelte": "^8.0.4", "@astrojs/vue": "^6.0.1", "@iconify-json/mdi": "^1.2.3", diff --git a/src/layout/BaseLayout.astro b/src/layout/BaseLayout.astro index 31bd852..05187d1 100644 --- a/src/layout/BaseLayout.astro +++ b/src/layout/BaseLayout.astro @@ -17,6 +17,12 @@ const { title = '小帕的小窝' } = Astro.props + {title} diff --git a/src/lib/apis/legacy/blog.ts b/src/lib/apis/legacy/blog.ts index e6f4448..b484619 100644 --- a/src/lib/apis/legacy/blog.ts +++ b/src/lib/apis/legacy/blog.ts @@ -1,5 +1,20 @@ import { legacyClient } from '../clients' +export type ListBlogItemType = { + id: number + title: string + + /** ISO8601 */ + created_at: string + + /** ISO8601 */ + updated_at: string + + featured_image: null | { + image_url: string + } +} + export const listBlogs = async ({ page = 1, limit = 20, @@ -8,13 +23,7 @@ export const listBlogs = async ({ limit?: number }) => { const resp = await legacyClient.post('/v1/blog/list', { page, limit }) - return resp.data.data as { - id: number - title: string - featured_image: null | { - image_url: string - } - }[] + return resp.data.data as ListBlogItemType[] } export const getBlog: ( diff --git a/src/pages/rss.xml.ts b/src/pages/rss.xml.ts new file mode 100644 index 0000000..ccee1e1 --- /dev/null +++ b/src/pages/rss.xml.ts @@ -0,0 +1,32 @@ +import rss from '@astrojs/rss' +import type { APIRoute } from 'astro' +import { listBlogs, type ListBlogItemType } from '../lib/apis/legacy/blog' + +export const GET = (async (context) => { + let blogs: ListBlogItemType[] = [] + let pid = 0 + + let newBlogs = [] + + while (pid == 0 || newBlogs.length > 0) { + newBlogs = await listBlogs({ + page: ++pid, + limit: 100, + }) + blogs = [...blogs, ...newBlogs] + } + + const site = context.site || 'https://passthem.top' + + return rss({ + title: '小帕的小窝', + description: '小帕和他朋友们的博客', + site, + items: blogs.map((blog) => ({ + title: blog.title, + link: `${site}/blogs/${blog.id}`, + pubDate: new Date(blog.created_at), + })), + customData: `zh-hans`, + }) +}) satisfies APIRoute