9/10
This commit is contained in:
66
src/utils/html.ts
Normal file
66
src/utils/html.ts
Normal file
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* 剥离 HTML 标签,提取纯文本
|
||||
* - 自动将 <img>/<video>/<audio> 替换为 [图片]/[视频]/[音频] 占位
|
||||
* - 自动解码 & 等 HTML entity
|
||||
* - 自动合并多余空白
|
||||
* - 可按需截断
|
||||
*/
|
||||
export function stripHtml(html: string | null | undefined, maxLen?: number): string {
|
||||
if (!html) return '';
|
||||
|
||||
let text: string = html;
|
||||
|
||||
// 1. 媒体标签替换为占位符(保留语义提示)
|
||||
text = text
|
||||
.replace(/<img[^>]*>/gi, '[图片]')
|
||||
.replace(/<video[^>]*>.*?<\/video>/gi, '[视频]')
|
||||
.replace(/<audio[^>]*>.*?<\/audio>/gi, '[音频]')
|
||||
.replace(/<iframe[^>]*>.*?<\/iframe>/gi, '[嵌入内容]');
|
||||
|
||||
// 2. 剥离所有剩余 HTML 标签(<p> <br> <div> ...)
|
||||
text = text.replace(/<[^>]+>/g, '');
|
||||
|
||||
// 3. HTML entity 解码
|
||||
text = decodeHtmlEntity(text);
|
||||
|
||||
// 4. 合并多余空白(多个空格/换行 → 单个空格)
|
||||
text = text.replace(/\s+/g, ' ').trim();
|
||||
|
||||
// 5. 截断
|
||||
if (maxLen && text.length > maxLen) {
|
||||
text = text.slice(0, maxLen) + '...';
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解码 HTML 实体
|
||||
* 浏览器环境用 DOMParser,非浏览器环境用正则 fallback
|
||||
*/
|
||||
function decodeHtmlEntity(str: string): string {
|
||||
if (typeof DOMParser === 'undefined') {
|
||||
const entityMap: Record<string, string> = {
|
||||
' ': ' ',
|
||||
'&': '&',
|
||||
'<': '<',
|
||||
'>': '>',
|
||||
'"': '"',
|
||||
''': "'",
|
||||
''': "'",
|
||||
'/': '/',
|
||||
'©': '©',
|
||||
'®': '®'
|
||||
};
|
||||
return str.replace(/&[a-z]+;|&#\d+;|&#x[0-9a-f]+;/gi, (match) => {
|
||||
if (entityMap[match]) return entityMap[match];
|
||||
const num = match.match(/&#(\d+);/)?.[1];
|
||||
if (num) return String.fromCharCode(Number(num));
|
||||
const hex = match.match(/&#x([0-9a-f]+);/i)?.[1];
|
||||
if (hex) return String.fromCharCode(parseInt(hex, 16));
|
||||
return match;
|
||||
});
|
||||
}
|
||||
const doc = new DOMParser().parseFromString(str, 'text/html');
|
||||
return doc.documentElement.textContent ?? '';
|
||||
}
|
||||
Reference in New Issue
Block a user