Refactor markdown processing in posts API; replace unified with marked and DOMPurify for improved HTML sanitization and performance.

This commit is contained in:
rattatwinko
2025-06-17 17:44:01 +02:00
parent 528a684699
commit ab15c7e20e

View File

@@ -2,13 +2,9 @@ import { NextResponse } from 'next/server';
import fs from 'fs'; import fs from 'fs';
import path from 'path'; import path from 'path';
import matter from 'gray-matter'; import matter from 'gray-matter';
import { marked } from 'marked';
import { unified } from 'unified'; import DOMPurify from 'dompurify';
import remarkParse from 'remark-parse'; import { JSDOM } from 'jsdom';
import remarkGfm from 'remark-gfm';
import remarkRehype from 'remark-rehype';
import rehypeRaw from 'rehype-raw';
import rehypeStringify from 'rehype-stringify';
const postsDirectory = path.join(process.cwd(), 'posts'); const postsDirectory = path.join(process.cwd(), 'posts');
@@ -35,17 +31,35 @@ async function getPostByPath(filePath: string, relPath: string) {
let processedContent = ''; let processedContent = '';
try { try {
const file = await unified() marked.setOptions({
.use(remarkParse as any) gfm: true,
.use(remarkGfm) breaks: true
.use(remarkRehype, { allowDangerousHtml: true }) });
.use(rehypeRaw) const rawHtml = marked.parse(content);
.use(rehypeStringify) const window = new JSDOM('').window;
.process(content); const purify = DOMPurify(window);
processedContent = purify.sanitize(rawHtml as string, {
processedContent = file.toString(); ALLOWED_TAGS: [
'h1', 'h2', 'h3', 'h4', 'h5', 'h6',
'p', 'a', 'ul', 'ol', 'li', 'blockquote',
'pre', 'code', 'em', 'strong', 'del',
'hr', 'br', 'img', 'table', 'thead', 'tbody',
'tr', 'th', 'td', 'div', 'span', 'iframe'
],
ALLOWED_ATTR: [
'class', 'id', 'style',
'href', 'target', 'rel',
'src', 'alt', 'title', 'width', 'height',
'frameborder', 'allowfullscreen'
],
ALLOWED_URI_REGEXP: /^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i
});
} catch (err) { } catch (err) {
console.error(`Error processing markdown for ${relPath}:`, err); console.error(`Error processing markdown for ${relPath}:`, err);
processedContent = `<div class="error-message">
<p>Error processing markdown content. Please check the console for details.</p>
<pre>${err instanceof Error ? err.message : 'Unknown error'}</pre>
</div>`;
} }
return { return {