darkreader 4.9.84 → 4.9.86

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 +139 -48
  2. package/package.json +12 -11
package/darkreader.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Dark Reader v4.9.84
2
+ * Dark Reader v4.9.86
3
3
  * https://darkreader.org/
4
4
  */
5
5
 
@@ -1041,12 +1041,14 @@
1041
1041
  escapedSelector = escapedSelector.replaceAll(/\s+/g, "\\s*");
1042
1042
  escapedSelector = escapedSelector.replaceAll(/::/g, "::?");
1043
1043
  const regexp = new RegExp(
1044
- `${escapedSelector}\\s*{[^}]*?${shorthand}:\\s*([^;}]+)`
1044
+ `${escapedSelector}\\s*{[^}]*${shorthand}:\\s*([^;}]+)`
1045
1045
  );
1046
1046
  const match = sourceCSSText.match(regexp);
1047
1047
  if (match) {
1048
1048
  iterate(shorthand, match[1]);
1049
1049
  }
1050
+ } else if (shorthand === "background") {
1051
+ iterate("background-color", "#ffffff");
1050
1052
  }
1051
1053
  }
1052
1054
  }
@@ -1069,9 +1071,11 @@
1069
1071
  }
1070
1072
  function replaceCSSRelativeURLsWithAbsolute($css, cssBasePath) {
1071
1073
  return $css.replace(cssURLRegex, (match) => {
1072
- const pathValue = getCSSURLValue(match);
1073
1074
  try {
1074
- return `url('${getAbsoluteURL(cssBasePath, pathValue)}')`;
1075
+ const url = getCSSURLValue(match);
1076
+ const absoluteURL = getAbsoluteURL(cssBasePath, url);
1077
+ const escapedURL = absoluteURL.replaceAll("'", "\\'");
1078
+ return `url('${escapedURL}')`;
1075
1079
  } catch (err) {
1076
1080
  return match;
1077
1081
  }
@@ -2105,11 +2109,38 @@
2105
2109
  return modifyBackgroundColor(rgb, theme);
2106
2110
  }
2107
2111
 
2112
+ const excludedSelectors = [
2113
+ "pre",
2114
+ "pre *",
2115
+ "code",
2116
+ '[aria-hidden="true"]',
2117
+ '[class*="fa-"]',
2118
+ ".fa",
2119
+ ".fab",
2120
+ ".fad",
2121
+ ".fal",
2122
+ ".far",
2123
+ ".fas",
2124
+ ".fass",
2125
+ ".fasr",
2126
+ ".fat",
2127
+ ".icofont",
2128
+ '[style*="font-"]',
2129
+ '[class*="icon"]',
2130
+ '[class*="Icon"]',
2131
+ '[class*="symbol"]',
2132
+ '[class*="Symbol"]',
2133
+ ".glyphicon",
2134
+ '[class*="material-symbol"]',
2135
+ '[class*="material-icon"]',
2136
+ "mu",
2137
+ '[class*="mu-"]',
2138
+ ".typcn",
2139
+ '[class*="vjs-"]'
2140
+ ];
2108
2141
  function createTextStyle(config) {
2109
2142
  const lines = [];
2110
- lines.push(
2111
- '*:not(pre, pre *, code, .far, .fa, .glyphicon, [class*="vjs-"], .fab, .fa-github, .fas, .material-icons, .icofont, .typcn, mu, [class*="mu-"], .glyphicon, .icon) {'
2112
- );
2143
+ lines.push(`*:not(${excludedSelectors.join(", ")}) {`);
2113
2144
  if (config.useFont && config.fontFamily) {
2114
2145
  lines.push(` font-family: ${config.fontFamily} !important;`);
2115
2146
  }
@@ -2186,6 +2217,9 @@
2186
2217
  const resolvers$1 = new Map();
2187
2218
  const rejectors = new Map();
2188
2219
  async function bgFetch(request) {
2220
+ if (window.DarkReader?.Plugins?.fetch) {
2221
+ return window.DarkReader.Plugins.fetch(request);
2222
+ }
2189
2223
  return new Promise((resolve, reject) => {
2190
2224
  const id = generateUID();
2191
2225
  resolvers$1.set(id, resolve);
@@ -3294,7 +3328,7 @@
3294
3328
  class VariablesStore {
3295
3329
  constructor() {
3296
3330
  this.varTypes = new Map();
3297
- this.rulesQueue = [];
3331
+ this.rulesQueue = new Set();
3298
3332
  this.inlineStyleQueue = [];
3299
3333
  this.definedVars = new Set();
3300
3334
  this.varRefs = new Map();
@@ -3308,7 +3342,7 @@
3308
3342
  }
3309
3343
  clear() {
3310
3344
  this.varTypes.clear();
3311
- this.rulesQueue.splice(0);
3345
+ this.rulesQueue.clear();
3312
3346
  this.inlineStyleQueue.splice(0);
3313
3347
  this.definedVars.clear();
3314
3348
  this.varRefs.clear();
@@ -3327,14 +3361,14 @@
3327
3361
  );
3328
3362
  }
3329
3363
  addRulesForMatching(rules) {
3330
- this.rulesQueue.push(rules);
3364
+ this.rulesQueue.add(rules);
3331
3365
  }
3332
3366
  addInlineStyleForMatching(style) {
3333
3367
  this.inlineStyleQueue.push(style);
3334
3368
  }
3335
3369
  matchVariablesAndDependents() {
3336
3370
  if (
3337
- this.rulesQueue.length === 0 &&
3371
+ this.rulesQueue.size === 0 &&
3338
3372
  this.inlineStyleQueue.length === 0
3339
3373
  ) {
3340
3374
  return;
@@ -3520,7 +3554,11 @@
3520
3554
  };
3521
3555
  }
3522
3556
  getModifierForVarDependant(property, sourceValue) {
3523
- if (sourceValue.match(/^\s*(rgb|hsl)a?\(/)) {
3557
+ const isConstructedColor = sourceValue.match(/^\s*(rgb|hsl)a?\(/);
3558
+ const isSimpleConstructedColor = sourceValue.match(
3559
+ /^rgba?\(var\(--[\-_A-Za-z0-9]+\)(\s*,?\/?\s*0?\.\d+)?\)$/
3560
+ );
3561
+ if (isConstructedColor && !isSimpleConstructedColor) {
3524
3562
  const isBg = property.startsWith("background");
3525
3563
  const isText = isTextColorProperty(property);
3526
3564
  return (theme) => {
@@ -3539,21 +3577,34 @@
3539
3577
  return modifier(value, theme);
3540
3578
  };
3541
3579
  }
3542
- if (property === "background-color") {
3580
+ if (
3581
+ property === "background-color" ||
3582
+ (isSimpleConstructedColor && property === "background")
3583
+ ) {
3543
3584
  return (theme) => {
3585
+ const defaultFallback = tryModifyBgColor(
3586
+ isConstructedColor ? "255, 255, 255" : "#ffffff",
3587
+ theme
3588
+ );
3544
3589
  return replaceCSSVariablesNames(
3545
3590
  sourceValue,
3546
3591
  (v) => wrapBgColorVariableName(v),
3547
- (fallback) => tryModifyBgColor(fallback, theme)
3592
+ (fallback) => tryModifyBgColor(fallback, theme),
3593
+ defaultFallback
3548
3594
  );
3549
3595
  };
3550
3596
  }
3551
3597
  if (isTextColorProperty(property)) {
3552
3598
  return (theme) => {
3599
+ const defaultFallback = tryModifyTextColor(
3600
+ isConstructedColor ? "0, 0, 0" : "#000000",
3601
+ theme
3602
+ );
3553
3603
  return replaceCSSVariablesNames(
3554
3604
  sourceValue,
3555
3605
  (v) => wrapTextColorVariableName(v),
3556
- (fallback) => tryModifyTextColor(fallback, theme)
3606
+ (fallback) => tryModifyTextColor(fallback, theme),
3607
+ defaultFallback
3557
3608
  );
3558
3609
  };
3559
3610
  }
@@ -3659,7 +3710,7 @@
3659
3710
  this.inlineStyleQueue.forEach((style) => {
3660
3711
  this.collectVarsFromCSSDeclarations(style);
3661
3712
  });
3662
- this.rulesQueue.splice(0);
3713
+ this.rulesQueue.clear();
3663
3714
  this.inlineStyleQueue.splice(0);
3664
3715
  }
3665
3716
  collectVarsFromCSSDeclarations(style) {
@@ -3674,7 +3725,7 @@
3674
3725
  }
3675
3726
  shouldProcessRootVariables() {
3676
3727
  return (
3677
- this.rulesQueue.length > 0 &&
3728
+ this.rulesQueue.size > 0 &&
3678
3729
  document.documentElement.getAttribute("style")?.includes("--")
3679
3730
  );
3680
3731
  }
@@ -3906,7 +3957,9 @@
3906
3957
  return input;
3907
3958
  }
3908
3959
  const inputLength = input.length;
3909
- const replacements = matches.map((m) => replacer(m.value));
3960
+ const replacements = matches.map((m) =>
3961
+ replacer(m.value, matches.length)
3962
+ );
3910
3963
  const parts = [];
3911
3964
  parts.push(input.substring(0, matches[0].start));
3912
3965
  for (let i = 0; i < matchesCount; i++) {
@@ -3931,11 +3984,19 @@
3931
3984
  }
3932
3985
  return {name, fallback};
3933
3986
  }
3934
- function replaceCSSVariablesNames(value, nameReplacer, fallbackReplacer) {
3987
+ function replaceCSSVariablesNames(
3988
+ value,
3989
+ nameReplacer,
3990
+ fallbackReplacer,
3991
+ finalFallback
3992
+ ) {
3935
3993
  const matchReplacer = (match) => {
3936
3994
  const {name, fallback} = getVariableNameAndFallback(match);
3937
3995
  const newName = nameReplacer(name);
3938
3996
  if (!fallback) {
3997
+ if (finalFallback) {
3998
+ return `var(${newName}, ${finalFallback})`;
3999
+ }
3939
4000
  return `var(${newName})`;
3940
4001
  }
3941
4002
  let newFallback;
@@ -3979,7 +4040,10 @@
3979
4040
  return value.includes("var(");
3980
4041
  }
3981
4042
  function isConstructedColorVar(value) {
3982
- return value.match(/^\s*(rgb|hsl)a?\(/);
4043
+ return (
4044
+ value.match(/^\s*(rgb|hsl)a?\(/) ||
4045
+ value.match(/^(((\d{1,3})|(var\([\-_A-Za-z0-9]+\))),?\s*?){3}$/)
4046
+ );
3983
4047
  }
3984
4048
  function isTextColorProperty(property) {
3985
4049
  return (
@@ -4023,10 +4087,11 @@
4023
4087
  function tryModifyBorderColor(color, theme) {
4024
4088
  return handleRawColorValue(color, theme, modifyBorderColor);
4025
4089
  }
4026
- function insertVarValues(source, varValues, stack = new Set()) {
4090
+ function insertVarValues(source, varValues, fullStack = new Set()) {
4027
4091
  let containsUnresolvedVar = false;
4028
- const matchReplacer = (match) => {
4092
+ const matchReplacer = (match, count) => {
4029
4093
  const {name, fallback} = getVariableNameAndFallback(match);
4094
+ const stack = count > 1 ? new Set(fullStack) : fullStack;
4030
4095
  if (stack.has(name)) {
4031
4096
  containsUnresolvedVar = true;
4032
4097
  return null;
@@ -4308,9 +4373,7 @@
4308
4373
  }
4309
4374
  const shouldAnalyze = Boolean(
4310
4375
  svg &&
4311
- (svg.role === "img" ||
4312
- svg.parentElement?.role === "img" ||
4313
- svg.getAttribute("class")?.includes("logo") ||
4376
+ (svg.getAttribute("class")?.includes("logo") ||
4314
4377
  svg.parentElement?.getAttribute("class")?.includes("logo"))
4315
4378
  );
4316
4379
  svgAnalysisConditionCache.set(svg, shouldAnalyze);
@@ -4435,7 +4498,7 @@
4435
4498
  }
4436
4499
  if (shouldAnalyzeSVGAsImage(svg)) {
4437
4500
  svgInversionCache.add(svg);
4438
- const handleSVGRoot = () => {
4501
+ const analyzeSVGAsImage = () => {
4439
4502
  let svgString = svg.outerHTML;
4440
4503
  svgString = svgString.replaceAll(
4441
4504
  '<style class="darkreader darkreader--sync" media="screen"></style>',
@@ -4453,13 +4516,16 @@
4453
4516
  "data-darkreader-inline-invert",
4454
4517
  ""
4455
4518
  );
4519
+ } else {
4520
+ svg.removeAttribute(
4521
+ "data-darkreader-inline-invert"
4522
+ );
4456
4523
  }
4457
4524
  });
4458
4525
  };
4459
- if (isReadyStateComplete()) {
4460
- handleSVGRoot();
4461
- } else {
4462
- addReadyStateCompleteListener(handleSVGRoot);
4526
+ analyzeSVGAsImage();
4527
+ if (!isDOMReady()) {
4528
+ addDOMReadyListener(analyzeSVGAsImage);
4463
4529
  }
4464
4530
  return;
4465
4531
  }
@@ -6036,7 +6102,6 @@
6036
6102
  const sheet = newSheets[i];
6037
6103
  if (overrides.has(sheet)) {
6038
6104
  newSheets.splice(i, 1);
6039
- overrides.delete(sheet);
6040
6105
  }
6041
6106
  }
6042
6107
  if (node.adoptedStyleSheets.length !== newSheets.length) {
@@ -7276,6 +7341,24 @@
7276
7341
  addMetaListener();
7277
7342
  return false;
7278
7343
  }
7344
+ let interceptorAttempts = 2;
7345
+ function interceptOldScript({success, failure}) {
7346
+ if (--interceptorAttempts <= 0) {
7347
+ failure();
7348
+ return;
7349
+ }
7350
+ const oldMeta = document.head.querySelector('meta[name="darkreader"]');
7351
+ if (!oldMeta || oldMeta.content === INSTANCE_ID) {
7352
+ return;
7353
+ }
7354
+ const lock = document.createElement("meta");
7355
+ lock.name = "darkreader-lock";
7356
+ document.head.append(lock);
7357
+ queueMicrotask(() => {
7358
+ lock.remove();
7359
+ success();
7360
+ });
7361
+ }
7279
7362
  function createOrUpdateDynamicThemeInternal(
7280
7363
  themeConfig,
7281
7364
  dynamicThemeFixes,
@@ -7302,20 +7385,32 @@
7302
7385
  });
7303
7386
  }
7304
7387
  isIFrame$1 = iframe;
7305
- if (document.head) {
7306
- if (isAnotherDarkReaderInstanceActive()) {
7388
+ const ready = () => {
7389
+ const success = () => {
7390
+ document.documentElement.setAttribute(
7391
+ "data-darkreader-mode",
7392
+ "dynamic"
7393
+ );
7394
+ document.documentElement.setAttribute(
7395
+ "data-darkreader-scheme",
7396
+ theme.mode ? "dark" : "dimmed"
7397
+ );
7398
+ createThemeAndWatchForUpdates();
7399
+ };
7400
+ const failure = () => {
7307
7401
  removeDynamicTheme();
7308
- return;
7402
+ };
7403
+ if (isAnotherDarkReaderInstanceActive()) {
7404
+ interceptOldScript({
7405
+ success,
7406
+ failure
7407
+ });
7408
+ } else {
7409
+ success();
7309
7410
  }
7310
- document.documentElement.setAttribute(
7311
- "data-darkreader-mode",
7312
- "dynamic"
7313
- );
7314
- document.documentElement.setAttribute(
7315
- "data-darkreader-scheme",
7316
- theme.mode ? "dark" : "dimmed"
7317
- );
7318
- createThemeAndWatchForUpdates();
7411
+ };
7412
+ if (document.head) {
7413
+ ready();
7319
7414
  } else {
7320
7415
  if (!isFirefox) {
7321
7416
  const fallbackStyle = createOrUpdateStyle(
@@ -7329,11 +7424,7 @@
7329
7424
  const headObserver = new MutationObserver(() => {
7330
7425
  if (document.head) {
7331
7426
  headObserver.disconnect();
7332
- if (isAnotherDarkReaderInstanceActive()) {
7333
- removeDynamicTheme();
7334
- return;
7335
- }
7336
- createThemeAndWatchForUpdates();
7427
+ ready();
7337
7428
  }
7338
7429
  });
7339
7430
  headObserver.observe(document, {childList: true, subtree: true});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "darkreader",
3
- "version": "4.9.84",
3
+ "version": "4.9.86",
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",
@@ -9,6 +9,7 @@
9
9
  "code-style": "npm run lint",
10
10
  "debug": "node --max-old-space-size=3072 tasks/cli.js build --debug",
11
11
  "debug:watch": "node --max-old-space-size=3072 tasks/cli.js build --debug --watch --chrome --firefox",
12
+ "debug:watch:mv3": "node --max-old-space-size=3072 tasks/cli.js build --debug --watch --chrome-mv3",
12
13
  "dependencies:upgrade": "node tasks/dependencies.js",
13
14
  "lint": "eslint --ignore-pattern '!.eslint-plugin-local.js' -- 'src/**/*.ts' 'src/**/*.tsx' 'tasks/**/*.js' 'tests/[!coverage]**/*.js' 'tests/**/*.ts' '.eslintrc.js' 'index.d.ts'",
14
15
  "lint:bundle": "(node ./tasks/check-exists.js ./build/debug/chrome || node tasks/build.js --debug --api --chrome) && eslint -- 'build/debug/chrome/**/*.js' 'darkreader.js'",
@@ -58,21 +59,21 @@
58
59
  "@rollup/plugin-node-resolve": "15.2.3",
59
60
  "@rollup/plugin-replace": "5.0.5",
60
61
  "@rollup/plugin-typescript": "11.1.6",
61
- "@types/chrome": "0.0.266",
62
- "@types/eslint": "8.56.7",
62
+ "@types/chrome": "0.0.268",
63
+ "@types/eslint": "8.56.10",
63
64
  "@types/jasmine": "5.1.4",
64
65
  "@types/jest": "29.5.12",
65
66
  "@types/karma": "6.3.8",
66
67
  "@types/karma-coverage": "2.0.3",
67
- "@types/node": "20.12.6",
68
+ "@types/node": "20.12.12",
68
69
  "@types/ws": "8.5.10",
69
- "@typescript-eslint/eslint-plugin": "7.6.0",
70
- "@typescript-eslint/parser": "7.6.0",
70
+ "@typescript-eslint/eslint-plugin": "7.9.0",
71
+ "@typescript-eslint/parser": "7.9.0",
71
72
  "chokidar": "3.6.0",
72
73
  "eslint": "8.57.0",
73
74
  "eslint-plugin-compat": "4.2.0",
74
75
  "eslint-plugin-import": "2.29.1",
75
- "eslint-plugin-local": "4.2.1",
76
+ "eslint-plugin-local": "4.2.2",
76
77
  "globby": "14.0.1",
77
78
  "jasmine-core": "5.1.2",
78
79
  "jest": "29.7.0",
@@ -88,14 +89,14 @@
88
89
  "less": "4.2.0",
89
90
  "malevic": "0.20.1",
90
91
  "prettier": "3.2.5",
91
- "puppeteer-core": "22.6.3",
92
- "rollup": "4.14.1",
92
+ "puppeteer-core": "22.8.2",
93
+ "rollup": "4.17.2",
93
94
  "rollup-plugin-istanbul": "5.0.0",
94
95
  "ts-jest": "29.1.2",
95
96
  "tslib": "2.6.2",
96
- "typescript": "5.4.4",
97
+ "typescript": "5.4.5",
97
98
  "web-ext": "7.11.0",
98
- "ws": "8.16.0",
99
+ "ws": "8.17.0",
99
100
  "yazl": "2.5.1"
100
101
  }
101
102
  }