/** * parser.js 单元测试 * 覆盖 Markdown 解析器的所有语法分支与安全特性 */ import { parseMarkdown, safeUrl, slugify } from '../src/parser.js'; describe('parseMarkdown - 基础', () => { test('空输入返回空字符串', () => { expect(parseMarkdown('')).toBe(''); expect(parseMarkdown(null)).toBe(''); expect(parseMarkdown(undefined)).toBe(''); }); test('非字符串输入被转换为字符串', () => { expect(parseMarkdown(123)).toBe('

123

'); }); test('Windows 换行符被规范化', () => { const html = parseMarkdown('line1\r\nline2'); expect(html).toContain('line1'); expect(html).toContain('line2'); expect(html).not.toContain('\r'); }); }); describe('parseMarkdown - 标题', () => { test('h1 到 h6', () => { expect(parseMarkdown('# T1')).toBe('

T1

'); expect(parseMarkdown('## T2')).toBe('

T2

'); expect(parseMarkdown('### T3')).toBe('

T3

'); expect(parseMarkdown('#### T4')).toBe('

T4

'); expect(parseMarkdown('##### T5')).toBe('
T5
'); expect(parseMarkdown('###### T6')).toBe('
T6
'); }); test('标题文本被内联渲染', () => { const html = parseMarkdown('# Hello **world**'); expect(html).toContain('world'); }); test('标题生成锚点 id', () => { expect(parseMarkdown('# Hello World')).toContain('id="hello-world"'); }); test('超过 6 个 # 不作为标题', () => { const html = parseMarkdown('####### not heading'); expect(html).not.toContain(''); }); }); describe('parseMarkdown - 段落', () => { test('单行段落', () => { expect(parseMarkdown('hello')).toBe('

hello

'); }); test('多行段落合并', () => { const html = parseMarkdown('line1\nline2'); expect(html).toBe('

line1
line2

'); }); test('空行分隔段落', () => { const html = parseMarkdown('p1\n\np2'); expect(html).toBe('

p1

\n

p2

'); }); }); describe('parseMarkdown - 行内格式', () => { test('粗体 **text**', () => { expect(parseMarkdown('**bold**')).toBe('

bold

'); }); test('粗体 __text__', () => { expect(parseMarkdown('__bold__')).toBe('

bold

'); }); test('斜体 *text*', () => { expect(parseMarkdown('a *italic* b')).toBe('

a italic b

'); }); test('斜体 _text_', () => { expect(parseMarkdown('a _italic_ b')).toBe('

a italic b

'); }); test('删除线 ~~text~~', () => { expect(parseMarkdown('~~del~~')).toBe('

del

'); }); test('行内代码 `code`', () => { const html = parseMarkdown('use `code` here'); expect(html).toContain('code'); }); test('行内代码内容不被解析为格式', () => { const html = parseMarkdown('`a **b** c`'); expect(html).toContain('a **b** c'); expect(html).not.toContain(''); }); test('行内代码内容被转义', () => { const html = parseMarkdown('`'); expect(html).toContain('<script>'); expect(html).not.toContain('