@pixui-dev/pixui-richtext-helper 0.2.11 → 0.2.12-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/RichTextCore.js +160 -30
- package/dist/version.d.ts +1 -0
- package/dist/version.js +5 -0
- package/package.json +1 -1
- package/readme.md +4 -1
package/dist/RichTextCore.js
CHANGED
|
@@ -34,6 +34,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
|
34
34
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
35
35
|
exports.RichTextCore = exports.LinkNodeType = void 0;
|
|
36
36
|
var cheerio = __importStar(require("cheerio"));
|
|
37
|
+
var version_1 = require("./version");
|
|
37
38
|
/*****************************************************
|
|
38
39
|
* 类型、枚举定义
|
|
39
40
|
*****************************************************/
|
|
@@ -129,15 +130,66 @@ var mergeStyles = function () {
|
|
|
129
130
|
return serializeStyleObject(mergedStyleObj);
|
|
130
131
|
};
|
|
131
132
|
var CLASS_STYLE_MAP = {
|
|
132
|
-
"ql-direction-rtl": function (old) { return mergeStyles("direction: rtl;"
|
|
133
|
-
"ql-align-right": function (old) { return mergeStyles("text-align: right;"
|
|
133
|
+
"ql-direction-rtl": function (old) { return mergeStyles(old, "direction: rtl;"); },
|
|
134
|
+
"ql-align-right": function (old) { return mergeStyles(old, "text-align: right;"); },
|
|
135
|
+
};
|
|
136
|
+
// data-list value → 需追加的 class 名
|
|
137
|
+
var DATA_LIST_CLASS_MAP = {
|
|
138
|
+
bullet: "ql-indent-0",
|
|
134
139
|
};
|
|
135
140
|
var _loop_1 = function (i) {
|
|
136
141
|
var cls = "ql-indent-".concat(i);
|
|
137
|
-
|
|
142
|
+
//如果之前加了ql-indent-x,取max
|
|
143
|
+
// 注意:此 mapper 可能在同一节点被多次调用(当存在多个 ql-indent-* 类时)
|
|
144
|
+
// 只有当当前 cls 对应的缩进值是该节点所有 ql-indent-* 中的最大值时才真正处理样式。
|
|
145
|
+
CLASS_STYLE_MAP[cls] = function (old, $elem) {
|
|
146
|
+
// 1) 计算该元素所有 ql-indent-* 中的最大值
|
|
147
|
+
var clsArr = ($elem.attr("class") || "").split(/\s+/).filter(Boolean);
|
|
148
|
+
var isRtl = clsArr.includes("ql-direction-rtl");
|
|
149
|
+
var maxIndentNum = 0;
|
|
150
|
+
clsArr.forEach(function (c) {
|
|
151
|
+
var m = c.match(/^ql-indent-(\d+)$/);
|
|
152
|
+
if (m) {
|
|
153
|
+
var n = parseInt(m[1]);
|
|
154
|
+
if (!isNaN(n) && n > maxIndentNum)
|
|
155
|
+
maxIndentNum = n;
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
// 当前 cls 对应的缩进级别
|
|
159
|
+
var currentIndentMatch = cls.match(/^ql-indent-(\d+)$/);
|
|
160
|
+
var currentIndentNum = currentIndentMatch ? parseInt(currentIndentMatch[1]) : 0;
|
|
161
|
+
// 当前处理的不是最大缩进级别
|
|
162
|
+
if (currentIndentNum !== maxIndentNum) {
|
|
163
|
+
return old;
|
|
164
|
+
}
|
|
165
|
+
// H5 基准:0级=1.5em,之后每级递增3em → padding = 1.5em + 3em * level
|
|
166
|
+
var desiredPadEm = 1.5 + (maxIndentNum + 1) * 3;
|
|
167
|
+
var styleObj = parseStyleString(old);
|
|
168
|
+
// 依据方向选择缩进属性键
|
|
169
|
+
var paddingKey = isRtl ? "padding-right" : "padding-left";
|
|
170
|
+
// 已有 padding-left/right,需比较取更大者
|
|
171
|
+
var existPadEm = -1;
|
|
172
|
+
var existPad = styleObj[paddingKey];
|
|
173
|
+
if (existPad) {
|
|
174
|
+
var m = existPad.match(/^([0-9.]+)(px|em)?$/i);
|
|
175
|
+
if (m) {
|
|
176
|
+
var num = parseFloat(m[1]);
|
|
177
|
+
var unit = (m[2] || "px").toLowerCase();
|
|
178
|
+
if (!isNaN(num)) {
|
|
179
|
+
existPadEm = unit === "em" ? num : num / 16;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
var finalPadEm = existPadEm > desiredPadEm ? existPadEm : desiredPadEm;
|
|
184
|
+
styleObj[paddingKey] = "".concat(finalPadEm, "em");
|
|
185
|
+
// 设置 list-style-type
|
|
186
|
+
var markersList = ["disc", "circle", "square", "empty square"];
|
|
187
|
+
styleObj["list-style-type"] = markersList[maxIndentNum % markersList.length];
|
|
188
|
+
return mergeStyles(old, serializeStyleObject(styleObj));
|
|
189
|
+
};
|
|
138
190
|
};
|
|
139
191
|
// 动态生成段落缩进 ql-indent-1 ~ ql-indent-10
|
|
140
|
-
for (var i =
|
|
192
|
+
for (var i = 0; i <= 10; i++) {
|
|
141
193
|
_loop_1(i);
|
|
142
194
|
}
|
|
143
195
|
/*****************************************************
|
|
@@ -167,6 +219,8 @@ var RichTextCore = /** @class */ (function () {
|
|
|
167
219
|
if ($1("text").length > 0) {
|
|
168
220
|
return str;
|
|
169
221
|
}
|
|
222
|
+
var oriNodeCount = $1("*").length;
|
|
223
|
+
console.log("pixui-richHelper转换---- 版本:" + " " + version_1.LIB_VERSION + " " + " 原始节点数:" + oriNodeCount);
|
|
170
224
|
// ---------- 第 1 步:段落分割(基础实现:根节点切分) ----------
|
|
171
225
|
var segments = RichTextCore.splitIntoSegments($1);
|
|
172
226
|
// ---------- 第 2/3 步:遍历 + 展平 ----------
|
|
@@ -175,7 +229,7 @@ var RichTextCore = /** @class */ (function () {
|
|
|
175
229
|
var processedSegments = segments.map(function (seg) { return RichTextCore.processSegment(seg, config); });
|
|
176
230
|
// ---------- 第 4 步:拼装 ----------
|
|
177
231
|
var Result = processedSegments.join("");
|
|
178
|
-
|
|
232
|
+
console.log(Result);
|
|
179
233
|
return Result;
|
|
180
234
|
};
|
|
181
235
|
/**
|
|
@@ -383,24 +437,39 @@ var RichTextCore = /** @class */ (function () {
|
|
|
383
437
|
// 根据映射表统一处理 class → style
|
|
384
438
|
$("*").each(function () {
|
|
385
439
|
var _this = this;
|
|
386
|
-
|
|
387
|
-
|
|
440
|
+
// 1) 先处理 data-list,可能追加 class
|
|
441
|
+
var dataList = $(this).attr("data-list");
|
|
442
|
+
if (dataList) {
|
|
443
|
+
var clsToAdd = DATA_LIST_CLASS_MAP[dataList];
|
|
444
|
+
if (clsToAdd) {
|
|
445
|
+
$(this).addClass(clsToAdd);
|
|
446
|
+
$(this).removeAttr("data-list");
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
// 2) 再处理 class → style 映射(包含刚刚追加的 class)
|
|
450
|
+
var classStrNow = $(this).attr("class") || "";
|
|
451
|
+
if (!classStrNow)
|
|
388
452
|
return;
|
|
389
|
-
var classArr =
|
|
453
|
+
var classArr = classStrNow.split(/\s+/).filter(Boolean);
|
|
390
454
|
if (classArr.length === 0)
|
|
391
455
|
return;
|
|
392
456
|
var styleStr = $(this).attr("style") || "";
|
|
393
457
|
var changed = false;
|
|
458
|
+
// 先累计样式,再统一移除命中的类,避免在 mapper 内部读取 class 时出现中途被修改导致的误判
|
|
459
|
+
var removedClasses = [];
|
|
394
460
|
classArr.forEach(function (cls) {
|
|
395
461
|
var mapper = CLASS_STYLE_MAP[cls];
|
|
396
462
|
if (mapper) {
|
|
397
463
|
styleStr = mapper(styleStr, $(_this));
|
|
398
|
-
|
|
464
|
+
removedClasses.push(cls);
|
|
399
465
|
changed = true;
|
|
400
466
|
}
|
|
401
467
|
});
|
|
402
468
|
if (changed) {
|
|
403
469
|
$(this).attr("style", styleStr);
|
|
470
|
+
if (removedClasses.length > 0) {
|
|
471
|
+
$(this).removeClass(removedClasses.join(" "));
|
|
472
|
+
}
|
|
404
473
|
}
|
|
405
474
|
});
|
|
406
475
|
// 在所有标题标签后插入换行 <br>
|
|
@@ -411,7 +480,7 @@ var RichTextCore = /** @class */ (function () {
|
|
|
411
480
|
$(this).after("<br>");
|
|
412
481
|
}
|
|
413
482
|
});
|
|
414
|
-
// 将所有的margin-left转换为padding-left
|
|
483
|
+
// 将所有的margin-left,margin-right转换为padding-left,padding-right
|
|
415
484
|
$("*").each(function () {
|
|
416
485
|
var oriStyle = $(this).attr("style") || "";
|
|
417
486
|
if (!oriStyle)
|
|
@@ -419,9 +488,12 @@ var RichTextCore = /** @class */ (function () {
|
|
|
419
488
|
var styleObj = parseStyleString(oriStyle);
|
|
420
489
|
// 1) 处理 margin-left 单独声明
|
|
421
490
|
var marginLeftVal = styleObj["margin-left"];
|
|
422
|
-
|
|
491
|
+
var marginRightVal = styleObj["margin-right"];
|
|
492
|
+
if (marginLeftVal !== undefined || marginRightVal !== undefined) {
|
|
423
493
|
delete styleObj["margin-left"];
|
|
494
|
+
delete styleObj["margin-right"];
|
|
424
495
|
styleObj["padding-left"] = styleObj["padding-left"] || marginLeftVal;
|
|
496
|
+
styleObj["padding-right"] = styleObj["padding-right"] || marginRightVal;
|
|
425
497
|
}
|
|
426
498
|
// 2) 处理 margin shorthand,提取 left
|
|
427
499
|
if (styleObj["margin"]) {
|
|
@@ -446,10 +518,9 @@ var RichTextCore = /** @class */ (function () {
|
|
|
446
518
|
bottom = parts[2];
|
|
447
519
|
left = parts[3];
|
|
448
520
|
}
|
|
449
|
-
// 将 left 移到 padding-left
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
}
|
|
521
|
+
// 将 left,right 移到 padding-left,padding-right
|
|
522
|
+
left && (styleObj["padding-left"] = styleObj["padding-left"] || left);
|
|
523
|
+
right && (styleObj["padding-right"] = styleObj["padding-right"] || right);
|
|
453
524
|
// 重构 margin,去掉 left(用 0 占位保持布局)
|
|
454
525
|
var newMargin = "".concat(top_1, " ").concat(right, " ").concat(bottom, " 0");
|
|
455
526
|
styleObj["margin"] = newMargin.trim();
|
|
@@ -568,17 +639,40 @@ var RichTextCore = /** @class */ (function () {
|
|
|
568
639
|
if (isOrdered) {
|
|
569
640
|
orderIndex = $child.prevAll("li").length + 1;
|
|
570
641
|
}
|
|
571
|
-
var marker = isOrdered ? "".concat(orderIndex, ".") : "•";
|
|
572
642
|
var paddingLeft = currentLevel * 2; // 每层缩进 2em
|
|
573
643
|
var $liClone = $child.clone();
|
|
574
644
|
$liClone.find("ol, ul").remove();
|
|
575
|
-
var textContent = $liClone.
|
|
645
|
+
var textContent = $liClone.html() || "";
|
|
576
646
|
var style = $child.attr("style") || "";
|
|
647
|
+
// 解析 style 判断 list-style-type
|
|
648
|
+
var styleObj = parseStyleString(style);
|
|
649
|
+
var listStyle = (styleObj["list-style-type"] || "").trim().toLowerCase();
|
|
650
|
+
// 查找有没有继承下来的属性
|
|
651
|
+
if (!listStyle) {
|
|
652
|
+
var parentStyleObj = parseStyleString($container.attr("style") || "");
|
|
653
|
+
listStyle = (parentStyleObj["list-style-type"] || "").trim().toLowerCase();
|
|
654
|
+
}
|
|
655
|
+
// 根据 list-style-type 与列表类型决定 marker
|
|
656
|
+
var BULLET_MARKER_MAP = {
|
|
657
|
+
disc: "●",
|
|
658
|
+
circle: "○",
|
|
659
|
+
square: "■",
|
|
660
|
+
"empty square": "□",
|
|
661
|
+
none: "",
|
|
662
|
+
};
|
|
663
|
+
var finalMarker = "";
|
|
664
|
+
if (listStyle && Object.prototype.hasOwnProperty.call(BULLET_MARKER_MAP, listStyle)) {
|
|
665
|
+
// 即使映射值为空字符串(none)也应使用
|
|
666
|
+
finalMarker = BULLET_MARKER_MAP[listStyle];
|
|
667
|
+
}
|
|
668
|
+
else {
|
|
669
|
+
finalMarker = isOrdered ? "".concat(orderIndex, ".") : "•";
|
|
670
|
+
}
|
|
577
671
|
items.push({
|
|
578
672
|
level: currentLevel,
|
|
579
673
|
isOrdered: isOrdered,
|
|
580
674
|
orderIndex: orderIndex,
|
|
581
|
-
marker:
|
|
675
|
+
marker: finalMarker,
|
|
582
676
|
paddingLeft: paddingLeft,
|
|
583
677
|
textContent: textContent,
|
|
584
678
|
style: style,
|
|
@@ -620,14 +714,38 @@ var RichTextCore = /** @class */ (function () {
|
|
|
620
714
|
var marginTopVal = idx === 0 ? 1 * lineHeightScale : 0.5 * lineHeightScale;
|
|
621
715
|
var marginBottomVal = idx === items.length - 1 ? 1 * lineHeightScale : 0.5 * lineHeightScale;
|
|
622
716
|
var marginAdjust = ["margin-top: ".concat(marginTopVal, "em"), "margin-bottom: ".concat(marginBottomVal, "em")];
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
717
|
+
// 解析 direction 与缩进,按 H5 悬挂缩进思路改为三列布局
|
|
718
|
+
var styleObj = parseStyleString(it.style || "");
|
|
719
|
+
var isRtl = (styleObj["direction"] || "").trim().toLowerCase() === "rtl";
|
|
720
|
+
var paddingKey = isRtl ? "padding-right" : "padding-left";
|
|
721
|
+
var padVal = styleObj[paddingKey];
|
|
722
|
+
var markerEm = 1.2;
|
|
723
|
+
var markerPx = markerEm * BASE_FONT_SIZE; // 约 19.2px
|
|
724
|
+
var indentPx = it.level * 40; // 回退:嵌套层级
|
|
725
|
+
if (padVal) {
|
|
726
|
+
var m = padVal.match(/^([0-9.]+)(px|em)?$/i);
|
|
727
|
+
if (m) {
|
|
728
|
+
var num = parseFloat(m[1]);
|
|
729
|
+
var unit = (m[2] || "px").toLowerCase();
|
|
730
|
+
if (!isNaN(num)) {
|
|
731
|
+
var padPx = unit === "em" ? num * BASE_FONT_SIZE : num;
|
|
732
|
+
indentPx = Math.max(padPx - markerPx, 0);
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
// 容器样式:移除 padding 与 list-style-type,设置 flex 布局并按方向翻转
|
|
737
|
+
delete styleObj["padding-left"];
|
|
738
|
+
delete styleObj["padding-right"];
|
|
739
|
+
delete styleObj["list-style-type"]; // 由三列布局承担
|
|
740
|
+
var rowDir = isRtl ? "row-reverse" : "row";
|
|
741
|
+
var outerStyle = mergeStyles.apply(void 0, __spreadArray(__spreadArray([serializeStyleObject(styleObj)], marginAdjust, false), ["flex-shrink: 0", "width: 100%", "display: flex", "flex-direction: ".concat(rowDir)], false));
|
|
742
|
+
// 三列:缩进列 + 标号列 + 文本列
|
|
743
|
+
var indentCol = "<key style=\"width:".concat(indentPx, "px;flex-shrink:0\"></key>");
|
|
744
|
+
var markerCol = it.marker
|
|
745
|
+
? "<key style=\"".concat(mergeStyles("flex-shrink: 0", "width: ".concat(markerEm, "em"), isRtl ? "padding-left: 0.3em" : "padding-right: 0.3em"), "\">").concat(it.marker, "</key>")
|
|
746
|
+
: "";
|
|
747
|
+
var textCol = "<text style=\"".concat(mergeStyles("flex: 1", "min-width: 0", "word-break: break-word"), "\">").concat(it.textContent, "</text>");
|
|
748
|
+
return "<div style=\"".concat(outerStyle, "\" data-list-item=\"true\">").concat(indentCol).concat(markerCol).concat(textCol, "</div>");
|
|
631
749
|
})
|
|
632
750
|
.join("");
|
|
633
751
|
placeholder.after(html);
|
|
@@ -698,7 +816,7 @@ var RichTextCore = /** @class */ (function () {
|
|
|
698
816
|
if (this.type === "text") {
|
|
699
817
|
var text = this.data.trim();
|
|
700
818
|
if (text.length > 0) {
|
|
701
|
-
$(this).replaceWith("<text style=\"".concat(mergeStyles("flex-shrink: 0", "flex-direction: row"), "\">").concat(text, "</text>"));
|
|
819
|
+
$(this).replaceWith("<text style=\"".concat(mergeStyles("flex-shrink: 0", "flex-direction: row", "word-break: break-word"), "\">").concat(text, "</text>"));
|
|
702
820
|
}
|
|
703
821
|
}
|
|
704
822
|
});
|
|
@@ -721,7 +839,13 @@ var RichTextCore = /** @class */ (function () {
|
|
|
721
839
|
$(tag).each(function () {
|
|
722
840
|
var html = $(this).html();
|
|
723
841
|
var oriStyle = $(this).attr("style") || "";
|
|
724
|
-
$(this).
|
|
842
|
+
var isInListTextColumn = $(this).closest("[data-list-item='true']").length > 0 && $(this).closest("text").length > 0;
|
|
843
|
+
if (isInListTextColumn) {
|
|
844
|
+
$(this).replaceWith("<key style=\"".concat(mergeStyles(oriStyle, style, "flex-shrink: 0", "word-break: break-word"), "\">").concat(html, "</key>"));
|
|
845
|
+
}
|
|
846
|
+
else {
|
|
847
|
+
$(this).replaceWith("<text style=\"".concat(mergeStyles(oriStyle, style, "flex-shrink: 0", "word-break: break-word"), "\">").concat(html, "</text>"));
|
|
848
|
+
}
|
|
725
849
|
hasLeftover = true;
|
|
726
850
|
});
|
|
727
851
|
});
|
|
@@ -729,7 +853,13 @@ var RichTextCore = /** @class */ (function () {
|
|
|
729
853
|
$("span").each(function () {
|
|
730
854
|
var html = $(this).html();
|
|
731
855
|
var oriStyle = $(this).attr("style") || "";
|
|
732
|
-
$(this).
|
|
856
|
+
var isInListTextColumn = $(this).closest("[data-list-item='true']").length > 0 && $(this).closest("text").length > 0;
|
|
857
|
+
if (isInListTextColumn) {
|
|
858
|
+
$(this).replaceWith("<key style=\"".concat(mergeStyles(oriStyle, "flex-shrink: 0", "word-break: break-word"), "\">").concat(html, "</key>"));
|
|
859
|
+
}
|
|
860
|
+
else {
|
|
861
|
+
$(this).replaceWith("<text style=\"".concat(mergeStyles(oriStyle, "flex-shrink: 0", "word-break: break-word"), "\">").concat(html, "</text>"));
|
|
862
|
+
}
|
|
733
863
|
hasLeftover = true;
|
|
734
864
|
});
|
|
735
865
|
}
|
|
@@ -857,7 +987,7 @@ var RichTextCore = /** @class */ (function () {
|
|
|
857
987
|
}
|
|
858
988
|
}
|
|
859
989
|
// 保证外层tag的style不合并子div的style
|
|
860
|
-
$(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, ">"));
|
|
990
|
+
$(node).replaceWith("<".concat(tag, " style=\"").concat(mergeStyles(tagStyle, "flex-direction: row"), "\"").concat(idAttr).concat(customAttrs, "><text style=\"").concat(mergeStyles("flex-shrink: 0", "width: 100%", "word-break: break-word"), "\">").concat(tagHtml, "</text></").concat(tag, ">"));
|
|
861
991
|
}
|
|
862
992
|
});
|
|
863
993
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const LIB_VERSION = "0.2.11";
|
package/dist/version.js
ADDED
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -31,6 +31,8 @@ componentDidMount() { // 在节点渲染后绑定点击事件
|
|
|
31
31
|
|
|
32
32
|
组件在转换长富文本(节点数量较多,参考节点数量大于100)的时候可能会比较慢阻塞活动显示,如果需要转换很长的富文本,建议询问管理端是否可以提供预转换服务,或者活动在前置虚拟机中预先转换以后保存到本地,活动中直接使用转换以后的结果。
|
|
33
33
|
|
|
34
|
+
组件当前只适配并测试过由floriazhang提供的管理端富文本编辑工具输出的富文本内容,除此之外的富文本内容不保证可以完全正确解析显示。
|
|
35
|
+
|
|
34
36
|
### 自定义节点样式
|
|
35
37
|
|
|
36
38
|
`convertRichTextToPixuiStyle` 在转换过程中会为特定节点增加 class 或 data-attribute,方便业务侧按需覆盖样式:
|
|
@@ -133,7 +135,8 @@ componentDidMount() { // 在节点渲染后绑定点击事件
|
|
|
133
135
|
|
|
134
136
|
1. 增加对class ql-align-right -> style="text-align: right;"的转换支持
|
|
135
137
|
|
|
136
|
-
0.2.11
|
|
138
|
+
0.2.11(f1dcaccc3b6c72b82b6b76cea654d50d5ba7ccad)
|
|
137
139
|
|
|
138
140
|
1. 修复图片原始尺寸和样式尺寸不一样,某些pixui版本尺寸不对的问题
|
|
139
141
|
2. 修复direction属性不生效的问题
|
|
142
|
+
3. text节点下的文本节点从div标签改为pixui推荐的key标签
|