// Task 5 失败测试(先于实现):WordPress 正文 HTML 白名单清洗 + SanitizeDiff[] 差异收集。 // 方案取舍(实现侧 JSDoc 为准):清洗本体交 sanitize-html;差异经 onOpenTag 观察钩子 // 按文档序收集(每次调用独立数组,纯函数)。 import { createReadStream } from 'node:fs' import { fileURLToPath } from 'node:url' import { describe, expect, it } from 'vitest' import sanitizeHtml, { type IOptions } from 'sanitize-html' import { parseWxrStream } from '../src/parse/wxr-stream.js' import { deriveMirrorView, SANITIZE_CONFIG, sanitizeBodyHtml, type SanitizeDiff, } from '../src/sanitize/html.js' const FIXTURE = fileURLToPath(new URL('../../../tests/fixtures/wxr/mini.xml', import.meta.url)) /** mini.xml post 101 的 content:encoded 原文(item-to-row 测试同款锚点) */ const MINI_101_BODY = '

Body with link and

' describe('sanitizeBodyHtml:危险内容移除(差异留痕)', () => { it('') expect(result.html).toBe('

ok

') // script 内文随 nonTextTags 语义一并丢弃 expect(result.diffs).toStrictEqual([{ type: 'removed-tag', tag: 'script', excerpt: 't2ok' const result = sanitizeBodyHtml(dirty) expect(result.html).toBe('

t1

t2fbok') expect(result.diffs).toStrictEqual([ { type: 'removed-attr', tag: 'p', attr: 'onclick', excerpt: 'onclick="a()"' }, { type: 'removed-tag', tag: 'script', excerpt: '' const first = sanitizeBodyHtml(dirty) const second = sanitizeBodyHtml(dirty) expect(second).toStrictEqual(first) expect(first.diffs).toHaveLength(4) // div.onclick / a.href / script / iframe }) it('大小写归一:z') expect(result.html).toBe('z') expect(result.diffs).toStrictEqual([ { type: 'removed-tag', tag: 'script', excerpt: ''], ['实体编码协议(: 解码后判定)', 'x'], ['控制字符走私(java\\u0001script:)', 'x'], ['NULL 字节走私(java\\u0000script:)', 'x'], ['URL 注释走私(javascript:)', 'x'], ['未加引号属性', 'x'], ['重复属性(解析器首值胜出)', 'd'], ['混合大小写标签与属性', 'y'], ['iframe + 事件属性混合', ''], ['多重违例混合', '

t1

t2ok'], ['data: 逗号内嵌 srcset(部分重写)', 's'], ['全 data: srcset(整属性删除)', ''], ['不可解析 srcset(,,,,,,)', 'u'], ['深嵌套 30 层 + 内层违例', `
${'
'.repeat(29)}

deep

${'
'.repeat(29)}
`], ['mini.xml 101 正文', MINI_101_BODY], ] it.each(samples)('sanitizeHtml(x, SANITIZE_CONFIG) ≡ sanitizeBodyHtml(x).html:%s', (_label, sample) => { expect(sanitizeBodyHtml(sample).html).toBe(sanitizeHtml(sample, { ...SANITIZE_CONFIG })) }) })