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 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,120 +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 aCenter = aBox.y + aBox.height / 2;
773
- const [_x, y, _w, h] = viewBox.split(" ").map((v) => Number(v));
774
- const viewCenter = y + h / 2;
775
- if (aBox.y < viewCenter && aBox.y + aBox.height > viewCenter) {
776
- line = "line-through";
777
- } else if (viewCenter > aCenter) {
778
- line = "overline";
779
- } else {
780
- 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
+ }
781
808
  }
809
+ } else {
810
+ line = "outline";
782
811
  }
783
812
  } else {
784
- line = "outline";
813
+ line = highlightLine;
785
814
  }
786
- } else {
787
- line = highlightLine;
788
- }
789
- switch (line) {
790
- case "outline": {
791
- const paddingX = cBox.width * 0.2;
792
- const paddingY = cBox.height * 0.2;
793
- cBox.width += paddingX;
794
- cBox.height += paddingY;
795
- if (isVertical) {
796
- cBox.x -= paddingY / 2;
797
- cBox.y -= paddingX / 2;
798
- cBox.x += cBox.height;
799
- } else {
800
- cBox.x -= paddingX / 2;
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
- 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;
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 = Math.ceil(groupBox.width / width); i < len; i++) {
836
- 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
+ }
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 colors) {
852
- 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];
853
885
  }
854
- if (path.style.stroke && path.style.stroke in colors) {
855
- 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];
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, index) => {
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, listStyleImageColors, listStyleSize, listStyleType, color } = style;
916
- const colors = Object.keys(listStyleImageColors).reduce((obj, key) => {
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 colors) {
974
- 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];
975
971
  }
976
- if (path.style.stroke && path.style.stroke in colors) {
977
- 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];
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
- listStyleImageColors: {},
1238
+ listStyleColormap: "none",
1243
1239
  listStyleSize: "cover",
1244
1240
  listStylePosition: "outside",
1245
1241
  // highlight
1246
1242
  highlightImage: "none",
1247
- highlightImageColors: {},
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
- 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 };