Skip to content

[Feature] Implement Server-Side Markdown Rendering Pipeline with Caching & SanitizationΒ #84

@Soulike

Description

@Soulike

πŸš€ Context & Motivation

Currently, raw Markdown is stored in the database. To improve frontend performance (First Contentful Paint), reduce bundle size (removing heavy parsing libraries from the client), and prepare for better SEO, we need to move the Markdown rendering logic to the backend.

πŸ— Proposed Architecture

The new pipeline will transform Markdown to HTML on the server-side, sanitize it, and cache the result.

  1. Source: Retrieve raw Markdown from the primary database (Postgres/DB).
  2. Transformation: Convert Markdown to HTML using markdown-it.
    • Apply syntax highlighting via highlight.js.
    • Sanitization: Clean the generated HTML using isomorphic-dompurify (Backend side) to ensure no XSS vectors are stored or transmitted.
  3. Caching: Store the sanitized HTML in the cache layer (Redis/Memory) with a TTL.
  4. Delivery: The API returns the pre-rendered HTML string to the client.
  5. Client: React frontend simply renders the HTML string (using html-react-parser or dangerouslySetInnerHTML).

πŸ›  Tech Stack & Libraries

  • Parser: markdown-it (CommonMark compliant, extensible).
  • Highlighter: highlight.js (Server-side syntax highlighting).
  • Sanitizer: isomorphic-dompurify (DOMPurify wrapper for Node.js).
  • CSS: github-markdown-css (Frontend styling).

πŸ“ Implementation Details

1. Backend (Node.js)
Create a service/helper function renderMarkdown(rawText: string): string.

// Pseudo-code flow
const raw = await db.getPost();
// Check Cache
const cached = await cache.get(`post:${id}:html`);
if (cached) return cached;

// Render & Sanitize
const unsafeHtml = md.render(raw);
const safeHtml = DOMPurify.sanitize(unsafeHtml);

// Set Cache
await cache.set(`post:${id}:html`, safeHtml, 'EX', 3600);
return safeHtml;

2. Frontend (React)
Refactor the ArticleViewer component to accept HTML strings instead of Markdown.

  • Ensure internal links (<a href="/...">) are handled correctly (prevent full page reload) if using html-react-parser.

βœ… Task List

  • Install backend dependencies: markdown-it, highlight.js, isomorphic-dompurify.
  • Configure markdown-it with highlight.js support.
  • Implement the MarkdownService with caching logic (Redis/Memory).
  • Update API response schema to include content_html.
  • Refactor Frontend ArticleDetail component to render HTML.
  • Import github-markdown-css and highlight.js styles in the frontend.
  • Verify XSS protection (Test with <script> tags in markdown).

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions