modern-text 0.5.3 → 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 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, clipRect } = options;
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] === obj2[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 === style.highlightImage && isEqualObject(prevStyle.highlightImageColors, style.highlightImageColors) && prevStyle.highlightLine === style.highlightLine && prevStyle.highlightSize === style.highlightSize && prevStyle.highlightThickness === style.highlightThickness && prevStyle.highlightOverflow === style.highlightOverflow) && group?.length && (isVertical ? group[0].inlineBox.left === inlineBox.left : group[0].inlineBox.top === inlineBox.top) && group[0].fontSize === fontSize) {
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,119 +753,119 @@ function highlight() {
720
753
  }
721
754
  prevStyle = style;
722
755
  });
723
- groups.filter((characters) => characters.length).map((characters) => {
756
+ groups.filter((characters) => characters.length).forEach((characters) => {
724
757
  const char = characters[0];
725
- return {
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
- highlightImageColors
764
+ highlightReferImage,
765
+ highlightColormap,
766
+ highlightLine,
767
+ highlightSize,
768
+ highlightThickness
741
769
  } = style;
742
770
  const isVertical = writingMode.includes("vertical");
743
- const thickness = parseThickness(highlightThickness, fontSize, groupBox.width);
744
- const charsPerRepeat = parseCharsPerRepeat(highlightSize, fontSize, groupBox.width);
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
- cBox.width = charsPerRepeat ? fontSize * charsPerRepeat : isVertical ? groupBox.height : groupBox.width;
764
- cBox.height = isVertical ? groupBox.width : groupBox.height;
765
- const width = isVertical ? cBox.height : cBox.width;
766
- let line;
767
- if (isNone(highlightLine)) {
768
- if (aBox.width / aBox.height > 4) {
769
- line = "underline";
770
- const viewBox = svgDom.getAttribute("viewBox");
771
- if (viewBox) {
772
- const [_x, y, _w, h] = viewBox.split(" ").map((v) => Number(v));
773
- const viewCenter = y + h / 2;
774
- if (aBox.y < viewCenter && aBox.y + aBox.height > viewCenter) {
775
- line = "line-through";
776
- } else if (aBox.y + aBox.height < viewCenter) {
777
- line = "overline";
778
- } else {
779
- line = "underline";
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
+ }
780
808
  }
809
+ } else {
810
+ line = "outline";
781
811
  }
782
812
  } else {
783
- line = "outline";
813
+ line = highlightLine;
784
814
  }
785
- } else {
786
- line = highlightLine;
787
- }
788
- switch (line) {
789
- case "outline": {
790
- const paddingX = cBox.width * 0.2;
791
- const paddingY = cBox.height * 0.2;
792
- cBox.width += paddingX;
793
- cBox.height += paddingY;
794
- if (isVertical) {
795
- cBox.x -= paddingY / 2;
796
- cBox.y -= paddingX / 2;
797
- cBox.x += cBox.height;
798
- } else {
799
- cBox.x -= paddingX / 2;
800
- 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;
801
830
  }
802
- break;
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;
803
855
  }
804
- case "overline":
805
- cBox.height = aBox.height * styleScale;
806
- if (isVertical) {
807
- cBox.x = char.inlineBox.left + char.inlineBox.width;
808
- } else {
809
- cBox.y = char.inlineBox.top;
810
- }
811
- break;
812
- case "line-through":
813
- cBox.height = aBox.height * styleScale;
814
- if (isVertical) {
815
- cBox.x = char.inlineBox.left + char.inlineBox.width - char.strikeoutPosition + cBox.height / 2;
816
- } else {
817
- cBox.y = char.inlineBox.top + char.strikeoutPosition - cBox.height / 2;
818
- }
819
- break;
820
- case "underline":
821
- cBox.height = aBox.height * styleScale;
822
- if (isVertical) {
823
- cBox.x = char.inlineBox.left + char.inlineBox.width - char.underlinePosition;
824
- } else {
825
- cBox.y = char.inlineBox.top + char.underlinePosition;
826
- }
827
- break;
828
856
  }
829
857
  const transform = new modernPath2d.Matrix3().translate(-aBox.x, -aBox.y).scale(cBox.width / aBox.width, cBox.height / aBox.height);
830
858
  if (isVertical) {
831
859
  transform.rotate(-Math.PI / 2);
832
860
  }
833
861
  transform.translate(cBox.x, cBox.y);
834
- for (let i = 0, len = Math.ceil(groupBox.width / width); i < len; i++) {
835
- const _transform = transform.clone().translate(i * width, 0);
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
+ }
836
869
  svgPaths.forEach((originalPath) => {
837
870
  const path = originalPath.clone().matrix(_transform);
838
871
  if (path.style.strokeWidth) {
@@ -847,30 +880,23 @@ function highlight() {
847
880
  if (path.style.strokeDasharray) {
848
881
  path.style.strokeDasharray = path.style.strokeDasharray.map((v) => v * styleScale);
849
882
  }
850
- if (path.style.fill && path.style.fill in colors) {
851
- path.style.fill = colors[path.style.fill];
883
+ if (path.style.fill && path.style.fill in colormap) {
884
+ path.style.fill = colormap[path.style.fill];
852
885
  }
853
- if (path.style.stroke && path.style.stroke in colors) {
854
- path.style.stroke = colors[path.style.stroke];
886
+ if (path.style.stroke && path.style.stroke in colormap) {
887
+ path.style.stroke = colormap[path.style.stroke];
855
888
  }
856
889
  paths.push(path);
857
- clipRects[paths.length - 1] = overflow === "hidden" ? new modernPath2d.BoundingBox(
858
- groupBox.left,
859
- groupBox.top - groupBox.height,
860
- groupBox.width,
861
- groupBox.height * 3
862
- ) : void 0;
863
890
  });
864
891
  }
865
892
  });
866
893
  },
867
894
  renderOrder: -1,
868
895
  render: (ctx, text) => {
869
- paths.forEach((path, index) => {
896
+ paths.forEach((path) => {
870
897
  drawPath({
871
898
  ctx,
872
899
  path,
873
- clipRect: clipRects[index],
874
900
  fontSize: text.computedStyle.fontSize
875
901
  });
876
902
  if (text.debug) {
@@ -884,22 +910,6 @@ function highlight() {
884
910
  });
885
911
  }
886
912
 
887
- function parseScale(size, fontSize, total) {
888
- if (size === "cover") {
889
- return 1;
890
- } else if (typeof size === "string") {
891
- if (size.endsWith("%")) {
892
- return Number(size.substring(0, size.length - 1)) / 100;
893
- } else if (size.endsWith("rem")) {
894
- const value = Number(size.substring(0, size.length - 3));
895
- return value * fontSize / total;
896
- } else {
897
- return Number(size) / total;
898
- }
899
- } else {
900
- return size / total;
901
- }
902
- }
903
913
  function listStyle() {
904
914
  const paths = [];
905
915
  return definePlugin({
@@ -911,20 +921,8 @@ function listStyle() {
911
921
  const padding = fontSize * 0.45;
912
922
  paragraphs.forEach((paragraph) => {
913
923
  const { computedStyle: style } = paragraph;
914
- const { listStyleImage, listStyleImageColors, listStyleSize, listStyleType, color } = style;
915
- const colors = Object.keys(listStyleImageColors).reduce((obj, key) => {
916
- let value = listStyleImageColors[key];
917
- const keyRgb = hexToRgb(key);
918
- const valueRgb = hexToRgb(value);
919
- if (keyRgb) {
920
- key = keyRgb;
921
- }
922
- if (valueRgb) {
923
- value = valueRgb;
924
- }
925
- obj[key] = value;
926
- return obj;
927
- }, {});
924
+ const { listStyleImage, listStyleColormap, listStyleSize, listStyleType, color } = style;
925
+ const colormap = parseColormap(listStyleColormap);
928
926
  let size = listStyleSize;
929
927
  let image;
930
928
  if (!isNone(listStyleImage)) {
@@ -948,9 +946,9 @@ function listStyle() {
948
946
  const box = paragraph.lineBox;
949
947
  const fBox = paragraph.fragments[0].inlineBox;
950
948
  if (fBox) {
949
+ const scale = size === "cover" ? 1 : parseValueNumber(size, { total: fontSize, fontSize }) / fontSize;
951
950
  const m = new modernPath2d.Matrix3();
952
951
  if (isVertical) {
953
- const scale = parseScale(size, fontSize, fontSize);
954
952
  const reScale = fontSize / imageBox.height * scale;
955
953
  m.translate(-imageBox.left, -imageBox.top);
956
954
  m.rotate(Math.PI / 2);
@@ -958,7 +956,6 @@ function listStyle() {
958
956
  m.translate(fontSize / 2 - imageBox.height * reScale / 2, 0);
959
957
  m.translate(box.left + (box.width - fontSize) / 2, fBox.top - padding);
960
958
  } else {
961
- const scale = parseScale(size, fontSize, fontSize);
962
959
  const reScale = fontSize / imageBox.height * scale;
963
960
  m.translate(-imageBox.left, -imageBox.top);
964
961
  m.translate(-imageBox.width, 0);
@@ -969,11 +966,11 @@ function listStyle() {
969
966
  paths.push(...imagePaths.map((p) => {
970
967
  const path = p.clone();
971
968
  path.matrix(m);
972
- if (path.style.fill && path.style.fill in colors) {
973
- path.style.fill = colors[path.style.fill];
969
+ if (path.style.fill && path.style.fill in colormap) {
970
+ path.style.fill = colormap[path.style.fill];
974
971
  }
975
- if (path.style.stroke && path.style.stroke in colors) {
976
- path.style.stroke = colors[path.style.stroke];
972
+ if (path.style.stroke && path.style.stroke in colormap) {
973
+ path.style.stroke = colormap[path.style.stroke];
977
974
  }
978
975
  return path;
979
976
  }));
@@ -1238,16 +1235,16 @@ const defaultTextStyles = {
1238
1235
  // listStyle
1239
1236
  listStyleType: "none",
1240
1237
  listStyleImage: "none",
1241
- listStyleImageColors: {},
1238
+ listStyleColormap: "none",
1242
1239
  listStyleSize: "cover",
1243
1240
  listStylePosition: "outside",
1244
1241
  // highlight
1245
1242
  highlightImage: "none",
1246
- highlightImageColors: {},
1243
+ highlightReferImage: "none",
1244
+ highlightColormap: "none",
1247
1245
  highlightLine: "none",
1248
1246
  highlightSize: "cover",
1249
1247
  highlightThickness: "100%",
1250
- highlightOverflow: "none",
1251
1248
  // shadow
1252
1249
  shadowColor: "rgba(0, 0, 0, 0)",
1253
1250
  shadowOffsetX: 0,
@@ -1484,6 +1481,7 @@ exports.Fragment = Fragment;
1484
1481
  exports.Measurer = Measurer;
1485
1482
  exports.Paragraph = Paragraph;
1486
1483
  exports.Text = Text;
1484
+ exports.closestDivisor = closestDivisor;
1487
1485
  exports.defaultTextStyles = defaultTextStyles;
1488
1486
  exports.definePlugin = definePlugin;
1489
1487
  exports.drawPath = drawPath;
@@ -1492,10 +1490,13 @@ exports.getTransform2D = getTransform2D;
1492
1490
  exports.hexToRgb = hexToRgb;
1493
1491
  exports.highlight = highlight;
1494
1492
  exports.isEqualObject = isEqualObject;
1493
+ exports.isEqualValue = isEqualValue;
1495
1494
  exports.isNone = isNone;
1496
1495
  exports.listStyle = listStyle;
1497
1496
  exports.measureText = measureText;
1498
1497
  exports.parseColor = parseColor;
1498
+ exports.parseColormap = parseColormap;
1499
+ exports.parseValueNumber = parseValueNumber;
1499
1500
  exports.render = render;
1500
1501
  exports.renderText = renderText;
1501
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
- listStyleImageColors: Record<string, string>;
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
- highlightImageColors: Record<string, string>;
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
- declare function isNone(val: string | undefined): boolean;
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 HighlightOverflow, type HighlightSize, type HighlightThickness, type LinearGradient, 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, defaultTextStyles, definePlugin, drawPath, filterEmpty, getTransform2D, hexToRgb, highlight, isEqualObject, isNone, listStyle, measureText, parseColor, render, renderText, setupView, textDecoration, uploadColor, uploadColors };
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
- listStyleImageColors: Record<string, string>;
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
- highlightImageColors: Record<string, string>;
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
- declare function isNone(val: string | undefined): boolean;
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 HighlightOverflow, type HighlightSize, type HighlightThickness, type LinearGradient, 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, defaultTextStyles, definePlugin, drawPath, filterEmpty, getTransform2D, hexToRgb, highlight, isEqualObject, isNone, listStyle, measureText, parseColor, render, renderText, setupView, textDecoration, uploadColor, uploadColors };
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 };