fix rss images
This commit is contained in:
parent
ecca2bf614
commit
fbd1b61458
@ -28,6 +28,7 @@
|
||||
"fast-glob": "^3.3.2",
|
||||
"lucide-react": "^0.396.0",
|
||||
"markdown-it": "^14.1.0",
|
||||
"node-html-parser": "^6.1.13",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-markdown": "^9.0.1",
|
||||
@ -41,6 +42,8 @@
|
||||
"typescript": "^5.5.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/markdown-it": "^14.1.1",
|
||||
"@types/sanitize-html": "^2.11.0",
|
||||
"pocketbase": "^0.21.3"
|
||||
}
|
||||
}
|
||||
|
77
pnpm-lock.yaml
generated
77
pnpm-lock.yaml
generated
@ -62,6 +62,9 @@ importers:
|
||||
markdown-it:
|
||||
specifier: ^14.1.0
|
||||
version: 14.1.0
|
||||
node-html-parser:
|
||||
specifier: ^6.1.13
|
||||
version: 6.1.13
|
||||
react:
|
||||
specifier: ^18.3.1
|
||||
version: 18.3.1
|
||||
@ -96,6 +99,12 @@ importers:
|
||||
specifier: ^5.5.2
|
||||
version: 5.5.2
|
||||
devDependencies:
|
||||
'@types/markdown-it':
|
||||
specifier: ^14.1.1
|
||||
version: 14.1.1
|
||||
'@types/sanitize-html':
|
||||
specifier: ^2.11.0
|
||||
version: 2.11.0
|
||||
pocketbase:
|
||||
specifier: ^0.21.3
|
||||
version: 0.21.3
|
||||
@ -932,9 +941,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.1':
|
||||
resolution: {integrity: sha512-4NpsnpYl2Gt1ljyBGrKMxFYAYvpqbnnkgP/i/g+NLpjEUa3obn1XJCur9YbEXKDAkaXqsR1LbDnGEJ0MmKFxfg==}
|
||||
|
||||
'@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==}
|
||||
|
||||
@ -956,6 +974,9 @@ packages:
|
||||
'@types/react@18.3.3':
|
||||
resolution: {integrity: sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==}
|
||||
|
||||
'@types/sanitize-html@2.11.0':
|
||||
resolution: {integrity: sha512-7oxPGNQHXLHE48r/r/qjn7q0hlrs3kL7oZnGj0Wf/h9tj/6ibFyRkNbsDxaBBZ4XUZ0Dx5LGCyDJ04ytSofacQ==}
|
||||
|
||||
'@types/unist@2.0.10':
|
||||
resolution: {integrity: sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==}
|
||||
|
||||
@ -1139,6 +1160,9 @@ packages:
|
||||
bindings@1.5.0:
|
||||
resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==}
|
||||
|
||||
boolbase@1.0.0:
|
||||
resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==}
|
||||
|
||||
boxen@7.1.1:
|
||||
resolution: {integrity: sha512-2hCgjEmP8YLWQ130n2FerGv7rYpfBmnmp9Uy2Le1vge6X3gZIfSmEzP5QTDElFxcvVcXlEn8Aq6MU/PZygIOog==}
|
||||
engines: {node: '>=14.16'}
|
||||
@ -1285,6 +1309,13 @@ packages:
|
||||
resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==}
|
||||
engines: {node: '>= 8'}
|
||||
|
||||
css-select@5.1.0:
|
||||
resolution: {integrity: sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==}
|
||||
|
||||
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'}
|
||||
@ -1610,6 +1641,10 @@ packages:
|
||||
hastscript@8.0.0:
|
||||
resolution: {integrity: sha512-dMOtzCEd3ABUeSIISmrETiKuyydk1w0pa+gE/uormcTpSYuaNJPbX1NU3JLyscSLjwAQM8bWMhhIlnCqnRvDTw==}
|
||||
|
||||
he@1.2.0:
|
||||
resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==}
|
||||
hasBin: true
|
||||
|
||||
html-escaper@3.0.3:
|
||||
resolution: {integrity: sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ==}
|
||||
|
||||
@ -2106,6 +2141,9 @@ packages:
|
||||
resolution: {integrity: sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw==}
|
||||
hasBin: true
|
||||
|
||||
node-html-parser@6.1.13:
|
||||
resolution: {integrity: sha512-qIsTMOY4C/dAa5Q5vsobRpOOvPfC4pB61UVW2uSwZNUp0QU/jCekTal1vMmbO0DgdHeLUJpv/ARmDqErVxA3Sg==}
|
||||
|
||||
node-releases@2.0.14:
|
||||
resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==}
|
||||
|
||||
@ -2130,6 +2168,9 @@ packages:
|
||||
resolution: {integrity: sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==}
|
||||
deprecated: This package is no longer supported.
|
||||
|
||||
nth-check@2.1.1:
|
||||
resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==}
|
||||
|
||||
object-assign@4.1.1:
|
||||
resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@ -3870,10 +3911,19 @@ snapshots:
|
||||
dependencies:
|
||||
'@types/unist': 3.0.2
|
||||
|
||||
'@types/linkify-it@5.0.0': {}
|
||||
|
||||
'@types/markdown-it@14.1.1':
|
||||
dependencies:
|
||||
'@types/linkify-it': 5.0.0
|
||||
'@types/mdurl': 2.0.0
|
||||
|
||||
'@types/mdast@4.0.4':
|
||||
dependencies:
|
||||
'@types/unist': 3.0.2
|
||||
|
||||
'@types/mdurl@2.0.0': {}
|
||||
|
||||
'@types/mdx@2.0.13': {}
|
||||
|
||||
'@types/ms@0.7.34': {}
|
||||
@ -3897,6 +3947,10 @@ snapshots:
|
||||
'@types/prop-types': 15.7.12
|
||||
csstype: 3.1.3
|
||||
|
||||
'@types/sanitize-html@2.11.0':
|
||||
dependencies:
|
||||
htmlparser2: 8.0.2
|
||||
|
||||
'@types/unist@2.0.10': {}
|
||||
|
||||
'@types/unist@3.0.2': {}
|
||||
@ -4176,6 +4230,8 @@ snapshots:
|
||||
dependencies:
|
||||
file-uri-to-path: 1.0.0
|
||||
|
||||
boolbase@1.0.0: {}
|
||||
|
||||
boxen@7.1.1:
|
||||
dependencies:
|
||||
ansi-align: 3.0.1
|
||||
@ -4315,6 +4371,16 @@ snapshots:
|
||||
shebang-command: 2.0.0
|
||||
which: 2.0.2
|
||||
|
||||
css-select@5.1.0:
|
||||
dependencies:
|
||||
boolbase: 1.0.0
|
||||
css-what: 6.1.0
|
||||
domhandler: 5.0.3
|
||||
domutils: 3.1.0
|
||||
nth-check: 2.1.1
|
||||
|
||||
css-what@6.1.0: {}
|
||||
|
||||
cssesc@3.0.0: {}
|
||||
|
||||
csstype@3.1.3: {}
|
||||
@ -4741,6 +4807,8 @@ snapshots:
|
||||
property-information: 6.5.0
|
||||
space-separated-tokens: 2.0.2
|
||||
|
||||
he@1.2.0: {}
|
||||
|
||||
html-escaper@3.0.3: {}
|
||||
|
||||
html-url-attributes@3.0.0: {}
|
||||
@ -5448,6 +5516,11 @@ snapshots:
|
||||
|
||||
node-gyp-build@4.8.1: {}
|
||||
|
||||
node-html-parser@6.1.13:
|
||||
dependencies:
|
||||
css-select: 5.1.0
|
||||
he: 1.2.0
|
||||
|
||||
node-releases@2.0.14: {}
|
||||
|
||||
nopt@5.0.0:
|
||||
@ -5469,6 +5542,10 @@ snapshots:
|
||||
gauge: 3.0.2
|
||||
set-blocking: 2.0.0
|
||||
|
||||
nth-check@2.1.1:
|
||||
dependencies:
|
||||
boolbase: 1.0.0
|
||||
|
||||
object-assign@4.1.1: {}
|
||||
|
||||
object-hash@3.0.0: {}
|
||||
|
@ -106,4 +106,4 @@ overwhelming myself, I'll keep my **ambitions simple**, but **constant**.
|
||||
|
||||
### Happy holidays!
|
||||
|
||||

|
||||

|
||||
|
@ -1,50 +0,0 @@
|
||||
import rss from "@astrojs/rss";
|
||||
import { getCollection } from "astro:content";
|
||||
import sanitizeHtml from "sanitize-html";
|
||||
import MarkdownIt from "markdown-it";
|
||||
const parser = new MarkdownIt();
|
||||
|
||||
export async function GET(context) {
|
||||
const blog = await getCollection(
|
||||
"blog",
|
||||
({ data }) => data.draft !== true && data.rss === true,
|
||||
);
|
||||
const portfolio = await getCollection(
|
||||
"portfolio",
|
||||
({ data }) => data.draft !== true && data.rss === true,
|
||||
);
|
||||
|
||||
const blogItems = blog.map((post) => ({
|
||||
title: post.data.title,
|
||||
pubDate: post.data.date,
|
||||
description: post.data.description,
|
||||
tags: post.data.tags,
|
||||
author: post.data.author,
|
||||
link: `/blog/${post.slug}/`,
|
||||
content: sanitizeHtml(parser.render(post.body), {
|
||||
allowedTags: sanitizeHtml.defaults.allowedTags.concat(["img"]),
|
||||
}),
|
||||
}));
|
||||
|
||||
const portfolioItems = portfolio.map((project) => ({
|
||||
title: project.data.title,
|
||||
pubDate: project.data.date,
|
||||
description: project.data.description,
|
||||
tags: project.data.tags,
|
||||
author: project.data.author,
|
||||
link: `/portfolio/${project.slug}/`,
|
||||
content: sanitizeHtml(parser.render(project.body), {
|
||||
allowedTags: sanitizeHtml.defaults.allowedTags.concat(["img"]),
|
||||
}),
|
||||
}));
|
||||
|
||||
const items = [...blogItems, ...portfolioItems];
|
||||
|
||||
return rss({
|
||||
title: "juancmandev",
|
||||
description: "Welcome to my domain, stranger.",
|
||||
customData: `<language>en-us</language><lastBuildDate>${new Date()}</lastBuildDate>`,
|
||||
site: context.site,
|
||||
items,
|
||||
});
|
||||
}
|
125
src/pages/rss.xml.ts
Normal file
125
src/pages/rss.xml.ts
Normal file
@ -0,0 +1,125 @@
|
||||
import rss from "@astrojs/rss";
|
||||
import type { RSSFeedItem } from "@astrojs/rss";
|
||||
import { getCollection } from "astro:content";
|
||||
import sanitizeHtml from "sanitize-html";
|
||||
import MarkdownIt from "markdown-it";
|
||||
import { parse as htmlParser } from "node-html-parser";
|
||||
import { getImage } from "astro:assets";
|
||||
import type { ImageMetadata } from "astro";
|
||||
|
||||
const markdownParser = new MarkdownIt();
|
||||
|
||||
const imagesBlog = import.meta.glob<{ default: ImageMetadata }>(
|
||||
"/src/assets/blog/**/**/*.{jpeg,jpg,png,gif,webp}",
|
||||
);
|
||||
const imagesPortfolio = import.meta.glob<{ default: ImageMetadata }>(
|
||||
"/src/assets/portfolio/**/**/*.{jpeg,jpg,png,gif,webp}",
|
||||
);
|
||||
|
||||
export async function GET(context: any) {
|
||||
const items: RSSFeedItem[] = [];
|
||||
|
||||
const blog = await getCollection(
|
||||
"blog",
|
||||
({ data }) => data.draft !== true && data.rss === true,
|
||||
);
|
||||
const portfolio = await getCollection(
|
||||
"portfolio",
|
||||
({ data }) => data.draft !== true && data.rss === true,
|
||||
);
|
||||
|
||||
for await (const post of blog) {
|
||||
const body = markdownParser.render(post.body);
|
||||
const html = htmlParser.parse(body);
|
||||
const images = html.querySelectorAll("img");
|
||||
|
||||
for await (const img of images) {
|
||||
const src = img.getAttribute("src")!;
|
||||
console.log(src);
|
||||
|
||||
if (src.startsWith("@/")) {
|
||||
const prefixRemoved = src.replace("@/", "");
|
||||
const imagePathPrefix = `/src/${prefixRemoved}`;
|
||||
const imagePath = await imagesBlog[imagePathPrefix]?.()?.then(
|
||||
(res: any) => res.default,
|
||||
);
|
||||
|
||||
if (imagePath) {
|
||||
const optimizedImg = await getImage({ src: imagePath });
|
||||
img.setAttribute(
|
||||
"src",
|
||||
context.site + optimizedImg.src.replace("/", ""),
|
||||
);
|
||||
}
|
||||
} else if (src.startsWith("/images")) {
|
||||
img.setAttribute("src", context.site + src.replace("/", ""));
|
||||
} else {
|
||||
throw Error("src unknown");
|
||||
}
|
||||
}
|
||||
|
||||
items.push({
|
||||
title: post.data.title,
|
||||
pubDate: post.data.date,
|
||||
description: post.data.description,
|
||||
author: post.data.author,
|
||||
link: `/blog/${post.slug}/`,
|
||||
content: sanitizeHtml(html.toString(), {
|
||||
allowedTags: sanitizeHtml.defaults.allowedTags.concat(["img"]),
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
for await (const project of portfolio) {
|
||||
const body = markdownParser.render(project.body);
|
||||
const html = htmlParser.parse(body);
|
||||
const images = html.querySelectorAll("img");
|
||||
|
||||
for await (const img of images) {
|
||||
const src = img.getAttribute("src")!;
|
||||
|
||||
if (src.startsWith("@/")) {
|
||||
const prefixRemoved = src.replace("@/", "");
|
||||
const imagePathPrefix = `/src/${prefixRemoved}`;
|
||||
const imagePath = await imagesPortfolio[imagePathPrefix]?.()?.then(
|
||||
(res: any) => res.default,
|
||||
);
|
||||
|
||||
if (imagePath) {
|
||||
const optimizedImg = await getImage({ src: imagePath });
|
||||
img.setAttribute(
|
||||
"src",
|
||||
context.site + optimizedImg.src.replace("/", ""),
|
||||
);
|
||||
}
|
||||
} else if (src.startsWith("/images")) {
|
||||
// images starting with `/images/` is the public dir
|
||||
img.setAttribute("src", context.site + src.replace("/", ""));
|
||||
} else {
|
||||
throw Error("src unknown");
|
||||
}
|
||||
}
|
||||
|
||||
items.push({
|
||||
title: project.data.title,
|
||||
pubDate: project.data.date,
|
||||
description: project.data.description,
|
||||
author: project.data.author,
|
||||
link: `/portfolio/${project.slug}/`,
|
||||
content: sanitizeHtml(html.toString(), {
|
||||
allowedTags: sanitizeHtml.defaults.allowedTags.concat(["img"]),
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
console.log(items);
|
||||
|
||||
return rss({
|
||||
title: "juancmandev",
|
||||
description: "Welcome to my domain, stranger.",
|
||||
customData: `<language>en-us</language>`,
|
||||
site: context.site,
|
||||
items,
|
||||
trailingSlash: false,
|
||||
});
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user