diff --git a/package.json b/package.json index 6afc4fd..5ddf652 100644 --- a/package.json +++ b/package.json @@ -46,6 +46,7 @@ "@types/unist": "^3.0.3", "astro": "^5.18.1", "astro-icon": "^1.1.5", + "markdown-it": "14.1.1", "marked": "^17.0.4", "marked-shiki": "^1.2.1", "mdast-util-to-string": "^4.0.0", @@ -64,6 +65,7 @@ "@eslint-react/eslint-plugin": "^2.13.0", "@tailwindcss/forms": "^0.5.11", "@tailwindcss/typography": "^0.5.19", + "@types/markdown-it": "14.1.2", "eslint": "^10.0.3", "eslint-config-prettier": "^10.1.8", "eslint-plugin-astro": "^1.6.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5718917..de9c553 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -65,6 +65,9 @@ importers: astro-icon: specifier: ^1.1.5 version: 1.1.5 + markdown-it: + specifier: 14.1.1 + version: 14.1.1 marked: specifier: ^17.0.4 version: 17.0.4 @@ -114,6 +117,9 @@ importers: '@tailwindcss/typography': specifier: ^0.5.19 version: 0.5.19(tailwindcss@4.2.1) + '@types/markdown-it': + specifier: 14.1.2 + version: 14.1.2 eslint: specifier: ^10.0.3 version: 10.0.3(jiti@2.6.1) @@ -2132,9 +2138,18 @@ packages: '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + '@types/linkify-it@5.0.0': + resolution: {integrity: sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==} + + '@types/markdown-it@14.1.2': + resolution: {integrity: sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==} + '@types/mdast@4.0.4': resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==} + '@types/mdurl@2.0.0': + resolution: {integrity: sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==} + '@types/ms@2.1.0': resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} @@ -3955,6 +3970,9 @@ packages: lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + linkify-it@5.0.0: + resolution: {integrity: sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==} + lit-element@4.2.2: resolution: {integrity: sha512-aFKhNToWxoyhkNDmWZwEva2SlQia+jfG0fjIWV//YeTaWrVnOxD89dPKfigCUspXFmjzOEUQpOkejH5Ly6sG0w==} @@ -4028,6 +4046,10 @@ packages: resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} engines: {node: '>=8'} + markdown-it@14.1.1: + resolution: {integrity: sha512-BuU2qnTti9YKgK5N+IeMubp14ZUKUUw7yeJbkjtosvHiP0AZ5c8IAgEMk79D0eC8F23r4Ac/q8cAIFdm2FtyoA==} + hasBin: true + markdown-table@3.0.4: resolution: {integrity: sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==} @@ -4101,6 +4123,9 @@ packages: mdn-data@2.27.1: resolution: {integrity: sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==} + mdurl@2.0.0: + resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==} + merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} @@ -4843,6 +4868,10 @@ packages: pump@3.0.4: resolution: {integrity: sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==} + punycode.js@2.3.1: + resolution: {integrity: sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==} + engines: {node: '>=6'} + punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} @@ -5478,6 +5507,9 @@ packages: engines: {node: '>=14.17'} hasBin: true + uc.micro@2.1.0: + resolution: {integrity: sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==} + ufo@1.6.3: resolution: {integrity: sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==} @@ -7982,10 +8014,19 @@ snapshots: '@types/json-schema@7.0.15': {} + '@types/linkify-it@5.0.0': {} + + '@types/markdown-it@14.1.2': + dependencies: + '@types/linkify-it': 5.0.0 + '@types/mdurl': 2.0.0 + '@types/mdast@4.0.4': dependencies: '@types/unist': 3.0.3 + '@types/mdurl@2.0.0': {} + '@types/ms@2.1.0': {} '@types/nlcst@2.0.3': @@ -10356,6 +10397,10 @@ snapshots: lines-and-columns@1.2.4: {} + linkify-it@5.0.0: + dependencies: + uc.micro: 2.1.0 + lit-element@4.2.2: dependencies: '@lit-labs/ssr-dom-shim': 1.5.1 @@ -10434,6 +10479,15 @@ snapshots: dependencies: semver: 6.3.1 + markdown-it@14.1.1: + dependencies: + argparse: 2.0.1 + entities: 4.5.0 + linkify-it: 5.0.0 + mdurl: 2.0.0 + punycode.js: 2.3.1 + uc.micro: 2.1.0 + markdown-table@3.0.4: {} marked-shiki@1.2.1(marked@17.0.4)(shiki@4.0.2): @@ -10580,6 +10634,8 @@ snapshots: mdn-data@2.27.1: {} + mdurl@2.0.0: {} + merge-stream@2.0.0: {} merge2@1.4.1: {} @@ -11427,6 +11483,8 @@ snapshots: end-of-stream: 1.4.5 once: 1.4.0 + punycode.js@2.3.1: {} + punycode@2.3.1: {} quansync@0.2.11: {} @@ -12253,6 +12311,8 @@ snapshots: typescript@5.9.3: {} + uc.micro@2.1.0: {} + ufo@1.6.3: {} ultrahtml@1.6.0: {} diff --git a/src/pages/rss.xml.ts b/src/pages/rss.xml.ts index 2af07e7..3928947 100644 --- a/src/pages/rss.xml.ts +++ b/src/pages/rss.xml.ts @@ -4,6 +4,8 @@ import rss, { type RSSFeedItem } from '@astrojs/rss'; import type { APIContext } from 'astro'; import { transform, walk } from 'ultrahtml'; import sanitize from 'ultrahtml/transformers/sanitize'; +import MarkdownIt from 'markdown-it'; + import { readItems, readSingleton } from '@directus/sdk'; import directus from '@lib/directus'; @@ -12,6 +14,8 @@ const global = await directus.request(readSingleton('site_global')); export async function GET(context: APIContext) { let baseUrl = context.site?.href || global.site_url; + const parser = new MarkdownIt(); + if (baseUrl.at(-1) === '/') { baseUrl = baseUrl.slice(0, -1); } @@ -26,7 +30,7 @@ export async function GET(context: APIContext) { const feedItems: RSSFeedItem[] = []; for (const post of posts) { - const content = await transform(post.content.replace(/^/, ''), [ + const content = await transform(parser.render(post.content), [ async (node) => { await walk(node, (node) => { if (node.name === 'a' && node.attributes.href?.startsWith('/')) {