modern-text 0.7.3 → 0.7.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.mjs CHANGED
@@ -101,12 +101,6 @@ function uploadColors(ctx, text) {
101
101
  });
102
102
  }
103
103
 
104
- var __defProp$5 = Object.defineProperty;
105
- var __defNormalProp$5 = (obj, key, value) => key in obj ? __defProp$5(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
106
- var __publicField$5 = (obj, key, value) => {
107
- __defNormalProp$5(obj, typeof key !== "symbol" ? key + "" : key, value);
108
- return value;
109
- };
110
104
  const set1 = /* @__PURE__ */ new Set(["\xA9", "\xAE", "\xF7"]);
111
105
  const set2 = /* @__PURE__ */ new Set([
112
106
  "\u2014",
@@ -146,29 +140,29 @@ class Character {
146
140
  this.content = content;
147
141
  this.index = index;
148
142
  this.parent = parent;
149
- __publicField$5(this, "path", new Path2D());
150
- __publicField$5(this, "lineBox", new BoundingBox());
151
- __publicField$5(this, "inlineBox", new BoundingBox());
152
- __publicField$5(this, "glyphBox");
153
- __publicField$5(this, "advanceWidth", 0);
154
- __publicField$5(this, "advanceHeight", 0);
155
- __publicField$5(this, "underlinePosition", 0);
156
- __publicField$5(this, "underlineThickness", 0);
157
- __publicField$5(this, "strikeoutPosition", 0);
158
- __publicField$5(this, "strikeoutSize", 0);
159
- __publicField$5(this, "ascender", 0);
160
- __publicField$5(this, "descender", 0);
161
- __publicField$5(this, "typoAscender", 0);
162
- __publicField$5(this, "typoDescender", 0);
163
- __publicField$5(this, "typoLineGap", 0);
164
- __publicField$5(this, "winAscent", 0);
165
- __publicField$5(this, "winDescent", 0);
166
- __publicField$5(this, "xHeight", 0);
167
- __publicField$5(this, "capHeight", 0);
168
- __publicField$5(this, "baseline", 0);
169
- __publicField$5(this, "centerDiviation", 0);
170
- __publicField$5(this, "fontStyle");
171
143
  }
144
+ path = new Path2D();
145
+ lineBox = new BoundingBox();
146
+ inlineBox = new BoundingBox();
147
+ glyphBox;
148
+ advanceWidth = 0;
149
+ advanceHeight = 0;
150
+ underlinePosition = 0;
151
+ underlineThickness = 0;
152
+ strikeoutPosition = 0;
153
+ strikeoutSize = 0;
154
+ ascender = 0;
155
+ descender = 0;
156
+ typoAscender = 0;
157
+ typoDescender = 0;
158
+ typoLineGap = 0;
159
+ winAscent = 0;
160
+ winDescent = 0;
161
+ xHeight = 0;
162
+ capHeight = 0;
163
+ baseline = 0;
164
+ centerDiviation = 0;
165
+ fontStyle;
172
166
  get center() {
173
167
  return this.glyphBox?.center;
174
168
  }
@@ -458,20 +452,14 @@ function needsFetch(source) {
458
452
  return source.startsWith("http://") || source.startsWith("https://") || source.startsWith("blob://");
459
453
  }
460
454
 
461
- var __defProp$4 = Object.defineProperty;
462
- var __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
463
- var __publicField$4 = (obj, key, value) => {
464
- __defNormalProp$4(obj, typeof key !== "symbol" ? key + "" : key, value);
465
- return value;
466
- };
467
455
  class Fragment {
468
456
  constructor(content, style = {}, parent) {
469
457
  this.content = content;
470
458
  this.style = style;
471
459
  this.parent = parent;
472
- __publicField$4(this, "inlineBox", new BoundingBox());
473
460
  this.updateComputedStyle().initCharacters();
474
461
  }
462
+ inlineBox = new BoundingBox();
475
463
  get computedContent() {
476
464
  const style = this.computedStyle;
477
465
  return style.textTransform === "uppercase" ? this.content.toUpperCase() : style.textTransform === "lowercase" ? this.content.toLowerCase() : this.content;
@@ -494,20 +482,14 @@ class Fragment {
494
482
  }
495
483
  }
496
484
 
497
- var __defProp$3 = Object.defineProperty;
498
- var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
499
- var __publicField$3 = (obj, key, value) => {
500
- __defNormalProp$3(obj, typeof key !== "symbol" ? key + "" : key, value);
501
- return value;
502
- };
503
485
  class Paragraph {
504
486
  constructor(style, parentStyle) {
505
487
  this.style = style;
506
488
  this.parentStyle = parentStyle;
507
- __publicField$3(this, "lineBox", new BoundingBox());
508
- __publicField$3(this, "fragments", []);
509
489
  this.updateComputedStyle();
510
490
  }
491
+ lineBox = new BoundingBox();
492
+ fragments = [];
511
493
  updateComputedStyle() {
512
494
  this.computedStyle = {
513
495
  ...filterEmpty(this.parentStyle),
@@ -526,17 +508,30 @@ function definePlugin(options) {
526
508
  return options;
527
509
  }
528
510
 
529
- var __defProp$2 = Object.defineProperty;
530
- var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
531
- var __publicField$2 = (obj, key, value) => {
532
- __defNormalProp$2(obj, typeof key !== "symbol" ? key + "" : key, value);
533
- return value;
534
- };
535
- const _Measurer = class _Measurer {
511
+ class Measurer {
512
+ static pxStyles = /* @__PURE__ */ new Set([
513
+ "width",
514
+ "height",
515
+ "fontSize",
516
+ "letterSpacing",
517
+ "textStrokeWidth",
518
+ "textIndent",
519
+ "shadowOffsetX",
520
+ "shadowOffsetY",
521
+ "shadowBlur",
522
+ "marginLeft",
523
+ "marginTop",
524
+ "marginRight",
525
+ "marginBottom",
526
+ "paddingLeft",
527
+ "paddingTop",
528
+ "paddingRight",
529
+ "paddingBottom"
530
+ ]);
536
531
  _styleToDomStyle(style) {
537
532
  const _style = { ...style };
538
533
  for (const key in style) {
539
- if (_Measurer.pxStyles.has(key)) {
534
+ if (Measurer.pxStyles.has(key)) {
540
535
  _style[key] = `${style[key]}px`;
541
536
  } else {
542
537
  _style[key] = style[key];
@@ -780,38 +775,10 @@ const _Measurer = class _Measurer {
780
775
  destory?.();
781
776
  return result;
782
777
  }
783
- };
784
- __publicField$2(_Measurer, "pxStyles", /* @__PURE__ */ new Set([
785
- "width",
786
- "height",
787
- "fontSize",
788
- "letterSpacing",
789
- "textStrokeWidth",
790
- "textIndent",
791
- "shadowOffsetX",
792
- "shadowOffsetY",
793
- "shadowBlur",
794
- "marginLeft",
795
- "marginTop",
796
- "marginRight",
797
- "marginBottom",
798
- "paddingLeft",
799
- "paddingTop",
800
- "paddingRight",
801
- "paddingBottom"
802
- ]));
803
- let Measurer = _Measurer;
778
+ }
804
779
 
805
- var __defProp$1 = Object.defineProperty;
806
- var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
807
- var __publicField$1 = (obj, key, value) => {
808
- __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
809
- return value;
810
- };
811
780
  class EventEmitter {
812
- constructor() {
813
- __publicField$1(this, "eventListeners", /* @__PURE__ */ new Map());
814
- }
781
+ eventListeners = /* @__PURE__ */ new Map();
815
782
  addEventListener(event, listener, options) {
816
783
  const object = { value: listener, options };
817
784
  const listeners = this.eventListeners.get(event);
@@ -896,6 +863,25 @@ class EventEmitter {
896
863
  }
897
864
  }
898
865
 
866
+ function getHighlightStyle(style) {
867
+ const {
868
+ highlight: highlight2,
869
+ highlightImage,
870
+ highlightReferImage,
871
+ highlightColormap,
872
+ highlightLine,
873
+ highlightSize,
874
+ highlightThickness
875
+ } = style;
876
+ return {
877
+ image: highlight2?.image ?? highlightImage ?? "none",
878
+ referImage: highlight2?.referImage ?? highlightReferImage ?? "none",
879
+ colormap: highlight2?.colormap ?? highlightColormap ?? "none",
880
+ line: highlight2?.line ?? highlightLine ?? "none",
881
+ size: highlight2?.size ?? highlightSize ?? "cover",
882
+ thickness: highlight2?.thickness ?? highlightThickness ?? "100%"
883
+ };
884
+ }
899
885
  function highlight() {
900
886
  const paths = [];
901
887
  const clipRects = [];
@@ -928,45 +914,46 @@ function highlight() {
928
914
  name: "highlight",
929
915
  paths,
930
916
  load: async (text) => {
931
- const promises = [];
917
+ const set = /* @__PURE__ */ new Set();
932
918
  text.forEachCharacter((character) => {
933
919
  const { computedStyle: style } = character;
934
- const { highlightImage, highlightReferImage } = style;
935
- if (needsFetch(highlightImage)) {
936
- promises.push(loadSvg(highlightImage));
920
+ const { image, referImage } = getHighlightStyle(style);
921
+ if (needsFetch(image)) {
922
+ set.add(image);
937
923
  }
938
- if (needsFetch(highlightReferImage)) {
939
- promises.push(loadSvg(highlightReferImage));
924
+ if (needsFetch(referImage)) {
925
+ set.add(referImage);
940
926
  }
941
927
  });
942
- await Promise.all(promises);
928
+ await Promise.all(Array.from(set).map((src) => loadSvg(src)));
943
929
  },
944
930
  update: (text) => {
945
931
  clipRects.length = 0;
946
932
  paths.length = 0;
947
933
  let groups = [];
948
934
  let group;
949
- let prevStyle;
935
+ let prevHighlight;
950
936
  text.forEachCharacter((character) => {
951
937
  const {
952
938
  computedStyle: style
953
939
  } = character;
940
+ const highlight2 = getHighlightStyle(style);
954
941
  const {
955
- highlightImage
956
- } = style;
957
- if (!isNone(highlightImage)) {
942
+ image,
943
+ colormap,
944
+ line,
945
+ size,
946
+ thickness
947
+ } = highlight2;
948
+ if (!isNone(image)) {
958
949
  const {
959
950
  inlineBox,
960
951
  isVertical
961
952
  } = character;
962
953
  const {
963
- fontSize,
964
- highlightColormap,
965
- highlightLine,
966
- highlightSize,
967
- highlightThickness
954
+ fontSize
968
955
  } = style;
969
- if ((!prevStyle || isEqualValue(prevStyle.highlightImage, highlightImage) && isEqualValue(prevStyle.highlightColormap, highlightColormap) && isEqualValue(prevStyle.highlightLine, highlightLine) && isEqualValue(prevStyle.highlightSize, highlightSize) && isEqualValue(prevStyle.highlightThickness, highlightThickness)) && group?.length && (isVertical ? group[0].inlineBox.left === inlineBox.left : group[0].inlineBox.top === inlineBox.top) && group[0].fontSize === fontSize) {
956
+ if ((!prevHighlight || isEqualValue(prevHighlight.image, image) && isEqualValue(prevHighlight.colormap, colormap) && isEqualValue(prevHighlight.line, line) && isEqualValue(prevHighlight.size, size) && isEqualValue(prevHighlight.thickness, thickness)) && group?.length && (isVertical ? group[0].inlineBox.left === inlineBox.left : group[0].inlineBox.top === inlineBox.top) && group[0].fontSize === fontSize) {
970
957
  group.push(character);
971
958
  } else {
972
959
  group = [];
@@ -979,7 +966,7 @@ function highlight() {
979
966
  groups.push(group);
980
967
  }
981
968
  }
982
- prevStyle = style;
969
+ prevHighlight = highlight2;
983
970
  });
984
971
  groups = groups.filter((characters) => characters.length);
985
972
  for (let i = 0; i < groups.length; i++) {
@@ -993,18 +980,20 @@ function highlight() {
993
980
  } = char;
994
981
  const {
995
982
  fontSize,
996
- writingMode,
997
- highlightImage,
998
- highlightReferImage,
999
- highlightColormap,
1000
- highlightLine,
1001
- highlightSize,
1002
- highlightThickness
983
+ writingMode
1003
984
  } = style;
985
+ const {
986
+ image,
987
+ referImage,
988
+ colormap,
989
+ line,
990
+ size,
991
+ thickness
992
+ } = getHighlightStyle(style);
1004
993
  const isVertical = writingMode.includes("vertical");
1005
- const thickness = parseValueNumber(highlightThickness, { fontSize, total: groupBox.width }) / groupBox.width;
1006
- const colormap = parseColormap(highlightColormap);
1007
- const { paths: svgPaths, dom: svgDom } = getPaths(highlightImage);
994
+ const _thickness = parseValueNumber(thickness, { fontSize, total: groupBox.width }) / groupBox.width;
995
+ const _colormap = parseColormap(colormap);
996
+ const { paths: svgPaths, dom: svgDom } = getPaths(image);
1008
997
  const aBox = getPathsBoundingBox(svgPaths, true);
1009
998
  const styleScale = fontSize / aBox.width * 2;
1010
999
  const cBox = new BoundingBox().copy(groupBox);
@@ -1015,37 +1004,37 @@ function highlight() {
1015
1004
  }
1016
1005
  const rawWidth = Math.floor(cBox.width);
1017
1006
  let userWidth = rawWidth;
1018
- if (highlightSize !== "cover") {
1019
- userWidth = parseValueNumber(highlightSize, { fontSize, total: groupBox.width });
1007
+ if (size !== "cover") {
1008
+ userWidth = parseValueNumber(size, { fontSize, total: groupBox.width }) || rawWidth;
1020
1009
  cBox.width = userWidth;
1021
1010
  }
1022
- if (!isNone(highlightReferImage) && isNone(highlightLine)) {
1023
- const bBox = getPathsBoundingBox(getPaths(highlightReferImage).paths, true);
1011
+ if (!isNone(referImage) && isNone(line)) {
1012
+ const bBox = getPathsBoundingBox(getPaths(referImage).paths, true);
1024
1013
  aBox.copy(bBox);
1025
1014
  } else {
1026
- let line;
1027
- if (isNone(highlightLine)) {
1015
+ let _line;
1016
+ if (isNone(line)) {
1028
1017
  if (aBox.width / aBox.height > 4) {
1029
- line = "underline";
1018
+ _line = "underline";
1030
1019
  const viewBox = svgDom.getAttribute("viewBox");
1031
1020
  if (viewBox) {
1032
1021
  const [_x, y, _w, h] = viewBox.split(" ").map((v) => Number(v));
1033
1022
  const viewCenter = y + h / 2;
1034
1023
  if (aBox.y < viewCenter && aBox.y + aBox.height > viewCenter) {
1035
- line = "line-through";
1024
+ _line = "line-through";
1036
1025
  } else if (aBox.y + aBox.height < viewCenter) {
1037
- line = "overline";
1026
+ _line = "overline";
1038
1027
  } else {
1039
- line = "underline";
1028
+ _line = "underline";
1040
1029
  }
1041
1030
  }
1042
1031
  } else {
1043
- line = "outline";
1032
+ _line = "outline";
1044
1033
  }
1045
1034
  } else {
1046
- line = highlightLine;
1035
+ _line = line;
1047
1036
  }
1048
- switch (line) {
1037
+ switch (_line) {
1049
1038
  case "outline": {
1050
1039
  const paddingX = cBox.width * 0.2;
1051
1040
  const paddingY = cBox.height * 0.2;
@@ -1102,7 +1091,7 @@ function highlight() {
1102
1091
  svgPaths.forEach((originalPath) => {
1103
1092
  const path = originalPath.clone().matrix(_transform);
1104
1093
  if (path.style.strokeWidth) {
1105
- path.style.strokeWidth *= styleScale * thickness;
1094
+ path.style.strokeWidth *= styleScale * _thickness;
1106
1095
  }
1107
1096
  if (path.style.strokeMiterlimit) {
1108
1097
  path.style.strokeMiterlimit *= styleScale;
@@ -1113,11 +1102,11 @@ function highlight() {
1113
1102
  if (path.style.strokeDasharray) {
1114
1103
  path.style.strokeDasharray = path.style.strokeDasharray.map((v) => v * styleScale);
1115
1104
  }
1116
- if (path.style.fill && path.style.fill in colormap) {
1117
- path.style.fill = colormap[path.style.fill];
1105
+ if (path.style.fill && path.style.fill in _colormap) {
1106
+ path.style.fill = _colormap[path.style.fill];
1118
1107
  }
1119
- if (path.style.stroke && path.style.stroke in colormap) {
1120
- path.style.stroke = colormap[path.style.stroke];
1108
+ if (path.style.stroke && path.style.stroke in _colormap) {
1109
+ path.style.stroke = _colormap[path.style.stroke];
1121
1110
  }
1122
1111
  paths.push(path);
1123
1112
  if (rawWidth !== userWidth) {
@@ -1490,12 +1479,6 @@ function textDecoration() {
1490
1479
  });
1491
1480
  }
1492
1481
 
1493
- var __defProp = Object.defineProperty;
1494
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1495
- var __publicField = (obj, key, value) => {
1496
- __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
1497
- return value;
1498
- };
1499
1482
  const defaultTextStyles = {
1500
1483
  writingMode: "horizontal-tb",
1501
1484
  verticalAlign: "baseline",
@@ -1526,13 +1509,6 @@ const defaultTextStyles = {
1526
1509
  listStyleColormap: "none",
1527
1510
  listStyleSize: "cover",
1528
1511
  listStylePosition: "outside",
1529
- // highlight
1530
- highlightImage: "none",
1531
- highlightReferImage: "none",
1532
- highlightColormap: "none",
1533
- highlightLine: "none",
1534
- highlightSize: "cover",
1535
- highlightThickness: "100%",
1536
1512
  // shadow
1537
1513
  shadowColor: "rgba(0, 0, 0, 0)",
1538
1514
  shadowOffsetX: 0,
@@ -1544,24 +1520,33 @@ const defaultTextStyles = {
1544
1520
  skewY: 0
1545
1521
  };
1546
1522
  class Text extends EventEmitter {
1523
+ debug;
1524
+ content;
1525
+ style;
1526
+ effects;
1527
+ measureDom;
1528
+ needsUpdate = true;
1529
+ computedStyle = { ...defaultTextStyles };
1530
+ paragraphs = [];
1531
+ lineBox = new BoundingBox();
1532
+ rawGlyphBox = new BoundingBox();
1533
+ glyphBox = new BoundingBox();
1534
+ pathBox = new BoundingBox();
1535
+ boundingBox = new BoundingBox();
1536
+ measurer = new Measurer();
1537
+ plugins = /* @__PURE__ */ new Map();
1538
+ fonts;
1539
+ get fontSize() {
1540
+ return this.computedStyle.fontSize;
1541
+ }
1542
+ get isVertical() {
1543
+ return this.computedStyle.writingMode.includes("vertical");
1544
+ }
1545
+ get characters() {
1546
+ return this.paragraphs.flatMap((p) => p.fragments.flatMap((f) => f.characters));
1547
+ }
1547
1548
  constructor(options = {}) {
1548
1549
  super();
1549
- __publicField(this, "debug");
1550
- __publicField(this, "content");
1551
- __publicField(this, "style");
1552
- __publicField(this, "effects");
1553
- __publicField(this, "measureDom");
1554
- __publicField(this, "needsUpdate", true);
1555
- __publicField(this, "computedStyle", { ...defaultTextStyles });
1556
- __publicField(this, "paragraphs", []);
1557
- __publicField(this, "lineBox", new BoundingBox());
1558
- __publicField(this, "rawGlyphBox", new BoundingBox());
1559
- __publicField(this, "glyphBox", new BoundingBox());
1560
- __publicField(this, "pathBox", new BoundingBox());
1561
- __publicField(this, "boundingBox", new BoundingBox());
1562
- __publicField(this, "measurer", new Measurer());
1563
- __publicField(this, "plugins", /* @__PURE__ */ new Map());
1564
- __publicField(this, "fonts");
1565
1550
  this.debug = options.debug ?? false;
1566
1551
  this.content = options.content ?? "";
1567
1552
  this.style = options.style ?? {};
@@ -1569,15 +1554,7 @@ class Text extends EventEmitter {
1569
1554
  this.effects = options.effects;
1570
1555
  this.fonts = options.fonts;
1571
1556
  this.use(listStyle()).use(textDecoration()).use(highlight()).use(render());
1572
- }
1573
- get fontSize() {
1574
- return this.computedStyle.fontSize;
1575
- }
1576
- get isVertical() {
1577
- return this.computedStyle.writingMode.includes("vertical");
1578
- }
1579
- get characters() {
1580
- return this.paragraphs.flatMap((p) => p.fragments.flatMap((f) => f.characters));
1557
+ this.updateParagraphs();
1581
1558
  }
1582
1559
  use(plugin) {
1583
1560
  this.plugins.set(plugin.name, plugin);
@@ -1728,6 +1705,7 @@ class Text extends EventEmitter {
1728
1705
  this[key] = result[key];
1729
1706
  }
1730
1707
  this.emit("update", { text: this });
1708
+ this.needsUpdate = false;
1731
1709
  return this;
1732
1710
  }
1733
1711
  render(options) {
@@ -1760,11 +1738,23 @@ class Text extends EventEmitter {
1760
1738
  }
1761
1739
 
1762
1740
  function measureText(options) {
1763
- return new Text(options).measure();
1741
+ const text = new Text(options);
1742
+ if (options.load) {
1743
+ return text.load().then(() => {
1744
+ return text.measure();
1745
+ });
1746
+ }
1747
+ return text.measure();
1764
1748
  }
1765
1749
 
1766
1750
  function renderText(options) {
1767
- new Text(options).render(options);
1751
+ const text = new Text(options);
1752
+ if (options.load) {
1753
+ return text.load().then(() => {
1754
+ return text.render(options);
1755
+ });
1756
+ }
1757
+ return text.render(options);
1768
1758
  }
1769
1759
 
1770
- export { Character, Fragment, Measurer, Paragraph, Text, defaultTextStyles, definePlugin, drawPath, filterEmpty, getTransform2D, hexToRgb, highlight, isEqualObject, isEqualValue, isNone, listStyle, measureText, needsFetch, parseColor, parseColormap, parseValueNumber, render, renderText, setupView, textDecoration, uploadColor, uploadColors };
1760
+ export { Character, Fragment, Measurer, Paragraph, Text, defaultTextStyles, definePlugin, drawPath, filterEmpty, getHighlightStyle, getTransform2D, hexToRgb, highlight, isEqualObject, isEqualValue, isNone, listStyle, measureText, needsFetch, parseColor, parseColormap, parseValueNumber, render, renderText, setupView, textDecoration, uploadColor, uploadColors };
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "modern-text",
3
3
  "type": "module",
4
- "version": "0.7.3",
5
- "packageManager": "pnpm@9.9.0",
4
+ "version": "0.7.4",
5
+ "packageManager": "pnpm@9.15.1",
6
6
  "description": "Measure and render text in a way that describes the DOM.",
7
7
  "author": "wxm",
8
8
  "license": "MIT",
@@ -58,20 +58,20 @@
58
58
  },
59
59
  "dependencies": {
60
60
  "modern-font": "^0.3.4",
61
- "modern-path2d": "^0.2.6"
61
+ "modern-path2d": "^0.2.9"
62
62
  },
63
63
  "devDependencies": {
64
- "@antfu/eslint-config": "^3.7.3",
65
- "@types/node": "^22.7.4",
66
- "bumpp": "^9.6.1",
64
+ "@antfu/eslint-config": "^3.12.0",
65
+ "@types/node": "^22.10.2",
66
+ "bumpp": "^9.9.2",
67
67
  "conventional-changelog-cli": "^5.0.0",
68
- "eslint": "^9.12.0",
69
- "lint-staged": "^15.2.10",
68
+ "eslint": "^9.17.0",
69
+ "lint-staged": "^15.2.11",
70
70
  "simple-git-hooks": "^2.11.1",
71
- "typescript": "^5.6.2",
72
- "unbuild": "^2.0.0",
73
- "vite": "^5.4.8",
74
- "vitest": "^2.1.2"
71
+ "typescript": "^5.7.2",
72
+ "unbuild": "^3.0.1",
73
+ "vite": "^6.0.5",
74
+ "vitest": "^2.1.8"
75
75
  },
76
76
  "simple-git-hooks": {
77
77
  "pre-commit": "pnpm lint-staged"