darkreader 4.9.81 → 4.9.83

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.
Files changed (2) hide show
  1. package/darkreader.js +93 -45
  2. package/package.json +9 -9
package/darkreader.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Dark Reader v4.9.81
2
+ * Dark Reader v4.9.83
3
3
  * https://darkreader.org/
4
4
  */
5
5
 
@@ -212,6 +212,10 @@
212
212
  });
213
213
  return dataURL;
214
214
  }
215
+ async function loadAsText(url, mimeType, origin) {
216
+ const response = await getOKResponse(url, mimeType, origin);
217
+ return await response.text();
218
+ }
215
219
 
216
220
  const throwCORSError = async (url) => {
217
221
  return Promise.reject(
@@ -785,6 +789,15 @@
785
789
  }
786
790
  return matches;
787
791
  }
792
+ function getHashCode(text) {
793
+ const len = text.length;
794
+ let hash = 0;
795
+ for (let i = 0; i < len; i++) {
796
+ const c = text.charCodeAt(i);
797
+ hash = ((hash << 5) - hash + c) & 4294967295;
798
+ }
799
+ return hash;
800
+ }
788
801
  function escapeRegExpSpecialChars(input) {
789
802
  return input.replaceAll(/[\^$.*+?\(\)\[\]{}|\-\\]/g, "\\$&");
790
803
  }
@@ -1005,26 +1018,33 @@
1005
1018
  cssText.includes("background-color: ;") &&
1006
1019
  !style.getPropertyValue("background")
1007
1020
  ) {
1008
- const parentRule = style.parentRule;
1009
- if (isStyleRule(parentRule)) {
1010
- const sourceCSSText =
1011
- parentRule.parentStyleSheet?.ownerNode?.textContent;
1012
- if (sourceCSSText) {
1013
- let escapedSelector = escapeRegExpSpecialChars(
1014
- parentRule.selectorText
1015
- );
1016
- escapedSelector = escapedSelector.replaceAll(
1017
- /\s+/g,
1018
- "\\s*"
1019
- );
1020
- escapedSelector = escapedSelector.replaceAll(/::/g, "::?");
1021
- const regexp = new RegExp(
1022
- `${escapedSelector}\\s*{[^}]*?background:\\s*([^;}]+)`
1023
- );
1024
- const match = sourceCSSText.match(regexp);
1025
- if (match) {
1026
- iterate("background", match[1]);
1027
- }
1021
+ handleEmptyShorthand("background", style, iterate);
1022
+ }
1023
+ if (
1024
+ cssText.includes("border-") &&
1025
+ cssText.includes("-color: ;") &&
1026
+ !style.getPropertyValue("border")
1027
+ ) {
1028
+ handleEmptyShorthand("border", style, iterate);
1029
+ }
1030
+ }
1031
+ function handleEmptyShorthand(shorthand, style, iterate) {
1032
+ const parentRule = style.parentRule;
1033
+ if (isStyleRule(parentRule)) {
1034
+ const sourceCSSText =
1035
+ parentRule.parentStyleSheet?.ownerNode?.textContent;
1036
+ if (sourceCSSText) {
1037
+ let escapedSelector = escapeRegExpSpecialChars(
1038
+ parentRule.selectorText
1039
+ );
1040
+ escapedSelector = escapedSelector.replaceAll(/\s+/g, "\\s*");
1041
+ escapedSelector = escapedSelector.replaceAll(/::/g, "::?");
1042
+ const regexp = new RegExp(
1043
+ `${escapedSelector}\\s*{[^}]*?${shorthand}:\\s*([^;}]+)`
1044
+ );
1045
+ const match = sourceCSSText.match(regexp);
1046
+ if (match) {
1047
+ iterate(shorthand, match[1]);
1028
1048
  }
1029
1049
  }
1030
1050
  }
@@ -1120,7 +1140,7 @@
1120
1140
  if (supportsRules.has(rule)) {
1121
1141
  return true;
1122
1142
  }
1123
- if (rule.cssText.startsWith("@supports")) {
1143
+ if (rule instanceof CSSSupportsRule) {
1124
1144
  supportsRules.add(rule);
1125
1145
  return true;
1126
1146
  }
@@ -1136,7 +1156,7 @@
1136
1156
  if (layerRules.has(rule)) {
1137
1157
  return true;
1138
1158
  }
1139
- if (rule.cssText.startsWith("@layer") && rule.cssRules) {
1159
+ if (rule instanceof CSSLayerBlockRule) {
1140
1160
  layerRules.add(rule);
1141
1161
  return true;
1142
1162
  }
@@ -2248,8 +2268,7 @@
2248
2268
  const analysis = analyzeImage(image);
2249
2269
  resolve({
2250
2270
  src: url,
2251
- blob,
2252
- dataURL,
2271
+ dataURL: analysis.isLarge ? "" : dataURL,
2253
2272
  width: image.width,
2254
2273
  height: image.height,
2255
2274
  ...analysis
@@ -2502,7 +2521,8 @@
2502
2521
  if (!isBlobURLSupported) {
2503
2522
  return null;
2504
2523
  }
2505
- let blobURL = dataURLBlobURLs.get(dataURL);
2524
+ const hash = getHashCode(dataURL);
2525
+ let blobURL = dataURLBlobURLs.get(hash);
2506
2526
  if (blobURL) {
2507
2527
  return blobURL;
2508
2528
  }
@@ -2512,7 +2532,7 @@
2512
2532
  blob = await response.blob();
2513
2533
  }
2514
2534
  blobURL = URL.createObjectURL(blob);
2515
- dataURLBlobURLs.set(dataURL, blobURL);
2535
+ dataURLBlobURLs.set(hash, blobURL);
2516
2536
  return blobURL;
2517
2537
  }
2518
2538
  function cleanImageProcessingCache() {
@@ -2628,7 +2648,29 @@
2628
2648
  property === "stroke" ||
2629
2649
  property === "stop-color"
2630
2650
  ) {
2631
- modifier = getColorModifier(property, value, rule);
2651
+ if (
2652
+ property.startsWith("border") &&
2653
+ property !== "border-color" &&
2654
+ value === "initial"
2655
+ ) {
2656
+ const borderSideProp = property.substring(
2657
+ 0,
2658
+ property.length - 6
2659
+ );
2660
+ const borderSideVal =
2661
+ rule.style.getPropertyValue(borderSideProp);
2662
+ if (
2663
+ borderSideVal.startsWith("0px") ||
2664
+ borderSideVal === "none"
2665
+ ) {
2666
+ property = borderSideProp;
2667
+ modifier = borderSideVal;
2668
+ } else {
2669
+ modifier = value;
2670
+ }
2671
+ } else {
2672
+ modifier = getColorModifier(property, value, rule);
2673
+ }
2632
2674
  } else if (
2633
2675
  property === "background-image" ||
2634
2676
  property === "list-style-image"
@@ -2664,11 +2706,12 @@
2664
2706
  );
2665
2707
  lines.push("}");
2666
2708
  }
2667
- if (isCSSColorSchemePropSupported) {
2709
+ if (isCSSColorSchemePropSupported && theme.mode === 1) {
2668
2710
  lines.push("html {");
2669
- lines.push(
2670
- ` color-scheme: ${theme.mode === 1 ? "dark" : "dark light"} !important;`
2671
- );
2711
+ lines.push(` color-scheme: dark !important;`);
2712
+ lines.push("}");
2713
+ lines.push("iframe {");
2714
+ lines.push(` color-scheme: initial;`);
2672
2715
  lines.push("}");
2673
2716
  }
2674
2717
  const bgSelectors = joinSelectors(
@@ -4572,6 +4615,13 @@
4572
4615
  const asyncQueue = createAsyncTasksQueue();
4573
4616
  function createStyleSheetModifier() {
4574
4617
  let renderId = 0;
4618
+ function getStyleRuleHash(rule) {
4619
+ let cssText = rule.cssText;
4620
+ if (isMediaRule(rule.parentRule)) {
4621
+ cssText = `${rule.parentRule.media.mediaText} { ${cssText} }`;
4622
+ }
4623
+ return getHashCode(cssText);
4624
+ }
4575
4625
  const rulesTextCache = new Set();
4576
4626
  const rulesModCache = new Map();
4577
4627
  const varTypeChangeCleaners = new Set();
@@ -4601,23 +4651,17 @@
4601
4651
  iterateCSSRules(
4602
4652
  rules,
4603
4653
  (rule) => {
4604
- let cssText = rule.cssText;
4654
+ const hash = getStyleRuleHash(rule);
4605
4655
  let textDiffersFromPrev = false;
4606
- notFoundCacheKeys.delete(cssText);
4607
- if (isMediaRule(rule.parentRule)) {
4608
- cssText += `;${rule.parentRule.media.mediaText}`;
4609
- }
4610
- if (isLayerRule(rule.parentRule)) {
4611
- cssText += `;${rule.parentRule.name}`;
4612
- }
4613
- if (!rulesTextCache.has(cssText)) {
4614
- rulesTextCache.add(cssText);
4656
+ notFoundCacheKeys.delete(hash);
4657
+ if (!rulesTextCache.has(hash)) {
4658
+ rulesTextCache.add(hash);
4615
4659
  textDiffersFromPrev = true;
4616
4660
  }
4617
4661
  if (textDiffersFromPrev) {
4618
4662
  rulesChanged = true;
4619
4663
  } else {
4620
- modRules.push(rulesModCache.get(cssText));
4664
+ modRules.push(rulesModCache.get(hash));
4621
4665
  return;
4622
4666
  }
4623
4667
  if (rule.style.all === "revert") {
@@ -4651,7 +4695,7 @@
4651
4695
  };
4652
4696
  modRules.push(modRule);
4653
4697
  }
4654
- rulesModCache.set(cssText, modRule);
4698
+ rulesModCache.set(hash, modRule);
4655
4699
  },
4656
4700
  () => {
4657
4701
  hasNonLoadedLink = true;
@@ -5509,11 +5553,15 @@
5509
5553
  if (url.startsWith("data:")) {
5510
5554
  return await (await fetch(url)).text();
5511
5555
  }
5556
+ const parsedURL = new URL(url);
5557
+ if (parsedURL.origin === location.origin) {
5558
+ return await loadAsText(url, "text/css", location.origin);
5559
+ }
5512
5560
  return await bgFetch({
5513
5561
  url,
5514
5562
  responseType: "text",
5515
5563
  mimeType: "text/css",
5516
- origin: window.location.origin
5564
+ origin: location.origin
5517
5565
  });
5518
5566
  }
5519
5567
  async function replaceCSSImports(cssText, basePath, cache = new Map()) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "darkreader",
3
- "version": "4.9.81",
3
+ "version": "4.9.83",
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",
@@ -58,16 +58,16 @@
58
58
  "@rollup/plugin-node-resolve": "15.2.3",
59
59
  "@rollup/plugin-replace": "5.0.5",
60
60
  "@rollup/plugin-typescript": "11.1.6",
61
- "@types/chrome": "0.0.263",
62
- "@types/eslint": "8.56.6",
61
+ "@types/chrome": "0.0.266",
62
+ "@types/eslint": "8.56.7",
63
63
  "@types/jasmine": "5.1.4",
64
64
  "@types/jest": "29.5.12",
65
65
  "@types/karma": "6.3.8",
66
66
  "@types/karma-coverage": "2.0.3",
67
- "@types/node": "20.12.2",
67
+ "@types/node": "20.12.6",
68
68
  "@types/ws": "8.5.10",
69
- "@typescript-eslint/eslint-plugin": "7.4.0",
70
- "@typescript-eslint/parser": "7.4.0",
69
+ "@typescript-eslint/eslint-plugin": "7.6.0",
70
+ "@typescript-eslint/parser": "7.6.0",
71
71
  "chokidar": "3.6.0",
72
72
  "eslint": "8.57.0",
73
73
  "eslint-plugin-compat": "4.2.0",
@@ -88,12 +88,12 @@
88
88
  "less": "4.2.0",
89
89
  "malevic": "0.20.1",
90
90
  "prettier": "3.2.5",
91
- "puppeteer-core": "22.6.1",
92
- "rollup": "4.13.2",
91
+ "puppeteer-core": "22.6.3",
92
+ "rollup": "4.14.1",
93
93
  "rollup-plugin-istanbul": "5.0.0",
94
94
  "ts-jest": "29.1.2",
95
95
  "tslib": "2.6.2",
96
- "typescript": "5.4.3",
96
+ "typescript": "5.4.4",
97
97
  "web-ext": "7.11.0",
98
98
  "ws": "8.16.0",
99
99
  "yazl": "2.5.1"