diff --git a/src/lib/components/MarkdownRenderer.svelte b/src/lib/components/MarkdownRenderer.svelte
index 35472e1..8c4f14c 100644
--- a/src/lib/components/MarkdownRenderer.svelte
+++ b/src/lib/components/MarkdownRenderer.svelte
@@ -1,9 +1,91 @@
+
{@html htmlContent}
diff --git a/src/lib/markdown/rendering.test.ts b/src/lib/markdown/rendering.test.ts
new file mode 100644
index 0000000..b147fb2
--- /dev/null
+++ b/src/lib/markdown/rendering.test.ts
@@ -0,0 +1,58 @@
+import { describe, expect, it } from 'vitest';
+import {
+ createHeadingId,
+ createUniqueHeadingId,
+ replaceGithubAdmonitions,
+ sanitizeMarkdownHtml
+} from './rendering';
+
+describe('replaceGithubAdmonitions', () => {
+ it('passes the type, title and quote body to the renderer', () => {
+ const rendered = replaceGithubAdmonitions(
+ 'Before\n\n> [!NOTE] Optional title\n> first line\n> second line\n\nAfter',
+ (type, title, content) => ``
+ );
+
+ expect(rendered).toContain(
+ ''
+ );
+ expect(rendered).toContain('Before');
+ expect(rendered).toContain('After');
+ });
+});
+
+describe('heading IDs', () => {
+ it('keeps Unicode letters and provides a deterministic fallback', () => {
+ expect(createHeadingId('中文 标题')).toBe('中文-标题');
+ expect(createHeadingId('🎉')).toBe('section');
+ });
+
+ it('makes duplicate heading IDs unique', () => {
+ const seen = new Map();
+ expect(createUniqueHeadingId('重复', seen)).toBe('重复');
+ expect(createUniqueHeadingId('重复', seen)).toBe('重复-2');
+ });
+});
+
+describe('sanitizeMarkdownHtml', () => {
+ it('removes active content and encoded script URLs during SSR', () => {
+ const sanitized = sanitizeMarkdownHtml(
+ 'bad
' +
+ '
' +
+ ''
+ );
+
+ expect(sanitized).not.toContain('javascript:');
+ expect(sanitized).not.toContain('onerror');
+ expect(sanitized).not.toContain('