@pixui-dev/pixui-richtext-helper 0.1.1-beta.4 → 0.1.1
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.
- package/dist/RichTextUtils.d.ts +2 -6
- package/dist/RichTextUtils.js +73 -248
- package/dist/index.d.ts +2 -2
- package/dist/index.js +4 -4
- package/package.json +3 -4
- package/dist/RichText.d.ts +0 -22
- package/dist/RichText.js +0 -24
- package/dist/richtext/RichText_Refactor.d.ts +0 -77
- package/dist/richtext/RichText_Refactor.js +0 -645
package/dist/RichTextUtils.d.ts
CHANGED
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* pixui富文本转换工具
|
|
3
|
-
* 将管理端下发的富文本转换成pixui的innerHtml可以使用的格式,被转换的富文本只应该包括文本和图片及相关的样式。
|
|
4
|
-
* 将富文本内容转换为:
|
|
5
|
-
* 段落div/h节点(不带样式,用来形成一个段落) -> text(只带text节点样式,pixui的段落需要在text节点下才能表现正常)-> <div>(带有文本的样式) 文本1 </div> <div>(带有文本的样式) 文本2 </div> <img>(带有图片的样式) 图片1 </img> <div>(带有文本的样式) 文本3 </div> (每个子div带有这一小段文本/图片的样式,这一段所有text节点下的div/img会被text节点正确的换行排列)
|
|
6
|
-
*/
|
|
7
1
|
export declare namespace RichText {
|
|
8
2
|
/**
|
|
9
3
|
* 富文本中的超链接节点类型
|
|
@@ -28,10 +22,12 @@ export declare namespace RichText {
|
|
|
28
22
|
* @param str 管理端下发的富文本
|
|
29
23
|
* @param config 配置
|
|
30
24
|
* @param config.lineHeightScale 行高缩放
|
|
25
|
+
* @param config.isToRem 是否将节点的 px 单位转换为 rem 的单位
|
|
31
26
|
* @returns pixui的innerHtml可以使用的格式
|
|
32
27
|
*/
|
|
33
28
|
const convertRichTextToPixuiStyle: (str: string, config?: {
|
|
34
29
|
lineHeightScale?: number;
|
|
30
|
+
isToRem?: boolean;
|
|
35
31
|
}) => string;
|
|
36
32
|
/**
|
|
37
33
|
* 为富文本中的链接节点绑定点击事件
|
package/dist/RichTextUtils.js
CHANGED
|
@@ -32,24 +32,9 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
32
32
|
return result;
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
|
-
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
36
|
-
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
37
|
-
if (ar || !(i in from)) {
|
|
38
|
-
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
39
|
-
ar[i] = from[i];
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
return to.concat(ar || Array.prototype.slice.call(from));
|
|
43
|
-
};
|
|
44
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
36
|
exports.RichText = void 0;
|
|
46
37
|
var cheerio = __importStar(require("cheerio"));
|
|
47
|
-
/**
|
|
48
|
-
* pixui富文本转换工具
|
|
49
|
-
* 将管理端下发的富文本转换成pixui的innerHtml可以使用的格式,被转换的富文本只应该包括文本和图片及相关的样式。
|
|
50
|
-
* 将富文本内容转换为:
|
|
51
|
-
* 段落div/h节点(不带样式,用来形成一个段落) -> text(只带text节点样式,pixui的段落需要在text节点下才能表现正常)-> <div>(带有文本的样式) 文本1 </div> <div>(带有文本的样式) 文本2 </div> <img>(带有图片的样式) 图片1 </img> <div>(带有文本的样式) 文本3 </div> (每个子div带有这一小段文本/图片的样式,这一段所有text节点下的div/img会被text节点正确的换行排列)
|
|
52
|
-
*/
|
|
53
38
|
var RichText;
|
|
54
39
|
(function (RichText) {
|
|
55
40
|
/**
|
|
@@ -62,30 +47,15 @@ var RichText;
|
|
|
62
47
|
})(LinkNodeType = RichText.LinkNodeType || (RichText.LinkNodeType = {}));
|
|
63
48
|
// 存储需要绑定点击事件的节点信息
|
|
64
49
|
var linkNodes = [];
|
|
65
|
-
// 添加工具函数来正确处理CSS样式拼接
|
|
66
|
-
var mergeStyles = function () {
|
|
67
|
-
var styles = [];
|
|
68
|
-
for (var _i = 0; _i < arguments.length; _i++) {
|
|
69
|
-
styles[_i] = arguments[_i];
|
|
70
|
-
}
|
|
71
|
-
return styles
|
|
72
|
-
.filter(function (style) { return style && style.trim(); })
|
|
73
|
-
.map(function (style) {
|
|
74
|
-
var trimmed = style.trim();
|
|
75
|
-
return trimmed.endsWith(";") ? trimmed : trimmed + ";";
|
|
76
|
-
})
|
|
77
|
-
.join(" ")
|
|
78
|
-
.replace(/\s*;\s*$/, ";"); // 确保最后只有一个分号
|
|
79
|
-
};
|
|
80
50
|
/**
|
|
81
51
|
* 富文本组件,将富文本转换成pixui的innerHtml可以使用的格式
|
|
82
52
|
* @param str 管理端下发的富文本
|
|
83
53
|
* @param config 配置
|
|
84
54
|
* @param config.lineHeightScale 行高缩放
|
|
55
|
+
* @param config.isToRem 是否将节点的 px 单位转换为 rem 的单位
|
|
85
56
|
* @returns pixui的innerHtml可以使用的格式
|
|
86
57
|
*/
|
|
87
58
|
RichText.convertRichTextToPixuiStyle = function (str, config) {
|
|
88
|
-
//将富文本内容转换为一个 段落div/h -> text -> 文字样式div/img -> 文本 的结构,保证pixui可以正常显示
|
|
89
59
|
var $ = cheerio.load(str, null, false);
|
|
90
60
|
var hrefIdCnt = 0;
|
|
91
61
|
linkNodes = []; // 重置链接节点信息
|
|
@@ -93,10 +63,10 @@ var RichText;
|
|
|
93
63
|
{
|
|
94
64
|
var _loop_1 = function (i) {
|
|
95
65
|
var indent = "ql-indent-".concat(i);
|
|
96
|
-
var extStyle = "padding-left: ".concat(i * 2, "rem");
|
|
66
|
+
var extStyle = "padding-left: ".concat(i * 2, "rem;");
|
|
97
67
|
$(".".concat(indent)).each(function () {
|
|
98
68
|
var oriStyle = $(this).attr("style") || "";
|
|
99
|
-
$(this).attr("style",
|
|
69
|
+
$(this).attr("style", "".concat(oriStyle, " ").concat(extStyle));
|
|
100
70
|
$(this).removeClass(indent);
|
|
101
71
|
});
|
|
102
72
|
};
|
|
@@ -104,185 +74,52 @@ var RichText;
|
|
|
104
74
|
for (var i = 1; i <= 10; i++) {
|
|
105
75
|
_loop_1(i);
|
|
106
76
|
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* pixui不支持ol,ul,li节点,将其递归转换成div并处理嵌套层级
|
|
122
|
-
* 记录每个列表容器的位置,在原位置插入转换后的结构
|
|
123
|
-
*/
|
|
124
|
-
// 第一步:找到所有顶层列表容器并标记其位置
|
|
125
|
-
var topLevelLists_1 = [];
|
|
126
|
-
// 递归收集列表项的函数
|
|
127
|
-
var collectListItems_1 = function ($container, currentLevel) {
|
|
128
|
-
if (currentLevel === void 0) { currentLevel = 0; }
|
|
129
|
-
var items = [];
|
|
130
|
-
$container.children().each(function () {
|
|
131
|
-
var $child = $(this);
|
|
132
|
-
if ($child.is("li")) {
|
|
133
|
-
var isOrdered = $child.parent().is("ol");
|
|
134
|
-
var orderIndex = 1;
|
|
135
|
-
if (isOrdered) {
|
|
136
|
-
// 计算在同一个ol中的序号
|
|
137
|
-
orderIndex = $child.prevAll("li").length + 1;
|
|
77
|
+
// 将px转换为rem,font-size不转换
|
|
78
|
+
if (config === null || config === void 0 ? void 0 : config.isToRem) {
|
|
79
|
+
$("*").each(function () {
|
|
80
|
+
var $element = $(this);
|
|
81
|
+
var style = $element.attr("style");
|
|
82
|
+
if (style) {
|
|
83
|
+
var newStyle = style.replace(/([\w-]+)\s*:\s*([^;]+)/g, function (match, property, value) {
|
|
84
|
+
if (property.trim() !== "font-size" && property.trim() !== "letter-spacing") {
|
|
85
|
+
var newValue = value.replace(/(\d+(?:\.\d+)?)px/g, function (pxMatch, pxValue) {
|
|
86
|
+
var remValue = parseFloat(pxValue) / 100;
|
|
87
|
+
return "".concat(remValue, "rem");
|
|
88
|
+
});
|
|
89
|
+
return "".concat(property, ": ").concat(newValue);
|
|
138
90
|
}
|
|
139
|
-
|
|
140
|
-
var marker = isOrdered ? "".concat(orderIndex, ".") : "•";
|
|
141
|
-
// 计算缩进
|
|
142
|
-
var paddingLeft = currentLevel * 2; // 每层缩进2rem
|
|
143
|
-
// 获取li的直接文本内容,不包括嵌套的子列表
|
|
144
|
-
var $liClone = $child.clone();
|
|
145
|
-
$liClone.find("ol, ul").remove();
|
|
146
|
-
var textContent = $liClone.text().trim() || "";
|
|
147
|
-
var style = $child.attr("style") || "";
|
|
148
|
-
items.push({
|
|
149
|
-
level: currentLevel,
|
|
150
|
-
isOrdered: isOrdered,
|
|
151
|
-
orderIndex: orderIndex,
|
|
152
|
-
marker: marker,
|
|
153
|
-
paddingLeft: paddingLeft,
|
|
154
|
-
textContent: textContent,
|
|
155
|
-
style: style,
|
|
156
|
-
});
|
|
157
|
-
// 递归处理li内的子列表(只处理真正嵌套在当前li内的列表)
|
|
158
|
-
$child.find("ol, ul").each(function () {
|
|
159
|
-
// 确保这个列表是当前li的直接子元素,而不是更深层的
|
|
160
|
-
var $nestedList = $(this);
|
|
161
|
-
if ($nestedList.parent().closest("li")[0] === $child[0]) {
|
|
162
|
-
var childItems = collectListItems_1($nestedList, currentLevel + 1);
|
|
163
|
-
items.push.apply(items, childItems);
|
|
164
|
-
}
|
|
165
|
-
});
|
|
166
|
-
}
|
|
167
|
-
});
|
|
168
|
-
return items;
|
|
169
|
-
};
|
|
170
|
-
// 找到所有顶层列表(直接在body下或其他容器中的ol/ul)
|
|
171
|
-
$("ol, ul").each(function () {
|
|
172
|
-
var $list = $(this);
|
|
173
|
-
// 检查是否为顶层列表(不在其他列表内部)
|
|
174
|
-
if ($list.parents("ol, ul").length === 0) {
|
|
175
|
-
// 创建占位符标记原始位置
|
|
176
|
-
var placeholder = $("<div data-list-placeholder=\"true\"></div>");
|
|
177
|
-
$list.before(placeholder);
|
|
178
|
-
// 收集该列表的所有项目
|
|
179
|
-
var items = collectListItems_1($list, 1);
|
|
180
|
-
topLevelLists_1.push({
|
|
181
|
-
element: $list,
|
|
182
|
-
placeholder: placeholder,
|
|
183
|
-
items: items,
|
|
91
|
+
return match;
|
|
184
92
|
});
|
|
93
|
+
$element.attr("style", newStyle);
|
|
185
94
|
}
|
|
186
95
|
});
|
|
187
|
-
// 第二步:移除所有ol/ul/li结构
|
|
188
|
-
$("ol, ul, li").remove();
|
|
189
|
-
// 第三步:在每个占位符位置插入转换后的列表项
|
|
190
|
-
topLevelLists_1.forEach(function (listInfo) {
|
|
191
|
-
var placeholder = listInfo.placeholder, items = listInfo.items;
|
|
192
|
-
// 为该列表生成HTML
|
|
193
|
-
var listHtml = items
|
|
194
|
-
.map(function (item) {
|
|
195
|
-
return ("<div style=\"".concat(mergeStyles(item.style, "padding-left: ".concat(item.paddingLeft, "rem"), "flex-shrink: 0", "width: 100%", "flex-direction: row", "display: flex"), "\" data-list-item=\"true\">") +
|
|
196
|
-
"<text style=\"".concat(mergeStyles("flex-shrink: 0", "width: 100%", "line-height: 1", "display: flex", "flex-direction: row"), "\">") +
|
|
197
|
-
"<div style=\"".concat(mergeStyles("word-break: break-word", "flex-shrink: 0", "margin-right: 0.5rem"), "\">").concat(item.marker, "</div>") +
|
|
198
|
-
"<div style=\"".concat(mergeStyles("word-break: break-word", "flex-shrink: 0", "flex: 1"), "\">").concat(item.textContent, "</div>") +
|
|
199
|
-
"</text>" +
|
|
200
|
-
"</div>");
|
|
201
|
-
})
|
|
202
|
-
.join("");
|
|
203
|
-
// 在占位符位置插入列表HTML
|
|
204
|
-
placeholder.after(listHtml);
|
|
205
|
-
// 移除占位符
|
|
206
|
-
placeholder.remove();
|
|
207
|
-
});
|
|
208
96
|
}
|
|
209
|
-
//pixui
|
|
210
|
-
$("
|
|
211
|
-
|
|
212
|
-
});
|
|
213
|
-
//将 a 标签替换为简单div,处理 href,预处理内部样式标签并合并样式
|
|
214
|
-
$("a").each(function (i, ele) {
|
|
215
|
-
var id = "PA_RichTextHrefId_".concat(hrefIdCnt++);
|
|
216
|
-
var href = $(this).attr("href");
|
|
217
|
-
var originalStyle = $(this).attr("style") || "";
|
|
218
|
-
var textContent = $(this).text(); // 获取纯文本内容
|
|
219
|
-
// 收集内部样式标签的样式
|
|
220
|
-
var mergedStyles = [];
|
|
221
|
-
if ($(this).find("strong").length > 0) {
|
|
222
|
-
mergedStyles.push("font-weight: bold;");
|
|
223
|
-
}
|
|
224
|
-
if ($(this).find("em").length > 0) {
|
|
225
|
-
mergedStyles.push("font-style: italic;");
|
|
226
|
-
}
|
|
227
|
-
if ($(this).find("u").length > 0) {
|
|
228
|
-
mergedStyles.push("text-decoration: underline;");
|
|
229
|
-
}
|
|
230
|
-
if ($(this).find("s").length > 0) {
|
|
231
|
-
mergedStyles.push("text-decoration: line-through;");
|
|
232
|
-
}
|
|
233
|
-
// 收集内部span等标签的style属性
|
|
97
|
+
//pixui不支持ol,li节点,将其替换成div并且手动补充li节点前面的标号和后面的br节点
|
|
98
|
+
$("ol").each(function () {
|
|
99
|
+
var i = 1;
|
|
234
100
|
$(this)
|
|
235
|
-
.
|
|
101
|
+
.children("li")
|
|
236
102
|
.each(function () {
|
|
237
|
-
|
|
238
|
-
if (innerStyle) {
|
|
239
|
-
mergedStyles.push(innerStyle);
|
|
240
|
-
}
|
|
103
|
+
$(this).prepend("<text style=\"flex-shrink: 0;\">".concat(i++, ".</text>"));
|
|
241
104
|
});
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
href: href,
|
|
251
|
-
id: id,
|
|
252
|
-
});
|
|
253
|
-
}
|
|
254
|
-
// 转换为简单div,样式已合并
|
|
255
|
-
$(this).replaceWith("<div style=\"".concat(finalStyle, "\" id=\"").concat(id, "\" class=\"PA_RichTextHref_ATag\" >").concat(textContent, "</div>"));
|
|
105
|
+
$(this).replaceWith($(this).html() || "");
|
|
106
|
+
});
|
|
107
|
+
$("li").each(function () {
|
|
108
|
+
$(this).before("<br>");
|
|
109
|
+
});
|
|
110
|
+
//pixui连续的br不生效,用透明文字占位
|
|
111
|
+
$("br").each(function () {
|
|
112
|
+
$(this).replaceWith("<span style='color: transparent; flex-shrink: 0;font-size: 20px;' class='pixui-richtext-br-placeholder'>1</span>");
|
|
256
113
|
});
|
|
257
114
|
//找到所有的文字节点,外层包裹text标签
|
|
258
115
|
$("*").each(function () {
|
|
259
|
-
// 跳过链接节点内部的文本处理
|
|
260
|
-
var nodeId = $(this).attr("id") || "";
|
|
261
|
-
if (nodeId.startsWith("PA_RichTextHrefId_")) {
|
|
262
|
-
return; // 跳过链接节点,不处理其内部文本
|
|
263
|
-
}
|
|
264
|
-
// 跳过列表项,因为已经处理完成
|
|
265
|
-
var isListItem = $(this).attr("data-list-item") === "true";
|
|
266
|
-
if (isListItem) {
|
|
267
|
-
return; // 跳过列表项
|
|
268
|
-
}
|
|
269
116
|
$(this)
|
|
270
117
|
.contents()
|
|
271
118
|
.each(function () {
|
|
272
|
-
// 检查当前文本节点是否在链接节点内部
|
|
273
|
-
var linkParent = $(this).closest("[id^='PA_RichTextHrefId_']");
|
|
274
|
-
if (linkParent.length > 0) {
|
|
275
|
-
return; // 跳过链接节点内部的文本
|
|
276
|
-
}
|
|
277
|
-
// 检查当前文本节点是否在列表项内部
|
|
278
|
-
var listParent = $(this).closest("[data-list-item='true']");
|
|
279
|
-
if (listParent.length > 0) {
|
|
280
|
-
return; // 跳过列表项内部的文本
|
|
281
|
-
}
|
|
282
119
|
if (this.type === "text") {
|
|
283
120
|
var text = this.data.trim();
|
|
284
121
|
if (text.length > 0) {
|
|
285
|
-
$(this).replaceWith("<text style=\"
|
|
122
|
+
$(this).replaceWith("<text style=\"word-break: break-word;flex-shrink: 0;flex-direction: row;\">".concat(text, "</text>"));
|
|
286
123
|
}
|
|
287
124
|
}
|
|
288
125
|
});
|
|
@@ -291,33 +128,33 @@ var RichText;
|
|
|
291
128
|
$("strong").each(function () {
|
|
292
129
|
var html = $(this).html();
|
|
293
130
|
var style = $(this).attr("style") || "";
|
|
294
|
-
$(this).replaceWith("<text style=\"".concat(
|
|
131
|
+
$(this).replaceWith("<text style=\"".concat(style, " font-weight: bold;flex-shrink: 0;\">").concat(html, "</text>"));
|
|
295
132
|
});
|
|
296
133
|
$("em").each(function () {
|
|
297
134
|
var html = $(this).html();
|
|
298
135
|
var style = $(this).attr("style") || "";
|
|
299
|
-
$(this).replaceWith("<text style=\"".concat(
|
|
136
|
+
$(this).replaceWith("<text style=\"".concat(style, " font-style: italic;flex-shrink: 0;\">").concat(html, "</text>"));
|
|
300
137
|
});
|
|
301
138
|
$("u").each(function () {
|
|
302
139
|
var html = $(this).html();
|
|
303
140
|
var style = $(this).attr("style") || "";
|
|
304
|
-
$(this).replaceWith("<text style=\"".concat(
|
|
141
|
+
$(this).replaceWith("<text style=\"".concat(style, " text-decoration: underline;flex-shrink: 0;\">").concat(html, "</text>"));
|
|
305
142
|
});
|
|
306
143
|
$("s").each(function () {
|
|
307
144
|
var html = $(this).html();
|
|
308
145
|
var style = $(this).attr("style") || "";
|
|
309
|
-
$(this).replaceWith("<text style=\"".concat(
|
|
146
|
+
$(this).replaceWith("<text style=\"".concat(style, " text-decoration: line-through;flex-shrink: 0;\">").concat(html, "</text>"));
|
|
310
147
|
});
|
|
311
148
|
$("span").each(function () {
|
|
312
149
|
var html = $(this).html();
|
|
313
150
|
var style = $(this).attr("style") || "";
|
|
314
|
-
$(this).replaceWith("<text style=\"".concat(
|
|
151
|
+
$(this).replaceWith("<text style=\"".concat(style, " flex-shrink: 0;\">").concat(html, "</text>"));
|
|
315
152
|
});
|
|
316
153
|
//p换成div
|
|
317
154
|
$("p").each(function () {
|
|
318
155
|
var html = $(this).html();
|
|
319
156
|
var style = $(this).attr("style") || "";
|
|
320
|
-
$(this).replaceWith("<div style=\"".concat(
|
|
157
|
+
$(this).replaceWith("<div style=\"".concat(style, " ;flex-shrink: 0;width:100%;\">").concat(html, "</div>"));
|
|
321
158
|
});
|
|
322
159
|
//处理 img 上的 href
|
|
323
160
|
$("img").each(function (i, ele) {
|
|
@@ -332,19 +169,27 @@ var RichText;
|
|
|
332
169
|
});
|
|
333
170
|
}
|
|
334
171
|
$(this).attr("href", "");
|
|
335
|
-
|
|
336
|
-
|
|
172
|
+
});
|
|
173
|
+
//将 a 标签替换为div,处理 href
|
|
174
|
+
$("a").each(function (i, ele) {
|
|
175
|
+
var id = "PA_RichTextHrefId_".concat(hrefIdCnt++);
|
|
176
|
+
var href = $(this).attr("href");
|
|
177
|
+
var style = $(this).attr("style") || "";
|
|
178
|
+
var html = $(this).html();
|
|
179
|
+
if (href) {
|
|
180
|
+
linkNodes.push({
|
|
181
|
+
type: LinkNodeType.DIV,
|
|
182
|
+
href: href,
|
|
183
|
+
id: id,
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
$(this).replaceWith("<div style=\"".concat(style, "\" id=\"").concat(id, "\">").concat(html, "</div>"));
|
|
337
187
|
});
|
|
338
188
|
//补充 flex-shrink: 0
|
|
339
189
|
["h1", "h2", "h3", "h4", "h5", "h6", "a", "img", "div"].forEach(function (tag) {
|
|
340
190
|
$("".concat(tag)).each(function () {
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
var inListItem = $(this).closest("[data-list-item='true']").length > 0;
|
|
344
|
-
if (!isListItem && !inListItem) {
|
|
345
|
-
var style = $(this).attr("style") || "";
|
|
346
|
-
$(this).attr("style", mergeStyles(style, "flex-shrink: 0"));
|
|
347
|
-
}
|
|
191
|
+
var style = $(this).attr("style") || "";
|
|
192
|
+
$(this).attr("style", "".concat(style, " flex-shrink: 0;"));
|
|
348
193
|
});
|
|
349
194
|
});
|
|
350
195
|
}
|
|
@@ -359,7 +204,7 @@ var RichText;
|
|
|
359
204
|
var $child = $(this);
|
|
360
205
|
var childStyle = $child.attr("style") || "";
|
|
361
206
|
// 合并style属性,将父节点的style附加到子节点上
|
|
362
|
-
var mergedStyle =
|
|
207
|
+
var mergedStyle = "".concat(parentStyle, "; ").concat(childStyle);
|
|
363
208
|
// 更新子元素的style属性
|
|
364
209
|
$child.attr("style", mergedStyle);
|
|
365
210
|
});
|
|
@@ -375,48 +220,22 @@ var RichText;
|
|
|
375
220
|
["h1", "h2", "h3", "h4", "h5", "h6", "div"].map(function (tag) {
|
|
376
221
|
// text的父节点
|
|
377
222
|
$("".concat(tag)).each(function () {
|
|
378
|
-
|
|
379
|
-
var isListItem = $(this).attr("data-list-item") === "true";
|
|
380
|
-
var inListItem = $(this).closest("[data-list-item='true']").length > 0;
|
|
381
|
-
// 跳过链接节点、列表项本身以及列表项内部的节点
|
|
382
|
-
if (!nodeId.startsWith("PA_RichTextHrefId_") && !isListItem && !inListItem) {
|
|
383
|
-
nodearr_1.push(this);
|
|
384
|
-
}
|
|
223
|
+
nodearr_1.push(this);
|
|
385
224
|
});
|
|
386
225
|
});
|
|
387
226
|
nodearr_1.forEach(function (node) {
|
|
388
227
|
var tag = $(node).prop("tagName");
|
|
389
|
-
var nodeId = $(node).attr("id") || ""; // 保存节点ID
|
|
390
|
-
// 处理text子节点,将text内容转换为div
|
|
391
228
|
$(node)
|
|
392
229
|
.children("text")
|
|
393
230
|
.each(function () {
|
|
394
|
-
// 检查是否在列表项内部
|
|
395
|
-
var inListItem = $(this).closest("[data-list-item='true']").length > 0;
|
|
396
|
-
if (inListItem) {
|
|
397
|
-
return; // 跳过列表项内部的text节点
|
|
398
|
-
}
|
|
399
231
|
var text = $(this).html();
|
|
400
232
|
var style = $(this).attr("style") || "";
|
|
401
|
-
$(this).replaceWith("<div style=\"".concat(
|
|
233
|
+
$(this).replaceWith("<div style=\"".concat(style, "\">").concat(text, "</div>"));
|
|
402
234
|
});
|
|
403
|
-
var taghtml = $(node).html()
|
|
235
|
+
var taghtml = $(node).html();
|
|
404
236
|
var tagstyle = $(node).attr("style") || "";
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
var idAttr = nodeId ? " id=\"".concat(nodeId, "\"") : "";
|
|
408
|
-
// 保留所有自定义属性
|
|
409
|
-
var customAttrs = "";
|
|
410
|
-
var attributes = $(node).get(0).attribs || {};
|
|
411
|
-
for (var _i = 0, _a = Object.entries(attributes); _i < _a.length; _i++) {
|
|
412
|
-
var _b = _a[_i], key = _b[0], value = _b[1];
|
|
413
|
-
if (key !== "style" && key !== "id") {
|
|
414
|
-
customAttrs += " ".concat(key, "=\"").concat(value, "\"");
|
|
415
|
-
}
|
|
416
|
-
}
|
|
417
|
-
//自己的子节点外套一个text,自己不变
|
|
418
|
-
$(node).replaceWith("<".concat(tag, " style=\"").concat(mergeStyles(tagstyle, "flex-direction: row"), "\"").concat(idAttr).concat(customAttrs, "><text style=\"").concat(mergeStyles("flex-shrink: 0", "width: 100%"), "\">").concat(taghtml, "</text></").concat(tag, ">"));
|
|
419
|
-
}
|
|
237
|
+
//自己的子节点外套一个text,自己不变
|
|
238
|
+
$(node).replaceWith("<".concat(tag, " style=\"").concat(tagstyle, ";flex-direction: row;\"><text style=\"flex-shrink: 0;width: 100%;\" tag=\"\u6BB5\u843Dtext\">").concat(taghtml, "</text></").concat(tag, ">"));
|
|
420
239
|
});
|
|
421
240
|
//text-indent 处理首行缩进
|
|
422
241
|
$("*").each(function () {
|
|
@@ -427,7 +246,7 @@ var RichText;
|
|
|
427
246
|
* 状态为<div style=text-indent:xxx><text><透明字符节点/><div style=样式>文字</div></text></div>
|
|
428
247
|
* 属性是几 em 就加几个字符
|
|
429
248
|
* */
|
|
430
|
-
var $spacerText = $("<div style=\"
|
|
249
|
+
var $spacerText = $("<div style=\"color: transparent; flex-shrink: 0;\">".concat("一".repeat(parseInt(textIndent)), "</div>"));
|
|
431
250
|
// 寻找子节点中的text节点
|
|
432
251
|
var textChild = $(this).children("text").first();
|
|
433
252
|
if (textChild.length > 0) {
|
|
@@ -455,9 +274,7 @@ var RichText;
|
|
|
455
274
|
});
|
|
456
275
|
var lineHeightScale = (config === null || config === void 0 ? void 0 : config.lineHeightScale) || 1;
|
|
457
276
|
// pixui 中的实际显示的距离可能与网页中实际显示的距离差距较大
|
|
458
|
-
|
|
459
|
-
$text.css("line-height", maxLineHeight * lineHeightScale + "");
|
|
460
|
-
}
|
|
277
|
+
$text.css("line-height", maxLineHeight * lineHeightScale + "");
|
|
461
278
|
});
|
|
462
279
|
//将div中的letter-spacing转移到text上
|
|
463
280
|
$("text").each(function () {
|
|
@@ -490,6 +307,14 @@ var RichText;
|
|
|
490
307
|
$(this).remove();
|
|
491
308
|
}
|
|
492
309
|
});
|
|
310
|
+
// $(`div`).each(function () {
|
|
311
|
+
// let style = $(this).attr("style") || "";
|
|
312
|
+
// console.log("???", style);
|
|
313
|
+
// //如果没有fontsize
|
|
314
|
+
// if (!style.includes("font-size")) {
|
|
315
|
+
// $(this).attr("style", `${style} font-size:16px;`);
|
|
316
|
+
// }
|
|
317
|
+
// });
|
|
493
318
|
var hTagRem_1 = ["2rem", "1.5rem", "1.17rem", "1rem", "0.83rem", "0.67rem"];
|
|
494
319
|
["h1", "h2", "h3", "h4", "h5", "h6"].map(function (tag) {
|
|
495
320
|
return $("".concat(tag)).each(function () {
|
|
@@ -497,7 +322,7 @@ var RichText;
|
|
|
497
322
|
var style = $(this).attr("style") || "";
|
|
498
323
|
//如果没有fontsize
|
|
499
324
|
if (!style.includes("font-size")) {
|
|
500
|
-
$(this).attr("style",
|
|
325
|
+
$(this).attr("style", "".concat(style, " font-size:").concat(hTagRem_1[idx]));
|
|
501
326
|
}
|
|
502
327
|
});
|
|
503
328
|
});
|
|
@@ -505,7 +330,7 @@ var RichText;
|
|
|
505
330
|
//手动替换nbsp
|
|
506
331
|
var res = $.html();
|
|
507
332
|
res = res.replaceAll(/<img([^>]+)>/g, "<img$1 />").replaceAll(/ /g, " ");
|
|
508
|
-
console.log(res);
|
|
333
|
+
// console.log(res);
|
|
509
334
|
return res;
|
|
510
335
|
}
|
|
511
336
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { RichText } from "./
|
|
2
|
-
export { RichText as default } from "./
|
|
1
|
+
export { RichText } from "./RichTextUtils";
|
|
2
|
+
export { RichText as default } from "./RichTextUtils";
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.default = exports.RichText = void 0;
|
|
4
|
-
var
|
|
5
|
-
Object.defineProperty(exports, "RichText", { enumerable: true, get: function () { return
|
|
6
|
-
var
|
|
7
|
-
Object.defineProperty(exports, "default", { enumerable: true, get: function () { return
|
|
4
|
+
var RichTextUtils_1 = require("./RichTextUtils");
|
|
5
|
+
Object.defineProperty(exports, "RichText", { enumerable: true, get: function () { return RichTextUtils_1.RichText; } });
|
|
6
|
+
var RichTextUtils_2 = require("./RichTextUtils");
|
|
7
|
+
Object.defineProperty(exports, "default", { enumerable: true, get: function () { return RichTextUtils_2.RichText; } });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pixui-dev/pixui-richtext-helper",
|
|
3
|
-
"version": "0.1.1
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "pixui richtext helper",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -19,9 +19,8 @@
|
|
|
19
19
|
"author": "jnjnjnzhang",
|
|
20
20
|
"license": "ISC",
|
|
21
21
|
"devDependencies": {
|
|
22
|
-
"@types/node": "^22.
|
|
23
|
-
"
|
|
24
|
-
"typescript": "^5.8.3"
|
|
22
|
+
"@types/node": "^22.5.4",
|
|
23
|
+
"typescript": "^5.0.0"
|
|
25
24
|
},
|
|
26
25
|
"dependencies": {
|
|
27
26
|
"cheerio": "1.0.0-rc.10"
|
package/dist/RichText.d.ts
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { RichText_Refactor, LinkNodeType, LinkClickParams } from "./richtext/RichText_Refactor";
|
|
2
|
-
/**
|
|
3
|
-
* 对外暴露的 RichText 组件。
|
|
4
|
-
* 保持旧版使用方式不变,内部委托给 RichText_Refactor 实现。
|
|
5
|
-
*/
|
|
6
|
-
export declare const RichText: {
|
|
7
|
-
/** 链接节点类型枚举 */
|
|
8
|
-
LinkNodeType: typeof LinkNodeType;
|
|
9
|
-
/**
|
|
10
|
-
* 将富文本转换为 PixUI innerHTML 兼容格式
|
|
11
|
-
* @see RichText_Refactor.convertRichTextToPixuiStyle
|
|
12
|
-
*/
|
|
13
|
-
convertRichTextToPixuiStyle: typeof RichText_Refactor.convertRichTextToPixuiStyle;
|
|
14
|
-
/**
|
|
15
|
-
* 绑定富文本中的链接点击事件
|
|
16
|
-
* @see RichText_Refactor.bindLinkClickEvents
|
|
17
|
-
*/
|
|
18
|
-
bindLinkClickEvents: typeof RichText_Refactor.bindLinkClickEvents;
|
|
19
|
-
};
|
|
20
|
-
export type { LinkClickParams };
|
|
21
|
-
export { LinkNodeType };
|
|
22
|
-
export default RichText;
|
package/dist/RichText.js
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.LinkNodeType = exports.RichText = void 0;
|
|
4
|
-
var RichText_Refactor_1 = require("./richtext/RichText_Refactor");
|
|
5
|
-
Object.defineProperty(exports, "LinkNodeType", { enumerable: true, get: function () { return RichText_Refactor_1.LinkNodeType; } });
|
|
6
|
-
/**
|
|
7
|
-
* 对外暴露的 RichText 组件。
|
|
8
|
-
* 保持旧版使用方式不变,内部委托给 RichText_Refactor 实现。
|
|
9
|
-
*/
|
|
10
|
-
exports.RichText = {
|
|
11
|
-
/** 链接节点类型枚举 */
|
|
12
|
-
LinkNodeType: RichText_Refactor_1.LinkNodeType,
|
|
13
|
-
/**
|
|
14
|
-
* 将富文本转换为 PixUI innerHTML 兼容格式
|
|
15
|
-
* @see RichText_Refactor.convertRichTextToPixuiStyle
|
|
16
|
-
*/
|
|
17
|
-
convertRichTextToPixuiStyle: RichText_Refactor_1.RichText_Refactor.convertRichTextToPixuiStyle,
|
|
18
|
-
/**
|
|
19
|
-
* 绑定富文本中的链接点击事件
|
|
20
|
-
* @see RichText_Refactor.bindLinkClickEvents
|
|
21
|
-
*/
|
|
22
|
-
bindLinkClickEvents: RichText_Refactor_1.RichText_Refactor.bindLinkClickEvents,
|
|
23
|
-
};
|
|
24
|
-
exports.default = exports.RichText;
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
/*****************************************************
|
|
2
|
-
* 类型、枚举定义
|
|
3
|
-
*****************************************************/
|
|
4
|
-
/** 链接节点的类型 */
|
|
5
|
-
export declare enum LinkNodeType {
|
|
6
|
-
IMG = "img",
|
|
7
|
-
DIV = "div"
|
|
8
|
-
}
|
|
9
|
-
/** 点击回调参数 */
|
|
10
|
-
export interface LinkClickParams {
|
|
11
|
-
type: LinkNodeType;
|
|
12
|
-
href: string;
|
|
13
|
-
id: string;
|
|
14
|
-
}
|
|
15
|
-
/*****************************************************
|
|
16
|
-
* RichText_Refactor 主类
|
|
17
|
-
*****************************************************/
|
|
18
|
-
export declare class RichText_Refactor {
|
|
19
|
-
private static linkNodes;
|
|
20
|
-
private static hrefIdCnt;
|
|
21
|
-
/**
|
|
22
|
-
* 富文本转换为 PixUI innerHTML 兼容格式
|
|
23
|
-
* @param str 原始富文本 HTML
|
|
24
|
-
* @param config 可选配置
|
|
25
|
-
*/
|
|
26
|
-
static convertRichTextToPixuiStyle(str: string, config?: {
|
|
27
|
-
lineHeightScale?: number;
|
|
28
|
-
}): string;
|
|
29
|
-
/**
|
|
30
|
-
* 绑定链接点击事件
|
|
31
|
-
*/
|
|
32
|
-
static bindLinkClickEvents(linkClickHandler: (params: LinkClickParams) => void): void;
|
|
33
|
-
/*****************************************************
|
|
34
|
-
* 内部流程函数
|
|
35
|
-
*****************************************************/
|
|
36
|
-
/**
|
|
37
|
-
* 将 HTML 切分为基础段落片段。
|
|
38
|
-
* 简易实现:以顶级节点为粒度切分,再根据最外层列表节点进行分割。
|
|
39
|
-
*/
|
|
40
|
-
private static splitIntoSegments;
|
|
41
|
-
/**
|
|
42
|
-
* 处理单个段落片段,返回转换后的片段 HTML
|
|
43
|
-
*/
|
|
44
|
-
private static processSegment;
|
|
45
|
-
private static handleIndentClass;
|
|
46
|
-
private static fixImgSizeUnit;
|
|
47
|
-
/** 列表处理(将 ol/ul/li 替换为 div 结构) */
|
|
48
|
-
private static handleLists;
|
|
49
|
-
/** 将连续 <br> 替换为透明占位文字,确保 PixUI 换行 */
|
|
50
|
-
private static replaceBrWithPlaceholder;
|
|
51
|
-
/** 处理 <a> 标签:转为 div、保留样式、记录链接 */
|
|
52
|
-
private static handleAnchorTag;
|
|
53
|
-
/** 用 text 标签包裹纯文本节点 */
|
|
54
|
-
private static wrapTextNodes;
|
|
55
|
-
/** strong / em / u / s / span 等标签替换成 text */
|
|
56
|
-
private static replaceStyleTags;
|
|
57
|
-
/** p → div */
|
|
58
|
-
private static replacePTag;
|
|
59
|
-
/** img 的 href 转移处理 & 记录链接 */
|
|
60
|
-
private static handleImgHref;
|
|
61
|
-
/** 给指定标签补 flex-shrink:0 */
|
|
62
|
-
private static addFlexShrink;
|
|
63
|
-
/** 把嵌套的 text 展平 */
|
|
64
|
-
private static flattenNestedText;
|
|
65
|
-
/** 将同一行的 text 节点转为 div 并外包一层 text */
|
|
66
|
-
private static convertSiblingTextToDiv;
|
|
67
|
-
/** text-indent 首行缩进处理 */
|
|
68
|
-
private static handleTextIndent;
|
|
69
|
-
/** line-height / letter-spacing 调整 */
|
|
70
|
-
private static adjustLineHeightAndLetterSpacing;
|
|
71
|
-
/** 把 div 的 text-align 转移到子 text 上 */
|
|
72
|
-
private static transferTextAlign;
|
|
73
|
-
/** 删除空 text 节点 */
|
|
74
|
-
private static removeEmptyText;
|
|
75
|
-
/** 补默认 heading 字体大小 */
|
|
76
|
-
private static fixHeadingFontSize;
|
|
77
|
-
}
|
|
@@ -1,645 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
36
|
-
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
37
|
-
if (ar || !(i in from)) {
|
|
38
|
-
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
39
|
-
ar[i] = from[i];
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
return to.concat(ar || Array.prototype.slice.call(from));
|
|
43
|
-
};
|
|
44
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
-
exports.RichText_Refactor = exports.LinkNodeType = void 0;
|
|
46
|
-
var cheerio = __importStar(require("cheerio"));
|
|
47
|
-
/*****************************************************
|
|
48
|
-
* 类型、枚举定义
|
|
49
|
-
*****************************************************/
|
|
50
|
-
/** 链接节点的类型 */
|
|
51
|
-
var LinkNodeType;
|
|
52
|
-
(function (LinkNodeType) {
|
|
53
|
-
LinkNodeType["IMG"] = "img";
|
|
54
|
-
LinkNodeType["DIV"] = "div";
|
|
55
|
-
})(LinkNodeType || (exports.LinkNodeType = LinkNodeType = {}));
|
|
56
|
-
/*****************************************************
|
|
57
|
-
* 工具函数
|
|
58
|
-
*****************************************************/
|
|
59
|
-
/**
|
|
60
|
-
* 解析 style 字符串为对象
|
|
61
|
-
*/
|
|
62
|
-
var parseStyleString = function (styleStr) {
|
|
63
|
-
var result = {};
|
|
64
|
-
if (!styleStr || !styleStr.trim())
|
|
65
|
-
return result;
|
|
66
|
-
// 分割多个样式声明
|
|
67
|
-
var declarations = styleStr.split(";").filter(function (decl) { return decl.trim(); });
|
|
68
|
-
declarations.forEach(function (decl) {
|
|
69
|
-
var colonIndex = decl.indexOf(":");
|
|
70
|
-
if (colonIndex > 0) {
|
|
71
|
-
var property = decl.substring(0, colonIndex).trim();
|
|
72
|
-
var value = decl.substring(colonIndex + 1).trim();
|
|
73
|
-
if (property && value) {
|
|
74
|
-
result[property] = value;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
});
|
|
78
|
-
return result;
|
|
79
|
-
};
|
|
80
|
-
/**
|
|
81
|
-
* 将样式对象序列化为字符串
|
|
82
|
-
*/
|
|
83
|
-
var serializeStyleObject = function (styleObj) {
|
|
84
|
-
return (Object.entries(styleObj)
|
|
85
|
-
.map(function (_a) {
|
|
86
|
-
var property = _a[0], value = _a[1];
|
|
87
|
-
return "".concat(property, ": ").concat(value);
|
|
88
|
-
})
|
|
89
|
-
.join("; ") + (Object.keys(styleObj).length > 0 ? ";" : ""));
|
|
90
|
-
};
|
|
91
|
-
/**
|
|
92
|
-
* 合并多个 style 字符串,自动处理分号与空格,后合并的覆盖前面的(符合CSS优先级规则)
|
|
93
|
-
*/
|
|
94
|
-
var mergeStyles = function () {
|
|
95
|
-
var styles = [];
|
|
96
|
-
for (var _i = 0; _i < arguments.length; _i++) {
|
|
97
|
-
styles[_i] = arguments[_i];
|
|
98
|
-
}
|
|
99
|
-
var mergedStyleObj = {};
|
|
100
|
-
// 过滤空值并解析每个样式字符串
|
|
101
|
-
var validStyles = styles.filter(function (s) { return !!s && s.trim().length > 0; });
|
|
102
|
-
// 按顺序合并,后面的覆盖前面的
|
|
103
|
-
validStyles.forEach(function (styleStr) {
|
|
104
|
-
var styleObj = parseStyleString(styleStr);
|
|
105
|
-
Object.assign(mergedStyleObj, styleObj);
|
|
106
|
-
});
|
|
107
|
-
return serializeStyleObject(mergedStyleObj);
|
|
108
|
-
};
|
|
109
|
-
/*****************************************************
|
|
110
|
-
* RichText_Refactor 主类
|
|
111
|
-
*****************************************************/
|
|
112
|
-
var RichText_Refactor = /** @class */ (function () {
|
|
113
|
-
function RichText_Refactor() {
|
|
114
|
-
}
|
|
115
|
-
/**
|
|
116
|
-
* 富文本转换为 PixUI innerHTML 兼容格式
|
|
117
|
-
* @param str 原始富文本 HTML
|
|
118
|
-
* @param config 可选配置
|
|
119
|
-
*/
|
|
120
|
-
RichText_Refactor.convertRichTextToPixuiStyle = function (str, config) {
|
|
121
|
-
// 重置全局状态
|
|
122
|
-
RichText_Refactor.linkNodes = [];
|
|
123
|
-
RichText_Refactor.hrefIdCnt = 0;
|
|
124
|
-
// ---------- 第 1 步:段落分割(基础实现:根节点切分) ----------
|
|
125
|
-
var segments = RichText_Refactor.splitIntoSegments(str);
|
|
126
|
-
// ---------- 第 2/3 步:遍历 + 展平 ----------
|
|
127
|
-
// 为保证兼容性,我们直接对 HTML 进行逐段处理并在内部构建 PixUI 结构。
|
|
128
|
-
// 这样既保持分段概念,又可复用旧逻辑的稳定性。
|
|
129
|
-
var processedSegments = segments.map(function (seg) { return RichText_Refactor.processSegment(seg, config); });
|
|
130
|
-
// ---------- 第 4 步:拼装 ----------
|
|
131
|
-
var Result = processedSegments.join("");
|
|
132
|
-
console.log(Result);
|
|
133
|
-
return Result;
|
|
134
|
-
};
|
|
135
|
-
/**
|
|
136
|
-
* 绑定链接点击事件
|
|
137
|
-
*/
|
|
138
|
-
RichText_Refactor.bindLinkClickEvents = function (linkClickHandler) {
|
|
139
|
-
RichText_Refactor.linkNodes.forEach(function (nodeInfo) {
|
|
140
|
-
var element = document.getElementById(nodeInfo.id);
|
|
141
|
-
if (element) {
|
|
142
|
-
element.onclick = function (e) {
|
|
143
|
-
e.stopPropagation();
|
|
144
|
-
e.preventDefault();
|
|
145
|
-
linkClickHandler({
|
|
146
|
-
type: nodeInfo.type,
|
|
147
|
-
href: nodeInfo.href,
|
|
148
|
-
id: nodeInfo.id,
|
|
149
|
-
});
|
|
150
|
-
return false;
|
|
151
|
-
};
|
|
152
|
-
}
|
|
153
|
-
});
|
|
154
|
-
};
|
|
155
|
-
/*****************************************************
|
|
156
|
-
* 内部流程函数
|
|
157
|
-
*****************************************************/
|
|
158
|
-
/**
|
|
159
|
-
* 将 HTML 切分为基础段落片段。
|
|
160
|
-
* 简易实现:以顶级节点为粒度切分,再根据最外层列表节点进行分割。
|
|
161
|
-
*/
|
|
162
|
-
RichText_Refactor.splitIntoSegments = function (html) {
|
|
163
|
-
var $ = cheerio.load(html, null, false);
|
|
164
|
-
var segments = [];
|
|
165
|
-
// 如果有 body,取其直接子节点;否则取根节点下的直接子节点
|
|
166
|
-
var roots = $("body").length > 0 ? $("body").children() : $.root().children();
|
|
167
|
-
roots.each(function () {
|
|
168
|
-
var nodeHtml = $(this).toString();
|
|
169
|
-
// 切分包含最外层列表的片段
|
|
170
|
-
if (/^<\s*(ol|ul)/i.test(nodeHtml)) {
|
|
171
|
-
segments.push(nodeHtml);
|
|
172
|
-
}
|
|
173
|
-
else {
|
|
174
|
-
// 进一步检查内部是否存在最外层的 ol/ul,需要分成 前段 + 列表 + 后段
|
|
175
|
-
var inner$_1 = cheerio.load(nodeHtml, null, false);
|
|
176
|
-
var outerLists_1 = [];
|
|
177
|
-
inner$_1("ol, ul").each(function () {
|
|
178
|
-
if (inner$_1(this).parents("ol, ul").length === 0) {
|
|
179
|
-
outerLists_1.push(inner$_1(this).toString());
|
|
180
|
-
}
|
|
181
|
-
});
|
|
182
|
-
if (outerLists_1.length === 0) {
|
|
183
|
-
segments.push(nodeHtml);
|
|
184
|
-
}
|
|
185
|
-
else {
|
|
186
|
-
var tempHtml_1 = nodeHtml;
|
|
187
|
-
outerLists_1.forEach(function (listHtml) {
|
|
188
|
-
var idx = tempHtml_1.indexOf(listHtml);
|
|
189
|
-
if (idx >= 0) {
|
|
190
|
-
var before = tempHtml_1.substring(0, idx);
|
|
191
|
-
if (before.trim())
|
|
192
|
-
segments.push(before);
|
|
193
|
-
segments.push(listHtml);
|
|
194
|
-
tempHtml_1 = tempHtml_1.substring(idx + listHtml.length);
|
|
195
|
-
}
|
|
196
|
-
});
|
|
197
|
-
if (tempHtml_1.trim())
|
|
198
|
-
segments.push(tempHtml_1);
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
});
|
|
202
|
-
// fallback:原样返回
|
|
203
|
-
if (segments.length === 0)
|
|
204
|
-
segments.push(html);
|
|
205
|
-
return segments;
|
|
206
|
-
};
|
|
207
|
-
/**
|
|
208
|
-
* 处理单个段落片段,返回转换后的片段 HTML
|
|
209
|
-
*/
|
|
210
|
-
RichText_Refactor.processSegment = function (segmentHtml, config) {
|
|
211
|
-
var $ = cheerio.load(segmentHtml, null, false);
|
|
212
|
-
// 按旧实现顺序进行处理,但重构为独立函数划分
|
|
213
|
-
this.handleIndentClass($);
|
|
214
|
-
this.fixImgSizeUnit($);
|
|
215
|
-
this.handleLists($, (config === null || config === void 0 ? void 0 : config.lineHeightScale) || 1);
|
|
216
|
-
this.replaceBrWithPlaceholder($);
|
|
217
|
-
this.handleAnchorTag($);
|
|
218
|
-
this.wrapTextNodes($);
|
|
219
|
-
this.replaceStyleTags($);
|
|
220
|
-
this.replacePTag($);
|
|
221
|
-
this.handleImgHref($);
|
|
222
|
-
this.addFlexShrink($);
|
|
223
|
-
this.flattenNestedText($);
|
|
224
|
-
this.convertSiblingTextToDiv($);
|
|
225
|
-
this.handleTextIndent($);
|
|
226
|
-
this.adjustLineHeightAndLetterSpacing($, config);
|
|
227
|
-
this.transferTextAlign($);
|
|
228
|
-
this.removeEmptyText($);
|
|
229
|
-
this.fixHeadingFontSize($);
|
|
230
|
-
// 最后:修正 img 结束标签、nbsp
|
|
231
|
-
var res = $.html();
|
|
232
|
-
res = res.replaceAll(/<img([^>]+)>/g, "<img$1 />").replaceAll(/ /g, " ");
|
|
233
|
-
return res;
|
|
234
|
-
};
|
|
235
|
-
// ------------------------------
|
|
236
|
-
// 各独立处理步骤实现
|
|
237
|
-
// ------------------------------
|
|
238
|
-
RichText_Refactor.handleIndentClass = function ($) {
|
|
239
|
-
var _loop_1 = function (i) {
|
|
240
|
-
var indent = "ql-indent-".concat(i);
|
|
241
|
-
var extStyle = "padding-left: ".concat(i * 2, "rem");
|
|
242
|
-
$(".".concat(indent)).each(function () {
|
|
243
|
-
var ori = $(this).attr("style") || "";
|
|
244
|
-
$(this).attr("style", mergeStyles(ori, extStyle));
|
|
245
|
-
$(this).removeClass(indent);
|
|
246
|
-
});
|
|
247
|
-
};
|
|
248
|
-
for (var i = 1; i <= 10; i++) {
|
|
249
|
-
_loop_1(i);
|
|
250
|
-
}
|
|
251
|
-
};
|
|
252
|
-
RichText_Refactor.fixImgSizeUnit = function ($) {
|
|
253
|
-
$("img").each(function () {
|
|
254
|
-
var width = $(this).attr("width");
|
|
255
|
-
var height = $(this).attr("height");
|
|
256
|
-
if (width && width + "" === parseInt(width) + "") {
|
|
257
|
-
$(this).attr("width", "".concat(width, "px"));
|
|
258
|
-
}
|
|
259
|
-
if (height && height + "" === parseInt(height) + "") {
|
|
260
|
-
$(this).attr("height", "".concat(height, "px"));
|
|
261
|
-
}
|
|
262
|
-
});
|
|
263
|
-
};
|
|
264
|
-
/** 列表处理(将 ol/ul/li 替换为 div 结构) */
|
|
265
|
-
RichText_Refactor.handleLists = function ($, lineHeightScale) {
|
|
266
|
-
if (lineHeightScale === void 0) { lineHeightScale = 1; }
|
|
267
|
-
var topLevelLists = [];
|
|
268
|
-
var collectListItems = function ($container, currentLevel) {
|
|
269
|
-
if (currentLevel === void 0) { currentLevel = 0; }
|
|
270
|
-
var items = [];
|
|
271
|
-
$container.children().each(function () {
|
|
272
|
-
var $child = $(this);
|
|
273
|
-
if ($child.is("li")) {
|
|
274
|
-
var isOrdered = $child.parent().is("ol");
|
|
275
|
-
var orderIndex = 1;
|
|
276
|
-
if (isOrdered) {
|
|
277
|
-
orderIndex = $child.prevAll("li").length + 1;
|
|
278
|
-
}
|
|
279
|
-
var marker = isOrdered ? "".concat(orderIndex, ".") : "•";
|
|
280
|
-
var paddingLeft = currentLevel * 2; // 每层缩进 2rem
|
|
281
|
-
var $liClone = $child.clone();
|
|
282
|
-
$liClone.find("ol, ul").remove();
|
|
283
|
-
var textContent = $liClone.text().trim() || "";
|
|
284
|
-
var style = $child.attr("style") || "";
|
|
285
|
-
items.push({
|
|
286
|
-
level: currentLevel,
|
|
287
|
-
isOrdered: isOrdered,
|
|
288
|
-
orderIndex: orderIndex,
|
|
289
|
-
marker: marker,
|
|
290
|
-
paddingLeft: paddingLeft,
|
|
291
|
-
textContent: textContent,
|
|
292
|
-
style: style,
|
|
293
|
-
});
|
|
294
|
-
// 处理子列表
|
|
295
|
-
$child.find("ol, ul").each(function () {
|
|
296
|
-
var $nestedList = $(this);
|
|
297
|
-
if ($nestedList.parent().closest("li")[0] === $child[0]) {
|
|
298
|
-
var childItems = collectListItems($nestedList, currentLevel + 1);
|
|
299
|
-
items.push.apply(items, childItems);
|
|
300
|
-
}
|
|
301
|
-
});
|
|
302
|
-
}
|
|
303
|
-
});
|
|
304
|
-
return items;
|
|
305
|
-
};
|
|
306
|
-
// 找到所有顶层列表
|
|
307
|
-
$("ol, ul").each(function () {
|
|
308
|
-
var $list = $(this);
|
|
309
|
-
if ($list.parents("ol, ul").length === 0) {
|
|
310
|
-
var placeholder = $("<div data-list-placeholder=\"true\"></div>");
|
|
311
|
-
$list.before(placeholder);
|
|
312
|
-
var items = collectListItems($list, 1);
|
|
313
|
-
topLevelLists.push({
|
|
314
|
-
element: $list,
|
|
315
|
-
placeholder: placeholder,
|
|
316
|
-
items: items,
|
|
317
|
-
});
|
|
318
|
-
}
|
|
319
|
-
});
|
|
320
|
-
// 移除原列表结构
|
|
321
|
-
$("ol, ul, li").remove();
|
|
322
|
-
// 插入新列表
|
|
323
|
-
topLevelLists.forEach(function (listInfo) {
|
|
324
|
-
var placeholder = listInfo.placeholder, items = listInfo.items;
|
|
325
|
-
var html = items
|
|
326
|
-
.map(function (it, idx) {
|
|
327
|
-
// 所有列表项默认上下 0.5 * lineHeightScale rem
|
|
328
|
-
var marginTopVal = idx === 0 ? 1 * lineHeightScale : 0.5 * lineHeightScale;
|
|
329
|
-
var marginBottomVal = idx === items.length - 1 ? 1 * lineHeightScale : 0.5 * lineHeightScale;
|
|
330
|
-
var marginAdjust = ["margin-top: ".concat(marginTopVal, "rem"), "margin-bottom: ".concat(marginBottomVal, "rem")];
|
|
331
|
-
return ("<div style=\"".concat(mergeStyles.apply(void 0, __spreadArray(__spreadArray([it.style], marginAdjust, false), ["padding-left: ".concat(it.paddingLeft, "rem"), "flex-shrink: 0",
|
|
332
|
-
"width: 100%",
|
|
333
|
-
"flex-direction: row",
|
|
334
|
-
"display: flex"], false)), "\" data-list-item=\"true\">") +
|
|
335
|
-
"<text style=\"".concat(mergeStyles("flex-shrink: 0", "width: 100%", "line-height: 1", "display: flex", "flex-direction: row"), "\">") +
|
|
336
|
-
"<div style=\"".concat(mergeStyles("word-break: break-word", "flex-shrink: 0", "margin-right: 0.5rem"), "\">").concat(it.marker, "</div>") +
|
|
337
|
-
"<div style=\"".concat(mergeStyles("word-break: break-word", "flex-shrink: 0", "flex: 1"), "\">").concat(it.textContent, "</div>") +
|
|
338
|
-
"</text></div>");
|
|
339
|
-
})
|
|
340
|
-
.join("");
|
|
341
|
-
placeholder.after(html);
|
|
342
|
-
placeholder.remove();
|
|
343
|
-
});
|
|
344
|
-
};
|
|
345
|
-
/** 将连续 <br> 替换为透明占位文字,确保 PixUI 换行 */
|
|
346
|
-
RichText_Refactor.replaceBrWithPlaceholder = function ($) {
|
|
347
|
-
$("br").each(function () {
|
|
348
|
-
$(this).replaceWith("<span style=\"".concat(mergeStyles("color: transparent", "flex-shrink: 0", "font-size: 20px"), "\" class='pixui-richtext-br-placeholder'>1</span>"));
|
|
349
|
-
});
|
|
350
|
-
};
|
|
351
|
-
/** 处理 <a> 标签:转为 div、保留样式、记录链接 */
|
|
352
|
-
RichText_Refactor.handleAnchorTag = function ($) {
|
|
353
|
-
var self = this;
|
|
354
|
-
$("a").each(function () {
|
|
355
|
-
var id = "PA_RichTextHrefId_".concat(self.hrefIdCnt++);
|
|
356
|
-
var href = $(this).attr("href");
|
|
357
|
-
var originalStyle = $(this).attr("style") || "";
|
|
358
|
-
var textContent = $(this).text();
|
|
359
|
-
var mergedStyles = [];
|
|
360
|
-
// 收集子元素的样式
|
|
361
|
-
if ($(this).find("strong").length > 0)
|
|
362
|
-
mergedStyles.push("font-weight: bold;");
|
|
363
|
-
if ($(this).find("em").length > 0)
|
|
364
|
-
mergedStyles.push("font-style: italic;");
|
|
365
|
-
if ($(this).find("u").length > 0)
|
|
366
|
-
mergedStyles.push("text-decoration: underline;");
|
|
367
|
-
if ($(this).find("s").length > 0)
|
|
368
|
-
mergedStyles.push("text-decoration: line-through;");
|
|
369
|
-
$(this)
|
|
370
|
-
.find("strong, em, u, s, span")
|
|
371
|
-
.each(function () {
|
|
372
|
-
var innerStyle = $(this).attr("style");
|
|
373
|
-
if (innerStyle)
|
|
374
|
-
mergedStyles.push(innerStyle);
|
|
375
|
-
});
|
|
376
|
-
var finalStyle = mergeStyles.apply(void 0, __spreadArray([originalStyle], mergedStyles, false));
|
|
377
|
-
if (href) {
|
|
378
|
-
self.linkNodes.push({ type: LinkNodeType.DIV, href: href, id: id });
|
|
379
|
-
}
|
|
380
|
-
// 确保link节点在正确的text层级内
|
|
381
|
-
var $parent = $(this).parent();
|
|
382
|
-
var isInText = $parent.is("text") || $parent.closest("text").length > 0;
|
|
383
|
-
if (isInText) {
|
|
384
|
-
// 如果已经在text内,直接替换为div
|
|
385
|
-
$(this).replaceWith("<div style=\"".concat(finalStyle, "\" id=\"").concat(id, "\" class=\"PA_RichTextHref_ATag\">").concat(textContent, "</div>"));
|
|
386
|
-
}
|
|
387
|
-
else {
|
|
388
|
-
// 如果不在text内,需要确保在正确的层级
|
|
389
|
-
$(this).replaceWith("<div style=\"".concat(finalStyle, "\" id=\"").concat(id, "\" class=\"PA_RichTextHref_ATag\">").concat(textContent, "</div>"));
|
|
390
|
-
}
|
|
391
|
-
});
|
|
392
|
-
};
|
|
393
|
-
/** 用 text 标签包裹纯文本节点 */
|
|
394
|
-
RichText_Refactor.wrapTextNodes = function ($) {
|
|
395
|
-
var self = this;
|
|
396
|
-
$("*").each(function () {
|
|
397
|
-
var nodeId = $(this).attr("id") || "";
|
|
398
|
-
if (nodeId.startsWith("PA_RichTextHrefId_"))
|
|
399
|
-
return;
|
|
400
|
-
var isListItem = $(this).attr("data-list-item") === "true";
|
|
401
|
-
if (isListItem)
|
|
402
|
-
return;
|
|
403
|
-
$(this)
|
|
404
|
-
.contents()
|
|
405
|
-
.each(function () {
|
|
406
|
-
var linkParent = $(this).closest("[id^='PA_RichTextHrefId_']");
|
|
407
|
-
if (linkParent.length > 0)
|
|
408
|
-
return;
|
|
409
|
-
var listParent = $(this).closest("[data-list-item='true']");
|
|
410
|
-
if (listParent.length > 0)
|
|
411
|
-
return;
|
|
412
|
-
if (this.type === "text") {
|
|
413
|
-
var text = this.data.trim();
|
|
414
|
-
if (text.length > 0) {
|
|
415
|
-
$(this).replaceWith("<text style=\"".concat(mergeStyles("word-break: break-word", "flex-shrink: 0", "flex-direction: row"), "\">").concat(text, "</text>"));
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
});
|
|
419
|
-
});
|
|
420
|
-
};
|
|
421
|
-
/** strong / em / u / s / span 等标签替换成 text */
|
|
422
|
-
RichText_Refactor.replaceStyleTags = function ($) {
|
|
423
|
-
var tagToStyle = {
|
|
424
|
-
strong: "font-weight: bold",
|
|
425
|
-
em: "font-style: italic",
|
|
426
|
-
u: "text-decoration: underline",
|
|
427
|
-
s: "text-decoration: line-through",
|
|
428
|
-
};
|
|
429
|
-
Object.entries(tagToStyle).forEach(function (_a) {
|
|
430
|
-
var tag = _a[0], style = _a[1];
|
|
431
|
-
$(tag).each(function () {
|
|
432
|
-
var html = $(this).html();
|
|
433
|
-
var oriStyle = $(this).attr("style") || "";
|
|
434
|
-
$(this).replaceWith("<text style=\"".concat(mergeStyles(oriStyle, style, "flex-shrink: 0"), "\">").concat(html, "</text>"));
|
|
435
|
-
});
|
|
436
|
-
});
|
|
437
|
-
$("span").each(function () {
|
|
438
|
-
var html = $(this).html();
|
|
439
|
-
var oriStyle = $(this).attr("style") || "";
|
|
440
|
-
$(this).replaceWith("<text style=\"".concat(mergeStyles(oriStyle, "flex-shrink: 0"), "\">").concat(html, "</text>"));
|
|
441
|
-
});
|
|
442
|
-
};
|
|
443
|
-
/** p → div */
|
|
444
|
-
RichText_Refactor.replacePTag = function ($) {
|
|
445
|
-
$("p").each(function () {
|
|
446
|
-
var html = $(this).html();
|
|
447
|
-
var style = $(this).attr("style") || "";
|
|
448
|
-
$(this).replaceWith("<div style=\"".concat(mergeStyles(style, "flex-shrink: 0", "width:100%"), "\">").concat(html, "</div>"));
|
|
449
|
-
});
|
|
450
|
-
};
|
|
451
|
-
/** img 的 href 转移处理 & 记录链接 */
|
|
452
|
-
RichText_Refactor.handleImgHref = function ($) {
|
|
453
|
-
var self = this;
|
|
454
|
-
$("img").each(function () {
|
|
455
|
-
var id = "PA_RichTextHrefId_".concat(self.hrefIdCnt++);
|
|
456
|
-
$(this).attr("id", id);
|
|
457
|
-
var href = $(this).attr("href");
|
|
458
|
-
if (href) {
|
|
459
|
-
self.linkNodes.push({ type: LinkNodeType.IMG, href: href, id: id });
|
|
460
|
-
}
|
|
461
|
-
$(this).attr("href", "");
|
|
462
|
-
$(this).attr("class", "PA_RichTextHref_ImgTag");
|
|
463
|
-
$(this).attr("data-href", href);
|
|
464
|
-
});
|
|
465
|
-
};
|
|
466
|
-
/** 给指定标签补 flex-shrink:0 */
|
|
467
|
-
RichText_Refactor.addFlexShrink = function ($) {
|
|
468
|
-
["h1", "h2", "h3", "h4", "h5", "h6", "a", "img", "div"].forEach(function (tag) {
|
|
469
|
-
$(tag).each(function () {
|
|
470
|
-
var isListItem = $(this).attr("data-list-item") === "true";
|
|
471
|
-
var inListItem = $(this).closest("[data-list-item='true']").length > 0;
|
|
472
|
-
if (!isListItem && !inListItem) {
|
|
473
|
-
var style = $(this).attr("style") || "";
|
|
474
|
-
$(this).attr("style", mergeStyles(style, "flex-shrink: 0"));
|
|
475
|
-
}
|
|
476
|
-
});
|
|
477
|
-
});
|
|
478
|
-
};
|
|
479
|
-
/** 把嵌套的 text 展平 */
|
|
480
|
-
RichText_Refactor.flattenNestedText = function ($) {
|
|
481
|
-
while ($("text > text").length > 0) {
|
|
482
|
-
$("text").each(function () {
|
|
483
|
-
var $this = $(this);
|
|
484
|
-
var parentStyle = $this.attr("style") || "";
|
|
485
|
-
$this.children("text").each(function () {
|
|
486
|
-
var $child = $(this);
|
|
487
|
-
var childStyle = $child.attr("style") || "";
|
|
488
|
-
var mergedStyle = mergeStyles(parentStyle, childStyle);
|
|
489
|
-
$child.attr("style", mergedStyle);
|
|
490
|
-
});
|
|
491
|
-
if ($this.children("text").length > 0) {
|
|
492
|
-
$this.replaceWith($this.html() || "");
|
|
493
|
-
}
|
|
494
|
-
});
|
|
495
|
-
}
|
|
496
|
-
};
|
|
497
|
-
/** 将同一行的 text 节点转为 div 并外包一层 text */
|
|
498
|
-
RichText_Refactor.convertSiblingTextToDiv = function ($) {
|
|
499
|
-
var nodeArr = [];
|
|
500
|
-
["h1", "h2", "h3", "h4", "h5", "h6", "div"].forEach(function (tag) {
|
|
501
|
-
$(tag).each(function () {
|
|
502
|
-
var nodeId = $(this).attr("id") || "";
|
|
503
|
-
var isListItem = $(this).attr("data-list-item") === "true";
|
|
504
|
-
var inListItem = $(this).closest("[data-list-item='true']").length > 0;
|
|
505
|
-
if (!nodeId.startsWith("PA_RichTextHrefId_") && !isListItem && !inListItem) {
|
|
506
|
-
nodeArr.push(this);
|
|
507
|
-
}
|
|
508
|
-
});
|
|
509
|
-
});
|
|
510
|
-
nodeArr.forEach(function (node) {
|
|
511
|
-
var tag = $(node).prop("tagName");
|
|
512
|
-
var nodeId = $(node).attr("id") || "";
|
|
513
|
-
// 处理子元素:将text转为div,但保留link节点
|
|
514
|
-
$(node)
|
|
515
|
-
.children("text")
|
|
516
|
-
.each(function () {
|
|
517
|
-
var inListItem = $(this).closest("[data-list-item='true']").length > 0;
|
|
518
|
-
if (inListItem)
|
|
519
|
-
return;
|
|
520
|
-
var text = $(this).html();
|
|
521
|
-
var style = $(this).attr("style") || "";
|
|
522
|
-
// 检查是否包含link节点
|
|
523
|
-
var hasLink = $(this).find('[id^="PA_RichTextHrefId_"]').length > 0;
|
|
524
|
-
if (hasLink) {
|
|
525
|
-
// 如果包含link节点,需要特殊处理以保持link在正确位置
|
|
526
|
-
var $tempDiv = $("<div style=\"".concat(mergeStyles(style, "word-break: break-word", "flex-shrink: 0", "flex-direction: row"), "\">").concat(text, "</div>"));
|
|
527
|
-
$(this).replaceWith($tempDiv);
|
|
528
|
-
}
|
|
529
|
-
else {
|
|
530
|
-
// 普通text节点直接转换
|
|
531
|
-
$(this).replaceWith("<div style=\"".concat(mergeStyles(style, "word-break: break-word", "flex-shrink: 0", "flex-direction: row"), "\">").concat(text, "</div>"));
|
|
532
|
-
}
|
|
533
|
-
});
|
|
534
|
-
var tagHtml = $(node).html() || "";
|
|
535
|
-
var tagStyle = $(node).attr("style") || "";
|
|
536
|
-
if (tagHtml.trim()) {
|
|
537
|
-
var idAttr = nodeId ? " id=\"".concat(nodeId, "\"") : "";
|
|
538
|
-
var customAttrs = "";
|
|
539
|
-
var attribs = ($(node).get(0) || {}).attribs || {};
|
|
540
|
-
for (var _i = 0, _a = Object.entries(attribs); _i < _a.length; _i++) {
|
|
541
|
-
var _b = _a[_i], k = _b[0], v = _b[1];
|
|
542
|
-
if (k !== "style" && k !== "id") {
|
|
543
|
-
customAttrs += " ".concat(k, "=\"").concat(v, "\"");
|
|
544
|
-
}
|
|
545
|
-
}
|
|
546
|
-
// 保证外层tag的style不合并子div的style
|
|
547
|
-
$(node).replaceWith("<".concat(tag, " style=\"").concat(mergeStyles(tagStyle, "flex-direction: row"), "\"").concat(idAttr).concat(customAttrs, "><text style=\"").concat(mergeStyles("flex-shrink: 0", "width: 100%", "line-height: 1"), "\">").concat(tagHtml, "</text></").concat(tag, ">"));
|
|
548
|
-
}
|
|
549
|
-
});
|
|
550
|
-
};
|
|
551
|
-
/** text-indent 首行缩进处理 */
|
|
552
|
-
RichText_Refactor.handleTextIndent = function ($) {
|
|
553
|
-
$("*").each(function () {
|
|
554
|
-
var textIndent = $(this).css("text-indent");
|
|
555
|
-
if (textIndent) {
|
|
556
|
-
var repeatCnt = parseInt(textIndent);
|
|
557
|
-
if (repeatCnt > 0) {
|
|
558
|
-
var spacer = "<div style=\"".concat(mergeStyles("color: transparent", "flex-shrink: 0", "font-size: 16px"), "\">").concat("一".repeat(repeatCnt), "</div>");
|
|
559
|
-
var textChild = $(this).children("text").first();
|
|
560
|
-
if (textChild.length > 0) {
|
|
561
|
-
var first = textChild.children().first();
|
|
562
|
-
if (first.length > 0)
|
|
563
|
-
first.before(spacer);
|
|
564
|
-
else
|
|
565
|
-
textChild.append(spacer);
|
|
566
|
-
}
|
|
567
|
-
}
|
|
568
|
-
}
|
|
569
|
-
});
|
|
570
|
-
};
|
|
571
|
-
/** line-height / letter-spacing 调整 */
|
|
572
|
-
RichText_Refactor.adjustLineHeightAndLetterSpacing = function ($, config) {
|
|
573
|
-
$("text").each(function () {
|
|
574
|
-
var $text = $(this);
|
|
575
|
-
var maxLineHeight = 0;
|
|
576
|
-
$text.children("div").each(function () {
|
|
577
|
-
var lh = parseInt($(this).css("line-height") || "1");
|
|
578
|
-
maxLineHeight = Math.max(maxLineHeight, lh);
|
|
579
|
-
});
|
|
580
|
-
var scale = (config === null || config === void 0 ? void 0 : config.lineHeightScale) || 1;
|
|
581
|
-
if (maxLineHeight > 0) {
|
|
582
|
-
var currentStyle = $text.attr("style") || "";
|
|
583
|
-
$text.attr("style", mergeStyles(currentStyle, "line-height: ".concat(maxLineHeight * scale)));
|
|
584
|
-
}
|
|
585
|
-
});
|
|
586
|
-
$("text").each(function () {
|
|
587
|
-
var $text = $(this);
|
|
588
|
-
var maxLS = 0;
|
|
589
|
-
$text.children("div").each(function () {
|
|
590
|
-
var ls = $(this).css("letter-spacing") || "0";
|
|
591
|
-
var lsNum = parseInt(ls);
|
|
592
|
-
maxLS = Math.max(maxLS, lsNum);
|
|
593
|
-
});
|
|
594
|
-
if (maxLS > 0) {
|
|
595
|
-
var currentStyle = $text.attr("style") || "";
|
|
596
|
-
$text.attr("style", mergeStyles(currentStyle, "letter-spacing: ".concat(maxLS, "rem")));
|
|
597
|
-
}
|
|
598
|
-
});
|
|
599
|
-
};
|
|
600
|
-
/** 把 div 的 text-align 转移到子 text 上 */
|
|
601
|
-
RichText_Refactor.transferTextAlign = function ($) {
|
|
602
|
-
$("div").each(function () {
|
|
603
|
-
var ta = $(this).css("text-align") || "";
|
|
604
|
-
if (ta) {
|
|
605
|
-
$(this)
|
|
606
|
-
.children("text")
|
|
607
|
-
.each(function () {
|
|
608
|
-
var currentStyle = $(this).attr("style") || "";
|
|
609
|
-
$(this).attr("style", mergeStyles(currentStyle, "text-align: ".concat(ta)));
|
|
610
|
-
});
|
|
611
|
-
// 清除div的text-align
|
|
612
|
-
var currentStyle = $(this).attr("style") || "";
|
|
613
|
-
var styleObj = parseStyleString(currentStyle);
|
|
614
|
-
delete styleObj["text-align"];
|
|
615
|
-
$(this).attr("style", serializeStyleObject(styleObj));
|
|
616
|
-
}
|
|
617
|
-
});
|
|
618
|
-
};
|
|
619
|
-
/** 删除空 text 节点 */
|
|
620
|
-
RichText_Refactor.removeEmptyText = function ($) {
|
|
621
|
-
$("text").each(function () {
|
|
622
|
-
var t = $(this).html() || "";
|
|
623
|
-
if (t.trim() === "")
|
|
624
|
-
$(this).remove();
|
|
625
|
-
});
|
|
626
|
-
};
|
|
627
|
-
/** 补默认 heading 字体大小 */
|
|
628
|
-
RichText_Refactor.fixHeadingFontSize = function ($) {
|
|
629
|
-
var hRem = ["2rem", "1.5rem", "1.17rem", "1rem", "0.83rem", "0.67rem"];
|
|
630
|
-
["h1", "h2", "h3", "h4", "h5", "h6"].forEach(function (tag) {
|
|
631
|
-
$(tag).each(function () {
|
|
632
|
-
var idx = parseInt(tag.replace("h", "")) - 1;
|
|
633
|
-
var style = $(this).attr("style") || "";
|
|
634
|
-
if (!style.includes("font-size")) {
|
|
635
|
-
$(this).attr("style", mergeStyles(style, "font-size:".concat(hRem[idx])));
|
|
636
|
-
}
|
|
637
|
-
});
|
|
638
|
-
});
|
|
639
|
-
};
|
|
640
|
-
// 存储需要绑定点击事件的节点
|
|
641
|
-
RichText_Refactor.linkNodes = [];
|
|
642
|
-
RichText_Refactor.hrefIdCnt = 0;
|
|
643
|
-
return RichText_Refactor;
|
|
644
|
-
}());
|
|
645
|
-
exports.RichText_Refactor = RichText_Refactor;
|