diff --git a/src/layouts/BlogLayout.astro b/src/layouts/BlogLayout.astro
index 504c5db..ed7baab 100644
--- a/src/layouts/BlogLayout.astro
+++ b/src/layouts/BlogLayout.astro
@@ -37,6 +37,18 @@ const authorX = author?.links?.find(l => l.name === 'X')?.id;
+
+
+
]+src=["']([^"']+)["'][^>]*>/g;
+ const mdImageRegex = /!\[[^\]]*\]\(([^)]+)\)/g;
+
+ const imgMatches = [...body.matchAll(imgTagRegex)];
+ const mdMatches = [...body.matchAll(mdImageRegex)];
+ const allUrls = [
+ ...imgMatches.map(match => match[1]),
+ ...mdMatches.map(match => match[1]),
+ ];
+
+ if (allUrls.length === 0) return null;
+
+ for (const url of allUrls) {
+ const isRelative = url.startsWith('/');
+ let fullUrl = url;
+ const ext = fullUrl.split('?')[0].split('.').pop()?.toLowerCase();
+ let type;
+
+ switch (ext) {
+ case 'jpg':
+ case 'jpeg':
+ type = 'image/jpeg';
+ break;
+ case 'png':
+ type = 'image/png';
+ break;
+ case 'gif':
+ type = 'image/gif';
+ break;
+ case 'webp':
+ type = 'image/webp';
+ break;
+ case 'svg':
+ type = 'image/svg+xml';
+ break;
+ default:
+ continue;
+ }
+
+ const imageObj = {
+ url: fullUrl,
+ type: type,
+ length: 0,
+ };
+
+ if (isRelative) {
+ relativeImages.push(imageObj);
+ } else {
+ absoluteImages.push(imageObj);
+ }
+ }
+
+ const images = [...relativeImages, ...absoluteImages];
+ return images.length > 0 ? images : null;
+}
+
+async function getFeed(
+ siteUrl: string,
+ maxItems?: number,
+ filter?: { tag?: string; author?: string }
+) {
+ let blogs = await getCollection('blog');
+ if (filter) {
+ if (filter.author) {
+ blogs = blogs.filter(blog => blog.data.author === filter.author);
+ }
+ if (filter.tag) {
+ blogs = blogs.filter(blog => blog.data.tags?.includes(filter.tag!));
+ }
+ }
+ blogs = blogs
+ .sort(
+ (a, b) =>
+ new Date(b.data.pubDate).getTime() - new Date(a.data.pubDate).getTime()
+ )
+ .slice(0, maxItems || 50);
+ let title = siteInfo.appName;
+ if (filter?.author) {
+ title += ` - Author: ${filter.author}`;
+ }
+ if (filter?.tag) {
+ title += ` - Tag: ${filter.tag}`;
+ }
+ const rssOptions: RSSOptions = {
+ title: title,
+ description: siteInfo.description,
+ site: siteUrl,
+ items: blogs.map(blog => ({
+ title: blog.data.title,
+ pubDate: new Date(blog.data.pubDate),
+ description: blog.data.description,
+ link: blog.data.externalUrl
+ ? blog.data.externalUrl
+ : `/blog/${blog.slug}/`,
+ categories: blog.data.tags,
+ enclosure: extractImageUrl(blog.body)?.[0] || {
+ url: `/og/${blog.slug}.png`,
+ type: 'image/png',
+ length: 0,
+ },
+ })),
+ customData: `ja-jp`,
+ };
+ return rssOptions;
+}
+
+export { getFeed };
diff --git a/src/pages/[author]/rss.xml.js b/src/pages/[author]/rss.xml.js
index 8300acf..f16dc3a 100644
--- a/src/pages/[author]/rss.xml.js
+++ b/src/pages/[author]/rss.xml.js
@@ -1,6 +1,5 @@
import rss from '@astrojs/rss';
-import { getCollection } from 'astro:content';
-import siteInfo from '@/data/siteInfo';
+import { getFeed } from '@/lib/getFeed';
import member from '@/data/member';
export async function getStaticPaths() {
@@ -13,21 +12,7 @@ export async function getStaticPaths() {
export async function GET(context) {
const { author } = context.params;
- const blogs = await getCollection('blog');
+ const feedOption = await getFeed(context.site, 50, { author });
- const filteredBlogs = blogs.filter(blog => blog.data.author === author);
-
- return rss({
- title: `${siteInfo.appName} - ${author}`,
- description: `${author}の記事一覧`,
- site: context.site,
- items: filteredBlogs.map(blog => ({
- title: blog.data.title,
- pubDate: blog.data.pubDate,
- description: blog.data.description,
- customData: blog.data.customData,
- link: `/blog/${blog.slug}/`,
- })),
- customData: 'ja-jp',
- });
+ return rss(feedOption);
}
diff --git a/src/pages/rss.xml.js b/src/pages/rss.xml.js
index d691c62..018bc0f 100644
--- a/src/pages/rss.xml.js
+++ b/src/pages/rss.xml.js
@@ -1,20 +1,7 @@
import rss from '@astrojs/rss';
-import { getCollection } from 'astro:content';
-import siteInfo from '@/data/siteInfo';
+import { getFeed } from '@/lib/getFeed';
export async function GET(context) {
- const blogs = await getCollection('blog');
- return rss({
- title: siteInfo.appName,
- description: siteInfo.description,
- site: context.site,
- items: blogs.map(blog => ({
- title: blog.data.title,
- pubDate: blog.data.pubDate,
- description: blog.data.description,
- customData: blog.data.customData,
- link: `/blog/${blog.slug}/`,
- })),
- customData: `ja-jp`,
- });
+ const feedOption = await getFeed(context.site);
+ return rss(feedOption);
}