From c867f2b648ce3dfb5a679ca86bb38f228317fc3b Mon Sep 17 00:00:00 2001
From: liujie <1793218484@qq.com>
Date: 星期四, 17 九月 2026 14:26:10 +0800
Subject: [PATCH] fix(小程序): 修复协议页无法解析后台 Word 富文本 HTML
---
mingdaojingjiang_uniapp/mingdaojingjiang_uniapp/common/html-parser.js | 81 ++++++++++++++++++++++++++++++++++++++--
1 files changed, 76 insertions(+), 5 deletions(-)
diff --git a/mingdaojingjiang_uniapp/mingdaojingjiang_uniapp/common/html-parser.js b/mingdaojingjiang_uniapp/mingdaojingjiang_uniapp/common/html-parser.js
index 20a89b2..9372e70 100644
--- a/mingdaojingjiang_uniapp/mingdaojingjiang_uniapp/common/html-parser.js
+++ b/mingdaojingjiang_uniapp/mingdaojingjiang_uniapp/common/html-parser.js
@@ -79,8 +79,10 @@
*
*/
// Regular Expressions for parsing tags and attributes
-var startTag = /^<([-A-Za-z0-9_]+)((?:\s+[a-zA-Z_:][-a-zA-Z0-9_:.]*(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)>/;
-var endTag = /^<\/([-A-Za-z0-9_]+)[^>]*>/;
+// fixed by 名导精讲 标签名允许冒号,兼容 Word 导出的 <o:p>、<v:shape> 等命名空间标签,
+// 否则解析循环无法前进会抛出 Parse Error,导致页面把整段 HTML 当纯文本显示。
+var startTag = /^<([-A-Za-z0-9_:]+)((?:\s+[a-zA-Z_:][-a-zA-Z0-9_:.]*(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)>/;
+var endTag = /^<\/([-A-Za-z0-9_:]+)[^>]*>/;
var attr = /([a-zA-Z_:][-a-zA-Z0-9_:.]*)(?:\s*=\s*(?:(?:"((?:\\.|[^"])*)")|(?:'((?:\\.|[^'])*)')|([^>\s]+)))?/g; // Empty Elements - HTML 5
var empty = makeMap('area,base,basefont,br,col,frame,hr,img,input,link,meta,param,embed,command,keygen,source,track,wbr'); // Block Elements - HTML 5
@@ -121,6 +123,10 @@
}
html = html.substring(index + 3);
+ chars = false;
+ } else {
+ // 未闭合注释:吞掉剩余内容,避免解析循环无法前进抛出 Parse Error
+ html = '';
chars = false;
} // end tag
@@ -251,7 +257,72 @@
}
function removeDOCTYPE(html) {
- return html.replace(/<\?xml.*\?>\n/, '').replace(/<!doctype.*>\n/, '').replace(/<!DOCTYPE.*>\n/, '');
+ return html
+ .replace(/<\?xml[\s\S]*?\?>/gi, '')
+ .replace(/<!DOCTYPE[^>]*>/gi, '');
+}
+
+// Word 导出 HTML 专用清洗:去掉小程序富文本无法处理的噪声内容。
+function sanitizeWordHtml(html) {
+ return removeDOCTYPE(html)
+ // downlevel-revealed 条件注释(<![if !supportLists]> / <![endif]>)不是标准注释,会让解析循环卡死
+ .replace(/<!\[if[\s\S]*?\]>/gi, '')
+ .replace(/<!\[endif\]>/gi, '')
+ // 标准注释与 downlevel-hidden 条件注释块(内含 <xml><w:WordDocument> 等大段配置)
+ .replace(/<!--[\s\S]*?-->/g, '')
+ .replace(/<head[\s\S]*?<\/head>/gi, '')
+ .replace(/<(style|script|xml)[\s\S]*?<\/\1>/gi, '')
+ // html/body 外壳 rich-text 不支持,可能连同子树一起被丢弃,只保留内部节点
+ .replace(/<\/?html[^>]*>/gi, '')
+ .replace(/<\/?body[^>]*>/gi, '')
+ // 命名空间标签(<o:p>、<v:shape>、<st1:place> 等)只删标签本身,保留其中的文本
+ .replace(/<\/?[A-Za-z][\w.-]*:[\w.-]*(?:\s[^>]*)?\/?>/g, '');
+}
+
+var namedEntities = {
+ nbsp: ' ',
+ ensp: ' ',
+ emsp: ' ',
+ quot: '"',
+ apos: "'",
+ amp: '&',
+ lt: '<',
+ gt: '>',
+ ldquo: '\u201c',
+ rdquo: '\u201d',
+ lsquo: '\u2018',
+ rsquo: '\u2019',
+ mdash: '\u2014',
+ ndash: '\u2013',
+ hellip: '\u2026',
+ middot: '\u00b7',
+ bull: '\u2022',
+ dagger: '\u2020',
+ permil: '\u2030',
+ lsaquo: '\u2039',
+ rsaquo: '\u203a',
+ times: '\u00d7',
+ divide: '\u00f7',
+ copy: '\u00a9',
+ reg: '\u00ae',
+ trade: '\u2122',
+ deg: '\u00b0',
+ minus: '\u2212',
+ szlig: '\u00df'
+};
+
+// rich-text 的文本节点不会解码实体,Word 正文里的 “ 等需要在这里转成字符。
+function decodeEntities(text) {
+ if (text.indexOf('&') < 0) return text;
+ return text.replace(/&(#[xX]?[0-9a-fA-F]+|[a-zA-Z][a-zA-Z0-9]*);/g, function (all, name) {
+ if (name[0] === '#') {
+ var code = name[1] === 'x' || name[1] === 'X' ? parseInt(name.slice(2), 16) : parseInt(name.slice(1), 10);
+ return isNaN(code) || code < 0 || code > 0x10ffff ? all : String.fromCodePoint(code);
+ }
+ // amp 最后解,避免 &lt; 被二次解码
+ if (name === 'amp') return '&';
+ return Object.prototype.hasOwnProperty.call(namedEntities, name) ? namedEntities[name] : all;
+ });
}
function parseAttrs(attrs) {
@@ -270,7 +341,7 @@
}
function parseHtml(html) {
- html = removeDOCTYPE(html);
+ html = sanitizeWordHtml(html);
var stacks = [];
var results = {
node: 'root',
@@ -317,7 +388,7 @@
chars: function chars(text) {
var node = {
type: 'text',
- text: text
+ text: decodeEntities(text)
};
if (stacks.length === 0) {
--
Gitblit v1.7.1