darkreader 4.9.118 → 4.9.119

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/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2025 Dark Reader Ltd.
3
+ Copyright (c) 2026 Dark Reader Ltd.
4
4
 
5
5
  All rights reserved.
6
6
 
package/darkreader.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Dark Reader v4.9.118
2
+ * Dark Reader v4.9.119
3
3
  * https://darkreader.org/
4
4
  */
5
5
 
@@ -2759,14 +2759,59 @@
2759
2759
  async function getImageDetails(url) {
2760
2760
  return new Promise(async (resolve, reject) => {
2761
2761
  try {
2762
- const dataURL = url.startsWith("data:")
2762
+ let dataURL = url.startsWith("data:")
2763
2763
  ? url
2764
2764
  : await getDataURL(url);
2765
2765
  const blob =
2766
2766
  tryConvertDataURLToBlobSync(dataURL) ??
2767
2767
  (await loadAsBlob(url));
2768
2768
  let image;
2769
+ let useViewBox = false;
2769
2770
  if (dataURL.startsWith("data:image/svg+xml")) {
2771
+ const commaIndex = dataURL.indexOf(",");
2772
+ if (commaIndex >= 0) {
2773
+ let svgText = dataURL.slice(commaIndex + 1);
2774
+ const encoding = dataURL
2775
+ .slice(0, commaIndex)
2776
+ .split(";")[1];
2777
+ if (encoding === "base64") {
2778
+ svgText = atob(svgText);
2779
+ }
2780
+ if (svgText.startsWith("<svg ")) {
2781
+ const closingIndex = svgText.indexOf(">");
2782
+ const svgOpening = svgText
2783
+ .slice(0, closingIndex + 1)
2784
+ .toLocaleLowerCase();
2785
+ if (
2786
+ svgOpening.includes("viewbox") &&
2787
+ !svgOpening.includes("width") &&
2788
+ !svgOpening.includes("height")
2789
+ ) {
2790
+ useViewBox = true;
2791
+ const viewboxIndex =
2792
+ svgOpening.indexOf('viewbox="');
2793
+ const viewboxCloseIndex = svgOpening.indexOf(
2794
+ 'viewbox="',
2795
+ viewboxIndex + 9
2796
+ );
2797
+ const viewBox = svgOpening
2798
+ .slice(
2799
+ viewboxIndex + 9,
2800
+ viewboxCloseIndex - 1
2801
+ )
2802
+ .split(" ")
2803
+ .map((x) => parseFloat(x));
2804
+ if (
2805
+ viewBox.length === 4 &&
2806
+ !viewBox.some((x) => isNaN(x))
2807
+ ) {
2808
+ const width = viewBox[2] - viewBox[0];
2809
+ const height = viewBox[3] - viewBox[1];
2810
+ dataURL = `data:image/svg+xml;base64,${btoa(`<svg width="${width}" height="${height}" ${svgText.slice(5)}`)}`;
2811
+ }
2812
+ }
2813
+ }
2814
+ }
2770
2815
  image = await loadImage(dataURL);
2771
2816
  } else {
2772
2817
  image =
@@ -2780,6 +2825,7 @@
2780
2825
  dataURL: analysis.isLarge ? "" : dataURL,
2781
2826
  width: image.width,
2782
2827
  height: image.height,
2828
+ useViewBox,
2783
2829
  ...analysis
2784
2830
  });
2785
2831
  });
@@ -2967,13 +3013,16 @@
2967
3013
  }
2968
3014
  document.addEventListener("securitypolicyviolation", onCSPError);
2969
3015
  const objectURLs = new Set();
2970
- function getFilteredImageURL({dataURL, width, height}, theme) {
3016
+ function getFilteredImageURL({dataURL, width, height, useViewBox}, theme) {
2971
3017
  if (dataURL.startsWith("data:image/svg+xml")) {
2972
3018
  dataURL = escapeXML(dataURL);
2973
3019
  }
2974
3020
  const matrix = getSVGFilterMatrixValue(theme);
3021
+ const size = useViewBox
3022
+ ? `viewBox="0 0 ${width} ${height}"`
3023
+ : `width="${width}" height="${height}"`;
2975
3024
  const svg = [
2976
- `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="${width}" height="${height}">`,
3025
+ `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" ${size}>`,
2977
3026
  "<defs>",
2978
3027
  '<filter id="darkreader-image-filter">',
2979
3028
  `<feColorMatrix type="matrix" values="${matrix}" />`,
@@ -4235,8 +4284,8 @@
4235
4284
  this.definedVars.add(varName);
4236
4285
  const isColor = Boolean(
4237
4286
  value.match(rawRGBSpaceRegex) ||
4238
- value.match(rawRGBCommaRegex) ||
4239
- parseColorWithCache(value)
4287
+ value.match(rawRGBCommaRegex) ||
4288
+ parseColorWithCache(value)
4240
4289
  );
4241
4290
  if (isColor) {
4242
4291
  this.unknownColorVars.add(varName);
@@ -5629,8 +5678,8 @@
5629
5678
  }
5630
5679
  const shouldAnalyze = Boolean(
5631
5680
  svg &&
5632
- (svg.getAttribute("class")?.includes("logo") ||
5633
- svg.parentElement?.getAttribute("class")?.includes("logo"))
5681
+ (svg.getAttribute("class")?.includes("logo") ||
5682
+ svg.parentElement?.getAttribute("class")?.includes("logo"))
5634
5683
  );
5635
5684
  svgAnalysisConditionCache.set(svg, shouldAnalyze);
5636
5685
  return shouldAnalyze;
@@ -5673,6 +5722,7 @@
5673
5722
  svgNodesRoots.set(svgElement, root);
5674
5723
  return root;
5675
5724
  }
5725
+ const inlineStringValueCache = new Map();
5676
5726
  function overrideInlineStyle(
5677
5727
  element,
5678
5728
  theme,
@@ -5700,6 +5750,13 @@
5700
5750
  }
5701
5751
  const unsetProps = new Set(Object.keys(overrides));
5702
5752
  function setCustomProp(targetCSSProp, modifierCSSProp, cssVal) {
5753
+ const cachedStringValue = inlineStringValueCache
5754
+ .get(modifierCSSProp)
5755
+ ?.get(cssVal);
5756
+ if (cachedStringValue) {
5757
+ setStaticValue(cachedStringValue);
5758
+ return;
5759
+ }
5703
5760
  const mod = getModifiableCSSDeclaration(
5704
5761
  modifierCSSProp,
5705
5762
  cssVal,
@@ -5766,6 +5823,10 @@
5766
5823
  typeof mod.value === "function" ? mod.value(theme) : mod.value;
5767
5824
  if (typeof value === "string") {
5768
5825
  setStaticValue(value);
5826
+ if (!inlineStringValueCache.has(modifierCSSProp)) {
5827
+ inlineStringValueCache.set(modifierCSSProp, new Map());
5828
+ }
5829
+ inlineStringValueCache.get(modifierCSSProp).set(cssVal, value);
5769
5830
  } else if (value instanceof Promise) {
5770
5831
  setAsyncValue(value, cssVal);
5771
5832
  } else if (typeof value === "object") {
@@ -5852,13 +5913,16 @@
5852
5913
  value.match(/^[0-9a-f]{6}$/i)
5853
5914
  ) {
5854
5915
  value = `#${value}`;
5916
+ } else if (value.match(/^#?[0-9a-f]{4}$/i)) {
5917
+ const hex = value.startsWith("#") ? value.substring(1) : value;
5918
+ value = `#${hex}00`;
5855
5919
  }
5856
5920
  setCustomProp("color", "color", value);
5857
5921
  }
5858
5922
  if (isSVGElement) {
5859
5923
  if (element.hasAttribute("fill")) {
5860
5924
  const value = element.getAttribute("fill");
5861
- if (value !== "none") {
5925
+ if (value !== "none" && value !== "currentColor") {
5862
5926
  if (!(element instanceof SVGTextElement)) {
5863
5927
  const handleSVGElement = () => {
5864
5928
  let isSVGSmall = false;
@@ -6190,7 +6254,7 @@
6190
6254
  forEach(node.querySelectorAll(STYLE_SELECTOR), (style) =>
6191
6255
  getManageableStyles(style, results, false)
6192
6256
  );
6193
- if (deep) {
6257
+ if (deep && (node.children?.length > 0 || node.shadowRoot)) {
6194
6258
  iterateShadowHosts(node, (host) =>
6195
6259
  getManageableStyles(host.shadowRoot, results, false)
6196
6260
  );
@@ -7358,10 +7422,23 @@
7358
7422
  removedStyles,
7359
7423
  movedStyles
7360
7424
  });
7425
+ const potentialHosts = new Set();
7361
7426
  additions.forEach((n) => {
7427
+ if (n.parentElement) {
7428
+ potentialHosts.add(n.parentElement);
7429
+ }
7430
+ if (n.previousElementSibling) {
7431
+ potentialHosts.add(n.previousElementSibling);
7432
+ }
7362
7433
  deepObserve(n);
7363
7434
  collectUndefinedElements(n);
7364
7435
  });
7436
+ potentialHosts.forEach((el) => {
7437
+ if (el.shadowRoot && !observedRoots.has(el)) {
7438
+ subscribeForShadowRootChanges(el);
7439
+ deepObserve(el.shadowRoot);
7440
+ }
7441
+ });
7365
7442
  additions.forEach(
7366
7443
  (node) => isCustomElement(node) && recordUndefinedElement(node)
7367
7444
  );
@@ -7475,6 +7552,14 @@
7475
7552
  });
7476
7553
  document.addEventListener("__darkreader__isDefined", handleIsDefined);
7477
7554
  collectUndefinedElements(document);
7555
+ addDOMReadyListener(() => {
7556
+ forEach(document.body.children, (el) => {
7557
+ if (el.shadowRoot && !observedRoots.has(el)) {
7558
+ subscribeForShadowRootChanges(el);
7559
+ deepObserve(el.shadowRoot);
7560
+ }
7561
+ });
7562
+ });
7478
7563
  }
7479
7564
  function resetObservers() {
7480
7565
  observers.forEach((o) => o.disconnect());
package/darkreader.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Dark Reader v4.9.118
2
+ * Dark Reader v4.9.119
3
3
  * https://darkreader.org/
4
4
  */
5
5
 
@@ -2671,13 +2671,51 @@ const imageManager = new AsyncQueue();
2671
2671
  async function getImageDetails(url) {
2672
2672
  return new Promise(async (resolve, reject) => {
2673
2673
  try {
2674
- const dataURL = url.startsWith("data:")
2675
- ? url
2676
- : await getDataURL(url);
2674
+ let dataURL = url.startsWith("data:") ? url : await getDataURL(url);
2677
2675
  const blob =
2678
2676
  tryConvertDataURLToBlobSync(dataURL) ?? (await loadAsBlob(url));
2679
2677
  let image;
2678
+ let useViewBox = false;
2680
2679
  if (dataURL.startsWith("data:image/svg+xml")) {
2680
+ const commaIndex = dataURL.indexOf(",");
2681
+ if (commaIndex >= 0) {
2682
+ let svgText = dataURL.slice(commaIndex + 1);
2683
+ const encoding = dataURL.slice(0, commaIndex).split(";")[1];
2684
+ if (encoding === "base64") {
2685
+ svgText = atob(svgText);
2686
+ }
2687
+ if (svgText.startsWith("<svg ")) {
2688
+ const closingIndex = svgText.indexOf(">");
2689
+ const svgOpening = svgText
2690
+ .slice(0, closingIndex + 1)
2691
+ .toLocaleLowerCase();
2692
+ if (
2693
+ svgOpening.includes("viewbox") &&
2694
+ !svgOpening.includes("width") &&
2695
+ !svgOpening.includes("height")
2696
+ ) {
2697
+ useViewBox = true;
2698
+ const viewboxIndex =
2699
+ svgOpening.indexOf('viewbox="');
2700
+ const viewboxCloseIndex = svgOpening.indexOf(
2701
+ 'viewbox="',
2702
+ viewboxIndex + 9
2703
+ );
2704
+ const viewBox = svgOpening
2705
+ .slice(viewboxIndex + 9, viewboxCloseIndex - 1)
2706
+ .split(" ")
2707
+ .map((x) => parseFloat(x));
2708
+ if (
2709
+ viewBox.length === 4 &&
2710
+ !viewBox.some((x) => isNaN(x))
2711
+ ) {
2712
+ const width = viewBox[2] - viewBox[0];
2713
+ const height = viewBox[3] - viewBox[1];
2714
+ dataURL = `data:image/svg+xml;base64,${btoa(`<svg width="${width}" height="${height}" ${svgText.slice(5)}`)}`;
2715
+ }
2716
+ }
2717
+ }
2718
+ }
2681
2719
  image = await loadImage(dataURL);
2682
2720
  } else {
2683
2721
  image =
@@ -2691,6 +2729,7 @@ async function getImageDetails(url) {
2691
2729
  dataURL: analysis.isLarge ? "" : dataURL,
2692
2730
  width: image.width,
2693
2731
  height: image.height,
2732
+ useViewBox,
2694
2733
  ...analysis
2695
2734
  });
2696
2735
  });
@@ -2877,13 +2916,16 @@ function onCSPError(err) {
2877
2916
  }
2878
2917
  document.addEventListener("securitypolicyviolation", onCSPError);
2879
2918
  const objectURLs = new Set();
2880
- function getFilteredImageURL({dataURL, width, height}, theme) {
2919
+ function getFilteredImageURL({dataURL, width, height, useViewBox}, theme) {
2881
2920
  if (dataURL.startsWith("data:image/svg+xml")) {
2882
2921
  dataURL = escapeXML(dataURL);
2883
2922
  }
2884
2923
  const matrix = getSVGFilterMatrixValue(theme);
2924
+ const size = useViewBox
2925
+ ? `viewBox="0 0 ${width} ${height}"`
2926
+ : `width="${width}" height="${height}"`;
2885
2927
  const svg = [
2886
- `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="${width}" height="${height}">`,
2928
+ `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" ${size}>`,
2887
2929
  "<defs>",
2888
2930
  '<filter id="darkreader-image-filter">',
2889
2931
  `<feColorMatrix type="matrix" values="${matrix}" />`,
@@ -4094,8 +4136,8 @@ class VariablesStore {
4094
4136
  this.definedVars.add(varName);
4095
4137
  const isColor = Boolean(
4096
4138
  value.match(rawRGBSpaceRegex) ||
4097
- value.match(rawRGBCommaRegex) ||
4098
- parseColorWithCache(value)
4139
+ value.match(rawRGBCommaRegex) ||
4140
+ parseColorWithCache(value)
4099
4141
  );
4100
4142
  if (isColor) {
4101
4143
  this.unknownColorVars.add(varName);
@@ -5466,8 +5508,8 @@ function shouldAnalyzeSVGAsImage(svg) {
5466
5508
  }
5467
5509
  const shouldAnalyze = Boolean(
5468
5510
  svg &&
5469
- (svg.getAttribute("class")?.includes("logo") ||
5470
- svg.parentElement?.getAttribute("class")?.includes("logo"))
5511
+ (svg.getAttribute("class")?.includes("logo") ||
5512
+ svg.parentElement?.getAttribute("class")?.includes("logo"))
5471
5513
  );
5472
5514
  svgAnalysisConditionCache.set(svg, shouldAnalyze);
5473
5515
  return shouldAnalyze;
@@ -5510,6 +5552,7 @@ function getSVGElementRoot(svgElement) {
5510
5552
  svgNodesRoots.set(svgElement, root);
5511
5553
  return root;
5512
5554
  }
5555
+ const inlineStringValueCache = new Map();
5513
5556
  function overrideInlineStyle(
5514
5557
  element,
5515
5558
  theme,
@@ -5537,6 +5580,13 @@ function overrideInlineStyle(
5537
5580
  }
5538
5581
  const unsetProps = new Set(Object.keys(overrides));
5539
5582
  function setCustomProp(targetCSSProp, modifierCSSProp, cssVal) {
5583
+ const cachedStringValue = inlineStringValueCache
5584
+ .get(modifierCSSProp)
5585
+ ?.get(cssVal);
5586
+ if (cachedStringValue) {
5587
+ setStaticValue(cachedStringValue);
5588
+ return;
5589
+ }
5540
5590
  const mod = getModifiableCSSDeclaration(
5541
5591
  modifierCSSProp,
5542
5592
  cssVal,
@@ -5602,6 +5652,10 @@ function overrideInlineStyle(
5602
5652
  typeof mod.value === "function" ? mod.value(theme) : mod.value;
5603
5653
  if (typeof value === "string") {
5604
5654
  setStaticValue(value);
5655
+ if (!inlineStringValueCache.has(modifierCSSProp)) {
5656
+ inlineStringValueCache.set(modifierCSSProp, new Map());
5657
+ }
5658
+ inlineStringValueCache.get(modifierCSSProp).set(cssVal, value);
5605
5659
  } else if (value instanceof Promise) {
5606
5660
  setAsyncValue(value, cssVal);
5607
5661
  } else if (typeof value === "object") {
@@ -5676,13 +5730,16 @@ function overrideInlineStyle(
5676
5730
  let value = element.getAttribute("color");
5677
5731
  if (value.match(/^[0-9a-f]{3}$/i) || value.match(/^[0-9a-f]{6}$/i)) {
5678
5732
  value = `#${value}`;
5733
+ } else if (value.match(/^#?[0-9a-f]{4}$/i)) {
5734
+ const hex = value.startsWith("#") ? value.substring(1) : value;
5735
+ value = `#${hex}00`;
5679
5736
  }
5680
5737
  setCustomProp("color", "color", value);
5681
5738
  }
5682
5739
  if (isSVGElement) {
5683
5740
  if (element.hasAttribute("fill")) {
5684
5741
  const value = element.getAttribute("fill");
5685
- if (value !== "none") {
5742
+ if (value !== "none" && value !== "currentColor") {
5686
5743
  if (!(element instanceof SVGTextElement)) {
5687
5744
  const handleSVGElement = () => {
5688
5745
  let isSVGSmall = false;
@@ -5994,7 +6051,7 @@ function getManageableStyles(node, results = [], deep = true) {
5994
6051
  forEach(node.querySelectorAll(STYLE_SELECTOR), (style) =>
5995
6052
  getManageableStyles(style, results, false)
5996
6053
  );
5997
- if (deep) {
6054
+ if (deep && (node.children?.length > 0 || node.shadowRoot)) {
5998
6055
  iterateShadowHosts(node, (host) =>
5999
6056
  getManageableStyles(host.shadowRoot, results, false)
6000
6057
  );
@@ -7120,10 +7177,23 @@ function watchForStylePositions(currentStyles, update, shadowRootDiscovered) {
7120
7177
  removedStyles,
7121
7178
  movedStyles
7122
7179
  });
7180
+ const potentialHosts = new Set();
7123
7181
  additions.forEach((n) => {
7182
+ if (n.parentElement) {
7183
+ potentialHosts.add(n.parentElement);
7184
+ }
7185
+ if (n.previousElementSibling) {
7186
+ potentialHosts.add(n.previousElementSibling);
7187
+ }
7124
7188
  deepObserve(n);
7125
7189
  collectUndefinedElements(n);
7126
7190
  });
7191
+ potentialHosts.forEach((el) => {
7192
+ if (el.shadowRoot && !observedRoots.has(el)) {
7193
+ subscribeForShadowRootChanges(el);
7194
+ deepObserve(el.shadowRoot);
7195
+ }
7196
+ });
7127
7197
  additions.forEach(
7128
7198
  (node) => isCustomElement(node) && recordUndefinedElement(node)
7129
7199
  );
@@ -7237,6 +7307,14 @@ function watchForStylePositions(currentStyles, update, shadowRootDiscovered) {
7237
7307
  });
7238
7308
  document.addEventListener("__darkreader__isDefined", handleIsDefined);
7239
7309
  collectUndefinedElements(document);
7310
+ addDOMReadyListener(() => {
7311
+ forEach(document.body.children, (el) => {
7312
+ if (el.shadowRoot && !observedRoots.has(el)) {
7313
+ subscribeForShadowRootChanges(el);
7314
+ deepObserve(el.shadowRoot);
7315
+ }
7316
+ });
7317
+ });
7240
7318
  }
7241
7319
  function resetObservers() {
7242
7320
  observers.forEach((o) => o.disconnect());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "darkreader",
3
- "version": "4.9.118",
3
+ "version": "4.9.119",
4
4
  "description": "Dark mode for every website",
5
5
  "scripts": {
6
6
  "api": "node --max-old-space-size=3072 tasks/cli.js build --api",
@@ -41,7 +41,7 @@
41
41
  "type": "module",
42
42
  "repository": {
43
43
  "type": "git",
44
- "url": "https://github.com/darkreader/darkreader.git"
44
+ "url": "git+https://github.com/darkreader/darkreader.git"
45
45
  },
46
46
  "author": "Alexander Shutau <darkreaderapp@gmail.com> (https://darkreader.org/)",
47
47
  "license": "MIT",
@@ -67,26 +67,26 @@
67
67
  },
68
68
  "devDependencies": {
69
69
  "@eslint/compat": "2.0.0",
70
- "@eslint/eslintrc": "3.3.1",
71
- "@eslint/js": "9.39.1",
70
+ "@eslint/eslintrc": "3.3.3",
71
+ "@eslint/js": "9.39.2",
72
72
  "@rollup/plugin-node-resolve": "16.0.3",
73
73
  "@rollup/plugin-replace": "6.0.3",
74
74
  "@rollup/plugin-typescript": "12.3.0",
75
75
  "@stylistic/eslint-plugin": "5.6.1",
76
- "@types/chrome": "0.1.31",
76
+ "@types/chrome": "0.1.32",
77
77
  "@types/eslint": "9.6.1",
78
78
  "@types/jasmine": "5.1.13",
79
79
  "@types/jest": "30.0.0",
80
80
  "@types/karma": "6.3.9",
81
81
  "@types/karma-coverage": "2.0.3",
82
- "@types/node": "24.10.1",
82
+ "@types/node": "25.0.3",
83
83
  "@types/ws": "8.18.1",
84
- "chokidar": "4.0.3",
84
+ "chokidar": "5.0.0",
85
85
  "eslint-plugin-compat": "6.0.2",
86
86
  "eslint-plugin-import": "2.32.0",
87
- "globals": "16.5.0",
88
- "globby": "16.0.0",
89
- "jasmine-core": "5.12.1",
87
+ "globals": "17.0.0",
88
+ "globby": "16.1.0",
89
+ "jasmine-core": "5.13.0",
90
90
  "jest": "30.2.0",
91
91
  "jest-extended": "7.0.0",
92
92
  "karma": "6.4.4",
@@ -97,20 +97,20 @@
97
97
  "karma-rollup-preprocessor": "7.0.8",
98
98
  "karma-safari-launcher": "1.0.0",
99
99
  "karma-spec-reporter": "0.0.36",
100
- "less": "4.4.2",
101
- "prettier": "3.6.2",
102
- "puppeteer-core": "24.30.0",
103
- "rollup": "4.53.3",
100
+ "less": "4.5.1",
101
+ "prettier": "3.7.4",
102
+ "puppeteer-core": "24.34.0",
103
+ "rollup": "4.55.1",
104
104
  "rollup-plugin-istanbul": "5.0.0",
105
- "ts-jest": "29.4.5",
105
+ "ts-jest": "29.4.6",
106
106
  "tslib": "2.8.1",
107
107
  "typescript": "5.9.3",
108
- "typescript-eslint": "8.47.0",
108
+ "typescript-eslint": "8.51.0",
109
109
  "ws": "8.18.3",
110
110
  "yazl": "3.3.1"
111
111
  },
112
112
  "optionalDependencies": {
113
- "@rollup/rollup-linux-x64-gnu": "4.53.3",
114
- "@rollup/rollup-win32-x64-msvc": "4.53.3"
113
+ "@rollup/rollup-linux-x64-gnu": "4.55.1",
114
+ "@rollup/rollup-win32-x64-msvc": "4.55.1"
115
115
  }
116
116
  }