modern-text 0.5.13 → 0.6.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/index.cjs +198 -104
- package/dist/index.d.cts +29 -22
- package/dist/index.d.mts +29 -22
- package/dist/index.d.ts +29 -22
- package/dist/index.js +4 -4
- package/dist/index.mjs +198 -105
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -454,6 +454,9 @@ function filterEmpty(val) {
|
|
|
454
454
|
}
|
|
455
455
|
return res;
|
|
456
456
|
}
|
|
457
|
+
function needsFetch(source) {
|
|
458
|
+
return source.startsWith("http://") || source.startsWith("https://") || source.startsWith("blob://");
|
|
459
|
+
}
|
|
457
460
|
|
|
458
461
|
var __defProp$3 = Object.defineProperty;
|
|
459
462
|
var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
@@ -524,9 +527,6 @@ function definePlugin(options) {
|
|
|
524
527
|
}
|
|
525
528
|
|
|
526
529
|
class Measurer {
|
|
527
|
-
constructor(_text) {
|
|
528
|
-
this._text = _text;
|
|
529
|
-
}
|
|
530
530
|
_styleToDomStyle(style) {
|
|
531
531
|
const _style = { ...style };
|
|
532
532
|
for (const key in style) {
|
|
@@ -558,8 +558,7 @@ class Measurer {
|
|
|
558
558
|
* </ul>
|
|
559
559
|
* </section>
|
|
560
560
|
*/
|
|
561
|
-
|
|
562
|
-
const { paragraphs, computedStyle } = this._text;
|
|
561
|
+
createParagraphDom(paragraphs, rootStyle) {
|
|
563
562
|
const documentFragment = document.createDocumentFragment();
|
|
564
563
|
const dom = document.createElement("section");
|
|
565
564
|
Object.assign(dom.style, {
|
|
@@ -567,7 +566,7 @@ class Measurer {
|
|
|
567
566
|
height: "max-content",
|
|
568
567
|
whiteSpace: "pre-wrap",
|
|
569
568
|
wordBreak: "break-all",
|
|
570
|
-
...this._styleToDomStyle(
|
|
569
|
+
...this._styleToDomStyle(rootStyle),
|
|
571
570
|
position: "fixed",
|
|
572
571
|
visibility: "hidden"
|
|
573
572
|
});
|
|
@@ -596,12 +595,41 @@ class Measurer {
|
|
|
596
595
|
destory: () => dom.parentNode?.removeChild(dom)
|
|
597
596
|
};
|
|
598
597
|
}
|
|
599
|
-
|
|
598
|
+
measureDomText(text) {
|
|
599
|
+
const range = document.createRange();
|
|
600
|
+
range.selectNodeContents(text);
|
|
601
|
+
const data = text.data ?? "";
|
|
602
|
+
let offset = 0;
|
|
603
|
+
return Array.from(data).map((char) => {
|
|
604
|
+
const start = offset += data.substring(offset).indexOf(char);
|
|
605
|
+
const end = start + char.length;
|
|
606
|
+
offset += char.length;
|
|
607
|
+
range.setStart(text, Math.max(start, 0));
|
|
608
|
+
range.setEnd(text, end);
|
|
609
|
+
const rects = range.getClientRects?.() ?? [range.getBoundingClientRect()];
|
|
610
|
+
let rect = rects[rects.length - 1];
|
|
611
|
+
if (rects.length > 1 && rect.width < 2) {
|
|
612
|
+
rect = rects[rects.length - 2];
|
|
613
|
+
}
|
|
614
|
+
const content = range.toString();
|
|
615
|
+
if (content !== "" && rect && rect.width + rect.height !== 0) {
|
|
616
|
+
return {
|
|
617
|
+
content,
|
|
618
|
+
top: rect.top,
|
|
619
|
+
left: rect.left,
|
|
620
|
+
height: rect.height,
|
|
621
|
+
width: rect.width
|
|
622
|
+
};
|
|
623
|
+
}
|
|
624
|
+
return void 0;
|
|
625
|
+
}).filter(Boolean);
|
|
626
|
+
}
|
|
627
|
+
measureDom(dom) {
|
|
600
628
|
const paragraphs = [];
|
|
601
629
|
const fragments = [];
|
|
602
630
|
const characters = [];
|
|
603
|
-
dom.querySelectorAll("li").forEach((
|
|
604
|
-
const pBox =
|
|
631
|
+
dom.querySelectorAll("li").forEach((pDom, paragraphIndex) => {
|
|
632
|
+
const pBox = pDom.getBoundingClientRect();
|
|
605
633
|
paragraphs.push({
|
|
606
634
|
paragraphIndex,
|
|
607
635
|
left: pBox.left,
|
|
@@ -609,8 +637,8 @@ class Measurer {
|
|
|
609
637
|
width: pBox.width,
|
|
610
638
|
height: pBox.height
|
|
611
639
|
});
|
|
612
|
-
|
|
613
|
-
const fBox =
|
|
640
|
+
pDom.querySelectorAll(":scope > *").forEach((fDom, fragmentIndex) => {
|
|
641
|
+
const fBox = fDom.getBoundingClientRect();
|
|
614
642
|
fragments.push({
|
|
615
643
|
paragraphIndex,
|
|
616
644
|
fragmentIndex,
|
|
@@ -619,37 +647,32 @@ class Measurer {
|
|
|
619
647
|
width: fBox.width,
|
|
620
648
|
height: fBox.height
|
|
621
649
|
});
|
|
622
|
-
|
|
623
|
-
if (
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
left: rect.left,
|
|
649
|
-
height: rect.height,
|
|
650
|
-
width: rect.width,
|
|
651
|
-
textWidth: -1,
|
|
652
|
-
textHeight: -1
|
|
650
|
+
let characterIndex = 0;
|
|
651
|
+
if (fDom.firstChild instanceof window.Text) {
|
|
652
|
+
this.measureDomText(fDom.firstChild).forEach((char) => {
|
|
653
|
+
characters.push({
|
|
654
|
+
...char,
|
|
655
|
+
newParagraphIndex: -1,
|
|
656
|
+
paragraphIndex,
|
|
657
|
+
fragmentIndex,
|
|
658
|
+
characterIndex: characterIndex++,
|
|
659
|
+
textWidth: -1,
|
|
660
|
+
textHeight: -1
|
|
661
|
+
});
|
|
662
|
+
});
|
|
663
|
+
} else {
|
|
664
|
+
fDom.querySelectorAll(":scope > *").forEach((cDom) => {
|
|
665
|
+
if (cDom.firstChild instanceof window.Text) {
|
|
666
|
+
this.measureDomText(cDom.firstChild).forEach((char) => {
|
|
667
|
+
characters.push({
|
|
668
|
+
...char,
|
|
669
|
+
newParagraphIndex: -1,
|
|
670
|
+
paragraphIndex,
|
|
671
|
+
fragmentIndex,
|
|
672
|
+
characterIndex: characterIndex++,
|
|
673
|
+
textWidth: -1,
|
|
674
|
+
textHeight: -1
|
|
675
|
+
});
|
|
653
676
|
});
|
|
654
677
|
}
|
|
655
678
|
});
|
|
@@ -662,10 +685,9 @@ class Measurer {
|
|
|
662
685
|
characters
|
|
663
686
|
};
|
|
664
687
|
}
|
|
665
|
-
|
|
666
|
-
const { paragraphs } = this._text;
|
|
688
|
+
measureParagraphDom(paragraphs, dom) {
|
|
667
689
|
const rect = dom.getBoundingClientRect();
|
|
668
|
-
const measured = this.
|
|
690
|
+
const measured = this.measureDom(dom);
|
|
669
691
|
measured.paragraphs.forEach((p) => {
|
|
670
692
|
const _p = paragraphs[p.paragraphIndex];
|
|
671
693
|
_p.lineBox.left = p.left - rect.left;
|
|
@@ -715,12 +737,12 @@ class Measurer {
|
|
|
715
737
|
boundingBox: new BoundingBox(0, 0, rect.width, rect.height)
|
|
716
738
|
};
|
|
717
739
|
}
|
|
718
|
-
measure(dom) {
|
|
740
|
+
measure(paragraphs, rootStyle, dom) {
|
|
719
741
|
let destory;
|
|
720
742
|
if (!dom) {
|
|
721
|
-
({ dom, destory } = this.
|
|
743
|
+
({ dom, destory } = this.createParagraphDom(paragraphs, rootStyle));
|
|
722
744
|
}
|
|
723
|
-
const result = this.
|
|
745
|
+
const result = this.measureParagraphDom(paragraphs, dom);
|
|
724
746
|
destory?.();
|
|
725
747
|
return result;
|
|
726
748
|
}
|
|
@@ -823,33 +845,74 @@ class EventEmitter {
|
|
|
823
845
|
function highlight() {
|
|
824
846
|
const paths = [];
|
|
825
847
|
const clipRects = [];
|
|
826
|
-
const
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
if (!
|
|
830
|
-
|
|
831
|
-
|
|
848
|
+
const loaded = /* @__PURE__ */ new Map();
|
|
849
|
+
const parsed = /* @__PURE__ */ new Map();
|
|
850
|
+
async function loadSvg(svg) {
|
|
851
|
+
if (!loaded.has(svg)) {
|
|
852
|
+
loaded.set(svg, svg);
|
|
853
|
+
try {
|
|
854
|
+
loaded.set(svg, await fetch(svg).then((rep) => rep.text()));
|
|
855
|
+
} catch (err) {
|
|
856
|
+
console.warn(err);
|
|
857
|
+
loaded.delete(svg);
|
|
832
858
|
}
|
|
833
|
-
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
function getPaths(svg) {
|
|
862
|
+
let result = parsed.get(svg);
|
|
863
|
+
if (!result) {
|
|
864
|
+
const dom = parseSvgToDom(
|
|
865
|
+
needsFetch(svg) ? loaded.get(svg) ?? svg : svg
|
|
866
|
+
);
|
|
834
867
|
const paths2 = parseSvg(dom);
|
|
835
868
|
result = { dom, paths: paths2 };
|
|
836
|
-
|
|
869
|
+
parsed.set(svg, result);
|
|
837
870
|
}
|
|
838
871
|
return result;
|
|
839
872
|
}
|
|
840
873
|
return definePlugin({
|
|
841
874
|
name: "highlight",
|
|
842
875
|
paths,
|
|
843
|
-
|
|
876
|
+
load: async (text) => {
|
|
877
|
+
const promises = [];
|
|
878
|
+
text.forEachCharacter((character) => {
|
|
879
|
+
const { computedStyle: style } = character;
|
|
880
|
+
const { highlightImage, highlightReferImage } = style;
|
|
881
|
+
if (needsFetch(highlightImage)) {
|
|
882
|
+
promises.push(loadSvg(highlightImage));
|
|
883
|
+
}
|
|
884
|
+
if (needsFetch(highlightReferImage)) {
|
|
885
|
+
promises.push(loadSvg(highlightReferImage));
|
|
886
|
+
}
|
|
887
|
+
});
|
|
888
|
+
await Promise.all(promises);
|
|
889
|
+
},
|
|
890
|
+
update: (text) => {
|
|
844
891
|
clipRects.length = 0;
|
|
845
892
|
paths.length = 0;
|
|
846
893
|
let groups = [];
|
|
847
894
|
let group;
|
|
848
895
|
let prevStyle;
|
|
849
896
|
text.forEachCharacter((character) => {
|
|
850
|
-
const {
|
|
851
|
-
|
|
852
|
-
|
|
897
|
+
const {
|
|
898
|
+
computedStyle: style
|
|
899
|
+
} = character;
|
|
900
|
+
const {
|
|
901
|
+
highlightImage
|
|
902
|
+
} = style;
|
|
903
|
+
if (!isNone(highlightImage)) {
|
|
904
|
+
const {
|
|
905
|
+
inlineBox,
|
|
906
|
+
isVertical
|
|
907
|
+
} = character;
|
|
908
|
+
const {
|
|
909
|
+
fontSize,
|
|
910
|
+
highlightColormap,
|
|
911
|
+
highlightLine,
|
|
912
|
+
highlightSize,
|
|
913
|
+
highlightThickness
|
|
914
|
+
} = style;
|
|
915
|
+
if ((!prevStyle || isEqualValue(prevStyle.highlightImage, highlightImage) && isEqualValue(prevStyle.highlightColormap, highlightColormap) && isEqualValue(prevStyle.highlightLine, highlightLine) && isEqualValue(prevStyle.highlightSize, highlightSize) && isEqualValue(prevStyle.highlightThickness, highlightThickness)) && group?.length && (isVertical ? group[0].inlineBox.left === inlineBox.left : group[0].inlineBox.top === inlineBox.top) && group[0].fontSize === fontSize) {
|
|
853
916
|
group.push(character);
|
|
854
917
|
} else {
|
|
855
918
|
group = [];
|
|
@@ -868,8 +931,12 @@ function highlight() {
|
|
|
868
931
|
for (let i = 0; i < groups.length; i++) {
|
|
869
932
|
const characters = groups[i];
|
|
870
933
|
const char = characters[0];
|
|
871
|
-
const groupBox = BoundingBox.from(
|
|
872
|
-
|
|
934
|
+
const groupBox = BoundingBox.from(
|
|
935
|
+
...characters.filter((c) => c.glyphBox).map((c) => c.glyphBox)
|
|
936
|
+
);
|
|
937
|
+
const {
|
|
938
|
+
computedStyle: style
|
|
939
|
+
} = char;
|
|
873
940
|
const {
|
|
874
941
|
fontSize,
|
|
875
942
|
writingMode,
|
|
@@ -883,7 +950,7 @@ function highlight() {
|
|
|
883
950
|
const isVertical = writingMode.includes("vertical");
|
|
884
951
|
const thickness = parseValueNumber(highlightThickness, { fontSize, total: groupBox.width }) / groupBox.width;
|
|
885
952
|
const colormap = parseColormap(highlightColormap);
|
|
886
|
-
const { paths: svgPaths, dom: svgDom } =
|
|
953
|
+
const { paths: svgPaths, dom: svgDom } = getPaths(highlightImage);
|
|
887
954
|
const aBox = getPathsBoundingBox(svgPaths, true);
|
|
888
955
|
const styleScale = fontSize / aBox.width * 2;
|
|
889
956
|
const cBox = new BoundingBox().copy(groupBox);
|
|
@@ -899,7 +966,7 @@ function highlight() {
|
|
|
899
966
|
cBox.width = userWidth;
|
|
900
967
|
}
|
|
901
968
|
if (!isNone(highlightReferImage) && isNone(highlightLine)) {
|
|
902
|
-
const bBox = getPathsBoundingBox(
|
|
969
|
+
const bBox = getPathsBoundingBox(getPaths(highlightReferImage).paths, true);
|
|
903
970
|
aBox.copy(bBox);
|
|
904
971
|
} else {
|
|
905
972
|
let line;
|
|
@@ -1050,8 +1117,16 @@ function listStyle() {
|
|
|
1050
1117
|
const { paragraphs, isVertical, fontSize } = text;
|
|
1051
1118
|
const padding = fontSize * 0.45;
|
|
1052
1119
|
paragraphs.forEach((paragraph) => {
|
|
1053
|
-
const {
|
|
1054
|
-
|
|
1120
|
+
const {
|
|
1121
|
+
computedStyle: style
|
|
1122
|
+
} = paragraph;
|
|
1123
|
+
const {
|
|
1124
|
+
color,
|
|
1125
|
+
listStyleImage,
|
|
1126
|
+
listStyleColormap,
|
|
1127
|
+
listStyleSize,
|
|
1128
|
+
listStyleType
|
|
1129
|
+
} = style;
|
|
1055
1130
|
const colormap = parseColormap(listStyleColormap);
|
|
1056
1131
|
let size = listStyleSize;
|
|
1057
1132
|
let image;
|
|
@@ -1080,18 +1155,10 @@ function listStyle() {
|
|
|
1080
1155
|
const m = new Matrix3();
|
|
1081
1156
|
if (isVertical) {
|
|
1082
1157
|
const reScale = fontSize / imageBox.height * scale;
|
|
1083
|
-
m.translate(-imageBox.left, -imageBox.top);
|
|
1084
|
-
m.rotate(Math.PI / 2);
|
|
1085
|
-
m.scale(reScale, reScale);
|
|
1086
|
-
m.translate(fontSize / 2 - imageBox.height * reScale / 2, 0);
|
|
1087
|
-
m.translate(box.left + (box.width - fontSize) / 2, fBox.top - padding);
|
|
1158
|
+
m.translate(-imageBox.left, -imageBox.top).rotate(Math.PI / 2).scale(reScale, reScale).translate(fontSize / 2 - imageBox.height * reScale / 2, 0).translate(box.left + (box.width - fontSize) / 2, fBox.top - padding);
|
|
1088
1159
|
} else {
|
|
1089
1160
|
const reScale = fontSize / imageBox.height * scale;
|
|
1090
|
-
m.translate(-imageBox.left, -imageBox.top);
|
|
1091
|
-
m.translate(-imageBox.width, 0);
|
|
1092
|
-
m.scale(reScale, reScale);
|
|
1093
|
-
m.translate(0, fontSize / 2 - imageBox.height * reScale / 2);
|
|
1094
|
-
m.translate(fBox.left - padding, box.top + (box.height - fontSize) / 2);
|
|
1161
|
+
m.translate(-imageBox.left, -imageBox.top).translate(-imageBox.width, 0).scale(reScale, reScale).translate(0, fontSize / 2 - imageBox.height * reScale / 2).translate(fBox.left - padding, box.top + (box.height - fontSize) / 2);
|
|
1095
1162
|
}
|
|
1096
1163
|
paths.push(...imagePaths.map((p) => {
|
|
1097
1164
|
const path = p.clone();
|
|
@@ -1227,11 +1294,24 @@ function textDecoration() {
|
|
|
1227
1294
|
let group;
|
|
1228
1295
|
let prevStyle;
|
|
1229
1296
|
text.forEachCharacter((character) => {
|
|
1230
|
-
const {
|
|
1231
|
-
|
|
1297
|
+
const {
|
|
1298
|
+
computedStyle: style,
|
|
1299
|
+
isVertical,
|
|
1300
|
+
inlineBox,
|
|
1301
|
+
underlinePosition,
|
|
1302
|
+
underlineThickness,
|
|
1303
|
+
strikeoutPosition,
|
|
1304
|
+
strikeoutSize
|
|
1305
|
+
} = character;
|
|
1306
|
+
const {
|
|
1307
|
+
color,
|
|
1308
|
+
textDecoration: textDecoration2,
|
|
1309
|
+
writingMode
|
|
1310
|
+
} = style;
|
|
1311
|
+
if (!isNone(textDecoration2)) {
|
|
1232
1312
|
let flag = false;
|
|
1233
|
-
if (prevStyle?.textDecoration ===
|
|
1234
|
-
switch (
|
|
1313
|
+
if (prevStyle?.textDecoration === textDecoration2 && prevStyle?.writingMode === writingMode && prevStyle?.color === color && (isVertical ? group[0].inlineBox.left === inlineBox.left : group[0].inlineBox.top === inlineBox.top)) {
|
|
1314
|
+
switch (textDecoration2) {
|
|
1235
1315
|
case "underline":
|
|
1236
1316
|
if (group[0].underlinePosition === underlinePosition && group[0].underlineThickness === underlineThickness) {
|
|
1237
1317
|
flag = true;
|
|
@@ -1257,8 +1337,18 @@ function textDecoration() {
|
|
|
1257
1337
|
}
|
|
1258
1338
|
});
|
|
1259
1339
|
groups.forEach((group2) => {
|
|
1260
|
-
const {
|
|
1261
|
-
|
|
1340
|
+
const {
|
|
1341
|
+
computedStyle: style,
|
|
1342
|
+
isVertical,
|
|
1343
|
+
underlinePosition,
|
|
1344
|
+
underlineThickness,
|
|
1345
|
+
strikeoutPosition,
|
|
1346
|
+
strikeoutSize
|
|
1347
|
+
} = group2[0];
|
|
1348
|
+
const {
|
|
1349
|
+
color,
|
|
1350
|
+
textDecoration: textDecoration2
|
|
1351
|
+
} = style;
|
|
1262
1352
|
const { left, top, width, height } = BoundingBox.from(...group2.map((c) => c.inlineBox));
|
|
1263
1353
|
let position = isVertical ? left + width : top;
|
|
1264
1354
|
const direction = isVertical ? -1 : 1;
|
|
@@ -1401,7 +1491,7 @@ class Text extends EventEmitter {
|
|
|
1401
1491
|
__publicField(this, "glyphBox", new BoundingBox());
|
|
1402
1492
|
__publicField(this, "pathBox", new BoundingBox());
|
|
1403
1493
|
__publicField(this, "boundingBox", new BoundingBox());
|
|
1404
|
-
__publicField(this, "measurer", new Measurer(
|
|
1494
|
+
__publicField(this, "measurer", new Measurer());
|
|
1405
1495
|
__publicField(this, "plugins", /* @__PURE__ */ new Map());
|
|
1406
1496
|
__publicField(this, "fonts");
|
|
1407
1497
|
this.debug = options.debug ?? false;
|
|
@@ -1435,6 +1525,9 @@ class Text extends EventEmitter {
|
|
|
1435
1525
|
});
|
|
1436
1526
|
return this;
|
|
1437
1527
|
}
|
|
1528
|
+
async load() {
|
|
1529
|
+
await Promise.all(Array.from(this.plugins.values()).map((p) => p.load?.(this)));
|
|
1530
|
+
}
|
|
1438
1531
|
updateParagraphs() {
|
|
1439
1532
|
this.computedStyle = { ...defaultTextStyles, ...this.style };
|
|
1440
1533
|
let { content, computedStyle: style } = this;
|
|
@@ -1486,7 +1579,7 @@ class Text extends EventEmitter {
|
|
|
1486
1579
|
this.paragraphs = paragraphs;
|
|
1487
1580
|
return this;
|
|
1488
1581
|
}
|
|
1489
|
-
|
|
1582
|
+
measure(dom = this.measureDom) {
|
|
1490
1583
|
const old = {
|
|
1491
1584
|
paragraphs: this.paragraphs,
|
|
1492
1585
|
lineBox: this.lineBox,
|
|
@@ -1496,18 +1589,16 @@ class Text extends EventEmitter {
|
|
|
1496
1589
|
boundingBox: this.boundingBox
|
|
1497
1590
|
};
|
|
1498
1591
|
this.updateParagraphs();
|
|
1499
|
-
const result = this.measurer.measure(dom);
|
|
1592
|
+
const result = this.measurer.measure(this.paragraphs, this.computedStyle, dom);
|
|
1500
1593
|
this.paragraphs = result.paragraphs;
|
|
1501
1594
|
this.lineBox = result.boundingBox;
|
|
1502
1595
|
this.characters.forEach((c) => {
|
|
1503
1596
|
c.update(this.fonts);
|
|
1504
1597
|
});
|
|
1505
1598
|
this.rawGlyphBox = this.getGlyphBox();
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
await plugins[i].update?.(this);
|
|
1510
|
-
}
|
|
1599
|
+
Array.from(this.plugins.values()).sort((a, b) => (a.updateOrder ?? 0) - (b.updateOrder ?? 0)).forEach((plugin) => {
|
|
1600
|
+
plugin.update?.(this);
|
|
1601
|
+
});
|
|
1511
1602
|
this.glyphBox = this.getGlyphBox();
|
|
1512
1603
|
this.updatePathBox().updateBoundingBox();
|
|
1513
1604
|
for (const key in old) {
|
|
@@ -1563,30 +1654,28 @@ class Text extends EventEmitter {
|
|
|
1563
1654
|
this.needsUpdate = true;
|
|
1564
1655
|
return this;
|
|
1565
1656
|
}
|
|
1566
|
-
|
|
1567
|
-
const result =
|
|
1657
|
+
update() {
|
|
1658
|
+
const result = this.measure();
|
|
1568
1659
|
for (const key in result) {
|
|
1569
1660
|
this[key] = result[key];
|
|
1570
1661
|
}
|
|
1571
1662
|
this.emit("update", { text: this });
|
|
1663
|
+
return this;
|
|
1572
1664
|
}
|
|
1573
|
-
|
|
1665
|
+
render(options) {
|
|
1574
1666
|
const { view, pixelRatio = 2 } = options;
|
|
1575
1667
|
const ctx = view.getContext("2d");
|
|
1576
1668
|
if (!ctx) {
|
|
1577
1669
|
return;
|
|
1578
1670
|
}
|
|
1579
1671
|
if (this.needsUpdate) {
|
|
1580
|
-
|
|
1672
|
+
this.update();
|
|
1581
1673
|
}
|
|
1582
1674
|
setupView(ctx, pixelRatio, this.boundingBox);
|
|
1583
1675
|
uploadColors(ctx, this);
|
|
1584
|
-
|
|
1585
|
-
plugins.sort((a, b) => (a.renderOrder ?? 0) - (b.renderOrder ?? 0));
|
|
1586
|
-
for (let i = 0; i < plugins.length; i++) {
|
|
1587
|
-
const plugin = plugins[i];
|
|
1676
|
+
Array.from(this.plugins.values()).sort((a, b) => (a.renderOrder ?? 0) - (b.renderOrder ?? 0)).forEach((plugin) => {
|
|
1588
1677
|
if (plugin.render) {
|
|
1589
|
-
|
|
1678
|
+
plugin.render?.(ctx, this);
|
|
1590
1679
|
} else if (plugin.paths) {
|
|
1591
1680
|
const style = this.computedStyle;
|
|
1592
1681
|
plugin.paths.forEach((path) => {
|
|
@@ -1597,17 +1686,21 @@ class Text extends EventEmitter {
|
|
|
1597
1686
|
});
|
|
1598
1687
|
});
|
|
1599
1688
|
}
|
|
1600
|
-
}
|
|
1689
|
+
});
|
|
1601
1690
|
this.emit("render", { text: this, view, pixelRatio });
|
|
1602
1691
|
}
|
|
1603
1692
|
}
|
|
1604
1693
|
|
|
1605
|
-
function measureText(options) {
|
|
1606
|
-
|
|
1694
|
+
async function measureText(options) {
|
|
1695
|
+
const text = new Text(options);
|
|
1696
|
+
await text.load();
|
|
1697
|
+
return text.measure();
|
|
1607
1698
|
}
|
|
1608
1699
|
|
|
1609
|
-
function renderText(options) {
|
|
1610
|
-
|
|
1700
|
+
async function renderText(options) {
|
|
1701
|
+
const text = new Text(options);
|
|
1702
|
+
await text.load();
|
|
1703
|
+
text.render(options);
|
|
1611
1704
|
}
|
|
1612
1705
|
|
|
1613
|
-
export { Character, Fragment, Measurer, Paragraph, Text, defaultTextStyles, definePlugin, drawPath, filterEmpty, getTransform2D, hexToRgb, highlight, isEqualObject, isEqualValue, isNone, listStyle, measureText, parseColor, parseColormap, parseValueNumber, render, renderText, setupView, textDecoration, uploadColor, uploadColors };
|
|
1706
|
+
export { Character, Fragment, Measurer, Paragraph, Text, defaultTextStyles, definePlugin, drawPath, filterEmpty, getTransform2D, hexToRgb, highlight, isEqualObject, isEqualValue, isNone, listStyle, measureText, needsFetch, parseColor, parseColormap, parseValueNumber, render, renderText, setupView, textDecoration, uploadColor, uploadColors };
|