@pixui-dev/pixui-richtext-helper 0.2.5 → 0.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -27,6 +27,7 @@ export declare class RichTextCore {
|
|
|
27
27
|
*/
|
|
28
28
|
static convertRichTextToPixuiStyle(str: string, config?: {
|
|
29
29
|
lineHeightScale?: number;
|
|
30
|
+
convertPxToEm?: boolean;
|
|
30
31
|
}): string;
|
|
31
32
|
/**
|
|
32
33
|
* 绑定链接点击事件
|
|
@@ -44,6 +45,12 @@ export declare class RichTextCore {
|
|
|
44
45
|
* 处理单个段落片段,返回转换后的片段 HTML
|
|
45
46
|
*/
|
|
46
47
|
private static processSegment;
|
|
48
|
+
/**
|
|
49
|
+
* 统一转换HTML中的所有px单位为em单位
|
|
50
|
+
* @param html 原始HTML字符串
|
|
51
|
+
* @returns 转换后的HTML字符串
|
|
52
|
+
*/
|
|
53
|
+
private static convertAllPxToEm;
|
|
47
54
|
private static preprocess;
|
|
48
55
|
private static fixImgSizeUnit;
|
|
49
56
|
/** 列表处理(将 ol/ul/li 替换为 div 结构) */
|
|
@@ -56,6 +56,33 @@ var LinkNodeType;
|
|
|
56
56
|
/*****************************************************
|
|
57
57
|
* 工具函数
|
|
58
58
|
*****************************************************/
|
|
59
|
+
/** 基准字体大小,用于px到em转换 */
|
|
60
|
+
var BASE_FONT_SIZE = 16;
|
|
61
|
+
/**
|
|
62
|
+
* 将px单位转换为em单位
|
|
63
|
+
* @param pxValue px数值
|
|
64
|
+
* @returns em值字符串
|
|
65
|
+
*/
|
|
66
|
+
var convertPxToEm = function (pxValue) {
|
|
67
|
+
var emValue = pxValue / BASE_FONT_SIZE;
|
|
68
|
+
return "".concat(emValue.toFixed(3), "em");
|
|
69
|
+
};
|
|
70
|
+
/**
|
|
71
|
+
* 转换样式字符串中的px单位为em单位
|
|
72
|
+
* @param styleStr 原始样式字符串
|
|
73
|
+
* @returns 转换后的样式字符串
|
|
74
|
+
*/
|
|
75
|
+
var convertStylePxToEm = function (styleStr) {
|
|
76
|
+
if (!styleStr || !styleStr.trim())
|
|
77
|
+
return styleStr;
|
|
78
|
+
return styleStr.replace(/(\d+(?:\.\d+)?)px/g, function (match, pxValue) {
|
|
79
|
+
var px = parseFloat(pxValue);
|
|
80
|
+
if (!isNaN(px)) {
|
|
81
|
+
return convertPxToEm(px);
|
|
82
|
+
}
|
|
83
|
+
return match;
|
|
84
|
+
});
|
|
85
|
+
};
|
|
59
86
|
/**
|
|
60
87
|
* 解析 style 字符串为对象
|
|
61
88
|
*/
|
|
@@ -121,7 +148,10 @@ var RichTextCore = /** @class */ (function () {
|
|
|
121
148
|
// 重置全局状态
|
|
122
149
|
RichTextCore.linkNodes = [];
|
|
123
150
|
RichTextCore.hrefIdCnt = 0;
|
|
124
|
-
var
|
|
151
|
+
var preEncodedStr = str.replace(/href="([^"]*?)"/g, function (_match, hrefVal) {
|
|
152
|
+
return "href=\"".concat(encodeURIComponent(hrefVal), "\"");
|
|
153
|
+
});
|
|
154
|
+
var $1 = cheerio.load(preEncodedStr, null, false);
|
|
125
155
|
//检查html,如果有text节点,说明是转换过的,直接返回
|
|
126
156
|
if ($1("text").length > 0) {
|
|
127
157
|
return str;
|
|
@@ -144,9 +174,38 @@ var RichTextCore = /** @class */ (function () {
|
|
|
144
174
|
// 直接查询统一的 class
|
|
145
175
|
setTimeout(function () {
|
|
146
176
|
var elements = Array.from(document.querySelectorAll(".".concat(RichTextCore.LINK_NODE_CLASS)));
|
|
177
|
+
// HTML 实体解码工具函数(纯算法实现,避免依赖 textarea 节点)
|
|
178
|
+
var decodeHtmlEntities = function (str) {
|
|
179
|
+
if (!str)
|
|
180
|
+
return str;
|
|
181
|
+
var named = {
|
|
182
|
+
quot: '"',
|
|
183
|
+
amp: "&",
|
|
184
|
+
lt: "<",
|
|
185
|
+
gt: ">",
|
|
186
|
+
apos: "'",
|
|
187
|
+
};
|
|
188
|
+
return str.replace(/&(#(?:x[0-9a-fA-F]+|\d+)|[a-zA-Z]+);/g, function (_, ent) {
|
|
189
|
+
if (ent[0] === "#") {
|
|
190
|
+
// 数字实体
|
|
191
|
+
var isHex = ent[1].toLowerCase() === "x";
|
|
192
|
+
var numStr = isHex ? ent.slice(2) : ent.slice(1);
|
|
193
|
+
var codePoint = parseInt(numStr, isHex ? 16 : 10);
|
|
194
|
+
if (!isNaN(codePoint)) {
|
|
195
|
+
return String.fromCodePoint(codePoint);
|
|
196
|
+
}
|
|
197
|
+
return _; // 解析失败,原样返回
|
|
198
|
+
}
|
|
199
|
+
// 命名实体
|
|
200
|
+
if (named.hasOwnProperty(ent))
|
|
201
|
+
return named[ent];
|
|
202
|
+
return _; // 未知实体,原样返回
|
|
203
|
+
});
|
|
204
|
+
};
|
|
147
205
|
elements.forEach(function (el) {
|
|
148
206
|
var hrefEncoded = el.getAttribute("data-link-href") || "";
|
|
149
|
-
|
|
207
|
+
// 先 URI 解码,再做 HTML 实体解码
|
|
208
|
+
var href = decodeHtmlEntities(decodeURIComponent(hrefEncoded));
|
|
150
209
|
var typeStr = el.getAttribute("data-link-type");
|
|
151
210
|
var type = typeStr === LinkNodeType.IMG ? LinkNodeType.IMG : LinkNodeType.DIV;
|
|
152
211
|
// 避免重复绑定
|
|
@@ -230,8 +289,12 @@ var RichTextCore = /** @class */ (function () {
|
|
|
230
289
|
if (tagName === "div" || tagName === "text") {
|
|
231
290
|
return []; // 丢弃空 div / text
|
|
232
291
|
}
|
|
292
|
+
else if (tagName === "img") {
|
|
293
|
+
// img标签直接返回,不包装在div中
|
|
294
|
+
return [$.html(node)];
|
|
295
|
+
}
|
|
233
296
|
else {
|
|
234
|
-
//
|
|
297
|
+
// 其它空标签保留
|
|
235
298
|
return [wrapNode($elem, "")];
|
|
236
299
|
}
|
|
237
300
|
}
|
|
@@ -281,8 +344,25 @@ var RichTextCore = /** @class */ (function () {
|
|
|
281
344
|
.replaceAll(/&/g, "&")
|
|
282
345
|
.replaceAll(/"/g, '"')
|
|
283
346
|
.replaceAll("\"", "\"");
|
|
347
|
+
// 统一进行px到em转换
|
|
348
|
+
if (config === null || config === void 0 ? void 0 : config.convertPxToEm) {
|
|
349
|
+
res = this.convertAllPxToEm(res);
|
|
350
|
+
}
|
|
284
351
|
return res;
|
|
285
352
|
};
|
|
353
|
+
/**
|
|
354
|
+
* 统一转换HTML中的所有px单位为em单位
|
|
355
|
+
* @param html 原始HTML字符串
|
|
356
|
+
* @returns 转换后的HTML字符串
|
|
357
|
+
*/
|
|
358
|
+
RichTextCore.convertAllPxToEm = function (html) {
|
|
359
|
+
// 转换style属性中的px
|
|
360
|
+
html = html.replace(/style="([^"]*?)"/g, function (match, styleContent) {
|
|
361
|
+
var convertedStyle = convertStylePxToEm(styleContent);
|
|
362
|
+
return "style=\"".concat(convertedStyle, "\"");
|
|
363
|
+
});
|
|
364
|
+
return html;
|
|
365
|
+
};
|
|
286
366
|
// ------------------------------
|
|
287
367
|
// 各独立处理步骤实现
|
|
288
368
|
// ------------------------------
|
|
@@ -479,7 +559,7 @@ var RichTextCore = /** @class */ (function () {
|
|
|
479
559
|
mergedStyles.push(innerStyle);
|
|
480
560
|
});
|
|
481
561
|
var finalStyle = mergeStyles.apply(void 0, __spreadArray([originalStyle], mergedStyles, false));
|
|
482
|
-
var encodedHref = href
|
|
562
|
+
var encodedHref = href || ""; // 已在预处理阶段编码,避免二次编码
|
|
483
563
|
if (href) {
|
|
484
564
|
self.linkNodes.push({ type: LinkNodeType.DIV, href: href, id: id });
|
|
485
565
|
}
|
|
@@ -566,7 +646,7 @@ var RichTextCore = /** @class */ (function () {
|
|
|
566
646
|
self.linkNodes.push({ type: LinkNodeType.IMG, href: href, id: id });
|
|
567
647
|
}
|
|
568
648
|
// 将链接信息以转义形式保存在 data- 属性中,避免默认跳转
|
|
569
|
-
var encodedHref = href
|
|
649
|
+
var encodedHref = href || ""; // 已在预处理阶段编码,避免二次编码
|
|
570
650
|
$(this).attr("data-link-type", "img");
|
|
571
651
|
$(this).attr("data-link-href", encodedHref);
|
|
572
652
|
$(this).attr("href", "");
|
|
@@ -654,7 +734,8 @@ var RichTextCore = /** @class */ (function () {
|
|
|
654
734
|
var attribs = ($(node).get(0) || {}).attribs || {};
|
|
655
735
|
for (var _i = 0, _a = Object.entries(attribs); _i < _a.length; _i++) {
|
|
656
736
|
var _b = _a[_i], k = _b[0], v = _b[1];
|
|
657
|
-
|
|
737
|
+
// 跳过style、id和href属性,避免重复处理或错误处理
|
|
738
|
+
if (k !== "style" && k !== "id" && k !== "href") {
|
|
658
739
|
customAttrs += " ".concat(k, "=\"").concat(v, "\"");
|
|
659
740
|
}
|
|
660
741
|
}
|
package/package.json
CHANGED