darkreader 4.9.105 → 4.9.109
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/README.md +8 -8
- package/darkreader.js +924 -844
- package/darkreader.mjs +881 -800
- package/package.json +27 -28
package/darkreader.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Dark Reader v4.9.
|
|
2
|
+
* Dark Reader v4.9.109
|
|
3
3
|
* https://darkreader.org/
|
|
4
4
|
*/
|
|
5
5
|
|
|
@@ -43,6 +43,8 @@
|
|
|
43
43
|
"ui-bg-apply-dev-static-themes";
|
|
44
44
|
MessageTypeUItoBG["RESET_DEV_STATIC_THEMES"] =
|
|
45
45
|
"ui-bg-reset-dev-static-themes";
|
|
46
|
+
MessageTypeUItoBG["START_ACTIVATION"] = "ui-bg-start-activation";
|
|
47
|
+
MessageTypeUItoBG["RESET_ACTIVATION"] = "ui-bg-reset-activation";
|
|
46
48
|
MessageTypeUItoBG["COLOR_SCHEME_CHANGE"] = "ui-bg-color-scheme-change";
|
|
47
49
|
MessageTypeUItoBG["HIDE_HIGHLIGHTS"] = "ui-bg-hide-highlights";
|
|
48
50
|
})(MessageTypeUItoBG || (MessageTypeUItoBG = {}));
|
|
@@ -372,9 +374,7 @@
|
|
|
372
374
|
];
|
|
373
375
|
({
|
|
374
376
|
customThemes: filterModeSites.map((url) => {
|
|
375
|
-
const engine =
|
|
376
|
-
? ThemeEngine.svgFilter
|
|
377
|
-
: ThemeEngine.cssFilter;
|
|
377
|
+
const engine = ThemeEngine.cssFilter;
|
|
378
378
|
return {
|
|
379
379
|
url: [url],
|
|
380
380
|
theme: {...DEFAULT_THEME, engine},
|
|
@@ -985,10 +985,16 @@
|
|
|
985
985
|
function parse($color) {
|
|
986
986
|
const c = $color.trim().toLowerCase();
|
|
987
987
|
if (c.includes("(from ")) {
|
|
988
|
+
if (c.indexOf("(from") !== c.lastIndexOf("(from")) {
|
|
989
|
+
return null;
|
|
990
|
+
}
|
|
988
991
|
return domParseColor(c);
|
|
989
992
|
}
|
|
990
993
|
if (c.match(rgbMatch)) {
|
|
991
994
|
if (c.startsWith("rgb(#") || c.startsWith("rgba(#")) {
|
|
995
|
+
if (c.lastIndexOf("rgb") > 0) {
|
|
996
|
+
return null;
|
|
997
|
+
}
|
|
992
998
|
return domParseColor(c);
|
|
993
999
|
}
|
|
994
1000
|
return parseRGB(c);
|
|
@@ -1011,7 +1017,10 @@
|
|
|
1011
1017
|
if (
|
|
1012
1018
|
c.endsWith(")") &&
|
|
1013
1019
|
supportedColorFuncs.some(
|
|
1014
|
-
(fn) =>
|
|
1020
|
+
(fn) =>
|
|
1021
|
+
c.startsWith(fn) &&
|
|
1022
|
+
c[fn.length] === "(" &&
|
|
1023
|
+
c.lastIndexOf(fn) === 0
|
|
1015
1024
|
)
|
|
1016
1025
|
) {
|
|
1017
1026
|
return domParseColor(c);
|
|
@@ -1840,6 +1849,9 @@
|
|
|
1840
1849
|
forEach(rules, (rule) => {
|
|
1841
1850
|
if (isStyleRule(rule)) {
|
|
1842
1851
|
iterate(rule);
|
|
1852
|
+
if (rule.cssRules?.length > 0) {
|
|
1853
|
+
iterateCSSRules(rule.cssRules, iterate);
|
|
1854
|
+
}
|
|
1843
1855
|
} else if (isImportRule(rule)) {
|
|
1844
1856
|
try {
|
|
1845
1857
|
iterateCSSRules(
|
|
@@ -2097,862 +2109,855 @@
|
|
|
2097
2109
|
return null;
|
|
2098
2110
|
}
|
|
2099
2111
|
|
|
2100
|
-
|
|
2101
|
-
const
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
if (index - possibleType.length >= 0) {
|
|
2114
|
-
const possibleGradient = value.substring(
|
|
2115
|
-
index - possibleType.length,
|
|
2116
|
-
index
|
|
2117
|
-
);
|
|
2118
|
-
if (possibleGradient === possibleType) {
|
|
2119
|
-
if (
|
|
2120
|
-
value.slice(
|
|
2121
|
-
index - possibleType.length - 10,
|
|
2122
|
-
index - possibleType.length - 1
|
|
2123
|
-
) === "repeating"
|
|
2124
|
-
) {
|
|
2125
|
-
typeGradient = `repeating-${possibleType}gradient`;
|
|
2126
|
-
return true;
|
|
2127
|
-
}
|
|
2128
|
-
if (
|
|
2129
|
-
value.slice(
|
|
2130
|
-
index - possibleType.length - 8,
|
|
2131
|
-
index - possibleType.length - 1
|
|
2132
|
-
) === "-webkit"
|
|
2133
|
-
) {
|
|
2134
|
-
typeGradient = `-webkit-${possibleType}gradient`;
|
|
2135
|
-
return true;
|
|
2136
|
-
}
|
|
2137
|
-
typeGradient = `${possibleType}gradient`;
|
|
2138
|
-
return true;
|
|
2139
|
-
}
|
|
2140
|
-
}
|
|
2112
|
+
let variablesSheet;
|
|
2113
|
+
const registeredColors = new Map();
|
|
2114
|
+
function registerVariablesSheet(sheet) {
|
|
2115
|
+
variablesSheet = sheet;
|
|
2116
|
+
const types = ["background", "text", "border"];
|
|
2117
|
+
registeredColors.forEach((registered) => {
|
|
2118
|
+
types.forEach((type) => {
|
|
2119
|
+
if (registered[type]) {
|
|
2120
|
+
const {variable, value} = registered[type];
|
|
2121
|
+
variablesSheet?.cssRules[0].style.setProperty(
|
|
2122
|
+
variable,
|
|
2123
|
+
value
|
|
2124
|
+
);
|
|
2141
2125
|
}
|
|
2142
|
-
);
|
|
2143
|
-
if (!typeGradient) {
|
|
2144
|
-
break;
|
|
2145
|
-
}
|
|
2146
|
-
const {start, end} = getParenthesesRange(
|
|
2147
|
-
value,
|
|
2148
|
-
index + gradientLength
|
|
2149
|
-
);
|
|
2150
|
-
const match = value.substring(start + 1, end - 1);
|
|
2151
|
-
startIndex = end + 1 + conicGradientLength;
|
|
2152
|
-
result.push({
|
|
2153
|
-
typeGradient,
|
|
2154
|
-
match,
|
|
2155
|
-
offset: typeGradient.length + 2,
|
|
2156
|
-
index: index - typeGradient.length + gradientLength,
|
|
2157
|
-
hasComma: true
|
|
2158
2126
|
});
|
|
2159
|
-
}
|
|
2160
|
-
if (result.length) {
|
|
2161
|
-
result[result.length - 1].hasComma = false;
|
|
2162
|
-
}
|
|
2163
|
-
return result;
|
|
2164
|
-
}
|
|
2165
|
-
|
|
2166
|
-
const STORAGE_KEY_IMAGE_DETAILS_LIST = "__darkreader__imageDetails_v2_list";
|
|
2167
|
-
const STORAGE_KEY_IMAGE_DETAILS_PREFIX = "__darkreader__imageDetails_v2_";
|
|
2168
|
-
const STORAGE_KEY_CSS_FETCH_PREFIX = "__darkreader__cssFetch_";
|
|
2169
|
-
let imageCacheTimeout = 0;
|
|
2170
|
-
const imageDetailsCacheQueue = new Map();
|
|
2171
|
-
const cachedImageUrls = [];
|
|
2172
|
-
function writeImageDetailsQueue() {
|
|
2173
|
-
imageDetailsCacheQueue.forEach((details, url) => {
|
|
2174
|
-
if (url && url.startsWith("https://")) {
|
|
2175
|
-
try {
|
|
2176
|
-
const json = JSON.stringify(details);
|
|
2177
|
-
sessionStorage.setItem(
|
|
2178
|
-
`${STORAGE_KEY_IMAGE_DETAILS_PREFIX}${url}`,
|
|
2179
|
-
json
|
|
2180
|
-
);
|
|
2181
|
-
cachedImageUrls.push(url);
|
|
2182
|
-
} catch (err) {}
|
|
2183
|
-
}
|
|
2184
2127
|
});
|
|
2185
|
-
imageDetailsCacheQueue.clear();
|
|
2186
|
-
sessionStorage.setItem(
|
|
2187
|
-
STORAGE_KEY_IMAGE_DETAILS_LIST,
|
|
2188
|
-
JSON.stringify(cachedImageUrls)
|
|
2189
|
-
);
|
|
2190
|
-
}
|
|
2191
|
-
function writeImageDetailsCache(url, imageDetails) {
|
|
2192
|
-
if (!url || !url.startsWith("https://")) {
|
|
2193
|
-
return;
|
|
2194
|
-
}
|
|
2195
|
-
imageDetailsCacheQueue.set(url, imageDetails);
|
|
2196
|
-
clearTimeout(imageCacheTimeout);
|
|
2197
|
-
imageCacheTimeout = setTimeout(writeImageDetailsQueue, 1000);
|
|
2198
2128
|
}
|
|
2199
|
-
function
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
STORAGE_KEY_IMAGE_DETAILS_LIST
|
|
2203
|
-
);
|
|
2204
|
-
if (!jsonList) {
|
|
2205
|
-
return;
|
|
2206
|
-
}
|
|
2207
|
-
const list = JSON.parse(jsonList);
|
|
2208
|
-
list.forEach((url) => {
|
|
2209
|
-
const json = sessionStorage.getItem(
|
|
2210
|
-
`${STORAGE_KEY_IMAGE_DETAILS_PREFIX}${url}`
|
|
2211
|
-
);
|
|
2212
|
-
if (json) {
|
|
2213
|
-
const details = JSON.parse(json);
|
|
2214
|
-
targetMap.set(url, details);
|
|
2215
|
-
}
|
|
2216
|
-
});
|
|
2217
|
-
} catch (err) {}
|
|
2129
|
+
function releaseVariablesSheet() {
|
|
2130
|
+
variablesSheet = null;
|
|
2131
|
+
clearColorPalette();
|
|
2218
2132
|
}
|
|
2219
|
-
function
|
|
2220
|
-
|
|
2221
|
-
try {
|
|
2222
|
-
sessionStorage.setItem(key, cssText);
|
|
2223
|
-
} catch (err) {}
|
|
2133
|
+
function getRegisteredVariableValue(type, registered) {
|
|
2134
|
+
return `var(${registered[type].variable}, ${registered[type].value})`;
|
|
2224
2135
|
}
|
|
2225
|
-
function
|
|
2226
|
-
const
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2136
|
+
function getRegisteredColor(type, parsed) {
|
|
2137
|
+
const hex = rgbToHexString(parsed);
|
|
2138
|
+
const registered = registeredColors.get(hex);
|
|
2139
|
+
if (registered?.[type]) {
|
|
2140
|
+
return getRegisteredVariableValue(type, registered);
|
|
2141
|
+
}
|
|
2230
2142
|
return null;
|
|
2231
2143
|
}
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
}
|
|
2242
|
-
|
|
2243
|
-
const MAX_FRAME_DURATION = 1000 / 60;
|
|
2244
|
-
class AsyncQueue {
|
|
2245
|
-
constructor() {
|
|
2246
|
-
this.queue = [];
|
|
2247
|
-
this.timerId = null;
|
|
2144
|
+
function registerColor(type, parsed, value) {
|
|
2145
|
+
const hex = rgbToHexString(parsed);
|
|
2146
|
+
let registered;
|
|
2147
|
+
if (registeredColors.has(hex)) {
|
|
2148
|
+
registered = registeredColors.get(hex);
|
|
2149
|
+
} else {
|
|
2150
|
+
const parsed = parseColorWithCache(hex);
|
|
2151
|
+
registered = {parsed};
|
|
2152
|
+
registeredColors.set(hex, registered);
|
|
2248
2153
|
}
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2154
|
+
const variable = `--darkreader-${type}-${hex.replace("#", "")}`;
|
|
2155
|
+
registered[type] = {variable, value};
|
|
2156
|
+
if (variablesSheet?.cssRules[0]?.style) {
|
|
2157
|
+
variablesSheet?.cssRules[0].style.setProperty(variable, value);
|
|
2252
2158
|
}
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2159
|
+
return getRegisteredVariableValue(type, registered);
|
|
2160
|
+
}
|
|
2161
|
+
function getColorPalette() {
|
|
2162
|
+
const background = [];
|
|
2163
|
+
const border = [];
|
|
2164
|
+
const text = [];
|
|
2165
|
+
registeredColors.forEach((registered) => {
|
|
2166
|
+
if (registered.background) {
|
|
2167
|
+
background.push(registered.parsed);
|
|
2257
2168
|
}
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
if (
|
|
2262
|
-
|
|
2169
|
+
if (registered.border) {
|
|
2170
|
+
border.push(registered.parsed);
|
|
2171
|
+
}
|
|
2172
|
+
if (registered.text) {
|
|
2173
|
+
text.push(registered.parsed);
|
|
2263
2174
|
}
|
|
2264
|
-
this.timerId = requestAnimationFrame(() => {
|
|
2265
|
-
this.timerId = null;
|
|
2266
|
-
const start = Date.now();
|
|
2267
|
-
let cb;
|
|
2268
|
-
while ((cb = this.queue.shift())) {
|
|
2269
|
-
cb();
|
|
2270
|
-
if (Date.now() - start >= MAX_FRAME_DURATION) {
|
|
2271
|
-
this.scheduleFrame();
|
|
2272
|
-
break;
|
|
2273
|
-
}
|
|
2274
|
-
}
|
|
2275
|
-
});
|
|
2276
|
-
}
|
|
2277
|
-
}
|
|
2278
|
-
|
|
2279
|
-
const resolvers$1 = new Map();
|
|
2280
|
-
const rejectors = new Map();
|
|
2281
|
-
async function bgFetch(request) {
|
|
2282
|
-
if (window.DarkReader?.Plugins?.fetch) {
|
|
2283
|
-
return window.DarkReader.Plugins.fetch(request);
|
|
2284
|
-
}
|
|
2285
|
-
return new Promise((resolve, reject) => {
|
|
2286
|
-
const id = generateUID();
|
|
2287
|
-
resolvers$1.set(id, resolve);
|
|
2288
|
-
rejectors.set(id, reject);
|
|
2289
|
-
chrome.runtime.sendMessage({
|
|
2290
|
-
type: MessageTypeCStoBG.FETCH,
|
|
2291
|
-
data: request,
|
|
2292
|
-
id
|
|
2293
|
-
});
|
|
2294
2175
|
});
|
|
2176
|
+
return {background, border, text};
|
|
2177
|
+
}
|
|
2178
|
+
function clearColorPalette() {
|
|
2179
|
+
registeredColors.clear();
|
|
2295
2180
|
}
|
|
2296
|
-
chrome.runtime.onMessage.addListener(({type, data, error, id}) => {
|
|
2297
|
-
if (type === MessageTypeBGtoCS.FETCH_RESPONSE) {
|
|
2298
|
-
const resolve = resolvers$1.get(id);
|
|
2299
|
-
const reject = rejectors.get(id);
|
|
2300
|
-
resolvers$1.delete(id);
|
|
2301
|
-
rejectors.delete(id);
|
|
2302
|
-
if (error) {
|
|
2303
|
-
reject && reject(error);
|
|
2304
|
-
} else {
|
|
2305
|
-
resolve && resolve(data);
|
|
2306
|
-
}
|
|
2307
|
-
}
|
|
2308
|
-
});
|
|
2309
2181
|
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
: await getDataURL(url);
|
|
2317
|
-
const blob =
|
|
2318
|
-
tryConvertDataURLToBlobSync(dataURL) ??
|
|
2319
|
-
(await loadAsBlob(url));
|
|
2320
|
-
let image;
|
|
2321
|
-
if (dataURL.startsWith("data:image/svg+xml")) {
|
|
2322
|
-
image = await loadImage(dataURL);
|
|
2323
|
-
} else {
|
|
2324
|
-
image =
|
|
2325
|
-
(await tryCreateImageBitmap(blob)) ??
|
|
2326
|
-
(await loadImage(dataURL));
|
|
2327
|
-
}
|
|
2328
|
-
imageManager.addTask(() => {
|
|
2329
|
-
const analysis = analyzeImage(image);
|
|
2330
|
-
resolve({
|
|
2331
|
-
src: url,
|
|
2332
|
-
dataURL: analysis.isLarge ? "" : dataURL,
|
|
2333
|
-
width: image.width,
|
|
2334
|
-
height: image.height,
|
|
2335
|
-
...analysis
|
|
2336
|
-
});
|
|
2337
|
-
});
|
|
2338
|
-
} catch (error) {
|
|
2339
|
-
reject(error);
|
|
2340
|
-
}
|
|
2341
|
-
});
|
|
2182
|
+
function getBgPole(theme) {
|
|
2183
|
+
const isDarkScheme = theme.mode === 1;
|
|
2184
|
+
const prop = isDarkScheme
|
|
2185
|
+
? "darkSchemeBackgroundColor"
|
|
2186
|
+
: "lightSchemeBackgroundColor";
|
|
2187
|
+
return theme[prop];
|
|
2342
2188
|
}
|
|
2343
|
-
|
|
2344
|
-
const
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
return
|
|
2189
|
+
function getFgPole(theme) {
|
|
2190
|
+
const isDarkScheme = theme.mode === 1;
|
|
2191
|
+
const prop = isDarkScheme
|
|
2192
|
+
? "darkSchemeTextColor"
|
|
2193
|
+
: "lightSchemeTextColor";
|
|
2194
|
+
return theme[prop];
|
|
2349
2195
|
}
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
} catch (err) {
|
|
2354
|
-
logWarn(
|
|
2355
|
-
`Unable to create image bitmap for type ${blob.type}: ${String(err)}`
|
|
2356
|
-
);
|
|
2357
|
-
return null;
|
|
2358
|
-
}
|
|
2196
|
+
const colorModificationCache = new Map();
|
|
2197
|
+
function clearColorModificationCache() {
|
|
2198
|
+
colorModificationCache.clear();
|
|
2359
2199
|
}
|
|
2360
|
-
const
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2200
|
+
const rgbCacheKeys = ["r", "g", "b", "a"];
|
|
2201
|
+
const themeCacheKeys = [
|
|
2202
|
+
"mode",
|
|
2203
|
+
"brightness",
|
|
2204
|
+
"contrast",
|
|
2205
|
+
"grayscale",
|
|
2206
|
+
"sepia",
|
|
2207
|
+
"darkSchemeBackgroundColor",
|
|
2208
|
+
"darkSchemeTextColor",
|
|
2209
|
+
"lightSchemeBackgroundColor",
|
|
2210
|
+
"lightSchemeTextColor"
|
|
2211
|
+
];
|
|
2212
|
+
function getCacheId(rgb, theme) {
|
|
2213
|
+
let resultId = "";
|
|
2214
|
+
rgbCacheKeys.forEach((key) => {
|
|
2215
|
+
resultId += `${rgb[key]};`;
|
|
2375
2216
|
});
|
|
2217
|
+
themeCacheKeys.forEach((key) => {
|
|
2218
|
+
resultId += `${theme[key]};`;
|
|
2219
|
+
});
|
|
2220
|
+
return resultId;
|
|
2376
2221
|
}
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
context.imageSmoothingEnabled = false;
|
|
2388
|
-
}
|
|
2389
|
-
function removeCanvas() {
|
|
2390
|
-
canvas = null;
|
|
2391
|
-
context = null;
|
|
2392
|
-
}
|
|
2393
|
-
const LARGE_IMAGE_PIXELS_COUNT = 512 * 512;
|
|
2394
|
-
function analyzeImage(image) {
|
|
2395
|
-
if (!canvas) {
|
|
2396
|
-
createCanvas();
|
|
2397
|
-
}
|
|
2398
|
-
let sw;
|
|
2399
|
-
let sh;
|
|
2400
|
-
if (image instanceof HTMLImageElement) {
|
|
2401
|
-
sw = image.naturalWidth;
|
|
2402
|
-
sh = image.naturalHeight;
|
|
2222
|
+
function modifyColorWithCache(
|
|
2223
|
+
rgb,
|
|
2224
|
+
theme,
|
|
2225
|
+
modifyHSL,
|
|
2226
|
+
poleColor,
|
|
2227
|
+
anotherPoleColor
|
|
2228
|
+
) {
|
|
2229
|
+
let fnCache;
|
|
2230
|
+
if (colorModificationCache.has(modifyHSL)) {
|
|
2231
|
+
fnCache = colorModificationCache.get(modifyHSL);
|
|
2403
2232
|
} else {
|
|
2404
|
-
|
|
2405
|
-
|
|
2233
|
+
fnCache = new Map();
|
|
2234
|
+
colorModificationCache.set(modifyHSL, fnCache);
|
|
2406
2235
|
}
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
return
|
|
2410
|
-
isDark: false,
|
|
2411
|
-
isLight: false,
|
|
2412
|
-
isTransparent: false,
|
|
2413
|
-
isLarge: false
|
|
2414
|
-
};
|
|
2236
|
+
const id = getCacheId(rgb, theme);
|
|
2237
|
+
if (fnCache.has(id)) {
|
|
2238
|
+
return fnCache.get(id);
|
|
2415
2239
|
}
|
|
2416
|
-
const
|
|
2417
|
-
const
|
|
2418
|
-
const
|
|
2419
|
-
|
|
2420
|
-
|
|
2240
|
+
const hsl = rgbToHSL(rgb);
|
|
2241
|
+
const pole = poleColor == null ? null : parseToHSLWithCache(poleColor);
|
|
2242
|
+
const anotherPole =
|
|
2243
|
+
anotherPoleColor == null
|
|
2244
|
+
? null
|
|
2245
|
+
: parseToHSLWithCache(anotherPoleColor);
|
|
2246
|
+
const modified = modifyHSL(hsl, pole, anotherPole);
|
|
2247
|
+
const {r, g, b, a} = hslToRGB(modified);
|
|
2248
|
+
const matrix = createFilterMatrix({...theme, mode: 0});
|
|
2249
|
+
const [rf, gf, bf] = applyColorMatrix([r, g, b], matrix);
|
|
2250
|
+
const color =
|
|
2251
|
+
a === 1
|
|
2252
|
+
? rgbToHexString({r: rf, g: gf, b: bf})
|
|
2253
|
+
: rgbToString({r: rf, g: gf, b: bf, a});
|
|
2254
|
+
fnCache.set(id, color);
|
|
2255
|
+
return color;
|
|
2256
|
+
}
|
|
2257
|
+
function modifyAndRegisterColor(type, rgb, theme, modifier) {
|
|
2258
|
+
const registered = getRegisteredColor(type, rgb);
|
|
2259
|
+
if (registered) {
|
|
2260
|
+
return registered;
|
|
2261
|
+
}
|
|
2262
|
+
const value = modifier(rgb, theme);
|
|
2263
|
+
return registerColor(type, rgb, value);
|
|
2264
|
+
}
|
|
2265
|
+
function modifyLightSchemeColor(rgb, theme) {
|
|
2266
|
+
const poleBg = getBgPole(theme);
|
|
2267
|
+
const poleFg = getFgPole(theme);
|
|
2268
|
+
return modifyColorWithCache(
|
|
2269
|
+
rgb,
|
|
2270
|
+
theme,
|
|
2271
|
+
modifyLightModeHSL,
|
|
2272
|
+
poleFg,
|
|
2273
|
+
poleBg
|
|
2421
2274
|
);
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
let
|
|
2433
|
-
let
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
g = d[i + 1];
|
|
2442
|
-
b = d[i + 2];
|
|
2443
|
-
a = d[i + 3];
|
|
2444
|
-
if (a / 255 < TRANSPARENT_ALPHA_THRESHOLD) {
|
|
2445
|
-
transparentPixelsCount++;
|
|
2446
|
-
} else {
|
|
2447
|
-
l = getSRGBLightness(r, g, b);
|
|
2448
|
-
if (l < DARK_LIGHTNESS_THRESHOLD) {
|
|
2449
|
-
darkPixelsCount++;
|
|
2450
|
-
}
|
|
2451
|
-
if (l > LIGHT_LIGHTNESS_THRESHOLD) {
|
|
2452
|
-
lightPixelsCount++;
|
|
2453
|
-
}
|
|
2454
|
-
}
|
|
2275
|
+
}
|
|
2276
|
+
function modifyLightModeHSL({h, s, l, a}, poleFg, poleBg) {
|
|
2277
|
+
const isDark = l < 0.5;
|
|
2278
|
+
let isNeutral;
|
|
2279
|
+
if (isDark) {
|
|
2280
|
+
isNeutral = l < 0.2 || s < 0.12;
|
|
2281
|
+
} else {
|
|
2282
|
+
const isBlue = h > 200 && h < 280;
|
|
2283
|
+
isNeutral = s < 0.24 || (l > 0.8 && isBlue);
|
|
2284
|
+
}
|
|
2285
|
+
let hx = h;
|
|
2286
|
+
let sx = s;
|
|
2287
|
+
if (isNeutral) {
|
|
2288
|
+
if (isDark) {
|
|
2289
|
+
hx = poleFg.h;
|
|
2290
|
+
sx = poleFg.s;
|
|
2291
|
+
} else {
|
|
2292
|
+
hx = poleBg.h;
|
|
2293
|
+
sx = poleBg.s;
|
|
2455
2294
|
}
|
|
2456
2295
|
}
|
|
2457
|
-
const
|
|
2458
|
-
|
|
2459
|
-
const DARK_IMAGE_THRESHOLD = 0.7;
|
|
2460
|
-
const LIGHT_IMAGE_THRESHOLD = 0.7;
|
|
2461
|
-
const TRANSPARENT_IMAGE_THRESHOLD = 0.1;
|
|
2462
|
-
return {
|
|
2463
|
-
isDark: darkPixelsCount / opaquePixelsCount >= DARK_IMAGE_THRESHOLD,
|
|
2464
|
-
isLight:
|
|
2465
|
-
lightPixelsCount / opaquePixelsCount >= LIGHT_IMAGE_THRESHOLD,
|
|
2466
|
-
isTransparent:
|
|
2467
|
-
transparentPixelsCount / totalPixelsCount >=
|
|
2468
|
-
TRANSPARENT_IMAGE_THRESHOLD,
|
|
2469
|
-
isLarge
|
|
2470
|
-
};
|
|
2296
|
+
const lx = scale(l, 0, 1, poleFg.l, poleBg.l);
|
|
2297
|
+
return {h: hx, s: sx, l: lx, a};
|
|
2471
2298
|
}
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2299
|
+
const MAX_BG_LIGHTNESS = 0.4;
|
|
2300
|
+
function modifyBgHSL({h, s, l, a}, pole) {
|
|
2301
|
+
const isDark = l < 0.5;
|
|
2302
|
+
const isBlue = h > 200 && h < 280;
|
|
2303
|
+
const isNeutral = s < 0.12 || (l > 0.8 && isBlue);
|
|
2304
|
+
if (isDark) {
|
|
2305
|
+
const lx = scale(l, 0, 0.5, 0, MAX_BG_LIGHTNESS);
|
|
2306
|
+
if (isNeutral) {
|
|
2307
|
+
const hx = pole.h;
|
|
2308
|
+
const sx = pole.s;
|
|
2309
|
+
return {h: hx, s: sx, l: lx, a};
|
|
2310
|
+
}
|
|
2311
|
+
return {h, s, l: lx, a};
|
|
2312
|
+
}
|
|
2313
|
+
let lx = scale(l, 0.5, 1, MAX_BG_LIGHTNESS, pole.l);
|
|
2314
|
+
if (isNeutral) {
|
|
2315
|
+
const hx = pole.h;
|
|
2316
|
+
const sx = pole.s;
|
|
2317
|
+
return {h: hx, s: sx, l: lx, a};
|
|
2318
|
+
}
|
|
2319
|
+
let hx = h;
|
|
2320
|
+
const isYellow = h > 60 && h < 180;
|
|
2321
|
+
if (isYellow) {
|
|
2322
|
+
const isCloserToGreen = h > 120;
|
|
2323
|
+
if (isCloserToGreen) {
|
|
2324
|
+
hx = scale(h, 120, 180, 135, 180);
|
|
2325
|
+
} else {
|
|
2326
|
+
hx = scale(h, 60, 120, 60, 105);
|
|
2327
|
+
}
|
|
2484
2328
|
}
|
|
2485
|
-
if (
|
|
2486
|
-
|
|
2487
|
-
blobURLCheckAwaiters.push(resolve)
|
|
2488
|
-
);
|
|
2329
|
+
if (hx > 40 && hx < 80) {
|
|
2330
|
+
lx *= 0.75;
|
|
2489
2331
|
}
|
|
2490
|
-
|
|
2491
|
-
await new Promise((resolve) => {
|
|
2492
|
-
document.addEventListener(
|
|
2493
|
-
"__darkreader__blobURLCheckResponse",
|
|
2494
|
-
(e) => {
|
|
2495
|
-
isBlobURLSupported = e.detail.blobURLAllowed;
|
|
2496
|
-
resolve();
|
|
2497
|
-
blobURLCheckAwaiters.forEach((r) => r());
|
|
2498
|
-
blobURLCheckAwaiters.splice(0);
|
|
2499
|
-
},
|
|
2500
|
-
{once: true}
|
|
2501
|
-
);
|
|
2502
|
-
document.dispatchEvent(
|
|
2503
|
-
new CustomEvent("__darkreader__blobURLCheckRequest")
|
|
2504
|
-
);
|
|
2505
|
-
});
|
|
2332
|
+
return {h: hx, s, l: lx, a};
|
|
2506
2333
|
}
|
|
2507
|
-
function
|
|
2508
|
-
|
|
2334
|
+
function _modifyBackgroundColor(rgb, theme) {
|
|
2335
|
+
if (theme.mode === 0) {
|
|
2336
|
+
return modifyLightSchemeColor(rgb, theme);
|
|
2337
|
+
}
|
|
2338
|
+
const pole = getBgPole(theme);
|
|
2339
|
+
return modifyColorWithCache(rgb, theme, modifyBgHSL, pole);
|
|
2509
2340
|
}
|
|
2510
|
-
function
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2341
|
+
function modifyBackgroundColor(
|
|
2342
|
+
rgb,
|
|
2343
|
+
theme,
|
|
2344
|
+
shouldRegisterColorVariable = true
|
|
2345
|
+
) {
|
|
2346
|
+
if (!shouldRegisterColorVariable) {
|
|
2347
|
+
return _modifyBackgroundColor(rgb, theme);
|
|
2514
2348
|
}
|
|
2349
|
+
return modifyAndRegisterColor(
|
|
2350
|
+
"background",
|
|
2351
|
+
rgb,
|
|
2352
|
+
theme,
|
|
2353
|
+
_modifyBackgroundColor
|
|
2354
|
+
);
|
|
2515
2355
|
}
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2356
|
+
const MIN_FG_LIGHTNESS = 0.55;
|
|
2357
|
+
function modifyBlueFgHue(hue) {
|
|
2358
|
+
return scale(hue, 205, 245, 205, 220);
|
|
2359
|
+
}
|
|
2360
|
+
function modifyFgHSL({h, s, l, a}, pole) {
|
|
2361
|
+
const isLight = l > 0.5;
|
|
2362
|
+
const isNeutral = l < 0.2 || s < 0.24;
|
|
2363
|
+
const isBlue = !isNeutral && h > 205 && h < 245;
|
|
2364
|
+
if (isLight) {
|
|
2365
|
+
const lx = scale(l, 0.5, 1, MIN_FG_LIGHTNESS, pole.l);
|
|
2366
|
+
if (isNeutral) {
|
|
2367
|
+
const hx = pole.h;
|
|
2368
|
+
const sx = pole.s;
|
|
2369
|
+
return {h: hx, s: sx, l: lx, a};
|
|
2370
|
+
}
|
|
2371
|
+
let hx = h;
|
|
2372
|
+
if (isBlue) {
|
|
2373
|
+
hx = modifyBlueFgHue(h);
|
|
2374
|
+
}
|
|
2375
|
+
return {h: hx, s, l: lx, a};
|
|
2521
2376
|
}
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
`<feColorMatrix type="matrix" values="${matrix}" />`,
|
|
2528
|
-
"</filter>",
|
|
2529
|
-
"</defs>",
|
|
2530
|
-
`<image width="${width}" height="${height}" filter="url(#darkreader-image-filter)" xlink:href="${dataURL}" />`,
|
|
2531
|
-
"</svg>"
|
|
2532
|
-
].join("");
|
|
2533
|
-
if (!isBlobURLSupported) {
|
|
2534
|
-
return `data:image/svg+xml;base64,${btoa(svg)}`;
|
|
2377
|
+
if (isNeutral) {
|
|
2378
|
+
const hx = pole.h;
|
|
2379
|
+
const sx = pole.s;
|
|
2380
|
+
const lx = scale(l, 0, 0.5, pole.l, MIN_FG_LIGHTNESS);
|
|
2381
|
+
return {h: hx, s: sx, l: lx, a};
|
|
2535
2382
|
}
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2383
|
+
let hx = h;
|
|
2384
|
+
let lx;
|
|
2385
|
+
if (isBlue) {
|
|
2386
|
+
hx = modifyBlueFgHue(h);
|
|
2387
|
+
lx = scale(l, 0, 0.5, pole.l, Math.min(1, MIN_FG_LIGHTNESS + 0.05));
|
|
2388
|
+
} else {
|
|
2389
|
+
lx = scale(l, 0, 0.5, pole.l, MIN_FG_LIGHTNESS);
|
|
2539
2390
|
}
|
|
2540
|
-
|
|
2541
|
-
const objectURL = URL.createObjectURL(blob);
|
|
2542
|
-
objectURLs.add(objectURL);
|
|
2543
|
-
return objectURL;
|
|
2391
|
+
return {h: hx, s, l: lx, a};
|
|
2544
2392
|
}
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
};
|
|
2552
|
-
function escapeXML(str) {
|
|
2553
|
-
return str.replace(/[<>&'"]/g, (c) => xmlEscapeChars[c] ?? c);
|
|
2393
|
+
function _modifyForegroundColor(rgb, theme) {
|
|
2394
|
+
if (theme.mode === 0) {
|
|
2395
|
+
return modifyLightSchemeColor(rgb, theme);
|
|
2396
|
+
}
|
|
2397
|
+
const pole = getFgPole(theme);
|
|
2398
|
+
return modifyColorWithCache(rgb, theme, modifyFgHSL, pole);
|
|
2554
2399
|
}
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
.toLocaleLowerCase();
|
|
2563
|
-
const mediaType = dataURL.substring(colonIndex + 1, semicolonIndex);
|
|
2564
|
-
if (encoding !== "base64" || !mediaType) {
|
|
2565
|
-
return null;
|
|
2400
|
+
function modifyForegroundColor(
|
|
2401
|
+
rgb,
|
|
2402
|
+
theme,
|
|
2403
|
+
shouldRegisterColorVariable = true
|
|
2404
|
+
) {
|
|
2405
|
+
if (!shouldRegisterColorVariable) {
|
|
2406
|
+
return _modifyForegroundColor(rgb, theme);
|
|
2566
2407
|
}
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2408
|
+
return modifyAndRegisterColor(
|
|
2409
|
+
"text",
|
|
2410
|
+
rgb,
|
|
2411
|
+
theme,
|
|
2412
|
+
_modifyForegroundColor
|
|
2413
|
+
);
|
|
2414
|
+
}
|
|
2415
|
+
function modifyBorderHSL({h, s, l, a}, poleFg, poleBg) {
|
|
2416
|
+
const isDark = l < 0.5;
|
|
2417
|
+
const isNeutral = l < 0.2 || s < 0.24;
|
|
2418
|
+
let hx = h;
|
|
2419
|
+
let sx = s;
|
|
2420
|
+
if (isNeutral) {
|
|
2421
|
+
if (isDark) {
|
|
2422
|
+
hx = poleFg.h;
|
|
2423
|
+
sx = poleFg.s;
|
|
2424
|
+
} else {
|
|
2425
|
+
hx = poleBg.h;
|
|
2426
|
+
sx = poleBg.s;
|
|
2427
|
+
}
|
|
2571
2428
|
}
|
|
2572
|
-
|
|
2429
|
+
const lx = scale(l, 0, 1, 0.5, 0.2);
|
|
2430
|
+
return {h: hx, s: sx, l: lx, a};
|
|
2573
2431
|
}
|
|
2574
|
-
|
|
2575
|
-
if (
|
|
2576
|
-
return
|
|
2432
|
+
function _modifyBorderColor(rgb, theme) {
|
|
2433
|
+
if (theme.mode === 0) {
|
|
2434
|
+
return modifyLightSchemeColor(rgb, theme);
|
|
2577
2435
|
}
|
|
2578
|
-
const
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2436
|
+
const poleFg = getFgPole(theme);
|
|
2437
|
+
const poleBg = getBgPole(theme);
|
|
2438
|
+
return modifyColorWithCache(
|
|
2439
|
+
rgb,
|
|
2440
|
+
theme,
|
|
2441
|
+
modifyBorderHSL,
|
|
2442
|
+
poleFg,
|
|
2443
|
+
poleBg
|
|
2444
|
+
);
|
|
2445
|
+
}
|
|
2446
|
+
function modifyBorderColor(rgb, theme, shouldRegisterColorVariable = true) {
|
|
2447
|
+
if (!shouldRegisterColorVariable) {
|
|
2448
|
+
return _modifyBorderColor(rgb, theme);
|
|
2449
|
+
}
|
|
2450
|
+
return modifyAndRegisterColor("border", rgb, theme, _modifyBorderColor);
|
|
2451
|
+
}
|
|
2452
|
+
function modifyShadowColor(rgb, theme) {
|
|
2453
|
+
return modifyBackgroundColor(rgb, theme);
|
|
2454
|
+
}
|
|
2455
|
+
function modifyGradientColor(rgb, theme) {
|
|
2456
|
+
return modifyBackgroundColor(rgb, theme);
|
|
2457
|
+
}
|
|
2458
|
+
|
|
2459
|
+
const gradientLength = "gradient".length;
|
|
2460
|
+
const conicGradient = "conic-";
|
|
2461
|
+
const conicGradientLength = conicGradient.length;
|
|
2462
|
+
const radialGradient = "radial-";
|
|
2463
|
+
const linearGradient = "linear-";
|
|
2464
|
+
function parseGradient(value) {
|
|
2465
|
+
const result = [];
|
|
2466
|
+
let index = 0;
|
|
2467
|
+
let startIndex = conicGradient.length;
|
|
2468
|
+
while ((index = value.indexOf("gradient", startIndex)) !== -1) {
|
|
2469
|
+
let typeGradient;
|
|
2470
|
+
[linearGradient, radialGradient, conicGradient].find(
|
|
2471
|
+
(possibleType) => {
|
|
2472
|
+
if (index - possibleType.length >= 0) {
|
|
2473
|
+
const possibleGradient = value.substring(
|
|
2474
|
+
index - possibleType.length,
|
|
2475
|
+
index
|
|
2476
|
+
);
|
|
2477
|
+
if (possibleGradient === possibleType) {
|
|
2478
|
+
if (
|
|
2479
|
+
value.slice(
|
|
2480
|
+
index - possibleType.length - 10,
|
|
2481
|
+
index - possibleType.length - 1
|
|
2482
|
+
) === "repeating"
|
|
2483
|
+
) {
|
|
2484
|
+
typeGradient = `repeating-${possibleType}gradient`;
|
|
2485
|
+
return true;
|
|
2486
|
+
}
|
|
2487
|
+
if (
|
|
2488
|
+
value.slice(
|
|
2489
|
+
index - possibleType.length - 8,
|
|
2490
|
+
index - possibleType.length - 1
|
|
2491
|
+
) === "-webkit"
|
|
2492
|
+
) {
|
|
2493
|
+
typeGradient = `-webkit-${possibleType}gradient`;
|
|
2494
|
+
return true;
|
|
2495
|
+
}
|
|
2496
|
+
typeGradient = `${possibleType}gradient`;
|
|
2497
|
+
return true;
|
|
2498
|
+
}
|
|
2499
|
+
}
|
|
2500
|
+
}
|
|
2501
|
+
);
|
|
2502
|
+
if (!typeGradient) {
|
|
2503
|
+
break;
|
|
2504
|
+
}
|
|
2505
|
+
const {start, end} = getParenthesesRange(
|
|
2506
|
+
value,
|
|
2507
|
+
index + gradientLength
|
|
2508
|
+
);
|
|
2509
|
+
const match = value.substring(start + 1, end - 1);
|
|
2510
|
+
startIndex = end + 1 + conicGradientLength;
|
|
2511
|
+
result.push({
|
|
2512
|
+
typeGradient,
|
|
2513
|
+
match,
|
|
2514
|
+
offset: typeGradient.length + 2,
|
|
2515
|
+
index: index - typeGradient.length + gradientLength,
|
|
2516
|
+
hasComma: true
|
|
2517
|
+
});
|
|
2582
2518
|
}
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
const response = await fetch(dataURL);
|
|
2586
|
-
blob = await response.blob();
|
|
2519
|
+
if (result.length) {
|
|
2520
|
+
result[result.length - 1].hasComma = false;
|
|
2587
2521
|
}
|
|
2588
|
-
|
|
2589
|
-
dataURLBlobURLs.set(hash, blobURL);
|
|
2590
|
-
return blobURL;
|
|
2591
|
-
}
|
|
2592
|
-
function cleanImageProcessingCache() {
|
|
2593
|
-
imageManager && imageManager.stop();
|
|
2594
|
-
removeCanvas();
|
|
2595
|
-
objectURLs.forEach((u) => URL.revokeObjectURL(u));
|
|
2596
|
-
objectURLs.clear();
|
|
2597
|
-
dataURLBlobURLs.forEach((u) => URL.revokeObjectURL(u));
|
|
2598
|
-
dataURLBlobURLs.clear();
|
|
2522
|
+
return result;
|
|
2599
2523
|
}
|
|
2600
2524
|
|
|
2601
|
-
|
|
2602
|
-
const
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2525
|
+
const STORAGE_KEY_IMAGE_DETAILS_LIST = "__darkreader__imageDetails_v2_list";
|
|
2526
|
+
const STORAGE_KEY_IMAGE_DETAILS_PREFIX = "__darkreader__imageDetails_v2_";
|
|
2527
|
+
const STORAGE_KEY_CSS_FETCH_PREFIX = "__darkreader__cssFetch_";
|
|
2528
|
+
let imageCacheTimeout = 0;
|
|
2529
|
+
const imageDetailsCacheQueue = new Map();
|
|
2530
|
+
const cachedImageUrls = [];
|
|
2531
|
+
function writeImageDetailsQueue() {
|
|
2532
|
+
imageDetailsCacheQueue.forEach((details, url) => {
|
|
2533
|
+
if (url && url.startsWith("https://")) {
|
|
2534
|
+
try {
|
|
2535
|
+
const json = JSON.stringify(details);
|
|
2536
|
+
sessionStorage.setItem(
|
|
2537
|
+
`${STORAGE_KEY_IMAGE_DETAILS_PREFIX}${url}`,
|
|
2538
|
+
json
|
|
2613
2539
|
);
|
|
2614
|
-
|
|
2615
|
-
|
|
2540
|
+
cachedImageUrls.push(url);
|
|
2541
|
+
} catch (err) {}
|
|
2542
|
+
}
|
|
2616
2543
|
});
|
|
2544
|
+
imageDetailsCacheQueue.clear();
|
|
2545
|
+
sessionStorage.setItem(
|
|
2546
|
+
STORAGE_KEY_IMAGE_DETAILS_LIST,
|
|
2547
|
+
JSON.stringify(cachedImageUrls)
|
|
2548
|
+
);
|
|
2617
2549
|
}
|
|
2618
|
-
function
|
|
2619
|
-
|
|
2620
|
-
|
|
2550
|
+
function writeImageDetailsCache(url, imageDetails) {
|
|
2551
|
+
if (!url || !url.startsWith("https://")) {
|
|
2552
|
+
return;
|
|
2553
|
+
}
|
|
2554
|
+
imageDetailsCacheQueue.set(url, imageDetails);
|
|
2555
|
+
clearTimeout(imageCacheTimeout);
|
|
2556
|
+
imageCacheTimeout = setTimeout(writeImageDetailsQueue, 1000);
|
|
2621
2557
|
}
|
|
2622
|
-
function
|
|
2623
|
-
|
|
2558
|
+
function readImageDetailsCache(targetMap) {
|
|
2559
|
+
try {
|
|
2560
|
+
const jsonList = sessionStorage.getItem(
|
|
2561
|
+
STORAGE_KEY_IMAGE_DETAILS_LIST
|
|
2562
|
+
);
|
|
2563
|
+
if (!jsonList) {
|
|
2564
|
+
return;
|
|
2565
|
+
}
|
|
2566
|
+
const list = JSON.parse(jsonList);
|
|
2567
|
+
list.forEach((url) => {
|
|
2568
|
+
const json = sessionStorage.getItem(
|
|
2569
|
+
`${STORAGE_KEY_IMAGE_DETAILS_PREFIX}${url}`
|
|
2570
|
+
);
|
|
2571
|
+
if (json) {
|
|
2572
|
+
const details = JSON.parse(json);
|
|
2573
|
+
targetMap.set(url, details);
|
|
2574
|
+
}
|
|
2575
|
+
});
|
|
2576
|
+
} catch (err) {}
|
|
2624
2577
|
}
|
|
2625
|
-
function
|
|
2626
|
-
const
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2578
|
+
function writeCSSFetchCache(url, cssText) {
|
|
2579
|
+
const key = `${STORAGE_KEY_CSS_FETCH_PREFIX}${url}`;
|
|
2580
|
+
try {
|
|
2581
|
+
sessionStorage.setItem(key, cssText);
|
|
2582
|
+
} catch (err) {}
|
|
2583
|
+
}
|
|
2584
|
+
function readCSSFetchCache(url) {
|
|
2585
|
+
const key = `${STORAGE_KEY_CSS_FETCH_PREFIX}${url}`;
|
|
2586
|
+
try {
|
|
2587
|
+
return sessionStorage.getItem(key) ?? null;
|
|
2588
|
+
} catch (err) {}
|
|
2631
2589
|
return null;
|
|
2632
2590
|
}
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2591
|
+
|
|
2592
|
+
function toSVGMatrix(matrix) {
|
|
2593
|
+
return matrix
|
|
2594
|
+
.slice(0, 4)
|
|
2595
|
+
.map((m) => m.map((m) => m.toFixed(3)).join(" "))
|
|
2596
|
+
.join(" ");
|
|
2597
|
+
}
|
|
2598
|
+
function getSVGFilterMatrixValue(config) {
|
|
2599
|
+
return toSVGMatrix(createFilterMatrix(config));
|
|
2600
|
+
}
|
|
2601
|
+
|
|
2602
|
+
const MAX_FRAME_DURATION = 1000 / 60;
|
|
2603
|
+
class AsyncQueue {
|
|
2604
|
+
constructor() {
|
|
2605
|
+
this.queue = [];
|
|
2606
|
+
this.timerId = null;
|
|
2642
2607
|
}
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
variablesSheet?.cssRules[0].style.setProperty(variable, value);
|
|
2608
|
+
addTask(task) {
|
|
2609
|
+
this.queue.push(task);
|
|
2610
|
+
this.scheduleFrame();
|
|
2647
2611
|
}
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
const border = [];
|
|
2653
|
-
const text = [];
|
|
2654
|
-
registeredColors.forEach((registered) => {
|
|
2655
|
-
if (registered.background) {
|
|
2656
|
-
background.push(registered.parsed);
|
|
2657
|
-
}
|
|
2658
|
-
if (registered.border) {
|
|
2659
|
-
border.push(registered.parsed);
|
|
2612
|
+
stop() {
|
|
2613
|
+
if (this.timerId !== null) {
|
|
2614
|
+
cancelAnimationFrame(this.timerId);
|
|
2615
|
+
this.timerId = null;
|
|
2660
2616
|
}
|
|
2661
|
-
|
|
2662
|
-
|
|
2617
|
+
this.queue = [];
|
|
2618
|
+
}
|
|
2619
|
+
scheduleFrame() {
|
|
2620
|
+
if (this.timerId) {
|
|
2621
|
+
return;
|
|
2663
2622
|
}
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
|
|
2623
|
+
this.timerId = requestAnimationFrame(() => {
|
|
2624
|
+
this.timerId = null;
|
|
2625
|
+
const start = Date.now();
|
|
2626
|
+
let cb;
|
|
2627
|
+
while ((cb = this.queue.shift())) {
|
|
2628
|
+
cb();
|
|
2629
|
+
if (Date.now() - start >= MAX_FRAME_DURATION) {
|
|
2630
|
+
this.scheduleFrame();
|
|
2631
|
+
break;
|
|
2632
|
+
}
|
|
2633
|
+
}
|
|
2634
|
+
});
|
|
2635
|
+
}
|
|
2669
2636
|
}
|
|
2670
2637
|
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
function clearColorModificationCache() {
|
|
2687
|
-
colorModificationCache.clear();
|
|
2688
|
-
}
|
|
2689
|
-
const rgbCacheKeys = ["r", "g", "b", "a"];
|
|
2690
|
-
const themeCacheKeys$1 = [
|
|
2691
|
-
"mode",
|
|
2692
|
-
"brightness",
|
|
2693
|
-
"contrast",
|
|
2694
|
-
"grayscale",
|
|
2695
|
-
"sepia",
|
|
2696
|
-
"darkSchemeBackgroundColor",
|
|
2697
|
-
"darkSchemeTextColor",
|
|
2698
|
-
"lightSchemeBackgroundColor",
|
|
2699
|
-
"lightSchemeTextColor"
|
|
2700
|
-
];
|
|
2701
|
-
function getCacheId(rgb, theme) {
|
|
2702
|
-
let resultId = "";
|
|
2703
|
-
rgbCacheKeys.forEach((key) => {
|
|
2704
|
-
resultId += `${rgb[key]};`;
|
|
2638
|
+
const resolvers$1 = new Map();
|
|
2639
|
+
const rejectors = new Map();
|
|
2640
|
+
async function bgFetch(request) {
|
|
2641
|
+
if (window.DarkReader?.Plugins?.fetch) {
|
|
2642
|
+
return window.DarkReader.Plugins.fetch(request);
|
|
2643
|
+
}
|
|
2644
|
+
return new Promise((resolve, reject) => {
|
|
2645
|
+
const id = generateUID();
|
|
2646
|
+
resolvers$1.set(id, resolve);
|
|
2647
|
+
rejectors.set(id, reject);
|
|
2648
|
+
chrome.runtime.sendMessage({
|
|
2649
|
+
type: MessageTypeCStoBG.FETCH,
|
|
2650
|
+
data: request,
|
|
2651
|
+
id
|
|
2652
|
+
});
|
|
2705
2653
|
});
|
|
2706
|
-
|
|
2707
|
-
|
|
2654
|
+
}
|
|
2655
|
+
chrome.runtime.onMessage.addListener(({type, data, error, id}) => {
|
|
2656
|
+
if (type === MessageTypeBGtoCS.FETCH_RESPONSE) {
|
|
2657
|
+
const resolve = resolvers$1.get(id);
|
|
2658
|
+
const reject = rejectors.get(id);
|
|
2659
|
+
resolvers$1.delete(id);
|
|
2660
|
+
rejectors.delete(id);
|
|
2661
|
+
if (error) {
|
|
2662
|
+
reject &&
|
|
2663
|
+
reject(
|
|
2664
|
+
typeof error === "string" ? new Error(error) : error
|
|
2665
|
+
);
|
|
2666
|
+
} else {
|
|
2667
|
+
resolve && resolve(data);
|
|
2668
|
+
}
|
|
2669
|
+
}
|
|
2670
|
+
});
|
|
2671
|
+
|
|
2672
|
+
const imageManager = new AsyncQueue();
|
|
2673
|
+
async function getImageDetails(url) {
|
|
2674
|
+
return new Promise(async (resolve, reject) => {
|
|
2675
|
+
try {
|
|
2676
|
+
const dataURL = url.startsWith("data:")
|
|
2677
|
+
? url
|
|
2678
|
+
: await getDataURL(url);
|
|
2679
|
+
const blob =
|
|
2680
|
+
tryConvertDataURLToBlobSync(dataURL) ??
|
|
2681
|
+
(await loadAsBlob(url));
|
|
2682
|
+
let image;
|
|
2683
|
+
if (dataURL.startsWith("data:image/svg+xml")) {
|
|
2684
|
+
image = await loadImage(dataURL);
|
|
2685
|
+
} else {
|
|
2686
|
+
image =
|
|
2687
|
+
(await tryCreateImageBitmap(blob)) ??
|
|
2688
|
+
(await loadImage(dataURL));
|
|
2689
|
+
}
|
|
2690
|
+
imageManager.addTask(() => {
|
|
2691
|
+
const analysis = analyzeImage(image);
|
|
2692
|
+
resolve({
|
|
2693
|
+
src: url,
|
|
2694
|
+
dataURL: analysis.isLarge ? "" : dataURL,
|
|
2695
|
+
width: image.width,
|
|
2696
|
+
height: image.height,
|
|
2697
|
+
...analysis
|
|
2698
|
+
});
|
|
2699
|
+
});
|
|
2700
|
+
} catch (error) {
|
|
2701
|
+
reject(error);
|
|
2702
|
+
}
|
|
2708
2703
|
});
|
|
2709
|
-
return resultId;
|
|
2710
2704
|
}
|
|
2711
|
-
function
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
poleColor,
|
|
2716
|
-
anotherPoleColor
|
|
2717
|
-
) {
|
|
2718
|
-
let fnCache;
|
|
2719
|
-
if (colorModificationCache.has(modifyHSL)) {
|
|
2720
|
-
fnCache = colorModificationCache.get(modifyHSL);
|
|
2721
|
-
} else {
|
|
2722
|
-
fnCache = new Map();
|
|
2723
|
-
colorModificationCache.set(modifyHSL, fnCache);
|
|
2724
|
-
}
|
|
2725
|
-
const id = getCacheId(rgb, theme);
|
|
2726
|
-
if (fnCache.has(id)) {
|
|
2727
|
-
return fnCache.get(id);
|
|
2705
|
+
async function getDataURL(url) {
|
|
2706
|
+
const parsedURL = new URL(url);
|
|
2707
|
+
if (parsedURL.origin === location.origin) {
|
|
2708
|
+
return await loadAsDataURL(url);
|
|
2728
2709
|
}
|
|
2729
|
-
|
|
2730
|
-
const pole = poleColor == null ? null : parseToHSLWithCache(poleColor);
|
|
2731
|
-
const anotherPole =
|
|
2732
|
-
anotherPoleColor == null
|
|
2733
|
-
? null
|
|
2734
|
-
: parseToHSLWithCache(anotherPoleColor);
|
|
2735
|
-
const modified = modifyHSL(hsl, pole, anotherPole);
|
|
2736
|
-
const {r, g, b, a} = hslToRGB(modified);
|
|
2737
|
-
const matrix = createFilterMatrix(theme);
|
|
2738
|
-
const [rf, gf, bf] = applyColorMatrix([r, g, b], matrix);
|
|
2739
|
-
const color =
|
|
2740
|
-
a === 1
|
|
2741
|
-
? rgbToHexString({r: rf, g: gf, b: bf})
|
|
2742
|
-
: rgbToString({r: rf, g: gf, b: bf, a});
|
|
2743
|
-
fnCache.set(id, color);
|
|
2744
|
-
return color;
|
|
2710
|
+
return await bgFetch({url, responseType: "data-url"});
|
|
2745
2711
|
}
|
|
2746
|
-
function
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2712
|
+
async function tryCreateImageBitmap(blob) {
|
|
2713
|
+
try {
|
|
2714
|
+
return await createImageBitmap(blob);
|
|
2715
|
+
} catch (err) {
|
|
2716
|
+
logWarn(
|
|
2717
|
+
`Unable to create image bitmap for type ${blob.type}: ${String(err)}`
|
|
2718
|
+
);
|
|
2719
|
+
return null;
|
|
2750
2720
|
}
|
|
2751
|
-
const value = modifier(rgb, theme);
|
|
2752
|
-
return registerColor(type, rgb, value);
|
|
2753
|
-
}
|
|
2754
|
-
function modifyLightSchemeColor(rgb, theme) {
|
|
2755
|
-
const poleBg = getBgPole(theme);
|
|
2756
|
-
const poleFg = getFgPole(theme);
|
|
2757
|
-
return modifyColorWithCache(
|
|
2758
|
-
rgb,
|
|
2759
|
-
theme,
|
|
2760
|
-
modifyLightModeHSL,
|
|
2761
|
-
poleFg,
|
|
2762
|
-
poleBg
|
|
2763
|
-
);
|
|
2764
2721
|
}
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
if (isDark) {
|
|
2778
|
-
hx = poleFg.h;
|
|
2779
|
-
sx = poleFg.s;
|
|
2722
|
+
const INCOMPLETE_DOC_LOADING_IMAGE_LIMIT = 256;
|
|
2723
|
+
let loadingImagesCount = 0;
|
|
2724
|
+
async function loadImage(url) {
|
|
2725
|
+
return new Promise((resolve, reject) => {
|
|
2726
|
+
const image = new Image();
|
|
2727
|
+
image.onload = () => resolve(image);
|
|
2728
|
+
image.onerror = () => reject(`Unable to load image ${url}`);
|
|
2729
|
+
if (
|
|
2730
|
+
++loadingImagesCount <= INCOMPLETE_DOC_LOADING_IMAGE_LIMIT ||
|
|
2731
|
+
isReadyStateComplete()
|
|
2732
|
+
) {
|
|
2733
|
+
image.src = url;
|
|
2780
2734
|
} else {
|
|
2781
|
-
|
|
2782
|
-
sx = poleBg.s;
|
|
2735
|
+
addReadyStateCompleteListener(() => (image.src = url));
|
|
2783
2736
|
}
|
|
2784
|
-
}
|
|
2785
|
-
const lx = scale(l, 0, 1, poleFg.l, poleBg.l);
|
|
2786
|
-
return {h: hx, s: sx, l: lx, a};
|
|
2737
|
+
});
|
|
2787
2738
|
}
|
|
2788
|
-
const
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
const
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2739
|
+
const MAX_ANALYSIS_PIXELS_COUNT = 32 * 32;
|
|
2740
|
+
let canvas;
|
|
2741
|
+
let context;
|
|
2742
|
+
function createCanvas() {
|
|
2743
|
+
const maxWidth = MAX_ANALYSIS_PIXELS_COUNT;
|
|
2744
|
+
const maxHeight = MAX_ANALYSIS_PIXELS_COUNT;
|
|
2745
|
+
canvas = document.createElement("canvas");
|
|
2746
|
+
canvas.width = maxWidth;
|
|
2747
|
+
canvas.height = maxHeight;
|
|
2748
|
+
context = canvas.getContext("2d", {willReadFrequently: true});
|
|
2749
|
+
context.imageSmoothingEnabled = false;
|
|
2750
|
+
}
|
|
2751
|
+
function removeCanvas() {
|
|
2752
|
+
canvas = null;
|
|
2753
|
+
context = null;
|
|
2754
|
+
}
|
|
2755
|
+
const LARGE_IMAGE_PIXELS_COUNT = 512 * 512;
|
|
2756
|
+
function analyzeImage(image) {
|
|
2757
|
+
if (!canvas) {
|
|
2758
|
+
createCanvas();
|
|
2801
2759
|
}
|
|
2802
|
-
let
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2760
|
+
let sw;
|
|
2761
|
+
let sh;
|
|
2762
|
+
if (image instanceof HTMLImageElement) {
|
|
2763
|
+
sw = image.naturalWidth;
|
|
2764
|
+
sh = image.naturalHeight;
|
|
2765
|
+
} else {
|
|
2766
|
+
sw = image.width;
|
|
2767
|
+
sh = image.height;
|
|
2807
2768
|
}
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2769
|
+
if (sw === 0 || sh === 0) {
|
|
2770
|
+
logWarn("Image is empty");
|
|
2771
|
+
return {
|
|
2772
|
+
isDark: false,
|
|
2773
|
+
isLight: false,
|
|
2774
|
+
isTransparent: false,
|
|
2775
|
+
isLarge: false
|
|
2776
|
+
};
|
|
2777
|
+
}
|
|
2778
|
+
const isLarge = sw * sh > LARGE_IMAGE_PIXELS_COUNT;
|
|
2779
|
+
const sourcePixelsCount = sw * sh;
|
|
2780
|
+
const k = Math.min(
|
|
2781
|
+
1,
|
|
2782
|
+
Math.sqrt(MAX_ANALYSIS_PIXELS_COUNT / sourcePixelsCount)
|
|
2783
|
+
);
|
|
2784
|
+
const width = Math.ceil(sw * k);
|
|
2785
|
+
const height = Math.ceil(sh * k);
|
|
2786
|
+
context.clearRect(0, 0, width, height);
|
|
2787
|
+
context.drawImage(image, 0, 0, sw, sh, 0, 0, width, height);
|
|
2788
|
+
const imageData = context.getImageData(0, 0, width, height);
|
|
2789
|
+
const d = imageData.data;
|
|
2790
|
+
const TRANSPARENT_ALPHA_THRESHOLD = 0.05;
|
|
2791
|
+
const DARK_LIGHTNESS_THRESHOLD = 0.4;
|
|
2792
|
+
const LIGHT_LIGHTNESS_THRESHOLD = 0.7;
|
|
2793
|
+
let transparentPixelsCount = 0;
|
|
2794
|
+
let darkPixelsCount = 0;
|
|
2795
|
+
let lightPixelsCount = 0;
|
|
2796
|
+
let i, x, y;
|
|
2797
|
+
let r, g, b, a;
|
|
2798
|
+
let l;
|
|
2799
|
+
for (y = 0; y < height; y++) {
|
|
2800
|
+
for (x = 0; x < width; x++) {
|
|
2801
|
+
i = 4 * (y * width + x);
|
|
2802
|
+
r = d[i + 0];
|
|
2803
|
+
g = d[i + 1];
|
|
2804
|
+
b = d[i + 2];
|
|
2805
|
+
a = d[i + 3];
|
|
2806
|
+
if (a / 255 < TRANSPARENT_ALPHA_THRESHOLD) {
|
|
2807
|
+
transparentPixelsCount++;
|
|
2808
|
+
} else {
|
|
2809
|
+
l = getSRGBLightness(r, g, b);
|
|
2810
|
+
if (l < DARK_LIGHTNESS_THRESHOLD) {
|
|
2811
|
+
darkPixelsCount++;
|
|
2812
|
+
}
|
|
2813
|
+
if (l > LIGHT_LIGHTNESS_THRESHOLD) {
|
|
2814
|
+
lightPixelsCount++;
|
|
2815
|
+
}
|
|
2816
|
+
}
|
|
2816
2817
|
}
|
|
2817
2818
|
}
|
|
2818
|
-
|
|
2819
|
-
|
|
2819
|
+
const totalPixelsCount = width * height;
|
|
2820
|
+
const opaquePixelsCount = totalPixelsCount - transparentPixelsCount;
|
|
2821
|
+
const DARK_IMAGE_THRESHOLD = 0.7;
|
|
2822
|
+
const LIGHT_IMAGE_THRESHOLD = 0.7;
|
|
2823
|
+
const TRANSPARENT_IMAGE_THRESHOLD = 0.1;
|
|
2824
|
+
return {
|
|
2825
|
+
isDark: darkPixelsCount / opaquePixelsCount >= DARK_IMAGE_THRESHOLD,
|
|
2826
|
+
isLight:
|
|
2827
|
+
lightPixelsCount / opaquePixelsCount >= LIGHT_IMAGE_THRESHOLD,
|
|
2828
|
+
isTransparent:
|
|
2829
|
+
transparentPixelsCount / totalPixelsCount >=
|
|
2830
|
+
TRANSPARENT_IMAGE_THRESHOLD,
|
|
2831
|
+
isLarge
|
|
2832
|
+
};
|
|
2833
|
+
}
|
|
2834
|
+
let isBlobURLSupported = null;
|
|
2835
|
+
let canUseProxy = false;
|
|
2836
|
+
let blobURLCheckRequested = false;
|
|
2837
|
+
const blobURLCheckAwaiters = [];
|
|
2838
|
+
document.addEventListener(
|
|
2839
|
+
"__darkreader__inlineScriptsAllowed",
|
|
2840
|
+
() => (canUseProxy = true),
|
|
2841
|
+
{once: true}
|
|
2842
|
+
);
|
|
2843
|
+
async function requestBlobURLCheck() {
|
|
2844
|
+
if (!canUseProxy) {
|
|
2845
|
+
return;
|
|
2820
2846
|
}
|
|
2821
|
-
|
|
2847
|
+
if (blobURLCheckRequested) {
|
|
2848
|
+
return await new Promise((resolve) =>
|
|
2849
|
+
blobURLCheckAwaiters.push(resolve)
|
|
2850
|
+
);
|
|
2851
|
+
}
|
|
2852
|
+
blobURLCheckRequested = true;
|
|
2853
|
+
await new Promise((resolve) => {
|
|
2854
|
+
document.addEventListener(
|
|
2855
|
+
"__darkreader__blobURLCheckResponse",
|
|
2856
|
+
(e) => {
|
|
2857
|
+
isBlobURLSupported = e.detail.blobURLAllowed;
|
|
2858
|
+
resolve();
|
|
2859
|
+
blobURLCheckAwaiters.forEach((r) => r());
|
|
2860
|
+
blobURLCheckAwaiters.splice(0);
|
|
2861
|
+
},
|
|
2862
|
+
{once: true}
|
|
2863
|
+
);
|
|
2864
|
+
document.dispatchEvent(
|
|
2865
|
+
new CustomEvent("__darkreader__blobURLCheckRequest")
|
|
2866
|
+
);
|
|
2867
|
+
});
|
|
2822
2868
|
}
|
|
2823
|
-
function
|
|
2824
|
-
|
|
2825
|
-
return modifyLightSchemeColor(rgb, theme);
|
|
2826
|
-
}
|
|
2827
|
-
const pole = getBgPole(theme);
|
|
2828
|
-
return modifyColorWithCache(
|
|
2829
|
-
rgb,
|
|
2830
|
-
{...theme, mode: 0},
|
|
2831
|
-
modifyBgHSL,
|
|
2832
|
-
pole
|
|
2833
|
-
);
|
|
2869
|
+
function isBlobURLCheckResultReady() {
|
|
2870
|
+
return isBlobURLSupported != null || !canUseProxy;
|
|
2834
2871
|
}
|
|
2835
|
-
function
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
) {
|
|
2840
|
-
if (!shouldRegisterColorVariable) {
|
|
2841
|
-
return _modifyBackgroundColor(rgb, theme);
|
|
2872
|
+
function onCSPError(err) {
|
|
2873
|
+
if (err.blockedURI === "blob") {
|
|
2874
|
+
isBlobURLSupported = false;
|
|
2875
|
+
document.removeEventListener("securitypolicyviolation", onCSPError);
|
|
2842
2876
|
}
|
|
2843
|
-
return modifyAndRegisterColor(
|
|
2844
|
-
"background",
|
|
2845
|
-
rgb,
|
|
2846
|
-
theme,
|
|
2847
|
-
_modifyBackgroundColor
|
|
2848
|
-
);
|
|
2849
|
-
}
|
|
2850
|
-
const MIN_FG_LIGHTNESS = 0.55;
|
|
2851
|
-
function modifyBlueFgHue(hue) {
|
|
2852
|
-
return scale(hue, 205, 245, 205, 220);
|
|
2853
2877
|
}
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
const lx = scale(l, 0.5, 1, MIN_FG_LIGHTNESS, pole.l);
|
|
2860
|
-
if (isNeutral) {
|
|
2861
|
-
const hx = pole.h;
|
|
2862
|
-
const sx = pole.s;
|
|
2863
|
-
return {h: hx, s: sx, l: lx, a};
|
|
2864
|
-
}
|
|
2865
|
-
let hx = h;
|
|
2866
|
-
if (isBlue) {
|
|
2867
|
-
hx = modifyBlueFgHue(h);
|
|
2868
|
-
}
|
|
2869
|
-
return {h: hx, s, l: lx, a};
|
|
2878
|
+
document.addEventListener("securitypolicyviolation", onCSPError);
|
|
2879
|
+
const objectURLs = new Set();
|
|
2880
|
+
function getFilteredImageURL({dataURL, width, height}, theme) {
|
|
2881
|
+
if (dataURL.startsWith("data:image/svg+xml")) {
|
|
2882
|
+
dataURL = escapeXML(dataURL);
|
|
2870
2883
|
}
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2884
|
+
const matrix = getSVGFilterMatrixValue(theme);
|
|
2885
|
+
const svg = [
|
|
2886
|
+
`<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="${width}" height="${height}">`,
|
|
2887
|
+
"<defs>",
|
|
2888
|
+
'<filter id="darkreader-image-filter">',
|
|
2889
|
+
`<feColorMatrix type="matrix" values="${matrix}" />`,
|
|
2890
|
+
"</filter>",
|
|
2891
|
+
"</defs>",
|
|
2892
|
+
`<image width="${width}" height="${height}" filter="url(#darkreader-image-filter)" xlink:href="${dataURL}" />`,
|
|
2893
|
+
"</svg>"
|
|
2894
|
+
].join("");
|
|
2895
|
+
if (!isBlobURLSupported) {
|
|
2896
|
+
return `data:image/svg+xml;base64,${btoa(svg)}`;
|
|
2876
2897
|
}
|
|
2877
|
-
|
|
2878
|
-
let
|
|
2879
|
-
|
|
2880
|
-
hx = modifyBlueFgHue(h);
|
|
2881
|
-
lx = scale(l, 0, 0.5, pole.l, Math.min(1, MIN_FG_LIGHTNESS + 0.05));
|
|
2882
|
-
} else {
|
|
2883
|
-
lx = scale(l, 0, 0.5, pole.l, MIN_FG_LIGHTNESS);
|
|
2898
|
+
const bytes = new Uint8Array(svg.length);
|
|
2899
|
+
for (let i = 0; i < svg.length; i++) {
|
|
2900
|
+
bytes[i] = svg.charCodeAt(i);
|
|
2884
2901
|
}
|
|
2885
|
-
|
|
2902
|
+
const blob = new Blob([bytes], {type: "image/svg+xml"});
|
|
2903
|
+
const objectURL = URL.createObjectURL(blob);
|
|
2904
|
+
objectURLs.add(objectURL);
|
|
2905
|
+
return objectURL;
|
|
2886
2906
|
}
|
|
2887
|
-
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
pole
|
|
2897
|
-
);
|
|
2907
|
+
const xmlEscapeChars = {
|
|
2908
|
+
"<": "<",
|
|
2909
|
+
">": ">",
|
|
2910
|
+
"&": "&",
|
|
2911
|
+
"'": "'",
|
|
2912
|
+
'"': """
|
|
2913
|
+
};
|
|
2914
|
+
function escapeXML(str) {
|
|
2915
|
+
return str.replace(/[<>&'"]/g, (c) => xmlEscapeChars[c] ?? c);
|
|
2898
2916
|
}
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2917
|
+
const dataURLBlobURLs = new Map();
|
|
2918
|
+
function tryConvertDataURLToBlobSync(dataURL) {
|
|
2919
|
+
const colonIndex = dataURL.indexOf(":");
|
|
2920
|
+
const semicolonIndex = dataURL.indexOf(";", colonIndex + 1);
|
|
2921
|
+
const commaIndex = dataURL.indexOf(",", semicolonIndex + 1);
|
|
2922
|
+
const encoding = dataURL
|
|
2923
|
+
.substring(semicolonIndex + 1, commaIndex)
|
|
2924
|
+
.toLocaleLowerCase();
|
|
2925
|
+
const mediaType = dataURL.substring(colonIndex + 1, semicolonIndex);
|
|
2926
|
+
if (encoding !== "base64" || !mediaType) {
|
|
2927
|
+
return null;
|
|
2906
2928
|
}
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
_modifyForegroundColor
|
|
2912
|
-
);
|
|
2913
|
-
}
|
|
2914
|
-
function modifyBorderHSL({h, s, l, a}, poleFg, poleBg) {
|
|
2915
|
-
const isDark = l < 0.5;
|
|
2916
|
-
const isNeutral = l < 0.2 || s < 0.24;
|
|
2917
|
-
let hx = h;
|
|
2918
|
-
let sx = s;
|
|
2919
|
-
if (isNeutral) {
|
|
2920
|
-
if (isDark) {
|
|
2921
|
-
hx = poleFg.h;
|
|
2922
|
-
sx = poleFg.s;
|
|
2923
|
-
} else {
|
|
2924
|
-
hx = poleBg.h;
|
|
2925
|
-
sx = poleBg.s;
|
|
2926
|
-
}
|
|
2929
|
+
const characters = atob(dataURL.substring(commaIndex + 1));
|
|
2930
|
+
const bytes = new Uint8Array(characters.length);
|
|
2931
|
+
for (let i = 0; i < characters.length; i++) {
|
|
2932
|
+
bytes[i] = characters.charCodeAt(i);
|
|
2927
2933
|
}
|
|
2928
|
-
|
|
2929
|
-
return {h: hx, s: sx, l: lx, a};
|
|
2934
|
+
return new Blob([bytes], {type: mediaType});
|
|
2930
2935
|
}
|
|
2931
|
-
function
|
|
2932
|
-
if (
|
|
2933
|
-
return
|
|
2936
|
+
async function tryConvertDataURLToBlobURL(dataURL) {
|
|
2937
|
+
if (!isBlobURLSupported) {
|
|
2938
|
+
return null;
|
|
2934
2939
|
}
|
|
2935
|
-
const
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
{...theme, mode: 0},
|
|
2940
|
-
modifyBorderHSL,
|
|
2941
|
-
poleFg,
|
|
2942
|
-
poleBg
|
|
2943
|
-
);
|
|
2944
|
-
}
|
|
2945
|
-
function modifyBorderColor(rgb, theme, shouldRegisterColorVariable = true) {
|
|
2946
|
-
if (!shouldRegisterColorVariable) {
|
|
2947
|
-
return _modifyBorderColor(rgb, theme);
|
|
2940
|
+
const hash = getHashCode(dataURL);
|
|
2941
|
+
let blobURL = dataURLBlobURLs.get(hash);
|
|
2942
|
+
if (blobURL) {
|
|
2943
|
+
return blobURL;
|
|
2948
2944
|
}
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
|
|
2945
|
+
let blob = tryConvertDataURLToBlobSync(dataURL);
|
|
2946
|
+
if (!blob) {
|
|
2947
|
+
const response = await fetch(dataURL);
|
|
2948
|
+
blob = await response.blob();
|
|
2949
|
+
}
|
|
2950
|
+
blobURL = URL.createObjectURL(blob);
|
|
2951
|
+
dataURLBlobURLs.set(hash, blobURL);
|
|
2952
|
+
return blobURL;
|
|
2953
2953
|
}
|
|
2954
|
-
function
|
|
2955
|
-
|
|
2954
|
+
function cleanImageProcessingCache() {
|
|
2955
|
+
imageManager && imageManager.stop();
|
|
2956
|
+
removeCanvas();
|
|
2957
|
+
objectURLs.forEach((u) => URL.revokeObjectURL(u));
|
|
2958
|
+
objectURLs.clear();
|
|
2959
|
+
dataURLBlobURLs.forEach((u) => URL.revokeObjectURL(u));
|
|
2960
|
+
dataURLBlobURLs.clear();
|
|
2956
2961
|
}
|
|
2957
2962
|
|
|
2958
2963
|
function getPriority(ruleStyle, property) {
|
|
@@ -3223,10 +3228,18 @@
|
|
|
3223
3228
|
"auto"
|
|
3224
3229
|
]);
|
|
3225
3230
|
function getColorModifier(prop, value, rule) {
|
|
3226
|
-
if (
|
|
3231
|
+
if (
|
|
3232
|
+
unparsableColors.has(value.toLowerCase()) &&
|
|
3233
|
+
!(prop === "color" && value === "initial")
|
|
3234
|
+
) {
|
|
3227
3235
|
return value;
|
|
3228
3236
|
}
|
|
3229
|
-
|
|
3237
|
+
let rgb = null;
|
|
3238
|
+
if (prop === "color" && value === "initial") {
|
|
3239
|
+
rgb = {r: 0, g: 0, b: 0, a: 1};
|
|
3240
|
+
} else {
|
|
3241
|
+
rgb = parseColorWithCache(value);
|
|
3242
|
+
}
|
|
3230
3243
|
if (!rgb) {
|
|
3231
3244
|
logWarn("Couldn't parse color", value);
|
|
3232
3245
|
return null;
|
|
@@ -3655,7 +3668,7 @@
|
|
|
3655
3668
|
return null;
|
|
3656
3669
|
}
|
|
3657
3670
|
return (theme) =>
|
|
3658
|
-
`${modifyForegroundColor(thumb, theme)} ${modifyBackgroundColor(
|
|
3671
|
+
`${modifyForegroundColor(thumb, theme)} ${modifyBackgroundColor(track, theme)}`;
|
|
3659
3672
|
}
|
|
3660
3673
|
function getColorSchemeModifier() {
|
|
3661
3674
|
return (theme) => (theme.mode === 0 ? "dark light" : "dark");
|
|
@@ -4014,7 +4027,7 @@
|
|
|
4014
4027
|
const modified = modify();
|
|
4015
4028
|
if (unknownVars.size > 0) {
|
|
4016
4029
|
const isFallbackResolved = modified.match(
|
|
4017
|
-
/^var\(.*?, (var\(--darkreader-bg--.*\))|(#[0-9A-Fa-f]+)|([a-z]+)|(rgba?\(.+\))|(hsla?\(.+\))\)$/
|
|
4030
|
+
/^var\(.*?, ((var\(--darkreader-bg--.*\))|(#[0-9A-Fa-f]+)|([a-z]+)|(rgba?\(.+\))|(hsla?\(.+\)))\)$/
|
|
4018
4031
|
);
|
|
4019
4032
|
if (isFallbackResolved) {
|
|
4020
4033
|
return modified;
|
|
@@ -4492,17 +4505,6 @@
|
|
|
4492
4505
|
return replaced;
|
|
4493
4506
|
}
|
|
4494
4507
|
|
|
4495
|
-
const themeCacheKeys = [
|
|
4496
|
-
"mode",
|
|
4497
|
-
"brightness",
|
|
4498
|
-
"contrast",
|
|
4499
|
-
"grayscale",
|
|
4500
|
-
"sepia",
|
|
4501
|
-
"darkSchemeBackgroundColor",
|
|
4502
|
-
"darkSchemeTextColor",
|
|
4503
|
-
"lightSchemeBackgroundColor",
|
|
4504
|
-
"lightSchemeTextColor"
|
|
4505
|
-
];
|
|
4506
4508
|
function getThemeKey(theme) {
|
|
4507
4509
|
let resultKey = "";
|
|
4508
4510
|
themeCacheKeys.forEach((key) => {
|
|
@@ -4816,6 +4818,12 @@
|
|
|
4816
4818
|
function buildStyleSheet() {
|
|
4817
4819
|
function createTarget(group, parent) {
|
|
4818
4820
|
const {rule} = group;
|
|
4821
|
+
if (isStyleRule(rule)) {
|
|
4822
|
+
const {selectorText} = rule;
|
|
4823
|
+
const index = parent.cssRules.length;
|
|
4824
|
+
parent.insertRule(`${selectorText} {}`, index);
|
|
4825
|
+
return parent.cssRules[index];
|
|
4826
|
+
}
|
|
4819
4827
|
if (isMediaRule(rule)) {
|
|
4820
4828
|
const {media} = rule;
|
|
4821
4829
|
const index = parent.cssRules.length;
|
|
@@ -5123,6 +5131,27 @@
|
|
|
5123
5131
|
return {render, destroy, commands};
|
|
5124
5132
|
}
|
|
5125
5133
|
|
|
5134
|
+
const hostsBreakingOnStylePosition = ["www.diffusioneshop.com", "zhale.me"];
|
|
5135
|
+
const mode = hostsBreakingOnStylePosition.includes(location.hostname)
|
|
5136
|
+
? "away"
|
|
5137
|
+
: "next";
|
|
5138
|
+
function getStyleInjectionMode() {
|
|
5139
|
+
return mode;
|
|
5140
|
+
}
|
|
5141
|
+
function injectStyleAway(styleElement) {
|
|
5142
|
+
let container = document.body.querySelector(
|
|
5143
|
+
".darkreader-style-container"
|
|
5144
|
+
);
|
|
5145
|
+
if (!container) {
|
|
5146
|
+
container = document.createElement("div");
|
|
5147
|
+
container.classList.add("darkreader");
|
|
5148
|
+
container.classList.add("darkreader-style-container");
|
|
5149
|
+
container.style.display = "none";
|
|
5150
|
+
document.body.append(container);
|
|
5151
|
+
}
|
|
5152
|
+
container.append(styleElement);
|
|
5153
|
+
}
|
|
5154
|
+
|
|
5126
5155
|
const overrides = {
|
|
5127
5156
|
"background-color": {
|
|
5128
5157
|
customProp: "--darkreader-inline-bgcolor",
|
|
@@ -5923,22 +5952,29 @@
|
|
|
5923
5952
|
rejectorsForLoadingLinks.clear();
|
|
5924
5953
|
}
|
|
5925
5954
|
function manageStyle(element, {update, loadingStart, loadingEnd}) {
|
|
5926
|
-
const
|
|
5927
|
-
let
|
|
5928
|
-
|
|
5929
|
-
|
|
5930
|
-
|
|
5931
|
-
|
|
5932
|
-
|
|
5933
|
-
|
|
5934
|
-
|
|
5935
|
-
|
|
5936
|
-
|
|
5937
|
-
|
|
5938
|
-
|
|
5939
|
-
|
|
5940
|
-
|
|
5941
|
-
|
|
5955
|
+
const inMode = getStyleInjectionMode();
|
|
5956
|
+
let corsCopy = null;
|
|
5957
|
+
let syncStyle = null;
|
|
5958
|
+
if (inMode === "next") {
|
|
5959
|
+
const prevStyles = [];
|
|
5960
|
+
let next = element;
|
|
5961
|
+
while (
|
|
5962
|
+
(next = next.nextElementSibling) &&
|
|
5963
|
+
next.matches(".darkreader")
|
|
5964
|
+
) {
|
|
5965
|
+
prevStyles.push(next);
|
|
5966
|
+
}
|
|
5967
|
+
corsCopy =
|
|
5968
|
+
prevStyles.find(
|
|
5969
|
+
(el) =>
|
|
5970
|
+
el.matches(".darkreader--cors") && !corsStyleSet.has(el)
|
|
5971
|
+
) || null;
|
|
5972
|
+
syncStyle =
|
|
5973
|
+
prevStyles.find(
|
|
5974
|
+
(el) =>
|
|
5975
|
+
el.matches(".darkreader--sync") && !syncStyleSet.has(el)
|
|
5976
|
+
) || null;
|
|
5977
|
+
}
|
|
5942
5978
|
let corsCopyPositionWatcher = null;
|
|
5943
5979
|
let syncStylePositionWatcher = null;
|
|
5944
5980
|
let cancelAsyncOperations = false;
|
|
@@ -6023,21 +6059,31 @@
|
|
|
6023
6059
|
return cssRules;
|
|
6024
6060
|
}
|
|
6025
6061
|
function insertStyle() {
|
|
6026
|
-
if (
|
|
6027
|
-
if (
|
|
6062
|
+
if (inMode === "next") {
|
|
6063
|
+
if (corsCopy) {
|
|
6064
|
+
if (element.nextSibling !== corsCopy) {
|
|
6065
|
+
element.parentNode.insertBefore(
|
|
6066
|
+
corsCopy,
|
|
6067
|
+
element.nextSibling
|
|
6068
|
+
);
|
|
6069
|
+
}
|
|
6070
|
+
if (corsCopy.nextSibling !== syncStyle) {
|
|
6071
|
+
element.parentNode.insertBefore(
|
|
6072
|
+
syncStyle,
|
|
6073
|
+
corsCopy.nextSibling
|
|
6074
|
+
);
|
|
6075
|
+
}
|
|
6076
|
+
} else if (element.nextSibling !== syncStyle) {
|
|
6028
6077
|
element.parentNode.insertBefore(
|
|
6029
|
-
|
|
6078
|
+
syncStyle,
|
|
6030
6079
|
element.nextSibling
|
|
6031
6080
|
);
|
|
6032
6081
|
}
|
|
6033
|
-
|
|
6034
|
-
|
|
6035
|
-
|
|
6036
|
-
corsCopy.nextSibling
|
|
6037
|
-
);
|
|
6082
|
+
} else if (inMode === "away") {
|
|
6083
|
+
if (corsCopy && !corsCopy.parentNode) {
|
|
6084
|
+
injectStyleAway(corsCopy);
|
|
6038
6085
|
}
|
|
6039
|
-
|
|
6040
|
-
element.parentNode.insertBefore(syncStyle, element.nextSibling);
|
|
6086
|
+
injectStyleAway(syncStyle);
|
|
6041
6087
|
}
|
|
6042
6088
|
}
|
|
6043
6089
|
function createSyncStyle() {
|
|
@@ -6095,7 +6141,12 @@
|
|
|
6095
6141
|
return cssRules;
|
|
6096
6142
|
}
|
|
6097
6143
|
}
|
|
6098
|
-
|
|
6144
|
+
try {
|
|
6145
|
+
cssText = await loadText(element.href);
|
|
6146
|
+
} catch (err) {
|
|
6147
|
+
logWarn(err);
|
|
6148
|
+
cssText = "";
|
|
6149
|
+
}
|
|
6099
6150
|
cssBasePath = getCSSBaseBath(element.href);
|
|
6100
6151
|
if (cancelAsyncOperations) {
|
|
6101
6152
|
return null;
|
|
@@ -6127,12 +6178,31 @@
|
|
|
6127
6178
|
corsCopy.textContent = fullCSSText;
|
|
6128
6179
|
}
|
|
6129
6180
|
} else {
|
|
6130
|
-
corsCopy = createCORSCopy(
|
|
6181
|
+
corsCopy = createCORSCopy(
|
|
6182
|
+
fullCSSText,
|
|
6183
|
+
inMode === "next"
|
|
6184
|
+
? (cc) =>
|
|
6185
|
+
element.parentNode.insertBefore(
|
|
6186
|
+
cc,
|
|
6187
|
+
element.nextSibling
|
|
6188
|
+
)
|
|
6189
|
+
: injectStyleAway
|
|
6190
|
+
);
|
|
6191
|
+
if (corsCopy) {
|
|
6192
|
+
if (inMode === "next") {
|
|
6193
|
+
element.parentNode.insertBefore(
|
|
6194
|
+
corsCopy,
|
|
6195
|
+
element.nextSibling
|
|
6196
|
+
);
|
|
6197
|
+
} else if (inMode === "away") {
|
|
6198
|
+
injectStyleAway(corsCopy);
|
|
6199
|
+
}
|
|
6200
|
+
}
|
|
6131
6201
|
}
|
|
6132
6202
|
} catch (err) {
|
|
6133
6203
|
logWarn(err);
|
|
6134
6204
|
}
|
|
6135
|
-
if (corsCopy) {
|
|
6205
|
+
if (corsCopy && inMode === "next") {
|
|
6136
6206
|
corsCopyPositionWatcher = watchForNodePosition(
|
|
6137
6207
|
corsCopy,
|
|
6138
6208
|
"prev-sibling"
|
|
@@ -6199,7 +6269,7 @@
|
|
|
6199
6269
|
removeCSSRulesFromSheet(sheet);
|
|
6200
6270
|
if (syncStylePositionWatcher) {
|
|
6201
6271
|
syncStylePositionWatcher.run();
|
|
6202
|
-
} else {
|
|
6272
|
+
} else if (inMode === "next") {
|
|
6203
6273
|
syncStylePositionWatcher = watchForNodePosition(
|
|
6204
6274
|
syncStyle,
|
|
6205
6275
|
"prev-sibling",
|
|
@@ -6422,7 +6492,7 @@
|
|
|
6422
6492
|
cssText = cssText.trim();
|
|
6423
6493
|
return cssText;
|
|
6424
6494
|
}
|
|
6425
|
-
function createCORSCopy(
|
|
6495
|
+
function createCORSCopy(cssText, inject) {
|
|
6426
6496
|
if (!cssText) {
|
|
6427
6497
|
return null;
|
|
6428
6498
|
}
|
|
@@ -6431,7 +6501,7 @@
|
|
|
6431
6501
|
cors.classList.add("darkreader--cors");
|
|
6432
6502
|
cors.media = "screen";
|
|
6433
6503
|
cors.textContent = cssText;
|
|
6434
|
-
|
|
6504
|
+
inject(cors);
|
|
6435
6505
|
cors.sheet.disabled = true;
|
|
6436
6506
|
corsStyleSet.add(cors);
|
|
6437
6507
|
return cors;
|
|
@@ -7234,20 +7304,24 @@
|
|
|
7234
7304
|
let isIFrame$1 = null;
|
|
7235
7305
|
let ignoredImageAnalysisSelectors = [];
|
|
7236
7306
|
let ignoredInlineSelectors = [];
|
|
7237
|
-
|
|
7307
|
+
let staticStyleMap = new WeakMap();
|
|
7238
7308
|
function createOrUpdateStyle(className, root = document.head || document) {
|
|
7239
7309
|
let element = root.querySelector(`.${className}`);
|
|
7310
|
+
if (!staticStyleMap.has(root)) {
|
|
7311
|
+
staticStyleMap.set(root, new Map());
|
|
7312
|
+
}
|
|
7313
|
+
const classMap = staticStyleMap.get(root);
|
|
7240
7314
|
if (element) {
|
|
7241
|
-
|
|
7242
|
-
} else if (
|
|
7243
|
-
element =
|
|
7315
|
+
classMap.set(className, element);
|
|
7316
|
+
} else if (classMap.has(className)) {
|
|
7317
|
+
element = classMap.get(className);
|
|
7244
7318
|
} else {
|
|
7245
7319
|
element = document.createElement("style");
|
|
7246
7320
|
element.classList.add("darkreader");
|
|
7247
7321
|
element.classList.add(className);
|
|
7248
7322
|
element.media = "screen";
|
|
7249
7323
|
element.textContent = "";
|
|
7250
|
-
|
|
7324
|
+
classMap.set(className, element);
|
|
7251
7325
|
}
|
|
7252
7326
|
return element;
|
|
7253
7327
|
}
|
|
@@ -7273,6 +7347,18 @@
|
|
|
7273
7347
|
forEach(nodePositionWatchers.values(), (watcher) => watcher.stop());
|
|
7274
7348
|
nodePositionWatchers.clear();
|
|
7275
7349
|
}
|
|
7350
|
+
function injectStaticStyle(style, prevNode, watchAlias, callback) {
|
|
7351
|
+
const mode = getStyleInjectionMode();
|
|
7352
|
+
if (mode === "next") {
|
|
7353
|
+
document.head.insertBefore(
|
|
7354
|
+
style,
|
|
7355
|
+
prevNode ? prevNode.nextSibling : document.head.firstChild
|
|
7356
|
+
);
|
|
7357
|
+
setupNodePositionWatcher(style, watchAlias, callback);
|
|
7358
|
+
} else if (mode === "away") {
|
|
7359
|
+
injectStyleAway(style);
|
|
7360
|
+
}
|
|
7361
|
+
}
|
|
7276
7362
|
function createStaticStyleOverrides() {
|
|
7277
7363
|
const fallbackStyle = createOrUpdateStyle(
|
|
7278
7364
|
"darkreader--fallback",
|
|
@@ -7281,24 +7367,21 @@
|
|
|
7281
7367
|
fallbackStyle.textContent = getModifiedFallbackStyle(theme, {
|
|
7282
7368
|
strict: true
|
|
7283
7369
|
});
|
|
7284
|
-
|
|
7285
|
-
setupNodePositionWatcher(fallbackStyle, "fallback");
|
|
7370
|
+
injectStaticStyle(fallbackStyle, null, "fallback");
|
|
7286
7371
|
const userAgentStyle = createOrUpdateStyle("darkreader--user-agent");
|
|
7287
7372
|
userAgentStyle.textContent = getModifiedUserAgentStyle(
|
|
7288
7373
|
theme,
|
|
7289
7374
|
isIFrame$1,
|
|
7290
7375
|
theme.styleSystemControls
|
|
7291
7376
|
);
|
|
7292
|
-
|
|
7293
|
-
setupNodePositionWatcher(userAgentStyle, "user-agent");
|
|
7377
|
+
injectStaticStyle(userAgentStyle, fallbackStyle, "user-agent");
|
|
7294
7378
|
const textStyle = createOrUpdateStyle("darkreader--text");
|
|
7295
7379
|
if (theme.useFont || theme.textStroke > 0) {
|
|
7296
7380
|
textStyle.textContent = createTextStyle(theme);
|
|
7297
7381
|
} else {
|
|
7298
7382
|
textStyle.textContent = "";
|
|
7299
7383
|
}
|
|
7300
|
-
|
|
7301
|
-
setupNodePositionWatcher(textStyle, "text");
|
|
7384
|
+
injectStaticStyle(textStyle, userAgentStyle, "text");
|
|
7302
7385
|
const invertStyle = createOrUpdateStyle("darkreader--invert");
|
|
7303
7386
|
if (fixes && Array.isArray(fixes.invert) && fixes.invert.length > 0) {
|
|
7304
7387
|
invertStyle.textContent = [
|
|
@@ -7315,17 +7398,10 @@
|
|
|
7315
7398
|
} else {
|
|
7316
7399
|
invertStyle.textContent = "";
|
|
7317
7400
|
}
|
|
7318
|
-
|
|
7319
|
-
setupNodePositionWatcher(invertStyle, "invert");
|
|
7401
|
+
injectStaticStyle(invertStyle, textStyle, "invert");
|
|
7320
7402
|
const inlineStyle = createOrUpdateStyle("darkreader--inline");
|
|
7321
7403
|
inlineStyle.textContent = getInlineOverrideStyle();
|
|
7322
|
-
|
|
7323
|
-
setupNodePositionWatcher(inlineStyle, "inline");
|
|
7324
|
-
const overrideStyle = createOrUpdateStyle("darkreader--override");
|
|
7325
|
-
overrideStyle.textContent =
|
|
7326
|
-
fixes && fixes.css ? replaceCSSTemplates(fixes.css) : "";
|
|
7327
|
-
document.head.appendChild(overrideStyle);
|
|
7328
|
-
setupNodePositionWatcher(overrideStyle, "override");
|
|
7404
|
+
injectStaticStyle(inlineStyle, invertStyle, "inline");
|
|
7329
7405
|
const variableStyle = createOrUpdateStyle("darkreader--variables");
|
|
7330
7406
|
const selectionColors = theme?.selectionColor
|
|
7331
7407
|
? getSelectionColor(theme)
|
|
@@ -7346,13 +7422,12 @@
|
|
|
7346
7422
|
` --darkreader-selection-text: ${selectionColors?.foregroundColorSelection ?? "initial"};`,
|
|
7347
7423
|
`}`
|
|
7348
7424
|
].join("\n");
|
|
7349
|
-
|
|
7350
|
-
setupNodePositionWatcher(variableStyle, "variables", () =>
|
|
7425
|
+
injectStaticStyle(variableStyle, inlineStyle, "variables", () =>
|
|
7351
7426
|
registerVariablesSheet(variableStyle.sheet)
|
|
7352
7427
|
);
|
|
7353
7428
|
registerVariablesSheet(variableStyle.sheet);
|
|
7354
7429
|
const rootVarsStyle = createOrUpdateStyle("darkreader--root-vars");
|
|
7355
|
-
|
|
7430
|
+
injectStaticStyle(rootVarsStyle, variableStyle, "root-vars");
|
|
7356
7431
|
const enableStyleSheetsProxy = !(
|
|
7357
7432
|
fixes && fixes.disableStyleSheetsProxy
|
|
7358
7433
|
);
|
|
@@ -7368,6 +7443,10 @@
|
|
|
7368
7443
|
document.head.insertBefore(proxyScript, rootVarsStyle.nextSibling);
|
|
7369
7444
|
proxyScript.remove();
|
|
7370
7445
|
}
|
|
7446
|
+
const overrideStyle = createOrUpdateStyle("darkreader--override");
|
|
7447
|
+
overrideStyle.textContent =
|
|
7448
|
+
fixes && fixes.css ? replaceCSSTemplates(fixes.css) : "";
|
|
7449
|
+
injectStaticStyle(overrideStyle, document.head.lastChild, "override");
|
|
7371
7450
|
}
|
|
7372
7451
|
const shadowRootsWithOverrides = new Set();
|
|
7373
7452
|
function createShadowStaticStyleOverridesInner(root) {
|
|
@@ -7443,7 +7522,8 @@
|
|
|
7443
7522
|
}
|
|
7444
7523
|
function cleanFallbackStyle() {
|
|
7445
7524
|
const fallback =
|
|
7446
|
-
staticStyleMap.get("darkreader--fallback") ||
|
|
7525
|
+
staticStyleMap.get(document.head)?.get("darkreader--fallback") ||
|
|
7526
|
+
staticStyleMap.get(document)?.get("darkreader--fallback") ||
|
|
7447
7527
|
document.querySelector(".darkreader--fallback");
|
|
7448
7528
|
if (fallback) {
|
|
7449
7529
|
fallback.textContent = "";
|
|
@@ -7992,7 +8072,7 @@
|
|
|
7992
8072
|
selectors.forEach((selector) =>
|
|
7993
8073
|
removeNode(document.head.querySelector(selector))
|
|
7994
8074
|
);
|
|
7995
|
-
staticStyleMap
|
|
8075
|
+
staticStyleMap = new WeakMap();
|
|
7996
8076
|
removeProxy();
|
|
7997
8077
|
}
|
|
7998
8078
|
shadowRootsWithOverrides.forEach((root) => {
|