@pixui-dev/pixui-richtext-helper 0.1.0 → 0.1.1-beta.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 +37 -37
- package/dist/RichTextUtils.js +522 -348
- package/dist/index.d.ts +2 -2
- package/dist/index.js +7 -7
- package/package.json +6 -12
package/dist/RichTextUtils.d.ts
CHANGED
|
@@ -1,37 +1,37 @@
|
|
|
1
|
-
export declare namespace RichText {
|
|
2
|
-
/**
|
|
3
|
-
* 富文本中的超链接节点类型
|
|
4
|
-
*/
|
|
5
|
-
enum LinkNodeType {
|
|
6
|
-
IMG = "img",
|
|
7
|
-
DIV = "div"
|
|
8
|
-
}
|
|
9
|
-
/**
|
|
10
|
-
* 富文本超链接点击回调参数
|
|
11
|
-
*/
|
|
12
|
-
interface LinkClickParams {
|
|
13
|
-
/** 节点类型 */
|
|
14
|
-
type: LinkNodeType;
|
|
15
|
-
/** 原始href内容 */
|
|
16
|
-
href: string;
|
|
17
|
-
/** 节点id */
|
|
18
|
-
id: string;
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* 富文本组件,将富文本转换成pixui的innerHtml可以使用的格式
|
|
22
|
-
* @param str 管理端下发的富文本
|
|
23
|
-
* @param config 配置
|
|
24
|
-
* @param config.lineHeightScale 行高缩放
|
|
25
|
-
* @param config.isToRem 是否将节点的 px 单位转换为 rem 的单位
|
|
26
|
-
* @returns pixui的innerHtml可以使用的格式
|
|
27
|
-
*/
|
|
28
|
-
const convertRichTextToPixuiStyle: (str: string, config?: {
|
|
29
|
-
lineHeightScale?: number;
|
|
30
|
-
isToRem?: boolean;
|
|
31
|
-
}) => string;
|
|
32
|
-
/**
|
|
33
|
-
* 为富文本中的链接节点绑定点击事件
|
|
34
|
-
* @param linkClickHandler 点击事件回调函数
|
|
35
|
-
*/
|
|
36
|
-
const bindLinkClickEvents: (linkClickHandler: (params: LinkClickParams) => void) => void;
|
|
37
|
-
}
|
|
1
|
+
export declare namespace RichText {
|
|
2
|
+
/**
|
|
3
|
+
* 富文本中的超链接节点类型
|
|
4
|
+
*/
|
|
5
|
+
enum LinkNodeType {
|
|
6
|
+
IMG = "img",
|
|
7
|
+
DIV = "div"
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* 富文本超链接点击回调参数
|
|
11
|
+
*/
|
|
12
|
+
interface LinkClickParams {
|
|
13
|
+
/** 节点类型 */
|
|
14
|
+
type: LinkNodeType;
|
|
15
|
+
/** 原始href内容 */
|
|
16
|
+
href: string;
|
|
17
|
+
/** 节点id */
|
|
18
|
+
id: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* 富文本组件,将富文本转换成pixui的innerHtml可以使用的格式
|
|
22
|
+
* @param str 管理端下发的富文本
|
|
23
|
+
* @param config 配置
|
|
24
|
+
* @param config.lineHeightScale 行高缩放
|
|
25
|
+
* @param config.isToRem 是否将节点的 px 单位转换为 rem 的单位
|
|
26
|
+
* @returns pixui的innerHtml可以使用的格式
|
|
27
|
+
*/
|
|
28
|
+
const convertRichTextToPixuiStyle: (str: string, config?: {
|
|
29
|
+
lineHeightScale?: number;
|
|
30
|
+
isToRem?: boolean;
|
|
31
|
+
}) => string;
|
|
32
|
+
/**
|
|
33
|
+
* 为富文本中的链接节点绑定点击事件
|
|
34
|
+
* @param linkClickHandler 点击事件回调函数
|
|
35
|
+
*/
|
|
36
|
+
const bindLinkClickEvents: (linkClickHandler: (params: LinkClickParams) => void) => void;
|
|
37
|
+
}
|
package/dist/RichTextUtils.js
CHANGED
|
@@ -1,348 +1,522 @@
|
|
|
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
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
*
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
$(""
|
|
213
|
-
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
$(
|
|
219
|
-
.
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
var
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
//
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.RichText = void 0;
|
|
37
|
+
var cheerio = __importStar(require("cheerio"));
|
|
38
|
+
var RichText;
|
|
39
|
+
(function (RichText) {
|
|
40
|
+
/**
|
|
41
|
+
* 富文本中的超链接节点类型
|
|
42
|
+
*/
|
|
43
|
+
var LinkNodeType;
|
|
44
|
+
(function (LinkNodeType) {
|
|
45
|
+
LinkNodeType["IMG"] = "img";
|
|
46
|
+
LinkNodeType["DIV"] = "div";
|
|
47
|
+
})(LinkNodeType = RichText.LinkNodeType || (RichText.LinkNodeType = {}));
|
|
48
|
+
// 存储需要绑定点击事件的节点信息
|
|
49
|
+
var linkNodes = [];
|
|
50
|
+
/**
|
|
51
|
+
* 富文本组件,将富文本转换成pixui的innerHtml可以使用的格式
|
|
52
|
+
* @param str 管理端下发的富文本
|
|
53
|
+
* @param config 配置
|
|
54
|
+
* @param config.lineHeightScale 行高缩放
|
|
55
|
+
* @param config.isToRem 是否将节点的 px 单位转换为 rem 的单位
|
|
56
|
+
* @returns pixui的innerHtml可以使用的格式
|
|
57
|
+
*/
|
|
58
|
+
RichText.convertRichTextToPixuiStyle = function (str, config) {
|
|
59
|
+
//将富文本内容转换为一个 段落div/h -> text -> 文字样式div/img -> 文本 的结构,保证pixui可以正常显示
|
|
60
|
+
var $ = cheerio.load(str, null, false);
|
|
61
|
+
var hrefIdCnt = 0;
|
|
62
|
+
linkNodes = []; // 重置链接节点信息
|
|
63
|
+
// 节点处理
|
|
64
|
+
{
|
|
65
|
+
var _loop_1 = function (i) {
|
|
66
|
+
var indent = "ql-indent-".concat(i);
|
|
67
|
+
var extStyle = "padding-left: ".concat(i * 2, "rem;");
|
|
68
|
+
$(".".concat(indent)).each(function () {
|
|
69
|
+
var oriStyle = $(this).attr("style") || "";
|
|
70
|
+
$(this).attr("style", "".concat(oriStyle, " ").concat(extStyle));
|
|
71
|
+
$(this).removeClass(indent);
|
|
72
|
+
});
|
|
73
|
+
};
|
|
74
|
+
//合并ql-indent class到style中
|
|
75
|
+
for (var i = 1; i <= 10; i++) {
|
|
76
|
+
_loop_1(i);
|
|
77
|
+
}
|
|
78
|
+
$("img").each(function () {
|
|
79
|
+
//给纯数字的width,height添加px单位
|
|
80
|
+
var width = $(this).attr("width");
|
|
81
|
+
var height = $(this).attr("height");
|
|
82
|
+
if (width && width + "" == parseInt(width) + "") {
|
|
83
|
+
$(this).attr("width", "".concat(width, "px"));
|
|
84
|
+
}
|
|
85
|
+
if (height && height + "" == parseInt(height) + "") {
|
|
86
|
+
$(this).attr("height", "".concat(height, "px"));
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
// 将px转换为rem,font-size不转换
|
|
90
|
+
if (config === null || config === void 0 ? void 0 : config.isToRem) {
|
|
91
|
+
$("*").each(function () {
|
|
92
|
+
var $element = $(this);
|
|
93
|
+
var style = $element.attr("style");
|
|
94
|
+
if (style) {
|
|
95
|
+
var newStyle = style.replace(/([\w-]+)\s*:\s*([^;]+)/g, function (match, property, value) {
|
|
96
|
+
if (property.trim() !== "font-size" && property.trim() !== "letter-spacing") {
|
|
97
|
+
var newValue = value.replace(/(\d+(?:\.\d+)?)px/g, function (pxMatch, pxValue) {
|
|
98
|
+
var remValue = parseFloat(pxValue) / 100;
|
|
99
|
+
return "".concat(remValue, "rem");
|
|
100
|
+
});
|
|
101
|
+
return "".concat(property, ": ").concat(newValue);
|
|
102
|
+
}
|
|
103
|
+
return match;
|
|
104
|
+
});
|
|
105
|
+
$element.attr("style", newStyle);
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
// 处理列表项
|
|
110
|
+
{
|
|
111
|
+
/**
|
|
112
|
+
* pixui不支持ol,ul,li节点,将其递归转换成div并处理嵌套层级
|
|
113
|
+
* 记录每个列表容器的位置,在原位置插入转换后的结构
|
|
114
|
+
*/
|
|
115
|
+
// 第一步:找到所有顶层列表容器并标记其位置
|
|
116
|
+
var topLevelLists_1 = [];
|
|
117
|
+
// 递归收集列表项的函数
|
|
118
|
+
var collectListItems_1 = function ($container, currentLevel) {
|
|
119
|
+
if (currentLevel === void 0) { currentLevel = 0; }
|
|
120
|
+
var items = [];
|
|
121
|
+
$container.children().each(function () {
|
|
122
|
+
var $child = $(this);
|
|
123
|
+
if ($child.is("li")) {
|
|
124
|
+
var isOrdered = $child.parent().is("ol");
|
|
125
|
+
var orderIndex = 1;
|
|
126
|
+
if (isOrdered) {
|
|
127
|
+
// 计算在同一个ol中的序号
|
|
128
|
+
orderIndex = $child.prevAll("li").length + 1;
|
|
129
|
+
}
|
|
130
|
+
// 生成marker
|
|
131
|
+
var marker = isOrdered ? "".concat(orderIndex, ".") : "•";
|
|
132
|
+
// 计算缩进
|
|
133
|
+
var paddingLeft = currentLevel * 2; // 每层缩进2rem
|
|
134
|
+
// 获取li的直接文本内容,不包括嵌套的子列表
|
|
135
|
+
var $liClone = $child.clone();
|
|
136
|
+
$liClone.find("ol, ul").remove();
|
|
137
|
+
var textContent = $liClone.text().trim() || "";
|
|
138
|
+
var style = $child.attr("style") || "";
|
|
139
|
+
items.push({
|
|
140
|
+
level: currentLevel,
|
|
141
|
+
isOrdered: isOrdered,
|
|
142
|
+
orderIndex: orderIndex,
|
|
143
|
+
marker: marker,
|
|
144
|
+
paddingLeft: paddingLeft,
|
|
145
|
+
textContent: textContent,
|
|
146
|
+
style: style,
|
|
147
|
+
});
|
|
148
|
+
// 递归处理li内的子列表(只处理真正嵌套在当前li内的列表)
|
|
149
|
+
$child.find("ol, ul").each(function () {
|
|
150
|
+
// 确保这个列表是当前li的直接子元素,而不是更深层的
|
|
151
|
+
var $nestedList = $(this);
|
|
152
|
+
if ($nestedList.parent().closest("li")[0] === $child[0]) {
|
|
153
|
+
var childItems = collectListItems_1($nestedList, currentLevel + 1);
|
|
154
|
+
items.push.apply(items, childItems);
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
return items;
|
|
160
|
+
};
|
|
161
|
+
// 找到所有顶层列表(直接在body下或其他容器中的ol/ul)
|
|
162
|
+
$("ol, ul").each(function () {
|
|
163
|
+
var $list = $(this);
|
|
164
|
+
// 检查是否为顶层列表(不在其他列表内部)
|
|
165
|
+
if ($list.parents("ol, ul").length === 0) {
|
|
166
|
+
// 创建占位符标记原始位置
|
|
167
|
+
var placeholder = $("<div data-list-placeholder=\"true\"></div>");
|
|
168
|
+
$list.before(placeholder);
|
|
169
|
+
// 收集该列表的所有项目
|
|
170
|
+
var items = collectListItems_1($list, 1);
|
|
171
|
+
topLevelLists_1.push({
|
|
172
|
+
element: $list,
|
|
173
|
+
placeholder: placeholder,
|
|
174
|
+
items: items,
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
// 第二步:移除所有ol/ul/li结构
|
|
179
|
+
$("ol, ul, li").remove();
|
|
180
|
+
// 第三步:在每个占位符位置插入转换后的列表项
|
|
181
|
+
topLevelLists_1.forEach(function (listInfo) {
|
|
182
|
+
var placeholder = listInfo.placeholder, items = listInfo.items;
|
|
183
|
+
// 为该列表生成HTML
|
|
184
|
+
var listHtml = items
|
|
185
|
+
.map(function (item) {
|
|
186
|
+
return ("<div style=\"".concat(item.style, " padding-left: ").concat(item.paddingLeft, "rem; flex-shrink: 0; width: 100%; flex-direction: row; display: flex;\" data-list-item=\"true\">") +
|
|
187
|
+
"<text style=\"flex-shrink: 0; width: 100%; line-height: 1; display: flex; flex-direction: row;\">" +
|
|
188
|
+
"<div style=\"word-break: break-word; flex-shrink: 0; margin-right: 0.5rem;\">".concat(item.marker, "</div>") +
|
|
189
|
+
"<div style=\"word-break: break-word; flex-shrink: 0; flex: 1;\">".concat(item.textContent, "</div>") +
|
|
190
|
+
"</text>" +
|
|
191
|
+
"</div>");
|
|
192
|
+
})
|
|
193
|
+
.join("");
|
|
194
|
+
// 在占位符位置插入列表HTML
|
|
195
|
+
placeholder.after(listHtml);
|
|
196
|
+
// 移除占位符
|
|
197
|
+
placeholder.remove();
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
//pixui连续的br不生效,用透明文字占位
|
|
201
|
+
$("br").each(function () {
|
|
202
|
+
$(this).replaceWith("<span style='color: transparent; flex-shrink: 0;font-size: 20px;' class='pixui-richtext-br-placeholder'>1</span>");
|
|
203
|
+
});
|
|
204
|
+
//将 a 标签替换为简单div,处理 href,预处理内部样式标签并合并样式
|
|
205
|
+
$("a").each(function (i, ele) {
|
|
206
|
+
var id = "PA_RichTextHrefId_".concat(hrefIdCnt++);
|
|
207
|
+
var href = $(this).attr("href");
|
|
208
|
+
var originalStyle = $(this).attr("style") || "";
|
|
209
|
+
var textContent = $(this).text(); // 获取纯文本内容
|
|
210
|
+
// 收集内部样式标签的样式
|
|
211
|
+
var mergedStyles = [];
|
|
212
|
+
if ($(this).find("strong").length > 0) {
|
|
213
|
+
mergedStyles.push("font-weight: bold;");
|
|
214
|
+
}
|
|
215
|
+
if ($(this).find("em").length > 0) {
|
|
216
|
+
mergedStyles.push("font-style: italic;");
|
|
217
|
+
}
|
|
218
|
+
if ($(this).find("u").length > 0) {
|
|
219
|
+
mergedStyles.push("text-decoration: underline;");
|
|
220
|
+
}
|
|
221
|
+
if ($(this).find("s").length > 0) {
|
|
222
|
+
mergedStyles.push("text-decoration: line-through;");
|
|
223
|
+
}
|
|
224
|
+
// 收集内部span等标签的style属性
|
|
225
|
+
$(this)
|
|
226
|
+
.find("strong, em, u, s, span")
|
|
227
|
+
.each(function () {
|
|
228
|
+
var innerStyle = $(this).attr("style");
|
|
229
|
+
if (innerStyle) {
|
|
230
|
+
mergedStyles.push(innerStyle);
|
|
231
|
+
}
|
|
232
|
+
});
|
|
233
|
+
// 合并所有样式
|
|
234
|
+
var finalStyle = originalStyle;
|
|
235
|
+
if (mergedStyles.length > 0) {
|
|
236
|
+
finalStyle = finalStyle ? "".concat(finalStyle, "; ").concat(mergedStyles.join("; ")) : mergedStyles.join("; ");
|
|
237
|
+
}
|
|
238
|
+
if (href) {
|
|
239
|
+
linkNodes.push({
|
|
240
|
+
type: LinkNodeType.DIV,
|
|
241
|
+
href: href,
|
|
242
|
+
id: id,
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
// 转换为简单div,样式已合并
|
|
246
|
+
$(this).replaceWith("<div style=\"".concat(finalStyle, "\" id=\"").concat(id, "\">").concat(textContent, "</div>"));
|
|
247
|
+
});
|
|
248
|
+
//找到所有的文字节点,外层包裹text标签
|
|
249
|
+
$("*").each(function () {
|
|
250
|
+
// 跳过链接节点内部的文本处理
|
|
251
|
+
var nodeId = $(this).attr("id") || "";
|
|
252
|
+
if (nodeId.startsWith("PA_RichTextHrefId_")) {
|
|
253
|
+
return; // 跳过链接节点,不处理其内部文本
|
|
254
|
+
}
|
|
255
|
+
// 跳过列表项,因为已经处理完成
|
|
256
|
+
var isListItem = $(this).attr("data-list-item") === "true";
|
|
257
|
+
if (isListItem) {
|
|
258
|
+
return; // 跳过列表项
|
|
259
|
+
}
|
|
260
|
+
$(this)
|
|
261
|
+
.contents()
|
|
262
|
+
.each(function () {
|
|
263
|
+
// 检查当前文本节点是否在链接节点内部
|
|
264
|
+
var linkParent = $(this).closest("[id^='PA_RichTextHrefId_']");
|
|
265
|
+
if (linkParent.length > 0) {
|
|
266
|
+
return; // 跳过链接节点内部的文本
|
|
267
|
+
}
|
|
268
|
+
// 检查当前文本节点是否在列表项内部
|
|
269
|
+
var listParent = $(this).closest("[data-list-item='true']");
|
|
270
|
+
if (listParent.length > 0) {
|
|
271
|
+
return; // 跳过列表项内部的文本
|
|
272
|
+
}
|
|
273
|
+
if (this.type === "text") {
|
|
274
|
+
var text = this.data.trim();
|
|
275
|
+
if (text.length > 0) {
|
|
276
|
+
$(this).replaceWith("<text style=\"word-break: break-word;flex-shrink: 0;flex-direction: row;\">".concat(text, "</text>"));
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
});
|
|
280
|
+
});
|
|
281
|
+
//将strong em u s标签替换成text标签
|
|
282
|
+
$("strong").each(function () {
|
|
283
|
+
var html = $(this).html();
|
|
284
|
+
var style = $(this).attr("style") || "";
|
|
285
|
+
$(this).replaceWith("<text style=\"".concat(style, " font-weight: bold;flex-shrink: 0;\">").concat(html, "</text>"));
|
|
286
|
+
});
|
|
287
|
+
$("em").each(function () {
|
|
288
|
+
var html = $(this).html();
|
|
289
|
+
var style = $(this).attr("style") || "";
|
|
290
|
+
$(this).replaceWith("<text style=\"".concat(style, " font-style: italic;flex-shrink: 0;\">").concat(html, "</text>"));
|
|
291
|
+
});
|
|
292
|
+
$("u").each(function () {
|
|
293
|
+
var html = $(this).html();
|
|
294
|
+
var style = $(this).attr("style") || "";
|
|
295
|
+
$(this).replaceWith("<text style=\"".concat(style, " text-decoration: underline;flex-shrink: 0;\">").concat(html, "</text>"));
|
|
296
|
+
});
|
|
297
|
+
$("s").each(function () {
|
|
298
|
+
var html = $(this).html();
|
|
299
|
+
var style = $(this).attr("style") || "";
|
|
300
|
+
$(this).replaceWith("<text style=\"".concat(style, " text-decoration: line-through;flex-shrink: 0;\">").concat(html, "</text>"));
|
|
301
|
+
});
|
|
302
|
+
$("span").each(function () {
|
|
303
|
+
var html = $(this).html();
|
|
304
|
+
var style = $(this).attr("style") || "";
|
|
305
|
+
$(this).replaceWith("<text style=\"".concat(style, " flex-shrink: 0;\">").concat(html, "</text>"));
|
|
306
|
+
});
|
|
307
|
+
//p换成div
|
|
308
|
+
$("p").each(function () {
|
|
309
|
+
var html = $(this).html();
|
|
310
|
+
var style = $(this).attr("style") || "";
|
|
311
|
+
$(this).replaceWith("<div style=\"".concat(style, " ;flex-shrink: 0;width:100%;\">").concat(html, "</div>"));
|
|
312
|
+
});
|
|
313
|
+
//处理 img 上的 href
|
|
314
|
+
$("img").each(function (i, ele) {
|
|
315
|
+
var id = "PA_RichTextHrefId_".concat(hrefIdCnt++);
|
|
316
|
+
$(this).attr("id", id);
|
|
317
|
+
var href = $(this).attr("href");
|
|
318
|
+
if (href) {
|
|
319
|
+
linkNodes.push({
|
|
320
|
+
type: LinkNodeType.IMG,
|
|
321
|
+
href: href,
|
|
322
|
+
id: id,
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
$(this).attr("href", "");
|
|
326
|
+
});
|
|
327
|
+
//补充 flex-shrink: 0
|
|
328
|
+
["h1", "h2", "h3", "h4", "h5", "h6", "a", "img", "div"].forEach(function (tag) {
|
|
329
|
+
$("".concat(tag)).each(function () {
|
|
330
|
+
// 跳过列表项内部的节点
|
|
331
|
+
var isListItem = $(this).attr("data-list-item") === "true";
|
|
332
|
+
var inListItem = $(this).closest("[data-list-item='true']").length > 0;
|
|
333
|
+
if (!isListItem && !inListItem) {
|
|
334
|
+
var style = $(this).attr("style") || "";
|
|
335
|
+
$(this).attr("style", "".concat(style, " flex-shrink: 0;"));
|
|
336
|
+
}
|
|
337
|
+
});
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
// 层级处理
|
|
341
|
+
{
|
|
342
|
+
//一行中的文字配置了不同样式的时候文字节点会嵌套,导致pixui样式异常。将嵌套的text节点摊平,同时合并内外的style
|
|
343
|
+
while ($("text > text").length > 0) {
|
|
344
|
+
$("text").each(function () {
|
|
345
|
+
var $this = $(this);
|
|
346
|
+
var parentStyle = $this.attr("style") || "";
|
|
347
|
+
$this.children("text").each(function () {
|
|
348
|
+
var $child = $(this);
|
|
349
|
+
var childStyle = $child.attr("style") || "";
|
|
350
|
+
// 合并style属性,将父节点的style附加到子节点上
|
|
351
|
+
var mergedStyle = "".concat(parentStyle, "; ").concat(childStyle);
|
|
352
|
+
// 更新子元素的style属性
|
|
353
|
+
$child.attr("style", mergedStyle);
|
|
354
|
+
});
|
|
355
|
+
//去掉父节点
|
|
356
|
+
if ($this.children("text").length > 0) {
|
|
357
|
+
$this.replaceWith($this.html() || "");
|
|
358
|
+
}
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
//!!一行的text节点会并列在父节点下无法换行,将其修改为div节点,外层再包一个text节点
|
|
362
|
+
// 会变成<段落div><text><单独一种样式div>文字
|
|
363
|
+
var nodearr_1 = [];
|
|
364
|
+
["h1", "h2", "h3", "h4", "h5", "h6", "div"].map(function (tag) {
|
|
365
|
+
// text的父节点
|
|
366
|
+
$("".concat(tag)).each(function () {
|
|
367
|
+
var nodeId = $(this).attr("id") || "";
|
|
368
|
+
var isListItem = $(this).attr("data-list-item") === "true";
|
|
369
|
+
var inListItem = $(this).closest("[data-list-item='true']").length > 0;
|
|
370
|
+
// 跳过链接节点、列表项本身以及列表项内部的节点
|
|
371
|
+
if (!nodeId.startsWith("PA_RichTextHrefId_") && !isListItem && !inListItem) {
|
|
372
|
+
nodearr_1.push(this);
|
|
373
|
+
}
|
|
374
|
+
});
|
|
375
|
+
});
|
|
376
|
+
nodearr_1.forEach(function (node) {
|
|
377
|
+
var tag = $(node).prop("tagName");
|
|
378
|
+
var nodeId = $(node).attr("id") || ""; // 保存节点ID
|
|
379
|
+
// 处理text子节点,将text内容转换为div
|
|
380
|
+
$(node)
|
|
381
|
+
.children("text")
|
|
382
|
+
.each(function () {
|
|
383
|
+
// 检查是否在列表项内部
|
|
384
|
+
var inListItem = $(this).closest("[data-list-item='true']").length > 0;
|
|
385
|
+
if (inListItem) {
|
|
386
|
+
return; // 跳过列表项内部的text节点
|
|
387
|
+
}
|
|
388
|
+
var text = $(this).html();
|
|
389
|
+
var style = $(this).attr("style") || "";
|
|
390
|
+
$(this).replaceWith("<div style=\"".concat(style, "\">").concat(text, "</div>"));
|
|
391
|
+
});
|
|
392
|
+
var taghtml = $(node).html() || "";
|
|
393
|
+
var tagstyle = $(node).attr("style") || "";
|
|
394
|
+
// 构建标准结构 - 为所有节点构建div-text-div-文字结构
|
|
395
|
+
if (taghtml && taghtml.trim()) {
|
|
396
|
+
var idAttr = nodeId ? " id=\"".concat(nodeId, "\"") : "";
|
|
397
|
+
// 保留所有自定义属性
|
|
398
|
+
var customAttrs = "";
|
|
399
|
+
var attributes = $(node).get(0).attribs || {};
|
|
400
|
+
for (var _i = 0, _a = Object.entries(attributes); _i < _a.length; _i++) {
|
|
401
|
+
var _b = _a[_i], key = _b[0], value = _b[1];
|
|
402
|
+
if (key !== "style" && key !== "id") {
|
|
403
|
+
customAttrs += " ".concat(key, "=\"").concat(value, "\"");
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
//自己的子节点外套一个text,自己不变
|
|
407
|
+
$(node).replaceWith("<".concat(tag, " style=\"").concat(tagstyle, ";flex-direction: row;\"").concat(idAttr).concat(customAttrs, "><text style=\"flex-shrink: 0;width: 100%;\">").concat(taghtml, "</text></").concat(tag, ">"));
|
|
408
|
+
}
|
|
409
|
+
});
|
|
410
|
+
//text-indent 处理首行缩进
|
|
411
|
+
$("*").each(function () {
|
|
412
|
+
var textIndent = $(this).css("text-indent");
|
|
413
|
+
if (textIndent) {
|
|
414
|
+
/**
|
|
415
|
+
* 创建透明字符占位,样式会加在段落的p节点上,将透明字符添加到text节点下保证换行以后状态正确。
|
|
416
|
+
* 状态为<div style=text-indent:xxx><text><透明字符节点/><div style=样式>文字</div></text></div>
|
|
417
|
+
* 属性是几 em 就加几个字符
|
|
418
|
+
* */
|
|
419
|
+
var $spacerText = $("<div style=\"color: transparent; flex-shrink: 0;\">".concat("一".repeat(parseInt(textIndent)), "</div>"));
|
|
420
|
+
// 寻找子节点中的text节点
|
|
421
|
+
var textChild = $(this).children("text").first();
|
|
422
|
+
if (textChild.length > 0) {
|
|
423
|
+
var firstTextChild = textChild.children().first();
|
|
424
|
+
if (firstTextChild.length > 0) {
|
|
425
|
+
// 如果text节点有子节点,在第一个子节点前插入
|
|
426
|
+
firstTextChild.before($spacerText);
|
|
427
|
+
}
|
|
428
|
+
else {
|
|
429
|
+
// 如果text节点没有子节点,直接添加
|
|
430
|
+
textChild.append($spacerText);
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
});
|
|
435
|
+
//pixui 的 line-height只在 text 上生效,所以将所有的 div 上的 line-height 转移到父 text 上
|
|
436
|
+
//当前的结构为 div > text > div,只处理一层就行
|
|
437
|
+
//遍历每个 text 的子 div,将其中最大的 line-height 转移到 text 上
|
|
438
|
+
$("text").each(function () {
|
|
439
|
+
var $text = $(this);
|
|
440
|
+
var maxLineHeight = 0;
|
|
441
|
+
$text.children("div").each(function () {
|
|
442
|
+
var lineHeight = parseInt($(this).css("line-height") || "1");
|
|
443
|
+
maxLineHeight = Math.max(maxLineHeight, lineHeight);
|
|
444
|
+
});
|
|
445
|
+
var lineHeightScale = (config === null || config === void 0 ? void 0 : config.lineHeightScale) || 1;
|
|
446
|
+
// pixui 中的实际显示的距离可能与网页中实际显示的距离差距较大
|
|
447
|
+
if (maxLineHeight > 0) {
|
|
448
|
+
$text.css("line-height", maxLineHeight * lineHeightScale + "");
|
|
449
|
+
}
|
|
450
|
+
});
|
|
451
|
+
//将div中的letter-spacing转移到text上
|
|
452
|
+
$("text").each(function () {
|
|
453
|
+
var $text = $(this);
|
|
454
|
+
var maxLetterSpacing = 0;
|
|
455
|
+
$text.children("div").each(function () {
|
|
456
|
+
var letterSpacing = $(this).css("letter-spacing") || "0";
|
|
457
|
+
var letterSpacingNum = parseInt(letterSpacing);
|
|
458
|
+
maxLetterSpacing = Math.max(maxLetterSpacing, letterSpacingNum);
|
|
459
|
+
});
|
|
460
|
+
if (maxLetterSpacing > 0) {
|
|
461
|
+
$text.css("letter-spacing", maxLetterSpacing + "rem");
|
|
462
|
+
}
|
|
463
|
+
});
|
|
464
|
+
//将div中的text-align转移到text子节点上
|
|
465
|
+
$("div").each(function () {
|
|
466
|
+
var textAlign = $(this).css("text-align") || "";
|
|
467
|
+
textAlign != "" &&
|
|
468
|
+
$(this)
|
|
469
|
+
.children("text")
|
|
470
|
+
.each(function () {
|
|
471
|
+
$(this).css("text-align", textAlign);
|
|
472
|
+
});
|
|
473
|
+
$(this).css("text-align", "");
|
|
474
|
+
});
|
|
475
|
+
//去除空的text节点
|
|
476
|
+
$("text").each(function () {
|
|
477
|
+
var t = $(this).html() || "";
|
|
478
|
+
if (t.trim() == "") {
|
|
479
|
+
$(this).remove();
|
|
480
|
+
}
|
|
481
|
+
});
|
|
482
|
+
var hTagRem_1 = ["2rem", "1.5rem", "1.17rem", "1rem", "0.83rem", "0.67rem"];
|
|
483
|
+
["h1", "h2", "h3", "h4", "h5", "h6"].map(function (tag) {
|
|
484
|
+
return $("".concat(tag)).each(function () {
|
|
485
|
+
var idx = parseInt(tag.replace("h", "")) - 1;
|
|
486
|
+
var style = $(this).attr("style") || "";
|
|
487
|
+
//如果没有fontsize
|
|
488
|
+
if (!style.includes("font-size")) {
|
|
489
|
+
$(this).attr("style", "".concat(style, " font-size:").concat(hTagRem_1[idx]));
|
|
490
|
+
}
|
|
491
|
+
});
|
|
492
|
+
});
|
|
493
|
+
//一些标签会没有结束/,手动补充
|
|
494
|
+
//手动替换nbsp
|
|
495
|
+
var res = $.html();
|
|
496
|
+
res = res.replaceAll(/<img([^>]+)>/g, "<img$1 />").replaceAll(/ /g, " ");
|
|
497
|
+
// console.log(res);
|
|
498
|
+
return res;
|
|
499
|
+
}
|
|
500
|
+
};
|
|
501
|
+
/**
|
|
502
|
+
* 为富文本中的链接节点绑定点击事件
|
|
503
|
+
* @param linkClickHandler 点击事件回调函数
|
|
504
|
+
*/
|
|
505
|
+
RichText.bindLinkClickEvents = function (linkClickHandler) {
|
|
506
|
+
linkNodes.forEach(function (nodeInfo) {
|
|
507
|
+
var element = document.getElementById(nodeInfo.id);
|
|
508
|
+
if (element) {
|
|
509
|
+
element.onclick = function (e) {
|
|
510
|
+
e.stopPropagation();
|
|
511
|
+
e.preventDefault();
|
|
512
|
+
linkClickHandler({
|
|
513
|
+
type: nodeInfo.type,
|
|
514
|
+
href: nodeInfo.href,
|
|
515
|
+
id: nodeInfo.id,
|
|
516
|
+
});
|
|
517
|
+
return false;
|
|
518
|
+
};
|
|
519
|
+
}
|
|
520
|
+
});
|
|
521
|
+
};
|
|
522
|
+
})(RichText || (exports.RichText = RichText = {}));
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { RichText } from "./RichTextUtils";
|
|
2
|
-
export { RichText as default } from "./RichTextUtils";
|
|
1
|
+
export { RichText } from "./RichTextUtils";
|
|
2
|
+
export { RichText as default } from "./RichTextUtils";
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.default = exports.RichText = void 0;
|
|
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; } });
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = exports.RichText = void 0;
|
|
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,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pixui-dev/pixui-richtext-helper",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.1.1-beta.1",
|
|
4
|
+
"description": "pixui richtext helper",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"files": [
|
|
@@ -16,19 +16,13 @@
|
|
|
16
16
|
"publishConfig": {
|
|
17
17
|
"access": "public"
|
|
18
18
|
},
|
|
19
|
-
"
|
|
20
|
-
|
|
21
|
-
"richtext",
|
|
22
|
-
"html",
|
|
23
|
-
"converter"
|
|
24
|
-
],
|
|
25
|
-
"author": "pixui-dev",
|
|
26
|
-
"license": "MIT",
|
|
19
|
+
"author": "jnjnjnzhang",
|
|
20
|
+
"license": "ISC",
|
|
27
21
|
"devDependencies": {
|
|
28
|
-
"@types/node": "^
|
|
22
|
+
"@types/node": "^22.5.4",
|
|
29
23
|
"typescript": "^5.0.0"
|
|
30
24
|
},
|
|
31
25
|
"dependencies": {
|
|
32
|
-
"cheerio": "
|
|
26
|
+
"cheerio": "1.0.0-rc.10"
|
|
33
27
|
}
|
|
34
28
|
}
|