modern-text 0.5.2 → 0.5.4
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 +180 -180
- package/dist/index.d.cts +16 -7
- package/dist/index.d.mts +16 -7
- package/dist/index.d.ts +16 -7
- package/dist/index.js +4 -4
- package/dist/index.mjs +177 -181
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -53,7 +53,7 @@ function parseCssLinearGradient(css, x, y, width, height) {
|
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
function drawPath(options) {
|
|
56
|
-
const { ctx, path, fontSize
|
|
56
|
+
const { ctx, path, fontSize } = options;
|
|
57
57
|
ctx.save();
|
|
58
58
|
ctx.beginPath();
|
|
59
59
|
const pathStyle = path.style;
|
|
@@ -67,11 +67,6 @@ function drawPath(options) {
|
|
|
67
67
|
shadowBlur: (options.shadowBlur ?? 0) * fontSize,
|
|
68
68
|
shadowColor: options.shadowColor
|
|
69
69
|
};
|
|
70
|
-
if (clipRect) {
|
|
71
|
-
ctx.rect(clipRect.left, clipRect.top, clipRect.width, clipRect.height);
|
|
72
|
-
ctx.clip();
|
|
73
|
-
ctx.beginPath();
|
|
74
|
-
}
|
|
75
70
|
path.drawTo(ctx, style);
|
|
76
71
|
ctx.restore();
|
|
77
72
|
}
|
|
@@ -353,6 +348,40 @@ class Character {
|
|
|
353
348
|
}
|
|
354
349
|
}
|
|
355
350
|
|
|
351
|
+
function parseValueNumber(value, ctx) {
|
|
352
|
+
if (typeof value === "number") {
|
|
353
|
+
return value;
|
|
354
|
+
} else {
|
|
355
|
+
if (value.endsWith("%")) {
|
|
356
|
+
value = value.substring(0, value.length - 1);
|
|
357
|
+
return Math.ceil(Number(value) / 100 * ctx.total);
|
|
358
|
+
} else if (value.endsWith("rem")) {
|
|
359
|
+
value = value.substring(0, value.length - 3);
|
|
360
|
+
return Number(value) * ctx.fontSize;
|
|
361
|
+
} else if (value.endsWith("em")) {
|
|
362
|
+
value = value.substring(0, value.length - 2);
|
|
363
|
+
return Number(value) * ctx.fontSize;
|
|
364
|
+
} else {
|
|
365
|
+
return Number(value);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
function parseColormap(colormap) {
|
|
370
|
+
const _colormap = isNone(colormap) ? {} : colormap;
|
|
371
|
+
return Object.keys(_colormap).reduce((obj, key) => {
|
|
372
|
+
let value = _colormap[key];
|
|
373
|
+
const keyRgb = hexToRgb(key);
|
|
374
|
+
const valueRgb = hexToRgb(value);
|
|
375
|
+
if (keyRgb) {
|
|
376
|
+
key = keyRgb;
|
|
377
|
+
}
|
|
378
|
+
if (valueRgb) {
|
|
379
|
+
value = valueRgb;
|
|
380
|
+
}
|
|
381
|
+
obj[key] = value;
|
|
382
|
+
return obj;
|
|
383
|
+
}, {});
|
|
384
|
+
}
|
|
356
385
|
function isNone(val) {
|
|
357
386
|
return !val || val === "none";
|
|
358
387
|
}
|
|
@@ -360,7 +389,18 @@ function isEqualObject(obj1, obj2) {
|
|
|
360
389
|
const keys1 = Object.keys(obj1);
|
|
361
390
|
const keys2 = Object.keys(obj2);
|
|
362
391
|
const keys = Array.from(/* @__PURE__ */ new Set([...keys1, ...keys2]));
|
|
363
|
-
return keys.every((key) => obj1[key]
|
|
392
|
+
return keys.every((key) => isEqualValue(obj1[key], obj2[key]));
|
|
393
|
+
}
|
|
394
|
+
function isEqualValue(val1, val2) {
|
|
395
|
+
const typeof1 = typeof val1;
|
|
396
|
+
const typeof2 = typeof val2;
|
|
397
|
+
if (typeof1 === typeof2) {
|
|
398
|
+
if (typeof1 === "object") {
|
|
399
|
+
return isEqualObject(val1, val2);
|
|
400
|
+
}
|
|
401
|
+
return val1 === val2;
|
|
402
|
+
}
|
|
403
|
+
return false;
|
|
364
404
|
}
|
|
365
405
|
function hexToRgb(hex) {
|
|
366
406
|
const cleanHex = hex.startsWith("#") ? hex.slice(1) : hex;
|
|
@@ -384,6 +424,30 @@ function filterEmpty(val) {
|
|
|
384
424
|
}
|
|
385
425
|
return res;
|
|
386
426
|
}
|
|
427
|
+
function closestDivisor(dividend, targetDivisor) {
|
|
428
|
+
if (dividend <= 0) {
|
|
429
|
+
throw new Error("Dividend must be a positive integer.");
|
|
430
|
+
}
|
|
431
|
+
const divisors = [];
|
|
432
|
+
for (let i = 1; i <= Math.sqrt(dividend); i++) {
|
|
433
|
+
if (dividend % i === 0) {
|
|
434
|
+
divisors.push(i);
|
|
435
|
+
if (i !== dividend / i) {
|
|
436
|
+
divisors.push(dividend / i);
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
let closest = divisors[0];
|
|
441
|
+
let minDifference = Math.abs(closest - targetDivisor);
|
|
442
|
+
for (const divisor of divisors) {
|
|
443
|
+
const difference = Math.abs(divisor - targetDivisor);
|
|
444
|
+
if (difference < minDifference) {
|
|
445
|
+
closest = divisor;
|
|
446
|
+
minDifference = difference;
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
return closest;
|
|
450
|
+
}
|
|
387
451
|
|
|
388
452
|
var __defProp$2 = Object.defineProperty;
|
|
389
453
|
var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
@@ -655,39 +719,8 @@ class Measurer {
|
|
|
655
719
|
}
|
|
656
720
|
}
|
|
657
721
|
|
|
658
|
-
function parseCharsPerRepeat(size, fontSize, total) {
|
|
659
|
-
if (size === "cover") {
|
|
660
|
-
return 0;
|
|
661
|
-
} else if (typeof size === "string") {
|
|
662
|
-
if (size.endsWith("%")) {
|
|
663
|
-
const rate = Number(size.substring(0, size.length - 1)) / 100;
|
|
664
|
-
return Math.ceil(rate * total / fontSize);
|
|
665
|
-
} else if (size.endsWith("rem")) {
|
|
666
|
-
return Number(size.substring(0, size.length - 3));
|
|
667
|
-
} else {
|
|
668
|
-
return Math.ceil(Number(size) / fontSize);
|
|
669
|
-
}
|
|
670
|
-
} else {
|
|
671
|
-
return Math.ceil(size / fontSize);
|
|
672
|
-
}
|
|
673
|
-
}
|
|
674
|
-
function parseThickness(thickness, fontSize, total) {
|
|
675
|
-
if (typeof thickness === "string") {
|
|
676
|
-
if (thickness.endsWith("%")) {
|
|
677
|
-
return Number(thickness.substring(0, thickness.length - 1)) / 100;
|
|
678
|
-
} else if (thickness.endsWith("rem")) {
|
|
679
|
-
const value = Number(thickness.substring(0, thickness.length - 3));
|
|
680
|
-
return value * fontSize / total;
|
|
681
|
-
} else {
|
|
682
|
-
return Number(thickness) / total;
|
|
683
|
-
}
|
|
684
|
-
} else {
|
|
685
|
-
return thickness / total;
|
|
686
|
-
}
|
|
687
|
-
}
|
|
688
722
|
function highlight() {
|
|
689
723
|
const paths = [];
|
|
690
|
-
const clipRects = [];
|
|
691
724
|
const svgStringToSvgPaths = /* @__PURE__ */ new Map();
|
|
692
725
|
function getPaths(svg) {
|
|
693
726
|
let result = svgStringToSvgPaths.get(svg);
|
|
@@ -710,7 +743,7 @@ function highlight() {
|
|
|
710
743
|
text.forEachCharacter((character) => {
|
|
711
744
|
const { isVertical, computedStyle: style, inlineBox, fontSize } = character;
|
|
712
745
|
if (!isNone(style.highlightImage) && character.glyphBox) {
|
|
713
|
-
if (style.highlightSize !== "1rem" && (!prevStyle || prevStyle.highlightImage
|
|
746
|
+
if (style.highlightSize !== "1rem" && (!prevStyle || isEqualValue(prevStyle.highlightImage, style.highlightImage) && isEqualValue(prevStyle.highlightColormap, style.highlightColormap) && isEqualValue(prevStyle.highlightLine, style.highlightLine) && isEqualValue(prevStyle.highlightSize, style.highlightSize) && isEqualValue(prevStyle.highlightThickness, style.highlightThickness)) && group?.length && (isVertical ? group[0].inlineBox.left === inlineBox.left : group[0].inlineBox.top === inlineBox.top) && group[0].fontSize === fontSize) {
|
|
714
747
|
group.push(character);
|
|
715
748
|
} else {
|
|
716
749
|
group = [];
|
|
@@ -720,120 +753,119 @@ function highlight() {
|
|
|
720
753
|
}
|
|
721
754
|
prevStyle = style;
|
|
722
755
|
});
|
|
723
|
-
groups.filter((characters) => characters.length).
|
|
756
|
+
groups.filter((characters) => characters.length).forEach((characters) => {
|
|
724
757
|
const char = characters[0];
|
|
725
|
-
|
|
726
|
-
char,
|
|
727
|
-
groupBox: modernPath2d.BoundingBox.from(...characters.map((c) => c.glyphBox))
|
|
728
|
-
};
|
|
729
|
-
}).forEach((group2) => {
|
|
730
|
-
const { char, groupBox } = group2;
|
|
758
|
+
const groupBox = modernPath2d.BoundingBox.from(...characters.map((c) => c.glyphBox));
|
|
731
759
|
const { computedStyle: style } = char;
|
|
732
760
|
const {
|
|
733
761
|
fontSize,
|
|
734
762
|
writingMode,
|
|
735
|
-
highlightThickness,
|
|
736
|
-
highlightSize,
|
|
737
|
-
highlightLine,
|
|
738
|
-
highlightOverflow,
|
|
739
763
|
highlightImage,
|
|
740
|
-
|
|
764
|
+
highlightReferImage,
|
|
765
|
+
highlightColormap,
|
|
766
|
+
highlightLine,
|
|
767
|
+
highlightSize,
|
|
768
|
+
highlightThickness
|
|
741
769
|
} = style;
|
|
742
770
|
const isVertical = writingMode.includes("vertical");
|
|
743
|
-
const thickness =
|
|
744
|
-
const
|
|
745
|
-
const overflow = isNone(highlightOverflow) ? charsPerRepeat ? "hidden" : "visible" : highlightOverflow;
|
|
746
|
-
const colors = Object.keys(highlightImageColors).reduce((obj, key) => {
|
|
747
|
-
let value = highlightImageColors[key];
|
|
748
|
-
const keyRgb = hexToRgb(key);
|
|
749
|
-
const valueRgb = hexToRgb(value);
|
|
750
|
-
if (keyRgb) {
|
|
751
|
-
key = keyRgb;
|
|
752
|
-
}
|
|
753
|
-
if (valueRgb) {
|
|
754
|
-
value = valueRgb;
|
|
755
|
-
}
|
|
756
|
-
obj[key] = value;
|
|
757
|
-
return obj;
|
|
758
|
-
}, {});
|
|
771
|
+
const thickness = parseValueNumber(highlightThickness, { fontSize, total: groupBox.width }) / groupBox.width;
|
|
772
|
+
const colormap = parseColormap(highlightColormap);
|
|
759
773
|
const { paths: svgPaths, dom: svgDom } = getPaths(highlightImage);
|
|
760
774
|
const aBox = modernPath2d.getPathsBoundingBox(svgPaths, true);
|
|
761
775
|
const styleScale = fontSize / aBox.width * 2;
|
|
762
776
|
const cBox = new modernPath2d.BoundingBox().copy(groupBox);
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
777
|
+
if (isVertical) {
|
|
778
|
+
cBox.width = groupBox.height;
|
|
779
|
+
cBox.height = groupBox.width;
|
|
780
|
+
cBox.left = groupBox.left + groupBox.width;
|
|
781
|
+
}
|
|
782
|
+
const rawWidth = Math.floor(cBox.width);
|
|
783
|
+
let userWidth = rawWidth;
|
|
784
|
+
if (highlightSize !== "cover") {
|
|
785
|
+
userWidth = parseValueNumber(highlightSize, { fontSize, total: groupBox.width });
|
|
786
|
+
userWidth = closestDivisor(rawWidth, userWidth);
|
|
787
|
+
cBox.width = userWidth;
|
|
788
|
+
}
|
|
789
|
+
if (!isNone(highlightReferImage) && isNone(highlightLine)) {
|
|
790
|
+
const bBox = modernPath2d.getPathsBoundingBox(getPaths(highlightReferImage).paths, true);
|
|
791
|
+
aBox.copy(bBox);
|
|
792
|
+
} else {
|
|
793
|
+
let line;
|
|
794
|
+
if (isNone(highlightLine)) {
|
|
795
|
+
if (aBox.width / aBox.height > 4) {
|
|
796
|
+
line = "underline";
|
|
797
|
+
const viewBox = svgDom.getAttribute("viewBox");
|
|
798
|
+
if (viewBox) {
|
|
799
|
+
const [_x, y, _w, h] = viewBox.split(" ").map((v) => Number(v));
|
|
800
|
+
const viewCenter = y + h / 2;
|
|
801
|
+
if (aBox.y < viewCenter && aBox.y + aBox.height > viewCenter) {
|
|
802
|
+
line = "line-through";
|
|
803
|
+
} else if (aBox.y + aBox.height < viewCenter) {
|
|
804
|
+
line = "overline";
|
|
805
|
+
} else {
|
|
806
|
+
line = "underline";
|
|
807
|
+
}
|
|
781
808
|
}
|
|
809
|
+
} else {
|
|
810
|
+
line = "outline";
|
|
782
811
|
}
|
|
783
812
|
} else {
|
|
784
|
-
line =
|
|
813
|
+
line = highlightLine;
|
|
785
814
|
}
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
cBox.y -= paddingY / 2;
|
|
815
|
+
switch (line) {
|
|
816
|
+
case "outline": {
|
|
817
|
+
const paddingX = cBox.width * 0.2;
|
|
818
|
+
const paddingY = cBox.height * 0.2;
|
|
819
|
+
cBox.width += paddingX;
|
|
820
|
+
cBox.height += paddingY;
|
|
821
|
+
if (isVertical) {
|
|
822
|
+
cBox.x -= paddingY / 2;
|
|
823
|
+
cBox.y -= paddingX / 2;
|
|
824
|
+
cBox.x += cBox.height;
|
|
825
|
+
} else {
|
|
826
|
+
cBox.x -= paddingX / 2;
|
|
827
|
+
cBox.y -= paddingY / 2;
|
|
828
|
+
}
|
|
829
|
+
break;
|
|
802
830
|
}
|
|
803
|
-
|
|
831
|
+
case "overline":
|
|
832
|
+
cBox.height = aBox.height * styleScale;
|
|
833
|
+
if (isVertical) {
|
|
834
|
+
cBox.x = char.inlineBox.left + char.inlineBox.width;
|
|
835
|
+
} else {
|
|
836
|
+
cBox.y = char.inlineBox.top;
|
|
837
|
+
}
|
|
838
|
+
break;
|
|
839
|
+
case "line-through":
|
|
840
|
+
cBox.height = aBox.height * styleScale;
|
|
841
|
+
if (isVertical) {
|
|
842
|
+
cBox.x = char.inlineBox.left + char.inlineBox.width - char.strikeoutPosition + cBox.height / 2;
|
|
843
|
+
} else {
|
|
844
|
+
cBox.y = char.inlineBox.top + char.strikeoutPosition - cBox.height / 2;
|
|
845
|
+
}
|
|
846
|
+
break;
|
|
847
|
+
case "underline":
|
|
848
|
+
cBox.height = aBox.height * styleScale;
|
|
849
|
+
if (isVertical) {
|
|
850
|
+
cBox.x = char.inlineBox.left + char.inlineBox.width - char.underlinePosition;
|
|
851
|
+
} else {
|
|
852
|
+
cBox.y = char.inlineBox.top + char.underlinePosition;
|
|
853
|
+
}
|
|
854
|
+
break;
|
|
804
855
|
}
|
|
805
|
-
case "overline":
|
|
806
|
-
cBox.height = aBox.height * styleScale;
|
|
807
|
-
if (isVertical) {
|
|
808
|
-
cBox.x = char.inlineBox.left + char.inlineBox.width;
|
|
809
|
-
} else {
|
|
810
|
-
cBox.y = char.inlineBox.top;
|
|
811
|
-
}
|
|
812
|
-
break;
|
|
813
|
-
case "line-through":
|
|
814
|
-
cBox.height = aBox.height * styleScale;
|
|
815
|
-
if (isVertical) {
|
|
816
|
-
cBox.x = char.inlineBox.left + char.inlineBox.width - char.strikeoutPosition + cBox.height / 2;
|
|
817
|
-
} else {
|
|
818
|
-
cBox.y = char.inlineBox.top + char.strikeoutPosition - cBox.height / 2;
|
|
819
|
-
}
|
|
820
|
-
break;
|
|
821
|
-
case "underline":
|
|
822
|
-
cBox.height = aBox.height * styleScale;
|
|
823
|
-
if (isVertical) {
|
|
824
|
-
cBox.x = char.inlineBox.left + char.inlineBox.width - char.underlinePosition;
|
|
825
|
-
} else {
|
|
826
|
-
cBox.y = char.inlineBox.top + char.underlinePosition;
|
|
827
|
-
}
|
|
828
|
-
break;
|
|
829
856
|
}
|
|
830
857
|
const transform = new modernPath2d.Matrix3().translate(-aBox.x, -aBox.y).scale(cBox.width / aBox.width, cBox.height / aBox.height);
|
|
831
858
|
if (isVertical) {
|
|
832
859
|
transform.rotate(-Math.PI / 2);
|
|
833
860
|
}
|
|
834
861
|
transform.translate(cBox.x, cBox.y);
|
|
835
|
-
for (let i = 0, len =
|
|
836
|
-
const _transform = transform.clone()
|
|
862
|
+
for (let i = 0, len = rawWidth / userWidth; i < len; i++) {
|
|
863
|
+
const _transform = transform.clone();
|
|
864
|
+
if (isVertical) {
|
|
865
|
+
_transform.translate(0, i * cBox.width);
|
|
866
|
+
} else {
|
|
867
|
+
_transform.translate(i * cBox.width, 0);
|
|
868
|
+
}
|
|
837
869
|
svgPaths.forEach((originalPath) => {
|
|
838
870
|
const path = originalPath.clone().matrix(_transform);
|
|
839
871
|
if (path.style.strokeWidth) {
|
|
@@ -848,30 +880,23 @@ function highlight() {
|
|
|
848
880
|
if (path.style.strokeDasharray) {
|
|
849
881
|
path.style.strokeDasharray = path.style.strokeDasharray.map((v) => v * styleScale);
|
|
850
882
|
}
|
|
851
|
-
if (path.style.fill && path.style.fill in
|
|
852
|
-
path.style.fill =
|
|
883
|
+
if (path.style.fill && path.style.fill in colormap) {
|
|
884
|
+
path.style.fill = colormap[path.style.fill];
|
|
853
885
|
}
|
|
854
|
-
if (path.style.stroke && path.style.stroke in
|
|
855
|
-
path.style.stroke =
|
|
886
|
+
if (path.style.stroke && path.style.stroke in colormap) {
|
|
887
|
+
path.style.stroke = colormap[path.style.stroke];
|
|
856
888
|
}
|
|
857
889
|
paths.push(path);
|
|
858
|
-
clipRects[paths.length - 1] = overflow === "hidden" ? new modernPath2d.BoundingBox(
|
|
859
|
-
groupBox.left,
|
|
860
|
-
groupBox.top - groupBox.height,
|
|
861
|
-
groupBox.width,
|
|
862
|
-
groupBox.height * 3
|
|
863
|
-
) : void 0;
|
|
864
890
|
});
|
|
865
891
|
}
|
|
866
892
|
});
|
|
867
893
|
},
|
|
868
894
|
renderOrder: -1,
|
|
869
895
|
render: (ctx, text) => {
|
|
870
|
-
paths.forEach((path
|
|
896
|
+
paths.forEach((path) => {
|
|
871
897
|
drawPath({
|
|
872
898
|
ctx,
|
|
873
899
|
path,
|
|
874
|
-
clipRect: clipRects[index],
|
|
875
900
|
fontSize: text.computedStyle.fontSize
|
|
876
901
|
});
|
|
877
902
|
if (text.debug) {
|
|
@@ -885,22 +910,6 @@ function highlight() {
|
|
|
885
910
|
});
|
|
886
911
|
}
|
|
887
912
|
|
|
888
|
-
function parseScale(size, fontSize, total) {
|
|
889
|
-
if (size === "cover") {
|
|
890
|
-
return 1;
|
|
891
|
-
} else if (typeof size === "string") {
|
|
892
|
-
if (size.endsWith("%")) {
|
|
893
|
-
return Number(size.substring(0, size.length - 1)) / 100;
|
|
894
|
-
} else if (size.endsWith("rem")) {
|
|
895
|
-
const value = Number(size.substring(0, size.length - 3));
|
|
896
|
-
return value * fontSize / total;
|
|
897
|
-
} else {
|
|
898
|
-
return Number(size) / total;
|
|
899
|
-
}
|
|
900
|
-
} else {
|
|
901
|
-
return size / total;
|
|
902
|
-
}
|
|
903
|
-
}
|
|
904
913
|
function listStyle() {
|
|
905
914
|
const paths = [];
|
|
906
915
|
return definePlugin({
|
|
@@ -912,20 +921,8 @@ function listStyle() {
|
|
|
912
921
|
const padding = fontSize * 0.45;
|
|
913
922
|
paragraphs.forEach((paragraph) => {
|
|
914
923
|
const { computedStyle: style } = paragraph;
|
|
915
|
-
const { listStyleImage,
|
|
916
|
-
const
|
|
917
|
-
let value = listStyleImageColors[key];
|
|
918
|
-
const keyRgb = hexToRgb(key);
|
|
919
|
-
const valueRgb = hexToRgb(value);
|
|
920
|
-
if (keyRgb) {
|
|
921
|
-
key = keyRgb;
|
|
922
|
-
}
|
|
923
|
-
if (valueRgb) {
|
|
924
|
-
value = valueRgb;
|
|
925
|
-
}
|
|
926
|
-
obj[key] = value;
|
|
927
|
-
return obj;
|
|
928
|
-
}, {});
|
|
924
|
+
const { listStyleImage, listStyleColormap, listStyleSize, listStyleType, color } = style;
|
|
925
|
+
const colormap = parseColormap(listStyleColormap);
|
|
929
926
|
let size = listStyleSize;
|
|
930
927
|
let image;
|
|
931
928
|
if (!isNone(listStyleImage)) {
|
|
@@ -949,9 +946,9 @@ function listStyle() {
|
|
|
949
946
|
const box = paragraph.lineBox;
|
|
950
947
|
const fBox = paragraph.fragments[0].inlineBox;
|
|
951
948
|
if (fBox) {
|
|
949
|
+
const scale = size === "cover" ? 1 : parseValueNumber(size, { total: fontSize, fontSize }) / fontSize;
|
|
952
950
|
const m = new modernPath2d.Matrix3();
|
|
953
951
|
if (isVertical) {
|
|
954
|
-
const scale = parseScale(size, fontSize, fontSize);
|
|
955
952
|
const reScale = fontSize / imageBox.height * scale;
|
|
956
953
|
m.translate(-imageBox.left, -imageBox.top);
|
|
957
954
|
m.rotate(Math.PI / 2);
|
|
@@ -959,7 +956,6 @@ function listStyle() {
|
|
|
959
956
|
m.translate(fontSize / 2 - imageBox.height * reScale / 2, 0);
|
|
960
957
|
m.translate(box.left + (box.width - fontSize) / 2, fBox.top - padding);
|
|
961
958
|
} else {
|
|
962
|
-
const scale = parseScale(size, fontSize, fontSize);
|
|
963
959
|
const reScale = fontSize / imageBox.height * scale;
|
|
964
960
|
m.translate(-imageBox.left, -imageBox.top);
|
|
965
961
|
m.translate(-imageBox.width, 0);
|
|
@@ -970,11 +966,11 @@ function listStyle() {
|
|
|
970
966
|
paths.push(...imagePaths.map((p) => {
|
|
971
967
|
const path = p.clone();
|
|
972
968
|
path.matrix(m);
|
|
973
|
-
if (path.style.fill && path.style.fill in
|
|
974
|
-
path.style.fill =
|
|
969
|
+
if (path.style.fill && path.style.fill in colormap) {
|
|
970
|
+
path.style.fill = colormap[path.style.fill];
|
|
975
971
|
}
|
|
976
|
-
if (path.style.stroke && path.style.stroke in
|
|
977
|
-
path.style.stroke =
|
|
972
|
+
if (path.style.stroke && path.style.stroke in colormap) {
|
|
973
|
+
path.style.stroke = colormap[path.style.stroke];
|
|
978
974
|
}
|
|
979
975
|
return path;
|
|
980
976
|
}));
|
|
@@ -1239,16 +1235,16 @@ const defaultTextStyles = {
|
|
|
1239
1235
|
// listStyle
|
|
1240
1236
|
listStyleType: "none",
|
|
1241
1237
|
listStyleImage: "none",
|
|
1242
|
-
|
|
1238
|
+
listStyleColormap: "none",
|
|
1243
1239
|
listStyleSize: "cover",
|
|
1244
1240
|
listStylePosition: "outside",
|
|
1245
1241
|
// highlight
|
|
1246
1242
|
highlightImage: "none",
|
|
1247
|
-
|
|
1243
|
+
highlightReferImage: "none",
|
|
1244
|
+
highlightColormap: "none",
|
|
1248
1245
|
highlightLine: "none",
|
|
1249
1246
|
highlightSize: "cover",
|
|
1250
1247
|
highlightThickness: "100%",
|
|
1251
|
-
highlightOverflow: "none",
|
|
1252
1248
|
// shadow
|
|
1253
1249
|
shadowColor: "rgba(0, 0, 0, 0)",
|
|
1254
1250
|
shadowOffsetX: 0,
|
|
@@ -1485,6 +1481,7 @@ exports.Fragment = Fragment;
|
|
|
1485
1481
|
exports.Measurer = Measurer;
|
|
1486
1482
|
exports.Paragraph = Paragraph;
|
|
1487
1483
|
exports.Text = Text;
|
|
1484
|
+
exports.closestDivisor = closestDivisor;
|
|
1488
1485
|
exports.defaultTextStyles = defaultTextStyles;
|
|
1489
1486
|
exports.definePlugin = definePlugin;
|
|
1490
1487
|
exports.drawPath = drawPath;
|
|
@@ -1493,10 +1490,13 @@ exports.getTransform2D = getTransform2D;
|
|
|
1493
1490
|
exports.hexToRgb = hexToRgb;
|
|
1494
1491
|
exports.highlight = highlight;
|
|
1495
1492
|
exports.isEqualObject = isEqualObject;
|
|
1493
|
+
exports.isEqualValue = isEqualValue;
|
|
1496
1494
|
exports.isNone = isNone;
|
|
1497
1495
|
exports.listStyle = listStyle;
|
|
1498
1496
|
exports.measureText = measureText;
|
|
1499
1497
|
exports.parseColor = parseColor;
|
|
1498
|
+
exports.parseColormap = parseColormap;
|
|
1499
|
+
exports.parseValueNumber = parseValueNumber;
|
|
1500
1500
|
exports.render = render;
|
|
1501
1501
|
exports.renderText = renderText;
|
|
1502
1502
|
exports.setupView = setupView;
|
package/dist/index.d.cts
CHANGED
|
@@ -191,13 +191,15 @@ type TextTransform = 'none' | 'uppercase' | 'lowercase';
|
|
|
191
191
|
type TextDecorationLine = 'none' | 'underline' | 'line-through' | 'overline';
|
|
192
192
|
type ListStyleType = 'none' | 'disc';
|
|
193
193
|
type ListStyleImage = 'none' | string;
|
|
194
|
+
type ListStyleColormap = 'none' | Record<string, string>;
|
|
194
195
|
type ListStyleSize = 'cover' | Sizeable;
|
|
195
196
|
type ListStylePosition = 'inside' | 'outside';
|
|
196
197
|
type HighlightLine = TextDecorationLine | 'outline';
|
|
197
198
|
type HighlightImage = 'none' | string;
|
|
199
|
+
type HighlightReferImage = 'none' | string;
|
|
200
|
+
type HighlightColormap = 'none' | Record<string, string>;
|
|
198
201
|
type HighlightSize = 'cover' | Sizeable;
|
|
199
202
|
type HighlightThickness = Sizeable;
|
|
200
|
-
type HighlightOverflow = 'none' | 'visible' | 'hidden';
|
|
201
203
|
interface TextLineStyle {
|
|
202
204
|
writingMode: WritingMode;
|
|
203
205
|
textWrap: TextWrap;
|
|
@@ -206,7 +208,7 @@ interface TextLineStyle {
|
|
|
206
208
|
lineHeight: number;
|
|
207
209
|
listStyleType: ListStyleType;
|
|
208
210
|
listStyleImage: ListStyleImage;
|
|
209
|
-
|
|
211
|
+
listStyleColormap: ListStyleColormap;
|
|
210
212
|
listStyleSize: ListStyleSize;
|
|
211
213
|
listStylePosition: ListStylePosition;
|
|
212
214
|
}
|
|
@@ -222,11 +224,11 @@ interface TextInlineStyle {
|
|
|
222
224
|
textOrientation: TextOrientation;
|
|
223
225
|
textDecoration: TextDecorationLine;
|
|
224
226
|
highlightImage: HighlightImage;
|
|
225
|
-
|
|
227
|
+
highlightReferImage: HighlightReferImage;
|
|
228
|
+
highlightColormap: HighlightColormap;
|
|
226
229
|
highlightLine: HighlightLine;
|
|
227
230
|
highlightSize: HighlightSize;
|
|
228
231
|
highlightThickness: HighlightThickness;
|
|
229
|
-
highlightOverflow: HighlightOverflow;
|
|
230
232
|
}
|
|
231
233
|
interface TextDrawStyle {
|
|
232
234
|
color: string | CanvasGradient | CanvasPattern;
|
|
@@ -287,7 +289,6 @@ interface DrawShapePathsOptions extends Partial<TextStyle> {
|
|
|
287
289
|
ctx: CanvasRenderingContext2D;
|
|
288
290
|
path: Path2D;
|
|
289
291
|
fontSize: number;
|
|
290
|
-
clipRect?: BoundingBox;
|
|
291
292
|
}
|
|
292
293
|
declare function drawPath(options: DrawShapePathsOptions): void;
|
|
293
294
|
|
|
@@ -310,9 +311,17 @@ declare function textDecoration(): TextPlugin;
|
|
|
310
311
|
|
|
311
312
|
declare function renderText(options: TextOptions & TextRenderOptions): Text;
|
|
312
313
|
|
|
313
|
-
|
|
314
|
+
interface ValueContext {
|
|
315
|
+
total: number;
|
|
316
|
+
fontSize: number;
|
|
317
|
+
}
|
|
318
|
+
declare function parseValueNumber(value: string | number, ctx: ValueContext): number;
|
|
319
|
+
declare function parseColormap(colormap: 'none' | Record<string, string>): Record<string, string>;
|
|
320
|
+
declare function isNone(val: any): boolean;
|
|
314
321
|
declare function isEqualObject(obj1: Record<string, any>, obj2: Record<string, any>): boolean;
|
|
322
|
+
declare function isEqualValue(val1: any, val2: any): boolean;
|
|
315
323
|
declare function hexToRgb(hex: string): string | null;
|
|
316
324
|
declare function filterEmpty(val: Record<string, any> | undefined): Record<string, any> | undefined;
|
|
325
|
+
declare function closestDivisor(dividend: number, targetDivisor: number): number;
|
|
317
326
|
|
|
318
|
-
export { Character, type DrawShapePathsOptions, type FontKerning, type FontStyle, type FontWeight, Fragment, type FragmentContent, type HighlightImage, type HighlightLine, type
|
|
327
|
+
export { Character, type DrawShapePathsOptions, type FontKerning, type FontStyle, type FontWeight, Fragment, type FragmentContent, type HighlightColormap, type HighlightImage, type HighlightLine, type HighlightReferImage, type HighlightSize, type HighlightThickness, type LinearGradient, type ListStyleColormap, type ListStyleImage, type ListStylePosition, type ListStyleSize, type ListStyleType, type MeasureDomResult, type MeasureResult, type MeasuredCharacter, type MeasuredFragment, type MeasuredParagraph, Measurer, Paragraph, type ParagraphContent, type Sizeable, Text, type TextAlign, type TextContent, type TextDecorationLine, type TextDrawStyle, type TextInlineStyle, type TextLineStyle, type TextOptions, type TextOrientation, type TextPlugin, type TextRenderOptions, type TextStyle, type TextTransform, type TextWrap, type VerticalAlign, type WritingMode, closestDivisor, defaultTextStyles, definePlugin, drawPath, filterEmpty, getTransform2D, hexToRgb, highlight, isEqualObject, isEqualValue, isNone, listStyle, measureText, parseColor, parseColormap, parseValueNumber, render, renderText, setupView, textDecoration, uploadColor, uploadColors };
|
package/dist/index.d.mts
CHANGED
|
@@ -191,13 +191,15 @@ type TextTransform = 'none' | 'uppercase' | 'lowercase';
|
|
|
191
191
|
type TextDecorationLine = 'none' | 'underline' | 'line-through' | 'overline';
|
|
192
192
|
type ListStyleType = 'none' | 'disc';
|
|
193
193
|
type ListStyleImage = 'none' | string;
|
|
194
|
+
type ListStyleColormap = 'none' | Record<string, string>;
|
|
194
195
|
type ListStyleSize = 'cover' | Sizeable;
|
|
195
196
|
type ListStylePosition = 'inside' | 'outside';
|
|
196
197
|
type HighlightLine = TextDecorationLine | 'outline';
|
|
197
198
|
type HighlightImage = 'none' | string;
|
|
199
|
+
type HighlightReferImage = 'none' | string;
|
|
200
|
+
type HighlightColormap = 'none' | Record<string, string>;
|
|
198
201
|
type HighlightSize = 'cover' | Sizeable;
|
|
199
202
|
type HighlightThickness = Sizeable;
|
|
200
|
-
type HighlightOverflow = 'none' | 'visible' | 'hidden';
|
|
201
203
|
interface TextLineStyle {
|
|
202
204
|
writingMode: WritingMode;
|
|
203
205
|
textWrap: TextWrap;
|
|
@@ -206,7 +208,7 @@ interface TextLineStyle {
|
|
|
206
208
|
lineHeight: number;
|
|
207
209
|
listStyleType: ListStyleType;
|
|
208
210
|
listStyleImage: ListStyleImage;
|
|
209
|
-
|
|
211
|
+
listStyleColormap: ListStyleColormap;
|
|
210
212
|
listStyleSize: ListStyleSize;
|
|
211
213
|
listStylePosition: ListStylePosition;
|
|
212
214
|
}
|
|
@@ -222,11 +224,11 @@ interface TextInlineStyle {
|
|
|
222
224
|
textOrientation: TextOrientation;
|
|
223
225
|
textDecoration: TextDecorationLine;
|
|
224
226
|
highlightImage: HighlightImage;
|
|
225
|
-
|
|
227
|
+
highlightReferImage: HighlightReferImage;
|
|
228
|
+
highlightColormap: HighlightColormap;
|
|
226
229
|
highlightLine: HighlightLine;
|
|
227
230
|
highlightSize: HighlightSize;
|
|
228
231
|
highlightThickness: HighlightThickness;
|
|
229
|
-
highlightOverflow: HighlightOverflow;
|
|
230
232
|
}
|
|
231
233
|
interface TextDrawStyle {
|
|
232
234
|
color: string | CanvasGradient | CanvasPattern;
|
|
@@ -287,7 +289,6 @@ interface DrawShapePathsOptions extends Partial<TextStyle> {
|
|
|
287
289
|
ctx: CanvasRenderingContext2D;
|
|
288
290
|
path: Path2D;
|
|
289
291
|
fontSize: number;
|
|
290
|
-
clipRect?: BoundingBox;
|
|
291
292
|
}
|
|
292
293
|
declare function drawPath(options: DrawShapePathsOptions): void;
|
|
293
294
|
|
|
@@ -310,9 +311,17 @@ declare function textDecoration(): TextPlugin;
|
|
|
310
311
|
|
|
311
312
|
declare function renderText(options: TextOptions & TextRenderOptions): Text;
|
|
312
313
|
|
|
313
|
-
|
|
314
|
+
interface ValueContext {
|
|
315
|
+
total: number;
|
|
316
|
+
fontSize: number;
|
|
317
|
+
}
|
|
318
|
+
declare function parseValueNumber(value: string | number, ctx: ValueContext): number;
|
|
319
|
+
declare function parseColormap(colormap: 'none' | Record<string, string>): Record<string, string>;
|
|
320
|
+
declare function isNone(val: any): boolean;
|
|
314
321
|
declare function isEqualObject(obj1: Record<string, any>, obj2: Record<string, any>): boolean;
|
|
322
|
+
declare function isEqualValue(val1: any, val2: any): boolean;
|
|
315
323
|
declare function hexToRgb(hex: string): string | null;
|
|
316
324
|
declare function filterEmpty(val: Record<string, any> | undefined): Record<string, any> | undefined;
|
|
325
|
+
declare function closestDivisor(dividend: number, targetDivisor: number): number;
|
|
317
326
|
|
|
318
|
-
export { Character, type DrawShapePathsOptions, type FontKerning, type FontStyle, type FontWeight, Fragment, type FragmentContent, type HighlightImage, type HighlightLine, type
|
|
327
|
+
export { Character, type DrawShapePathsOptions, type FontKerning, type FontStyle, type FontWeight, Fragment, type FragmentContent, type HighlightColormap, type HighlightImage, type HighlightLine, type HighlightReferImage, type HighlightSize, type HighlightThickness, type LinearGradient, type ListStyleColormap, type ListStyleImage, type ListStylePosition, type ListStyleSize, type ListStyleType, type MeasureDomResult, type MeasureResult, type MeasuredCharacter, type MeasuredFragment, type MeasuredParagraph, Measurer, Paragraph, type ParagraphContent, type Sizeable, Text, type TextAlign, type TextContent, type TextDecorationLine, type TextDrawStyle, type TextInlineStyle, type TextLineStyle, type TextOptions, type TextOrientation, type TextPlugin, type TextRenderOptions, type TextStyle, type TextTransform, type TextWrap, type VerticalAlign, type WritingMode, closestDivisor, defaultTextStyles, definePlugin, drawPath, filterEmpty, getTransform2D, hexToRgb, highlight, isEqualObject, isEqualValue, isNone, listStyle, measureText, parseColor, parseColormap, parseValueNumber, render, renderText, setupView, textDecoration, uploadColor, uploadColors };
|