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.mjs
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
|
|
|
@@ -29,6 +29,8 @@ var MessageTypeUItoBG;
|
|
|
29
29
|
"ui-bg-apply-dev-static-themes";
|
|
30
30
|
MessageTypeUItoBG["RESET_DEV_STATIC_THEMES"] =
|
|
31
31
|
"ui-bg-reset-dev-static-themes";
|
|
32
|
+
MessageTypeUItoBG["START_ACTIVATION"] = "ui-bg-start-activation";
|
|
33
|
+
MessageTypeUItoBG["RESET_ACTIVATION"] = "ui-bg-reset-activation";
|
|
32
34
|
MessageTypeUItoBG["COLOR_SCHEME_CHANGE"] = "ui-bg-color-scheme-change";
|
|
33
35
|
MessageTypeUItoBG["HIDE_HIGHLIGHTS"] = "ui-bg-hide-highlights";
|
|
34
36
|
})(MessageTypeUItoBG || (MessageTypeUItoBG = {}));
|
|
@@ -355,9 +357,7 @@ const filterModeSites = [
|
|
|
355
357
|
];
|
|
356
358
|
({
|
|
357
359
|
customThemes: filterModeSites.map((url) => {
|
|
358
|
-
const engine =
|
|
359
|
-
? ThemeEngine.svgFilter
|
|
360
|
-
: ThemeEngine.cssFilter;
|
|
360
|
+
const engine = ThemeEngine.cssFilter;
|
|
361
361
|
return {
|
|
362
362
|
url: [url],
|
|
363
363
|
theme: {...DEFAULT_THEME, engine},
|
|
@@ -956,10 +956,16 @@ const supportedColorFuncs = [
|
|
|
956
956
|
function parse($color) {
|
|
957
957
|
const c = $color.trim().toLowerCase();
|
|
958
958
|
if (c.includes("(from ")) {
|
|
959
|
+
if (c.indexOf("(from") !== c.lastIndexOf("(from")) {
|
|
960
|
+
return null;
|
|
961
|
+
}
|
|
959
962
|
return domParseColor(c);
|
|
960
963
|
}
|
|
961
964
|
if (c.match(rgbMatch)) {
|
|
962
965
|
if (c.startsWith("rgb(#") || c.startsWith("rgba(#")) {
|
|
966
|
+
if (c.lastIndexOf("rgb") > 0) {
|
|
967
|
+
return null;
|
|
968
|
+
}
|
|
963
969
|
return domParseColor(c);
|
|
964
970
|
}
|
|
965
971
|
return parseRGB(c);
|
|
@@ -982,7 +988,10 @@ function parse($color) {
|
|
|
982
988
|
if (
|
|
983
989
|
c.endsWith(")") &&
|
|
984
990
|
supportedColorFuncs.some(
|
|
985
|
-
(fn) =>
|
|
991
|
+
(fn) =>
|
|
992
|
+
c.startsWith(fn) &&
|
|
993
|
+
c[fn.length] === "(" &&
|
|
994
|
+
c.lastIndexOf(fn) === 0
|
|
986
995
|
)
|
|
987
996
|
) {
|
|
988
997
|
return domParseColor(c);
|
|
@@ -1798,6 +1807,9 @@ function iterateCSSRules(rules, iterate, onImportError) {
|
|
|
1798
1807
|
forEach(rules, (rule) => {
|
|
1799
1808
|
if (isStyleRule(rule)) {
|
|
1800
1809
|
iterate(rule);
|
|
1810
|
+
if (rule.cssRules?.length > 0) {
|
|
1811
|
+
iterateCSSRules(rule.cssRules, iterate);
|
|
1812
|
+
}
|
|
1801
1813
|
} else if (isImportRule(rule)) {
|
|
1802
1814
|
try {
|
|
1803
1815
|
iterateCSSRules(
|
|
@@ -2055,817 +2067,812 @@ function getSheetScope(sheet) {
|
|
|
2055
2067
|
return null;
|
|
2056
2068
|
}
|
|
2057
2069
|
|
|
2058
|
-
|
|
2059
|
-
const
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
const
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
let typeGradient;
|
|
2069
|
-
[linearGradient, radialGradient, conicGradient].find((possibleType) => {
|
|
2070
|
-
if (index - possibleType.length >= 0) {
|
|
2071
|
-
const possibleGradient = value.substring(
|
|
2072
|
-
index - possibleType.length,
|
|
2073
|
-
index
|
|
2074
|
-
);
|
|
2075
|
-
if (possibleGradient === possibleType) {
|
|
2076
|
-
if (
|
|
2077
|
-
value.slice(
|
|
2078
|
-
index - possibleType.length - 10,
|
|
2079
|
-
index - possibleType.length - 1
|
|
2080
|
-
) === "repeating"
|
|
2081
|
-
) {
|
|
2082
|
-
typeGradient = `repeating-${possibleType}gradient`;
|
|
2083
|
-
return true;
|
|
2084
|
-
}
|
|
2085
|
-
if (
|
|
2086
|
-
value.slice(
|
|
2087
|
-
index - possibleType.length - 8,
|
|
2088
|
-
index - possibleType.length - 1
|
|
2089
|
-
) === "-webkit"
|
|
2090
|
-
) {
|
|
2091
|
-
typeGradient = `-webkit-${possibleType}gradient`;
|
|
2092
|
-
return true;
|
|
2093
|
-
}
|
|
2094
|
-
typeGradient = `${possibleType}gradient`;
|
|
2095
|
-
return true;
|
|
2096
|
-
}
|
|
2070
|
+
let variablesSheet;
|
|
2071
|
+
const registeredColors = new Map();
|
|
2072
|
+
function registerVariablesSheet(sheet) {
|
|
2073
|
+
variablesSheet = sheet;
|
|
2074
|
+
const types = ["background", "text", "border"];
|
|
2075
|
+
registeredColors.forEach((registered) => {
|
|
2076
|
+
types.forEach((type) => {
|
|
2077
|
+
if (registered[type]) {
|
|
2078
|
+
const {variable, value} = registered[type];
|
|
2079
|
+
variablesSheet?.cssRules[0].style.setProperty(variable, value);
|
|
2097
2080
|
}
|
|
2098
2081
|
});
|
|
2099
|
-
if (!typeGradient) {
|
|
2100
|
-
break;
|
|
2101
|
-
}
|
|
2102
|
-
const {start, end} = getParenthesesRange(value, index + gradientLength);
|
|
2103
|
-
const match = value.substring(start + 1, end - 1);
|
|
2104
|
-
startIndex = end + 1 + conicGradientLength;
|
|
2105
|
-
result.push({
|
|
2106
|
-
typeGradient,
|
|
2107
|
-
match,
|
|
2108
|
-
offset: typeGradient.length + 2,
|
|
2109
|
-
index: index - typeGradient.length + gradientLength,
|
|
2110
|
-
hasComma: true
|
|
2111
|
-
});
|
|
2112
|
-
}
|
|
2113
|
-
if (result.length) {
|
|
2114
|
-
result[result.length - 1].hasComma = false;
|
|
2115
|
-
}
|
|
2116
|
-
return result;
|
|
2117
|
-
}
|
|
2118
|
-
|
|
2119
|
-
const STORAGE_KEY_IMAGE_DETAILS_LIST = "__darkreader__imageDetails_v2_list";
|
|
2120
|
-
const STORAGE_KEY_IMAGE_DETAILS_PREFIX = "__darkreader__imageDetails_v2_";
|
|
2121
|
-
const STORAGE_KEY_CSS_FETCH_PREFIX = "__darkreader__cssFetch_";
|
|
2122
|
-
let imageCacheTimeout = 0;
|
|
2123
|
-
const imageDetailsCacheQueue = new Map();
|
|
2124
|
-
const cachedImageUrls = [];
|
|
2125
|
-
function writeImageDetailsQueue() {
|
|
2126
|
-
imageDetailsCacheQueue.forEach((details, url) => {
|
|
2127
|
-
if (url && url.startsWith("https://")) {
|
|
2128
|
-
try {
|
|
2129
|
-
const json = JSON.stringify(details);
|
|
2130
|
-
sessionStorage.setItem(
|
|
2131
|
-
`${STORAGE_KEY_IMAGE_DETAILS_PREFIX}${url}`,
|
|
2132
|
-
json
|
|
2133
|
-
);
|
|
2134
|
-
cachedImageUrls.push(url);
|
|
2135
|
-
} catch (err) {}
|
|
2136
|
-
}
|
|
2137
2082
|
});
|
|
2138
|
-
imageDetailsCacheQueue.clear();
|
|
2139
|
-
sessionStorage.setItem(
|
|
2140
|
-
STORAGE_KEY_IMAGE_DETAILS_LIST,
|
|
2141
|
-
JSON.stringify(cachedImageUrls)
|
|
2142
|
-
);
|
|
2143
|
-
}
|
|
2144
|
-
function writeImageDetailsCache(url, imageDetails) {
|
|
2145
|
-
if (!url || !url.startsWith("https://")) {
|
|
2146
|
-
return;
|
|
2147
|
-
}
|
|
2148
|
-
imageDetailsCacheQueue.set(url, imageDetails);
|
|
2149
|
-
clearTimeout(imageCacheTimeout);
|
|
2150
|
-
imageCacheTimeout = setTimeout(writeImageDetailsQueue, 1000);
|
|
2151
2083
|
}
|
|
2152
|
-
function
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
if (!jsonList) {
|
|
2156
|
-
return;
|
|
2157
|
-
}
|
|
2158
|
-
const list = JSON.parse(jsonList);
|
|
2159
|
-
list.forEach((url) => {
|
|
2160
|
-
const json = sessionStorage.getItem(
|
|
2161
|
-
`${STORAGE_KEY_IMAGE_DETAILS_PREFIX}${url}`
|
|
2162
|
-
);
|
|
2163
|
-
if (json) {
|
|
2164
|
-
const details = JSON.parse(json);
|
|
2165
|
-
targetMap.set(url, details);
|
|
2166
|
-
}
|
|
2167
|
-
});
|
|
2168
|
-
} catch (err) {}
|
|
2084
|
+
function releaseVariablesSheet() {
|
|
2085
|
+
variablesSheet = null;
|
|
2086
|
+
clearColorPalette();
|
|
2169
2087
|
}
|
|
2170
|
-
function
|
|
2171
|
-
|
|
2172
|
-
try {
|
|
2173
|
-
sessionStorage.setItem(key, cssText);
|
|
2174
|
-
} catch (err) {}
|
|
2088
|
+
function getRegisteredVariableValue(type, registered) {
|
|
2089
|
+
return `var(${registered[type].variable}, ${registered[type].value})`;
|
|
2175
2090
|
}
|
|
2176
|
-
function
|
|
2177
|
-
const
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2091
|
+
function getRegisteredColor(type, parsed) {
|
|
2092
|
+
const hex = rgbToHexString(parsed);
|
|
2093
|
+
const registered = registeredColors.get(hex);
|
|
2094
|
+
if (registered?.[type]) {
|
|
2095
|
+
return getRegisteredVariableValue(type, registered);
|
|
2096
|
+
}
|
|
2181
2097
|
return null;
|
|
2182
2098
|
}
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
}
|
|
2193
|
-
|
|
2194
|
-
const MAX_FRAME_DURATION = 1000 / 60;
|
|
2195
|
-
class AsyncQueue {
|
|
2196
|
-
constructor() {
|
|
2197
|
-
this.queue = [];
|
|
2198
|
-
this.timerId = null;
|
|
2099
|
+
function registerColor(type, parsed, value) {
|
|
2100
|
+
const hex = rgbToHexString(parsed);
|
|
2101
|
+
let registered;
|
|
2102
|
+
if (registeredColors.has(hex)) {
|
|
2103
|
+
registered = registeredColors.get(hex);
|
|
2104
|
+
} else {
|
|
2105
|
+
const parsed = parseColorWithCache(hex);
|
|
2106
|
+
registered = {parsed};
|
|
2107
|
+
registeredColors.set(hex, registered);
|
|
2199
2108
|
}
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2109
|
+
const variable = `--darkreader-${type}-${hex.replace("#", "")}`;
|
|
2110
|
+
registered[type] = {variable, value};
|
|
2111
|
+
if (variablesSheet?.cssRules[0]?.style) {
|
|
2112
|
+
variablesSheet?.cssRules[0].style.setProperty(variable, value);
|
|
2203
2113
|
}
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2114
|
+
return getRegisteredVariableValue(type, registered);
|
|
2115
|
+
}
|
|
2116
|
+
function getColorPalette() {
|
|
2117
|
+
const background = [];
|
|
2118
|
+
const border = [];
|
|
2119
|
+
const text = [];
|
|
2120
|
+
registeredColors.forEach((registered) => {
|
|
2121
|
+
if (registered.background) {
|
|
2122
|
+
background.push(registered.parsed);
|
|
2208
2123
|
}
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
if (
|
|
2213
|
-
|
|
2124
|
+
if (registered.border) {
|
|
2125
|
+
border.push(registered.parsed);
|
|
2126
|
+
}
|
|
2127
|
+
if (registered.text) {
|
|
2128
|
+
text.push(registered.parsed);
|
|
2214
2129
|
}
|
|
2215
|
-
this.timerId = requestAnimationFrame(() => {
|
|
2216
|
-
this.timerId = null;
|
|
2217
|
-
const start = Date.now();
|
|
2218
|
-
let cb;
|
|
2219
|
-
while ((cb = this.queue.shift())) {
|
|
2220
|
-
cb();
|
|
2221
|
-
if (Date.now() - start >= MAX_FRAME_DURATION) {
|
|
2222
|
-
this.scheduleFrame();
|
|
2223
|
-
break;
|
|
2224
|
-
}
|
|
2225
|
-
}
|
|
2226
|
-
});
|
|
2227
|
-
}
|
|
2228
|
-
}
|
|
2229
|
-
|
|
2230
|
-
const resolvers$1 = new Map();
|
|
2231
|
-
const rejectors = new Map();
|
|
2232
|
-
async function bgFetch(request) {
|
|
2233
|
-
if (window.DarkReader?.Plugins?.fetch) {
|
|
2234
|
-
return window.DarkReader.Plugins.fetch(request);
|
|
2235
|
-
}
|
|
2236
|
-
return new Promise((resolve, reject) => {
|
|
2237
|
-
const id = generateUID();
|
|
2238
|
-
resolvers$1.set(id, resolve);
|
|
2239
|
-
rejectors.set(id, reject);
|
|
2240
|
-
chrome.runtime.sendMessage({
|
|
2241
|
-
type: MessageTypeCStoBG.FETCH,
|
|
2242
|
-
data: request,
|
|
2243
|
-
id
|
|
2244
|
-
});
|
|
2245
2130
|
});
|
|
2131
|
+
return {background, border, text};
|
|
2132
|
+
}
|
|
2133
|
+
function clearColorPalette() {
|
|
2134
|
+
registeredColors.clear();
|
|
2246
2135
|
}
|
|
2247
|
-
chrome.runtime.onMessage.addListener(({type, data, error, id}) => {
|
|
2248
|
-
if (type === MessageTypeBGtoCS.FETCH_RESPONSE) {
|
|
2249
|
-
const resolve = resolvers$1.get(id);
|
|
2250
|
-
const reject = rejectors.get(id);
|
|
2251
|
-
resolvers$1.delete(id);
|
|
2252
|
-
rejectors.delete(id);
|
|
2253
|
-
if (error) {
|
|
2254
|
-
reject && reject(error);
|
|
2255
|
-
} else {
|
|
2256
|
-
resolve && resolve(data);
|
|
2257
|
-
}
|
|
2258
|
-
}
|
|
2259
|
-
});
|
|
2260
2136
|
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2137
|
+
function getBgPole(theme) {
|
|
2138
|
+
const isDarkScheme = theme.mode === 1;
|
|
2139
|
+
const prop = isDarkScheme
|
|
2140
|
+
? "darkSchemeBackgroundColor"
|
|
2141
|
+
: "lightSchemeBackgroundColor";
|
|
2142
|
+
return theme[prop];
|
|
2143
|
+
}
|
|
2144
|
+
function getFgPole(theme) {
|
|
2145
|
+
const isDarkScheme = theme.mode === 1;
|
|
2146
|
+
const prop = isDarkScheme ? "darkSchemeTextColor" : "lightSchemeTextColor";
|
|
2147
|
+
return theme[prop];
|
|
2148
|
+
}
|
|
2149
|
+
const colorModificationCache = new Map();
|
|
2150
|
+
function clearColorModificationCache() {
|
|
2151
|
+
colorModificationCache.clear();
|
|
2152
|
+
}
|
|
2153
|
+
const rgbCacheKeys = ["r", "g", "b", "a"];
|
|
2154
|
+
const themeCacheKeys = [
|
|
2155
|
+
"mode",
|
|
2156
|
+
"brightness",
|
|
2157
|
+
"contrast",
|
|
2158
|
+
"grayscale",
|
|
2159
|
+
"sepia",
|
|
2160
|
+
"darkSchemeBackgroundColor",
|
|
2161
|
+
"darkSchemeTextColor",
|
|
2162
|
+
"lightSchemeBackgroundColor",
|
|
2163
|
+
"lightSchemeTextColor"
|
|
2164
|
+
];
|
|
2165
|
+
function getCacheId(rgb, theme) {
|
|
2166
|
+
let resultId = "";
|
|
2167
|
+
rgbCacheKeys.forEach((key) => {
|
|
2168
|
+
resultId += `${rgb[key]};`;
|
|
2169
|
+
});
|
|
2170
|
+
themeCacheKeys.forEach((key) => {
|
|
2171
|
+
resultId += `${theme[key]};`;
|
|
2291
2172
|
});
|
|
2173
|
+
return resultId;
|
|
2292
2174
|
}
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2175
|
+
function modifyColorWithCache(
|
|
2176
|
+
rgb,
|
|
2177
|
+
theme,
|
|
2178
|
+
modifyHSL,
|
|
2179
|
+
poleColor,
|
|
2180
|
+
anotherPoleColor
|
|
2181
|
+
) {
|
|
2182
|
+
let fnCache;
|
|
2183
|
+
if (colorModificationCache.has(modifyHSL)) {
|
|
2184
|
+
fnCache = colorModificationCache.get(modifyHSL);
|
|
2185
|
+
} else {
|
|
2186
|
+
fnCache = new Map();
|
|
2187
|
+
colorModificationCache.set(modifyHSL, fnCache);
|
|
2297
2188
|
}
|
|
2298
|
-
|
|
2189
|
+
const id = getCacheId(rgb, theme);
|
|
2190
|
+
if (fnCache.has(id)) {
|
|
2191
|
+
return fnCache.get(id);
|
|
2192
|
+
}
|
|
2193
|
+
const hsl = rgbToHSL(rgb);
|
|
2194
|
+
const pole = poleColor == null ? null : parseToHSLWithCache(poleColor);
|
|
2195
|
+
const anotherPole =
|
|
2196
|
+
anotherPoleColor == null ? null : parseToHSLWithCache(anotherPoleColor);
|
|
2197
|
+
const modified = modifyHSL(hsl, pole, anotherPole);
|
|
2198
|
+
const {r, g, b, a} = hslToRGB(modified);
|
|
2199
|
+
const matrix = createFilterMatrix({...theme, mode: 0});
|
|
2200
|
+
const [rf, gf, bf] = applyColorMatrix([r, g, b], matrix);
|
|
2201
|
+
const color =
|
|
2202
|
+
a === 1
|
|
2203
|
+
? rgbToHexString({r: rf, g: gf, b: bf})
|
|
2204
|
+
: rgbToString({r: rf, g: gf, b: bf, a});
|
|
2205
|
+
fnCache.set(id, color);
|
|
2206
|
+
return color;
|
|
2299
2207
|
}
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
logWarn(
|
|
2305
|
-
`Unable to create image bitmap for type ${blob.type}: ${String(err)}`
|
|
2306
|
-
);
|
|
2307
|
-
return null;
|
|
2208
|
+
function modifyAndRegisterColor(type, rgb, theme, modifier) {
|
|
2209
|
+
const registered = getRegisteredColor(type, rgb);
|
|
2210
|
+
if (registered) {
|
|
2211
|
+
return registered;
|
|
2308
2212
|
}
|
|
2213
|
+
const value = modifier(rgb, theme);
|
|
2214
|
+
return registerColor(type, rgb, value);
|
|
2309
2215
|
}
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
return
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2216
|
+
function modifyLightSchemeColor(rgb, theme) {
|
|
2217
|
+
const poleBg = getBgPole(theme);
|
|
2218
|
+
const poleFg = getFgPole(theme);
|
|
2219
|
+
return modifyColorWithCache(rgb, theme, modifyLightModeHSL, poleFg, poleBg);
|
|
2220
|
+
}
|
|
2221
|
+
function modifyLightModeHSL({h, s, l, a}, poleFg, poleBg) {
|
|
2222
|
+
const isDark = l < 0.5;
|
|
2223
|
+
let isNeutral;
|
|
2224
|
+
if (isDark) {
|
|
2225
|
+
isNeutral = l < 0.2 || s < 0.12;
|
|
2226
|
+
} else {
|
|
2227
|
+
const isBlue = h > 200 && h < 280;
|
|
2228
|
+
isNeutral = s < 0.24 || (l > 0.8 && isBlue);
|
|
2229
|
+
}
|
|
2230
|
+
let hx = h;
|
|
2231
|
+
let sx = s;
|
|
2232
|
+
if (isNeutral) {
|
|
2233
|
+
if (isDark) {
|
|
2234
|
+
hx = poleFg.h;
|
|
2235
|
+
sx = poleFg.s;
|
|
2322
2236
|
} else {
|
|
2323
|
-
|
|
2237
|
+
hx = poleBg.h;
|
|
2238
|
+
sx = poleBg.s;
|
|
2324
2239
|
}
|
|
2325
|
-
}
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
let canvas;
|
|
2329
|
-
let context;
|
|
2330
|
-
function createCanvas() {
|
|
2331
|
-
const maxWidth = MAX_ANALYSIS_PIXELS_COUNT;
|
|
2332
|
-
const maxHeight = MAX_ANALYSIS_PIXELS_COUNT;
|
|
2333
|
-
canvas = document.createElement("canvas");
|
|
2334
|
-
canvas.width = maxWidth;
|
|
2335
|
-
canvas.height = maxHeight;
|
|
2336
|
-
context = canvas.getContext("2d", {willReadFrequently: true});
|
|
2337
|
-
context.imageSmoothingEnabled = false;
|
|
2338
|
-
}
|
|
2339
|
-
function removeCanvas() {
|
|
2340
|
-
canvas = null;
|
|
2341
|
-
context = null;
|
|
2240
|
+
}
|
|
2241
|
+
const lx = scale(l, 0, 1, poleFg.l, poleBg.l);
|
|
2242
|
+
return {h: hx, s: sx, l: lx, a};
|
|
2342
2243
|
}
|
|
2343
|
-
const
|
|
2344
|
-
function
|
|
2345
|
-
|
|
2346
|
-
|
|
2244
|
+
const MAX_BG_LIGHTNESS = 0.4;
|
|
2245
|
+
function modifyBgHSL({h, s, l, a}, pole) {
|
|
2246
|
+
const isDark = l < 0.5;
|
|
2247
|
+
const isBlue = h > 200 && h < 280;
|
|
2248
|
+
const isNeutral = s < 0.12 || (l > 0.8 && isBlue);
|
|
2249
|
+
if (isDark) {
|
|
2250
|
+
const lx = scale(l, 0, 0.5, 0, MAX_BG_LIGHTNESS);
|
|
2251
|
+
if (isNeutral) {
|
|
2252
|
+
const hx = pole.h;
|
|
2253
|
+
const sx = pole.s;
|
|
2254
|
+
return {h: hx, s: sx, l: lx, a};
|
|
2255
|
+
}
|
|
2256
|
+
return {h, s, l: lx, a};
|
|
2347
2257
|
}
|
|
2348
|
-
let
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
} else {
|
|
2354
|
-
sw = image.width;
|
|
2355
|
-
sh = image.height;
|
|
2258
|
+
let lx = scale(l, 0.5, 1, MAX_BG_LIGHTNESS, pole.l);
|
|
2259
|
+
if (isNeutral) {
|
|
2260
|
+
const hx = pole.h;
|
|
2261
|
+
const sx = pole.s;
|
|
2262
|
+
return {h: hx, s: sx, l: lx, a};
|
|
2356
2263
|
}
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2264
|
+
let hx = h;
|
|
2265
|
+
const isYellow = h > 60 && h < 180;
|
|
2266
|
+
if (isYellow) {
|
|
2267
|
+
const isCloserToGreen = h > 120;
|
|
2268
|
+
if (isCloserToGreen) {
|
|
2269
|
+
hx = scale(h, 120, 180, 135, 180);
|
|
2270
|
+
} else {
|
|
2271
|
+
hx = scale(h, 60, 120, 60, 105);
|
|
2272
|
+
}
|
|
2365
2273
|
}
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2274
|
+
if (hx > 40 && hx < 80) {
|
|
2275
|
+
lx *= 0.75;
|
|
2276
|
+
}
|
|
2277
|
+
return {h: hx, s, l: lx, a};
|
|
2278
|
+
}
|
|
2279
|
+
function _modifyBackgroundColor(rgb, theme) {
|
|
2280
|
+
if (theme.mode === 0) {
|
|
2281
|
+
return modifyLightSchemeColor(rgb, theme);
|
|
2282
|
+
}
|
|
2283
|
+
const pole = getBgPole(theme);
|
|
2284
|
+
return modifyColorWithCache(rgb, theme, modifyBgHSL, pole);
|
|
2285
|
+
}
|
|
2286
|
+
function modifyBackgroundColor(rgb, theme, shouldRegisterColorVariable = true) {
|
|
2287
|
+
if (!shouldRegisterColorVariable) {
|
|
2288
|
+
return _modifyBackgroundColor(rgb, theme);
|
|
2289
|
+
}
|
|
2290
|
+
return modifyAndRegisterColor(
|
|
2291
|
+
"background",
|
|
2292
|
+
rgb,
|
|
2293
|
+
theme,
|
|
2294
|
+
_modifyBackgroundColor
|
|
2371
2295
|
);
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
const
|
|
2379
|
-
const
|
|
2380
|
-
const
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
g = d[i + 1];
|
|
2392
|
-
b = d[i + 2];
|
|
2393
|
-
a = d[i + 3];
|
|
2394
|
-
if (a / 255 < TRANSPARENT_ALPHA_THRESHOLD) {
|
|
2395
|
-
transparentPixelsCount++;
|
|
2396
|
-
} else {
|
|
2397
|
-
l = getSRGBLightness(r, g, b);
|
|
2398
|
-
if (l < DARK_LIGHTNESS_THRESHOLD) {
|
|
2399
|
-
darkPixelsCount++;
|
|
2400
|
-
}
|
|
2401
|
-
if (l > LIGHT_LIGHTNESS_THRESHOLD) {
|
|
2402
|
-
lightPixelsCount++;
|
|
2403
|
-
}
|
|
2404
|
-
}
|
|
2296
|
+
}
|
|
2297
|
+
const MIN_FG_LIGHTNESS = 0.55;
|
|
2298
|
+
function modifyBlueFgHue(hue) {
|
|
2299
|
+
return scale(hue, 205, 245, 205, 220);
|
|
2300
|
+
}
|
|
2301
|
+
function modifyFgHSL({h, s, l, a}, pole) {
|
|
2302
|
+
const isLight = l > 0.5;
|
|
2303
|
+
const isNeutral = l < 0.2 || s < 0.24;
|
|
2304
|
+
const isBlue = !isNeutral && h > 205 && h < 245;
|
|
2305
|
+
if (isLight) {
|
|
2306
|
+
const lx = scale(l, 0.5, 1, MIN_FG_LIGHTNESS, pole.l);
|
|
2307
|
+
if (isNeutral) {
|
|
2308
|
+
const hx = pole.h;
|
|
2309
|
+
const sx = pole.s;
|
|
2310
|
+
return {h: hx, s: sx, l: lx, a};
|
|
2311
|
+
}
|
|
2312
|
+
let hx = h;
|
|
2313
|
+
if (isBlue) {
|
|
2314
|
+
hx = modifyBlueFgHue(h);
|
|
2405
2315
|
}
|
|
2316
|
+
return {h: hx, s, l: lx, a};
|
|
2406
2317
|
}
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2318
|
+
if (isNeutral) {
|
|
2319
|
+
const hx = pole.h;
|
|
2320
|
+
const sx = pole.s;
|
|
2321
|
+
const lx = scale(l, 0, 0.5, pole.l, MIN_FG_LIGHTNESS);
|
|
2322
|
+
return {h: hx, s: sx, l: lx, a};
|
|
2323
|
+
}
|
|
2324
|
+
let hx = h;
|
|
2325
|
+
let lx;
|
|
2326
|
+
if (isBlue) {
|
|
2327
|
+
hx = modifyBlueFgHue(h);
|
|
2328
|
+
lx = scale(l, 0, 0.5, pole.l, Math.min(1, MIN_FG_LIGHTNESS + 0.05));
|
|
2329
|
+
} else {
|
|
2330
|
+
lx = scale(l, 0, 0.5, pole.l, MIN_FG_LIGHTNESS);
|
|
2331
|
+
}
|
|
2332
|
+
return {h: hx, s, l: lx, a};
|
|
2420
2333
|
}
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
const blobURLCheckAwaiters = [];
|
|
2425
|
-
document.addEventListener(
|
|
2426
|
-
"__darkreader__inlineScriptsAllowed",
|
|
2427
|
-
() => (canUseProxy = true),
|
|
2428
|
-
{once: true}
|
|
2429
|
-
);
|
|
2430
|
-
async function requestBlobURLCheck() {
|
|
2431
|
-
if (!canUseProxy) {
|
|
2432
|
-
return;
|
|
2334
|
+
function _modifyForegroundColor(rgb, theme) {
|
|
2335
|
+
if (theme.mode === 0) {
|
|
2336
|
+
return modifyLightSchemeColor(rgb, theme);
|
|
2433
2337
|
}
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2338
|
+
const pole = getFgPole(theme);
|
|
2339
|
+
return modifyColorWithCache(rgb, theme, modifyFgHSL, pole);
|
|
2340
|
+
}
|
|
2341
|
+
function modifyForegroundColor(rgb, theme, shouldRegisterColorVariable = true) {
|
|
2342
|
+
if (!shouldRegisterColorVariable) {
|
|
2343
|
+
return _modifyForegroundColor(rgb, theme);
|
|
2438
2344
|
}
|
|
2439
|
-
|
|
2440
|
-
await new Promise((resolve) => {
|
|
2441
|
-
document.addEventListener(
|
|
2442
|
-
"__darkreader__blobURLCheckResponse",
|
|
2443
|
-
(e) => {
|
|
2444
|
-
isBlobURLSupported = e.detail.blobURLAllowed;
|
|
2445
|
-
resolve();
|
|
2446
|
-
blobURLCheckAwaiters.forEach((r) => r());
|
|
2447
|
-
blobURLCheckAwaiters.splice(0);
|
|
2448
|
-
},
|
|
2449
|
-
{once: true}
|
|
2450
|
-
);
|
|
2451
|
-
document.dispatchEvent(
|
|
2452
|
-
new CustomEvent("__darkreader__blobURLCheckRequest")
|
|
2453
|
-
);
|
|
2454
|
-
});
|
|
2345
|
+
return modifyAndRegisterColor("text", rgb, theme, _modifyForegroundColor);
|
|
2455
2346
|
}
|
|
2456
|
-
function
|
|
2457
|
-
|
|
2347
|
+
function modifyBorderHSL({h, s, l, a}, poleFg, poleBg) {
|
|
2348
|
+
const isDark = l < 0.5;
|
|
2349
|
+
const isNeutral = l < 0.2 || s < 0.24;
|
|
2350
|
+
let hx = h;
|
|
2351
|
+
let sx = s;
|
|
2352
|
+
if (isNeutral) {
|
|
2353
|
+
if (isDark) {
|
|
2354
|
+
hx = poleFg.h;
|
|
2355
|
+
sx = poleFg.s;
|
|
2356
|
+
} else {
|
|
2357
|
+
hx = poleBg.h;
|
|
2358
|
+
sx = poleBg.s;
|
|
2359
|
+
}
|
|
2360
|
+
}
|
|
2361
|
+
const lx = scale(l, 0, 1, 0.5, 0.2);
|
|
2362
|
+
return {h: hx, s: sx, l: lx, a};
|
|
2458
2363
|
}
|
|
2459
|
-
function
|
|
2460
|
-
if (
|
|
2461
|
-
|
|
2462
|
-
document.removeEventListener("securitypolicyviolation", onCSPError);
|
|
2364
|
+
function _modifyBorderColor(rgb, theme) {
|
|
2365
|
+
if (theme.mode === 0) {
|
|
2366
|
+
return modifyLightSchemeColor(rgb, theme);
|
|
2463
2367
|
}
|
|
2368
|
+
const poleFg = getFgPole(theme);
|
|
2369
|
+
const poleBg = getBgPole(theme);
|
|
2370
|
+
return modifyColorWithCache(rgb, theme, modifyBorderHSL, poleFg, poleBg);
|
|
2464
2371
|
}
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
if (dataURL.startsWith("data:image/svg+xml")) {
|
|
2469
|
-
dataURL = escapeXML(dataURL);
|
|
2372
|
+
function modifyBorderColor(rgb, theme, shouldRegisterColorVariable = true) {
|
|
2373
|
+
if (!shouldRegisterColorVariable) {
|
|
2374
|
+
return _modifyBorderColor(rgb, theme);
|
|
2470
2375
|
}
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2376
|
+
return modifyAndRegisterColor("border", rgb, theme, _modifyBorderColor);
|
|
2377
|
+
}
|
|
2378
|
+
function modifyShadowColor(rgb, theme) {
|
|
2379
|
+
return modifyBackgroundColor(rgb, theme);
|
|
2380
|
+
}
|
|
2381
|
+
function modifyGradientColor(rgb, theme) {
|
|
2382
|
+
return modifyBackgroundColor(rgb, theme);
|
|
2383
|
+
}
|
|
2384
|
+
|
|
2385
|
+
const gradientLength = "gradient".length;
|
|
2386
|
+
const conicGradient = "conic-";
|
|
2387
|
+
const conicGradientLength = conicGradient.length;
|
|
2388
|
+
const radialGradient = "radial-";
|
|
2389
|
+
const linearGradient = "linear-";
|
|
2390
|
+
function parseGradient(value) {
|
|
2391
|
+
const result = [];
|
|
2392
|
+
let index = 0;
|
|
2393
|
+
let startIndex = conicGradient.length;
|
|
2394
|
+
while ((index = value.indexOf("gradient", startIndex)) !== -1) {
|
|
2395
|
+
let typeGradient;
|
|
2396
|
+
[linearGradient, radialGradient, conicGradient].find((possibleType) => {
|
|
2397
|
+
if (index - possibleType.length >= 0) {
|
|
2398
|
+
const possibleGradient = value.substring(
|
|
2399
|
+
index - possibleType.length,
|
|
2400
|
+
index
|
|
2401
|
+
);
|
|
2402
|
+
if (possibleGradient === possibleType) {
|
|
2403
|
+
if (
|
|
2404
|
+
value.slice(
|
|
2405
|
+
index - possibleType.length - 10,
|
|
2406
|
+
index - possibleType.length - 1
|
|
2407
|
+
) === "repeating"
|
|
2408
|
+
) {
|
|
2409
|
+
typeGradient = `repeating-${possibleType}gradient`;
|
|
2410
|
+
return true;
|
|
2411
|
+
}
|
|
2412
|
+
if (
|
|
2413
|
+
value.slice(
|
|
2414
|
+
index - possibleType.length - 8,
|
|
2415
|
+
index - possibleType.length - 1
|
|
2416
|
+
) === "-webkit"
|
|
2417
|
+
) {
|
|
2418
|
+
typeGradient = `-webkit-${possibleType}gradient`;
|
|
2419
|
+
return true;
|
|
2420
|
+
}
|
|
2421
|
+
typeGradient = `${possibleType}gradient`;
|
|
2422
|
+
return true;
|
|
2423
|
+
}
|
|
2424
|
+
}
|
|
2425
|
+
});
|
|
2426
|
+
if (!typeGradient) {
|
|
2427
|
+
break;
|
|
2428
|
+
}
|
|
2429
|
+
const {start, end} = getParenthesesRange(value, index + gradientLength);
|
|
2430
|
+
const match = value.substring(start + 1, end - 1);
|
|
2431
|
+
startIndex = end + 1 + conicGradientLength;
|
|
2432
|
+
result.push({
|
|
2433
|
+
typeGradient,
|
|
2434
|
+
match,
|
|
2435
|
+
offset: typeGradient.length + 2,
|
|
2436
|
+
index: index - typeGradient.length + gradientLength,
|
|
2437
|
+
hasComma: true
|
|
2438
|
+
});
|
|
2484
2439
|
}
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
bytes[i] = svg.charCodeAt(i);
|
|
2440
|
+
if (result.length) {
|
|
2441
|
+
result[result.length - 1].hasComma = false;
|
|
2488
2442
|
}
|
|
2489
|
-
|
|
2490
|
-
const objectURL = URL.createObjectURL(blob);
|
|
2491
|
-
objectURLs.add(objectURL);
|
|
2492
|
-
return objectURL;
|
|
2493
|
-
}
|
|
2494
|
-
const xmlEscapeChars = {
|
|
2495
|
-
"<": "<",
|
|
2496
|
-
">": ">",
|
|
2497
|
-
"&": "&",
|
|
2498
|
-
"'": "'",
|
|
2499
|
-
'"': """
|
|
2500
|
-
};
|
|
2501
|
-
function escapeXML(str) {
|
|
2502
|
-
return str.replace(/[<>&'"]/g, (c) => xmlEscapeChars[c] ?? c);
|
|
2443
|
+
return result;
|
|
2503
2444
|
}
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2445
|
+
|
|
2446
|
+
const STORAGE_KEY_IMAGE_DETAILS_LIST = "__darkreader__imageDetails_v2_list";
|
|
2447
|
+
const STORAGE_KEY_IMAGE_DETAILS_PREFIX = "__darkreader__imageDetails_v2_";
|
|
2448
|
+
const STORAGE_KEY_CSS_FETCH_PREFIX = "__darkreader__cssFetch_";
|
|
2449
|
+
let imageCacheTimeout = 0;
|
|
2450
|
+
const imageDetailsCacheQueue = new Map();
|
|
2451
|
+
const cachedImageUrls = [];
|
|
2452
|
+
function writeImageDetailsQueue() {
|
|
2453
|
+
imageDetailsCacheQueue.forEach((details, url) => {
|
|
2454
|
+
if (url && url.startsWith("https://")) {
|
|
2455
|
+
try {
|
|
2456
|
+
const json = JSON.stringify(details);
|
|
2457
|
+
sessionStorage.setItem(
|
|
2458
|
+
`${STORAGE_KEY_IMAGE_DETAILS_PREFIX}${url}`,
|
|
2459
|
+
json
|
|
2460
|
+
);
|
|
2461
|
+
cachedImageUrls.push(url);
|
|
2462
|
+
} catch (err) {}
|
|
2463
|
+
}
|
|
2464
|
+
});
|
|
2465
|
+
imageDetailsCacheQueue.clear();
|
|
2466
|
+
sessionStorage.setItem(
|
|
2467
|
+
STORAGE_KEY_IMAGE_DETAILS_LIST,
|
|
2468
|
+
JSON.stringify(cachedImageUrls)
|
|
2469
|
+
);
|
|
2522
2470
|
}
|
|
2523
|
-
|
|
2524
|
-
if (!
|
|
2525
|
-
return
|
|
2526
|
-
}
|
|
2527
|
-
const hash = getHashCode(dataURL);
|
|
2528
|
-
let blobURL = dataURLBlobURLs.get(hash);
|
|
2529
|
-
if (blobURL) {
|
|
2530
|
-
return blobURL;
|
|
2531
|
-
}
|
|
2532
|
-
let blob = tryConvertDataURLToBlobSync(dataURL);
|
|
2533
|
-
if (!blob) {
|
|
2534
|
-
const response = await fetch(dataURL);
|
|
2535
|
-
blob = await response.blob();
|
|
2471
|
+
function writeImageDetailsCache(url, imageDetails) {
|
|
2472
|
+
if (!url || !url.startsWith("https://")) {
|
|
2473
|
+
return;
|
|
2536
2474
|
}
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
}
|
|
2541
|
-
function cleanImageProcessingCache() {
|
|
2542
|
-
imageManager && imageManager.stop();
|
|
2543
|
-
removeCanvas();
|
|
2544
|
-
objectURLs.forEach((u) => URL.revokeObjectURL(u));
|
|
2545
|
-
objectURLs.clear();
|
|
2546
|
-
dataURLBlobURLs.forEach((u) => URL.revokeObjectURL(u));
|
|
2547
|
-
dataURLBlobURLs.clear();
|
|
2475
|
+
imageDetailsCacheQueue.set(url, imageDetails);
|
|
2476
|
+
clearTimeout(imageCacheTimeout);
|
|
2477
|
+
imageCacheTimeout = setTimeout(writeImageDetailsQueue, 1000);
|
|
2548
2478
|
}
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
const
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2479
|
+
function readImageDetailsCache(targetMap) {
|
|
2480
|
+
try {
|
|
2481
|
+
const jsonList = sessionStorage.getItem(STORAGE_KEY_IMAGE_DETAILS_LIST);
|
|
2482
|
+
if (!jsonList) {
|
|
2483
|
+
return;
|
|
2484
|
+
}
|
|
2485
|
+
const list = JSON.parse(jsonList);
|
|
2486
|
+
list.forEach((url) => {
|
|
2487
|
+
const json = sessionStorage.getItem(
|
|
2488
|
+
`${STORAGE_KEY_IMAGE_DETAILS_PREFIX}${url}`
|
|
2489
|
+
);
|
|
2490
|
+
if (json) {
|
|
2491
|
+
const details = JSON.parse(json);
|
|
2492
|
+
targetMap.set(url, details);
|
|
2560
2493
|
}
|
|
2561
2494
|
});
|
|
2562
|
-
})
|
|
2563
|
-
}
|
|
2564
|
-
function releaseVariablesSheet() {
|
|
2565
|
-
variablesSheet = null;
|
|
2566
|
-
clearColorPalette();
|
|
2495
|
+
} catch (err) {}
|
|
2567
2496
|
}
|
|
2568
|
-
function
|
|
2569
|
-
|
|
2497
|
+
function writeCSSFetchCache(url, cssText) {
|
|
2498
|
+
const key = `${STORAGE_KEY_CSS_FETCH_PREFIX}${url}`;
|
|
2499
|
+
try {
|
|
2500
|
+
sessionStorage.setItem(key, cssText);
|
|
2501
|
+
} catch (err) {}
|
|
2570
2502
|
}
|
|
2571
|
-
function
|
|
2572
|
-
const
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
}
|
|
2503
|
+
function readCSSFetchCache(url) {
|
|
2504
|
+
const key = `${STORAGE_KEY_CSS_FETCH_PREFIX}${url}`;
|
|
2505
|
+
try {
|
|
2506
|
+
return sessionStorage.getItem(key) ?? null;
|
|
2507
|
+
} catch (err) {}
|
|
2577
2508
|
return null;
|
|
2578
2509
|
}
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2510
|
+
|
|
2511
|
+
function toSVGMatrix(matrix) {
|
|
2512
|
+
return matrix
|
|
2513
|
+
.slice(0, 4)
|
|
2514
|
+
.map((m) => m.map((m) => m.toFixed(3)).join(" "))
|
|
2515
|
+
.join(" ");
|
|
2516
|
+
}
|
|
2517
|
+
function getSVGFilterMatrixValue(config) {
|
|
2518
|
+
return toSVGMatrix(createFilterMatrix(config));
|
|
2519
|
+
}
|
|
2520
|
+
|
|
2521
|
+
const MAX_FRAME_DURATION = 1000 / 60;
|
|
2522
|
+
class AsyncQueue {
|
|
2523
|
+
constructor() {
|
|
2524
|
+
this.queue = [];
|
|
2525
|
+
this.timerId = null;
|
|
2588
2526
|
}
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
variablesSheet?.cssRules[0].style.setProperty(variable, value);
|
|
2527
|
+
addTask(task) {
|
|
2528
|
+
this.queue.push(task);
|
|
2529
|
+
this.scheduleFrame();
|
|
2593
2530
|
}
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
const border = [];
|
|
2599
|
-
const text = [];
|
|
2600
|
-
registeredColors.forEach((registered) => {
|
|
2601
|
-
if (registered.background) {
|
|
2602
|
-
background.push(registered.parsed);
|
|
2531
|
+
stop() {
|
|
2532
|
+
if (this.timerId !== null) {
|
|
2533
|
+
cancelAnimationFrame(this.timerId);
|
|
2534
|
+
this.timerId = null;
|
|
2603
2535
|
}
|
|
2604
|
-
|
|
2605
|
-
|
|
2536
|
+
this.queue = [];
|
|
2537
|
+
}
|
|
2538
|
+
scheduleFrame() {
|
|
2539
|
+
if (this.timerId) {
|
|
2540
|
+
return;
|
|
2606
2541
|
}
|
|
2607
|
-
|
|
2608
|
-
|
|
2542
|
+
this.timerId = requestAnimationFrame(() => {
|
|
2543
|
+
this.timerId = null;
|
|
2544
|
+
const start = Date.now();
|
|
2545
|
+
let cb;
|
|
2546
|
+
while ((cb = this.queue.shift())) {
|
|
2547
|
+
cb();
|
|
2548
|
+
if (Date.now() - start >= MAX_FRAME_DURATION) {
|
|
2549
|
+
this.scheduleFrame();
|
|
2550
|
+
break;
|
|
2551
|
+
}
|
|
2552
|
+
}
|
|
2553
|
+
});
|
|
2554
|
+
}
|
|
2555
|
+
}
|
|
2556
|
+
|
|
2557
|
+
const resolvers$1 = new Map();
|
|
2558
|
+
const rejectors = new Map();
|
|
2559
|
+
async function bgFetch(request) {
|
|
2560
|
+
if (window.DarkReader?.Plugins?.fetch) {
|
|
2561
|
+
return window.DarkReader.Plugins.fetch(request);
|
|
2562
|
+
}
|
|
2563
|
+
return new Promise((resolve, reject) => {
|
|
2564
|
+
const id = generateUID();
|
|
2565
|
+
resolvers$1.set(id, resolve);
|
|
2566
|
+
rejectors.set(id, reject);
|
|
2567
|
+
chrome.runtime.sendMessage({
|
|
2568
|
+
type: MessageTypeCStoBG.FETCH,
|
|
2569
|
+
data: request,
|
|
2570
|
+
id
|
|
2571
|
+
});
|
|
2572
|
+
});
|
|
2573
|
+
}
|
|
2574
|
+
chrome.runtime.onMessage.addListener(({type, data, error, id}) => {
|
|
2575
|
+
if (type === MessageTypeBGtoCS.FETCH_RESPONSE) {
|
|
2576
|
+
const resolve = resolvers$1.get(id);
|
|
2577
|
+
const reject = rejectors.get(id);
|
|
2578
|
+
resolvers$1.delete(id);
|
|
2579
|
+
rejectors.delete(id);
|
|
2580
|
+
if (error) {
|
|
2581
|
+
reject &&
|
|
2582
|
+
reject(typeof error === "string" ? new Error(error) : error);
|
|
2583
|
+
} else {
|
|
2584
|
+
resolve && resolve(data);
|
|
2585
|
+
}
|
|
2586
|
+
}
|
|
2587
|
+
});
|
|
2588
|
+
|
|
2589
|
+
const imageManager = new AsyncQueue();
|
|
2590
|
+
async function getImageDetails(url) {
|
|
2591
|
+
return new Promise(async (resolve, reject) => {
|
|
2592
|
+
try {
|
|
2593
|
+
const dataURL = url.startsWith("data:")
|
|
2594
|
+
? url
|
|
2595
|
+
: await getDataURL(url);
|
|
2596
|
+
const blob =
|
|
2597
|
+
tryConvertDataURLToBlobSync(dataURL) ?? (await loadAsBlob(url));
|
|
2598
|
+
let image;
|
|
2599
|
+
if (dataURL.startsWith("data:image/svg+xml")) {
|
|
2600
|
+
image = await loadImage(dataURL);
|
|
2601
|
+
} else {
|
|
2602
|
+
image =
|
|
2603
|
+
(await tryCreateImageBitmap(blob)) ??
|
|
2604
|
+
(await loadImage(dataURL));
|
|
2605
|
+
}
|
|
2606
|
+
imageManager.addTask(() => {
|
|
2607
|
+
const analysis = analyzeImage(image);
|
|
2608
|
+
resolve({
|
|
2609
|
+
src: url,
|
|
2610
|
+
dataURL: analysis.isLarge ? "" : dataURL,
|
|
2611
|
+
width: image.width,
|
|
2612
|
+
height: image.height,
|
|
2613
|
+
...analysis
|
|
2614
|
+
});
|
|
2615
|
+
});
|
|
2616
|
+
} catch (error) {
|
|
2617
|
+
reject(error);
|
|
2609
2618
|
}
|
|
2610
2619
|
});
|
|
2611
|
-
return {background, border, text};
|
|
2612
2620
|
}
|
|
2613
|
-
function
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
const prop = isDarkScheme
|
|
2620
|
-
? "darkSchemeBackgroundColor"
|
|
2621
|
-
: "lightSchemeBackgroundColor";
|
|
2622
|
-
return theme[prop];
|
|
2623
|
-
}
|
|
2624
|
-
function getFgPole(theme) {
|
|
2625
|
-
const isDarkScheme = theme.mode === 1;
|
|
2626
|
-
const prop = isDarkScheme ? "darkSchemeTextColor" : "lightSchemeTextColor";
|
|
2627
|
-
return theme[prop];
|
|
2621
|
+
async function getDataURL(url) {
|
|
2622
|
+
const parsedURL = new URL(url);
|
|
2623
|
+
if (parsedURL.origin === location.origin) {
|
|
2624
|
+
return await loadAsDataURL(url);
|
|
2625
|
+
}
|
|
2626
|
+
return await bgFetch({url, responseType: "data-url"});
|
|
2628
2627
|
}
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2628
|
+
async function tryCreateImageBitmap(blob) {
|
|
2629
|
+
try {
|
|
2630
|
+
return await createImageBitmap(blob);
|
|
2631
|
+
} catch (err) {
|
|
2632
|
+
logWarn(
|
|
2633
|
+
`Unable to create image bitmap for type ${blob.type}: ${String(err)}`
|
|
2634
|
+
);
|
|
2635
|
+
return null;
|
|
2636
|
+
}
|
|
2632
2637
|
}
|
|
2633
|
-
const
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
resultId += `${rgb[key]};`;
|
|
2649
|
-
});
|
|
2650
|
-
themeCacheKeys$1.forEach((key) => {
|
|
2651
|
-
resultId += `${theme[key]};`;
|
|
2638
|
+
const INCOMPLETE_DOC_LOADING_IMAGE_LIMIT = 256;
|
|
2639
|
+
let loadingImagesCount = 0;
|
|
2640
|
+
async function loadImage(url) {
|
|
2641
|
+
return new Promise((resolve, reject) => {
|
|
2642
|
+
const image = new Image();
|
|
2643
|
+
image.onload = () => resolve(image);
|
|
2644
|
+
image.onerror = () => reject(`Unable to load image ${url}`);
|
|
2645
|
+
if (
|
|
2646
|
+
++loadingImagesCount <= INCOMPLETE_DOC_LOADING_IMAGE_LIMIT ||
|
|
2647
|
+
isReadyStateComplete()
|
|
2648
|
+
) {
|
|
2649
|
+
image.src = url;
|
|
2650
|
+
} else {
|
|
2651
|
+
addReadyStateCompleteListener(() => (image.src = url));
|
|
2652
|
+
}
|
|
2652
2653
|
});
|
|
2653
|
-
return resultId;
|
|
2654
|
-
}
|
|
2655
|
-
function modifyColorWithCache(
|
|
2656
|
-
rgb,
|
|
2657
|
-
theme,
|
|
2658
|
-
modifyHSL,
|
|
2659
|
-
poleColor,
|
|
2660
|
-
anotherPoleColor
|
|
2661
|
-
) {
|
|
2662
|
-
let fnCache;
|
|
2663
|
-
if (colorModificationCache.has(modifyHSL)) {
|
|
2664
|
-
fnCache = colorModificationCache.get(modifyHSL);
|
|
2665
|
-
} else {
|
|
2666
|
-
fnCache = new Map();
|
|
2667
|
-
colorModificationCache.set(modifyHSL, fnCache);
|
|
2668
|
-
}
|
|
2669
|
-
const id = getCacheId(rgb, theme);
|
|
2670
|
-
if (fnCache.has(id)) {
|
|
2671
|
-
return fnCache.get(id);
|
|
2672
|
-
}
|
|
2673
|
-
const hsl = rgbToHSL(rgb);
|
|
2674
|
-
const pole = poleColor == null ? null : parseToHSLWithCache(poleColor);
|
|
2675
|
-
const anotherPole =
|
|
2676
|
-
anotherPoleColor == null ? null : parseToHSLWithCache(anotherPoleColor);
|
|
2677
|
-
const modified = modifyHSL(hsl, pole, anotherPole);
|
|
2678
|
-
const {r, g, b, a} = hslToRGB(modified);
|
|
2679
|
-
const matrix = createFilterMatrix(theme);
|
|
2680
|
-
const [rf, gf, bf] = applyColorMatrix([r, g, b], matrix);
|
|
2681
|
-
const color =
|
|
2682
|
-
a === 1
|
|
2683
|
-
? rgbToHexString({r: rf, g: gf, b: bf})
|
|
2684
|
-
: rgbToString({r: rf, g: gf, b: bf, a});
|
|
2685
|
-
fnCache.set(id, color);
|
|
2686
|
-
return color;
|
|
2687
2654
|
}
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
const
|
|
2694
|
-
|
|
2655
|
+
const MAX_ANALYSIS_PIXELS_COUNT = 32 * 32;
|
|
2656
|
+
let canvas;
|
|
2657
|
+
let context;
|
|
2658
|
+
function createCanvas() {
|
|
2659
|
+
const maxWidth = MAX_ANALYSIS_PIXELS_COUNT;
|
|
2660
|
+
const maxHeight = MAX_ANALYSIS_PIXELS_COUNT;
|
|
2661
|
+
canvas = document.createElement("canvas");
|
|
2662
|
+
canvas.width = maxWidth;
|
|
2663
|
+
canvas.height = maxHeight;
|
|
2664
|
+
context = canvas.getContext("2d", {willReadFrequently: true});
|
|
2665
|
+
context.imageSmoothingEnabled = false;
|
|
2695
2666
|
}
|
|
2696
|
-
function
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
return modifyColorWithCache(rgb, theme, modifyLightModeHSL, poleFg, poleBg);
|
|
2667
|
+
function removeCanvas() {
|
|
2668
|
+
canvas = null;
|
|
2669
|
+
context = null;
|
|
2700
2670
|
}
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
2671
|
+
const LARGE_IMAGE_PIXELS_COUNT = 512 * 512;
|
|
2672
|
+
function analyzeImage(image) {
|
|
2673
|
+
if (!canvas) {
|
|
2674
|
+
createCanvas();
|
|
2675
|
+
}
|
|
2676
|
+
let sw;
|
|
2677
|
+
let sh;
|
|
2678
|
+
if (image instanceof HTMLImageElement) {
|
|
2679
|
+
sw = image.naturalWidth;
|
|
2680
|
+
sh = image.naturalHeight;
|
|
2706
2681
|
} else {
|
|
2707
|
-
|
|
2708
|
-
|
|
2682
|
+
sw = image.width;
|
|
2683
|
+
sh = image.height;
|
|
2709
2684
|
}
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
sx = poleBg.s;
|
|
2719
|
-
}
|
|
2685
|
+
if (sw === 0 || sh === 0) {
|
|
2686
|
+
logWarn("Image is empty");
|
|
2687
|
+
return {
|
|
2688
|
+
isDark: false,
|
|
2689
|
+
isLight: false,
|
|
2690
|
+
isTransparent: false,
|
|
2691
|
+
isLarge: false
|
|
2692
|
+
};
|
|
2720
2693
|
}
|
|
2721
|
-
const
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
const
|
|
2728
|
-
const
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
2694
|
+
const isLarge = sw * sh > LARGE_IMAGE_PIXELS_COUNT;
|
|
2695
|
+
const sourcePixelsCount = sw * sh;
|
|
2696
|
+
const k = Math.min(
|
|
2697
|
+
1,
|
|
2698
|
+
Math.sqrt(MAX_ANALYSIS_PIXELS_COUNT / sourcePixelsCount)
|
|
2699
|
+
);
|
|
2700
|
+
const width = Math.ceil(sw * k);
|
|
2701
|
+
const height = Math.ceil(sh * k);
|
|
2702
|
+
context.clearRect(0, 0, width, height);
|
|
2703
|
+
context.drawImage(image, 0, 0, sw, sh, 0, 0, width, height);
|
|
2704
|
+
const imageData = context.getImageData(0, 0, width, height);
|
|
2705
|
+
const d = imageData.data;
|
|
2706
|
+
const TRANSPARENT_ALPHA_THRESHOLD = 0.05;
|
|
2707
|
+
const DARK_LIGHTNESS_THRESHOLD = 0.4;
|
|
2708
|
+
const LIGHT_LIGHTNESS_THRESHOLD = 0.7;
|
|
2709
|
+
let transparentPixelsCount = 0;
|
|
2710
|
+
let darkPixelsCount = 0;
|
|
2711
|
+
let lightPixelsCount = 0;
|
|
2712
|
+
let i, x, y;
|
|
2713
|
+
let r, g, b, a;
|
|
2714
|
+
let l;
|
|
2715
|
+
for (y = 0; y < height; y++) {
|
|
2716
|
+
for (x = 0; x < width; x++) {
|
|
2717
|
+
i = 4 * (y * width + x);
|
|
2718
|
+
r = d[i + 0];
|
|
2719
|
+
g = d[i + 1];
|
|
2720
|
+
b = d[i + 2];
|
|
2721
|
+
a = d[i + 3];
|
|
2722
|
+
if (a / 255 < TRANSPARENT_ALPHA_THRESHOLD) {
|
|
2723
|
+
transparentPixelsCount++;
|
|
2724
|
+
} else {
|
|
2725
|
+
l = getSRGBLightness(r, g, b);
|
|
2726
|
+
if (l < DARK_LIGHTNESS_THRESHOLD) {
|
|
2727
|
+
darkPixelsCount++;
|
|
2728
|
+
}
|
|
2729
|
+
if (l > LIGHT_LIGHTNESS_THRESHOLD) {
|
|
2730
|
+
lightPixelsCount++;
|
|
2731
|
+
}
|
|
2732
|
+
}
|
|
2735
2733
|
}
|
|
2736
|
-
return {h, s, l: lx, a};
|
|
2737
|
-
}
|
|
2738
|
-
let lx = scale(l, 0.5, 1, MAX_BG_LIGHTNESS, pole.l);
|
|
2739
|
-
if (isNeutral) {
|
|
2740
|
-
const hx = pole.h;
|
|
2741
|
-
const sx = pole.s;
|
|
2742
|
-
return {h: hx, s: sx, l: lx, a};
|
|
2743
2734
|
}
|
|
2744
|
-
|
|
2745
|
-
const
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
2735
|
+
const totalPixelsCount = width * height;
|
|
2736
|
+
const opaquePixelsCount = totalPixelsCount - transparentPixelsCount;
|
|
2737
|
+
const DARK_IMAGE_THRESHOLD = 0.7;
|
|
2738
|
+
const LIGHT_IMAGE_THRESHOLD = 0.7;
|
|
2739
|
+
const TRANSPARENT_IMAGE_THRESHOLD = 0.1;
|
|
2740
|
+
return {
|
|
2741
|
+
isDark: darkPixelsCount / opaquePixelsCount >= DARK_IMAGE_THRESHOLD,
|
|
2742
|
+
isLight: lightPixelsCount / opaquePixelsCount >= LIGHT_IMAGE_THRESHOLD,
|
|
2743
|
+
isTransparent:
|
|
2744
|
+
transparentPixelsCount / totalPixelsCount >=
|
|
2745
|
+
TRANSPARENT_IMAGE_THRESHOLD,
|
|
2746
|
+
isLarge
|
|
2747
|
+
};
|
|
2748
|
+
}
|
|
2749
|
+
let isBlobURLSupported = null;
|
|
2750
|
+
let canUseProxy = false;
|
|
2751
|
+
let blobURLCheckRequested = false;
|
|
2752
|
+
const blobURLCheckAwaiters = [];
|
|
2753
|
+
document.addEventListener(
|
|
2754
|
+
"__darkreader__inlineScriptsAllowed",
|
|
2755
|
+
() => (canUseProxy = true),
|
|
2756
|
+
{once: true}
|
|
2757
|
+
);
|
|
2758
|
+
async function requestBlobURLCheck() {
|
|
2759
|
+
if (!canUseProxy) {
|
|
2760
|
+
return;
|
|
2753
2761
|
}
|
|
2754
|
-
if (
|
|
2755
|
-
|
|
2762
|
+
if (blobURLCheckRequested) {
|
|
2763
|
+
return await new Promise((resolve) =>
|
|
2764
|
+
blobURLCheckAwaiters.push(resolve)
|
|
2765
|
+
);
|
|
2756
2766
|
}
|
|
2757
|
-
|
|
2767
|
+
blobURLCheckRequested = true;
|
|
2768
|
+
await new Promise((resolve) => {
|
|
2769
|
+
document.addEventListener(
|
|
2770
|
+
"__darkreader__blobURLCheckResponse",
|
|
2771
|
+
(e) => {
|
|
2772
|
+
isBlobURLSupported = e.detail.blobURLAllowed;
|
|
2773
|
+
resolve();
|
|
2774
|
+
blobURLCheckAwaiters.forEach((r) => r());
|
|
2775
|
+
blobURLCheckAwaiters.splice(0);
|
|
2776
|
+
},
|
|
2777
|
+
{once: true}
|
|
2778
|
+
);
|
|
2779
|
+
document.dispatchEvent(
|
|
2780
|
+
new CustomEvent("__darkreader__blobURLCheckRequest")
|
|
2781
|
+
);
|
|
2782
|
+
});
|
|
2758
2783
|
}
|
|
2759
|
-
function
|
|
2760
|
-
|
|
2761
|
-
return modifyLightSchemeColor(rgb, theme);
|
|
2762
|
-
}
|
|
2763
|
-
const pole = getBgPole(theme);
|
|
2764
|
-
return modifyColorWithCache(rgb, {...theme, mode: 0}, modifyBgHSL, pole);
|
|
2784
|
+
function isBlobURLCheckResultReady() {
|
|
2785
|
+
return isBlobURLSupported != null || !canUseProxy;
|
|
2765
2786
|
}
|
|
2766
|
-
function
|
|
2767
|
-
if (
|
|
2768
|
-
|
|
2787
|
+
function onCSPError(err) {
|
|
2788
|
+
if (err.blockedURI === "blob") {
|
|
2789
|
+
isBlobURLSupported = false;
|
|
2790
|
+
document.removeEventListener("securitypolicyviolation", onCSPError);
|
|
2769
2791
|
}
|
|
2770
|
-
return modifyAndRegisterColor(
|
|
2771
|
-
"background",
|
|
2772
|
-
rgb,
|
|
2773
|
-
theme,
|
|
2774
|
-
_modifyBackgroundColor
|
|
2775
|
-
);
|
|
2776
|
-
}
|
|
2777
|
-
const MIN_FG_LIGHTNESS = 0.55;
|
|
2778
|
-
function modifyBlueFgHue(hue) {
|
|
2779
|
-
return scale(hue, 205, 245, 205, 220);
|
|
2780
2792
|
}
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
const lx = scale(l, 0.5, 1, MIN_FG_LIGHTNESS, pole.l);
|
|
2787
|
-
if (isNeutral) {
|
|
2788
|
-
const hx = pole.h;
|
|
2789
|
-
const sx = pole.s;
|
|
2790
|
-
return {h: hx, s: sx, l: lx, a};
|
|
2791
|
-
}
|
|
2792
|
-
let hx = h;
|
|
2793
|
-
if (isBlue) {
|
|
2794
|
-
hx = modifyBlueFgHue(h);
|
|
2795
|
-
}
|
|
2796
|
-
return {h: hx, s, l: lx, a};
|
|
2793
|
+
document.addEventListener("securitypolicyviolation", onCSPError);
|
|
2794
|
+
const objectURLs = new Set();
|
|
2795
|
+
function getFilteredImageURL({dataURL, width, height}, theme) {
|
|
2796
|
+
if (dataURL.startsWith("data:image/svg+xml")) {
|
|
2797
|
+
dataURL = escapeXML(dataURL);
|
|
2797
2798
|
}
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2799
|
+
const matrix = getSVGFilterMatrixValue(theme);
|
|
2800
|
+
const svg = [
|
|
2801
|
+
`<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="${width}" height="${height}">`,
|
|
2802
|
+
"<defs>",
|
|
2803
|
+
'<filter id="darkreader-image-filter">',
|
|
2804
|
+
`<feColorMatrix type="matrix" values="${matrix}" />`,
|
|
2805
|
+
"</filter>",
|
|
2806
|
+
"</defs>",
|
|
2807
|
+
`<image width="${width}" height="${height}" filter="url(#darkreader-image-filter)" xlink:href="${dataURL}" />`,
|
|
2808
|
+
"</svg>"
|
|
2809
|
+
].join("");
|
|
2810
|
+
if (!isBlobURLSupported) {
|
|
2811
|
+
return `data:image/svg+xml;base64,${btoa(svg)}`;
|
|
2803
2812
|
}
|
|
2804
|
-
|
|
2805
|
-
let
|
|
2806
|
-
|
|
2807
|
-
hx = modifyBlueFgHue(h);
|
|
2808
|
-
lx = scale(l, 0, 0.5, pole.l, Math.min(1, MIN_FG_LIGHTNESS + 0.05));
|
|
2809
|
-
} else {
|
|
2810
|
-
lx = scale(l, 0, 0.5, pole.l, MIN_FG_LIGHTNESS);
|
|
2813
|
+
const bytes = new Uint8Array(svg.length);
|
|
2814
|
+
for (let i = 0; i < svg.length; i++) {
|
|
2815
|
+
bytes[i] = svg.charCodeAt(i);
|
|
2811
2816
|
}
|
|
2812
|
-
|
|
2817
|
+
const blob = new Blob([bytes], {type: "image/svg+xml"});
|
|
2818
|
+
const objectURL = URL.createObjectURL(blob);
|
|
2819
|
+
objectURLs.add(objectURL);
|
|
2820
|
+
return objectURL;
|
|
2813
2821
|
}
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
|
|
2822
|
+
const xmlEscapeChars = {
|
|
2823
|
+
"<": "<",
|
|
2824
|
+
">": ">",
|
|
2825
|
+
"&": "&",
|
|
2826
|
+
"'": "'",
|
|
2827
|
+
'"': """
|
|
2828
|
+
};
|
|
2829
|
+
function escapeXML(str) {
|
|
2830
|
+
return str.replace(/[<>&'"]/g, (c) => xmlEscapeChars[c] ?? c);
|
|
2820
2831
|
}
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2832
|
+
const dataURLBlobURLs = new Map();
|
|
2833
|
+
function tryConvertDataURLToBlobSync(dataURL) {
|
|
2834
|
+
const colonIndex = dataURL.indexOf(":");
|
|
2835
|
+
const semicolonIndex = dataURL.indexOf(";", colonIndex + 1);
|
|
2836
|
+
const commaIndex = dataURL.indexOf(",", semicolonIndex + 1);
|
|
2837
|
+
const encoding = dataURL
|
|
2838
|
+
.substring(semicolonIndex + 1, commaIndex)
|
|
2839
|
+
.toLocaleLowerCase();
|
|
2840
|
+
const mediaType = dataURL.substring(colonIndex + 1, semicolonIndex);
|
|
2841
|
+
if (encoding !== "base64" || !mediaType) {
|
|
2842
|
+
return null;
|
|
2824
2843
|
}
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
const isNeutral = l < 0.2 || s < 0.24;
|
|
2830
|
-
let hx = h;
|
|
2831
|
-
let sx = s;
|
|
2832
|
-
if (isNeutral) {
|
|
2833
|
-
if (isDark) {
|
|
2834
|
-
hx = poleFg.h;
|
|
2835
|
-
sx = poleFg.s;
|
|
2836
|
-
} else {
|
|
2837
|
-
hx = poleBg.h;
|
|
2838
|
-
sx = poleBg.s;
|
|
2839
|
-
}
|
|
2844
|
+
const characters = atob(dataURL.substring(commaIndex + 1));
|
|
2845
|
+
const bytes = new Uint8Array(characters.length);
|
|
2846
|
+
for (let i = 0; i < characters.length; i++) {
|
|
2847
|
+
bytes[i] = characters.charCodeAt(i);
|
|
2840
2848
|
}
|
|
2841
|
-
|
|
2842
|
-
return {h: hx, s: sx, l: lx, a};
|
|
2849
|
+
return new Blob([bytes], {type: mediaType});
|
|
2843
2850
|
}
|
|
2844
|
-
function
|
|
2845
|
-
if (
|
|
2846
|
-
return
|
|
2851
|
+
async function tryConvertDataURLToBlobURL(dataURL) {
|
|
2852
|
+
if (!isBlobURLSupported) {
|
|
2853
|
+
return null;
|
|
2847
2854
|
}
|
|
2848
|
-
const
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
{...theme, mode: 0},
|
|
2853
|
-
modifyBorderHSL,
|
|
2854
|
-
poleFg,
|
|
2855
|
-
poleBg
|
|
2856
|
-
);
|
|
2857
|
-
}
|
|
2858
|
-
function modifyBorderColor(rgb, theme, shouldRegisterColorVariable = true) {
|
|
2859
|
-
if (!shouldRegisterColorVariable) {
|
|
2860
|
-
return _modifyBorderColor(rgb, theme);
|
|
2855
|
+
const hash = getHashCode(dataURL);
|
|
2856
|
+
let blobURL = dataURLBlobURLs.get(hash);
|
|
2857
|
+
if (blobURL) {
|
|
2858
|
+
return blobURL;
|
|
2861
2859
|
}
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
2860
|
+
let blob = tryConvertDataURLToBlobSync(dataURL);
|
|
2861
|
+
if (!blob) {
|
|
2862
|
+
const response = await fetch(dataURL);
|
|
2863
|
+
blob = await response.blob();
|
|
2864
|
+
}
|
|
2865
|
+
blobURL = URL.createObjectURL(blob);
|
|
2866
|
+
dataURLBlobURLs.set(hash, blobURL);
|
|
2867
|
+
return blobURL;
|
|
2866
2868
|
}
|
|
2867
|
-
function
|
|
2868
|
-
|
|
2869
|
+
function cleanImageProcessingCache() {
|
|
2870
|
+
imageManager && imageManager.stop();
|
|
2871
|
+
removeCanvas();
|
|
2872
|
+
objectURLs.forEach((u) => URL.revokeObjectURL(u));
|
|
2873
|
+
objectURLs.clear();
|
|
2874
|
+
dataURLBlobURLs.forEach((u) => URL.revokeObjectURL(u));
|
|
2875
|
+
dataURLBlobURLs.clear();
|
|
2869
2876
|
}
|
|
2870
2877
|
|
|
2871
2878
|
function getPriority(ruleStyle, property) {
|
|
@@ -3126,10 +3133,18 @@ const unparsableColors = new Set([
|
|
|
3126
3133
|
"auto"
|
|
3127
3134
|
]);
|
|
3128
3135
|
function getColorModifier(prop, value, rule) {
|
|
3129
|
-
if (
|
|
3136
|
+
if (
|
|
3137
|
+
unparsableColors.has(value.toLowerCase()) &&
|
|
3138
|
+
!(prop === "color" && value === "initial")
|
|
3139
|
+
) {
|
|
3130
3140
|
return value;
|
|
3131
3141
|
}
|
|
3132
|
-
|
|
3142
|
+
let rgb = null;
|
|
3143
|
+
if (prop === "color" && value === "initial") {
|
|
3144
|
+
rgb = {r: 0, g: 0, b: 0, a: 1};
|
|
3145
|
+
} else {
|
|
3146
|
+
rgb = parseColorWithCache(value);
|
|
3147
|
+
}
|
|
3133
3148
|
if (!rgb) {
|
|
3134
3149
|
logWarn("Couldn't parse color", value);
|
|
3135
3150
|
return null;
|
|
@@ -3531,7 +3546,7 @@ function getScrollbarColorModifier(value) {
|
|
|
3531
3546
|
return null;
|
|
3532
3547
|
}
|
|
3533
3548
|
return (theme) =>
|
|
3534
|
-
`${modifyForegroundColor(thumb, theme)} ${modifyBackgroundColor(
|
|
3549
|
+
`${modifyForegroundColor(thumb, theme)} ${modifyBackgroundColor(track, theme)}`;
|
|
3535
3550
|
}
|
|
3536
3551
|
function getColorSchemeModifier() {
|
|
3537
3552
|
return (theme) => (theme.mode === 0 ? "dark light" : "dark");
|
|
@@ -3882,7 +3897,7 @@ class VariablesStore {
|
|
|
3882
3897
|
const modified = modify();
|
|
3883
3898
|
if (unknownVars.size > 0) {
|
|
3884
3899
|
const isFallbackResolved = modified.match(
|
|
3885
|
-
/^var\(.*?, (var\(--darkreader-bg--.*\))|(#[0-9A-Fa-f]+)|([a-z]+)|(rgba?\(.+\))|(hsla?\(.+\))\)$/
|
|
3900
|
+
/^var\(.*?, ((var\(--darkreader-bg--.*\))|(#[0-9A-Fa-f]+)|([a-z]+)|(rgba?\(.+\))|(hsla?\(.+\)))\)$/
|
|
3886
3901
|
);
|
|
3887
3902
|
if (isFallbackResolved) {
|
|
3888
3903
|
return modified;
|
|
@@ -4352,17 +4367,6 @@ function insertVarValues(source, varValues, fullStack = new Set()) {
|
|
|
4352
4367
|
return replaced;
|
|
4353
4368
|
}
|
|
4354
4369
|
|
|
4355
|
-
const themeCacheKeys = [
|
|
4356
|
-
"mode",
|
|
4357
|
-
"brightness",
|
|
4358
|
-
"contrast",
|
|
4359
|
-
"grayscale",
|
|
4360
|
-
"sepia",
|
|
4361
|
-
"darkSchemeBackgroundColor",
|
|
4362
|
-
"darkSchemeTextColor",
|
|
4363
|
-
"lightSchemeBackgroundColor",
|
|
4364
|
-
"lightSchemeTextColor"
|
|
4365
|
-
];
|
|
4366
4370
|
function getThemeKey(theme) {
|
|
4367
4371
|
let resultKey = "";
|
|
4368
4372
|
themeCacheKeys.forEach((key) => {
|
|
@@ -4673,6 +4677,12 @@ function createStyleSheetModifier() {
|
|
|
4673
4677
|
function buildStyleSheet() {
|
|
4674
4678
|
function createTarget(group, parent) {
|
|
4675
4679
|
const {rule} = group;
|
|
4680
|
+
if (isStyleRule(rule)) {
|
|
4681
|
+
const {selectorText} = rule;
|
|
4682
|
+
const index = parent.cssRules.length;
|
|
4683
|
+
parent.insertRule(`${selectorText} {}`, index);
|
|
4684
|
+
return parent.cssRules[index];
|
|
4685
|
+
}
|
|
4676
4686
|
if (isMediaRule(rule)) {
|
|
4677
4687
|
const {media} = rule;
|
|
4678
4688
|
const index = parent.cssRules.length;
|
|
@@ -4973,6 +4983,25 @@ function createAdoptedStyleSheetFallback() {
|
|
|
4973
4983
|
return {render, destroy, commands};
|
|
4974
4984
|
}
|
|
4975
4985
|
|
|
4986
|
+
const hostsBreakingOnStylePosition = ["www.diffusioneshop.com", "zhale.me"];
|
|
4987
|
+
const mode = hostsBreakingOnStylePosition.includes(location.hostname)
|
|
4988
|
+
? "away"
|
|
4989
|
+
: "next";
|
|
4990
|
+
function getStyleInjectionMode() {
|
|
4991
|
+
return mode;
|
|
4992
|
+
}
|
|
4993
|
+
function injectStyleAway(styleElement) {
|
|
4994
|
+
let container = document.body.querySelector(".darkreader-style-container");
|
|
4995
|
+
if (!container) {
|
|
4996
|
+
container = document.createElement("div");
|
|
4997
|
+
container.classList.add("darkreader");
|
|
4998
|
+
container.classList.add("darkreader-style-container");
|
|
4999
|
+
container.style.display = "none";
|
|
5000
|
+
document.body.append(container);
|
|
5001
|
+
}
|
|
5002
|
+
container.append(styleElement);
|
|
5003
|
+
}
|
|
5004
|
+
|
|
4976
5005
|
const overrides = {
|
|
4977
5006
|
"background-color": {
|
|
4978
5007
|
customProp: "--darkreader-inline-bgcolor",
|
|
@@ -5738,19 +5767,27 @@ function cleanLoadingLinks() {
|
|
|
5738
5767
|
rejectorsForLoadingLinks.clear();
|
|
5739
5768
|
}
|
|
5740
5769
|
function manageStyle(element, {update, loadingStart, loadingEnd}) {
|
|
5741
|
-
const
|
|
5742
|
-
let
|
|
5743
|
-
|
|
5744
|
-
|
|
5745
|
-
|
|
5746
|
-
|
|
5747
|
-
|
|
5748
|
-
(
|
|
5749
|
-
|
|
5750
|
-
|
|
5751
|
-
|
|
5752
|
-
|
|
5753
|
-
|
|
5770
|
+
const inMode = getStyleInjectionMode();
|
|
5771
|
+
let corsCopy = null;
|
|
5772
|
+
let syncStyle = null;
|
|
5773
|
+
if (inMode === "next") {
|
|
5774
|
+
const prevStyles = [];
|
|
5775
|
+
let next = element;
|
|
5776
|
+
while (
|
|
5777
|
+
(next = next.nextElementSibling) &&
|
|
5778
|
+
next.matches(".darkreader")
|
|
5779
|
+
) {
|
|
5780
|
+
prevStyles.push(next);
|
|
5781
|
+
}
|
|
5782
|
+
corsCopy =
|
|
5783
|
+
prevStyles.find(
|
|
5784
|
+
(el) => el.matches(".darkreader--cors") && !corsStyleSet.has(el)
|
|
5785
|
+
) || null;
|
|
5786
|
+
syncStyle =
|
|
5787
|
+
prevStyles.find(
|
|
5788
|
+
(el) => el.matches(".darkreader--sync") && !syncStyleSet.has(el)
|
|
5789
|
+
) || null;
|
|
5790
|
+
}
|
|
5754
5791
|
let corsCopyPositionWatcher = null;
|
|
5755
5792
|
let syncStylePositionWatcher = null;
|
|
5756
5793
|
let cancelAsyncOperations = false;
|
|
@@ -5830,18 +5867,28 @@ function manageStyle(element, {update, loadingStart, loadingEnd}) {
|
|
|
5830
5867
|
return cssRules;
|
|
5831
5868
|
}
|
|
5832
5869
|
function insertStyle() {
|
|
5833
|
-
if (
|
|
5834
|
-
if (
|
|
5835
|
-
|
|
5870
|
+
if (inMode === "next") {
|
|
5871
|
+
if (corsCopy) {
|
|
5872
|
+
if (element.nextSibling !== corsCopy) {
|
|
5873
|
+
element.parentNode.insertBefore(
|
|
5874
|
+
corsCopy,
|
|
5875
|
+
element.nextSibling
|
|
5876
|
+
);
|
|
5877
|
+
}
|
|
5878
|
+
if (corsCopy.nextSibling !== syncStyle) {
|
|
5879
|
+
element.parentNode.insertBefore(
|
|
5880
|
+
syncStyle,
|
|
5881
|
+
corsCopy.nextSibling
|
|
5882
|
+
);
|
|
5883
|
+
}
|
|
5884
|
+
} else if (element.nextSibling !== syncStyle) {
|
|
5885
|
+
element.parentNode.insertBefore(syncStyle, element.nextSibling);
|
|
5836
5886
|
}
|
|
5837
|
-
|
|
5838
|
-
|
|
5839
|
-
|
|
5840
|
-
corsCopy.nextSibling
|
|
5841
|
-
);
|
|
5887
|
+
} else if (inMode === "away") {
|
|
5888
|
+
if (corsCopy && !corsCopy.parentNode) {
|
|
5889
|
+
injectStyleAway(corsCopy);
|
|
5842
5890
|
}
|
|
5843
|
-
|
|
5844
|
-
element.parentNode.insertBefore(syncStyle, element.nextSibling);
|
|
5891
|
+
injectStyleAway(syncStyle);
|
|
5845
5892
|
}
|
|
5846
5893
|
}
|
|
5847
5894
|
function createSyncStyle() {
|
|
@@ -5899,7 +5946,12 @@ function manageStyle(element, {update, loadingStart, loadingEnd}) {
|
|
|
5899
5946
|
return cssRules;
|
|
5900
5947
|
}
|
|
5901
5948
|
}
|
|
5902
|
-
|
|
5949
|
+
try {
|
|
5950
|
+
cssText = await loadText(element.href);
|
|
5951
|
+
} catch (err) {
|
|
5952
|
+
logWarn(err);
|
|
5953
|
+
cssText = "";
|
|
5954
|
+
}
|
|
5903
5955
|
cssBasePath = getCSSBaseBath(element.href);
|
|
5904
5956
|
if (cancelAsyncOperations) {
|
|
5905
5957
|
return null;
|
|
@@ -5930,12 +5982,31 @@ function manageStyle(element, {update, loadingStart, loadingEnd}) {
|
|
|
5930
5982
|
corsCopy.textContent = fullCSSText;
|
|
5931
5983
|
}
|
|
5932
5984
|
} else {
|
|
5933
|
-
corsCopy = createCORSCopy(
|
|
5985
|
+
corsCopy = createCORSCopy(
|
|
5986
|
+
fullCSSText,
|
|
5987
|
+
inMode === "next"
|
|
5988
|
+
? (cc) =>
|
|
5989
|
+
element.parentNode.insertBefore(
|
|
5990
|
+
cc,
|
|
5991
|
+
element.nextSibling
|
|
5992
|
+
)
|
|
5993
|
+
: injectStyleAway
|
|
5994
|
+
);
|
|
5995
|
+
if (corsCopy) {
|
|
5996
|
+
if (inMode === "next") {
|
|
5997
|
+
element.parentNode.insertBefore(
|
|
5998
|
+
corsCopy,
|
|
5999
|
+
element.nextSibling
|
|
6000
|
+
);
|
|
6001
|
+
} else if (inMode === "away") {
|
|
6002
|
+
injectStyleAway(corsCopy);
|
|
6003
|
+
}
|
|
6004
|
+
}
|
|
5934
6005
|
}
|
|
5935
6006
|
} catch (err) {
|
|
5936
6007
|
logWarn(err);
|
|
5937
6008
|
}
|
|
5938
|
-
if (corsCopy) {
|
|
6009
|
+
if (corsCopy && inMode === "next") {
|
|
5939
6010
|
corsCopyPositionWatcher = watchForNodePosition(
|
|
5940
6011
|
corsCopy,
|
|
5941
6012
|
"prev-sibling"
|
|
@@ -6002,7 +6073,7 @@ function manageStyle(element, {update, loadingStart, loadingEnd}) {
|
|
|
6002
6073
|
removeCSSRulesFromSheet(sheet);
|
|
6003
6074
|
if (syncStylePositionWatcher) {
|
|
6004
6075
|
syncStylePositionWatcher.run();
|
|
6005
|
-
} else {
|
|
6076
|
+
} else if (inMode === "next") {
|
|
6006
6077
|
syncStylePositionWatcher = watchForNodePosition(
|
|
6007
6078
|
syncStyle,
|
|
6008
6079
|
"prev-sibling",
|
|
@@ -6223,7 +6294,7 @@ async function replaceCSSImports(cssText, basePath, cache = new Map()) {
|
|
|
6223
6294
|
cssText = cssText.trim();
|
|
6224
6295
|
return cssText;
|
|
6225
6296
|
}
|
|
6226
|
-
function createCORSCopy(
|
|
6297
|
+
function createCORSCopy(cssText, inject) {
|
|
6227
6298
|
if (!cssText) {
|
|
6228
6299
|
return null;
|
|
6229
6300
|
}
|
|
@@ -6232,7 +6303,7 @@ function createCORSCopy(srcElement, cssText) {
|
|
|
6232
6303
|
cors.classList.add("darkreader--cors");
|
|
6233
6304
|
cors.media = "screen";
|
|
6234
6305
|
cors.textContent = cssText;
|
|
6235
|
-
|
|
6306
|
+
inject(cors);
|
|
6236
6307
|
cors.sheet.disabled = true;
|
|
6237
6308
|
corsStyleSet.add(cors);
|
|
6238
6309
|
return cors;
|
|
@@ -7007,20 +7078,24 @@ let fixes = null;
|
|
|
7007
7078
|
let isIFrame$1 = null;
|
|
7008
7079
|
let ignoredImageAnalysisSelectors = [];
|
|
7009
7080
|
let ignoredInlineSelectors = [];
|
|
7010
|
-
|
|
7081
|
+
let staticStyleMap = new WeakMap();
|
|
7011
7082
|
function createOrUpdateStyle(className, root = document.head || document) {
|
|
7012
7083
|
let element = root.querySelector(`.${className}`);
|
|
7084
|
+
if (!staticStyleMap.has(root)) {
|
|
7085
|
+
staticStyleMap.set(root, new Map());
|
|
7086
|
+
}
|
|
7087
|
+
const classMap = staticStyleMap.get(root);
|
|
7013
7088
|
if (element) {
|
|
7014
|
-
|
|
7015
|
-
} else if (
|
|
7016
|
-
element =
|
|
7089
|
+
classMap.set(className, element);
|
|
7090
|
+
} else if (classMap.has(className)) {
|
|
7091
|
+
element = classMap.get(className);
|
|
7017
7092
|
} else {
|
|
7018
7093
|
element = document.createElement("style");
|
|
7019
7094
|
element.classList.add("darkreader");
|
|
7020
7095
|
element.classList.add(className);
|
|
7021
7096
|
element.media = "screen";
|
|
7022
7097
|
element.textContent = "";
|
|
7023
|
-
|
|
7098
|
+
classMap.set(className, element);
|
|
7024
7099
|
}
|
|
7025
7100
|
return element;
|
|
7026
7101
|
}
|
|
@@ -7045,27 +7120,36 @@ function stopStylePositionWatchers() {
|
|
|
7045
7120
|
forEach(nodePositionWatchers.values(), (watcher) => watcher.stop());
|
|
7046
7121
|
nodePositionWatchers.clear();
|
|
7047
7122
|
}
|
|
7123
|
+
function injectStaticStyle(style, prevNode, watchAlias, callback) {
|
|
7124
|
+
const mode = getStyleInjectionMode();
|
|
7125
|
+
if (mode === "next") {
|
|
7126
|
+
document.head.insertBefore(
|
|
7127
|
+
style,
|
|
7128
|
+
prevNode ? prevNode.nextSibling : document.head.firstChild
|
|
7129
|
+
);
|
|
7130
|
+
setupNodePositionWatcher(style, watchAlias, callback);
|
|
7131
|
+
} else if (mode === "away") {
|
|
7132
|
+
injectStyleAway(style);
|
|
7133
|
+
}
|
|
7134
|
+
}
|
|
7048
7135
|
function createStaticStyleOverrides() {
|
|
7049
7136
|
const fallbackStyle = createOrUpdateStyle("darkreader--fallback", document);
|
|
7050
7137
|
fallbackStyle.textContent = getModifiedFallbackStyle(theme, {strict: true});
|
|
7051
|
-
|
|
7052
|
-
setupNodePositionWatcher(fallbackStyle, "fallback");
|
|
7138
|
+
injectStaticStyle(fallbackStyle, null, "fallback");
|
|
7053
7139
|
const userAgentStyle = createOrUpdateStyle("darkreader--user-agent");
|
|
7054
7140
|
userAgentStyle.textContent = getModifiedUserAgentStyle(
|
|
7055
7141
|
theme,
|
|
7056
7142
|
isIFrame$1,
|
|
7057
7143
|
theme.styleSystemControls
|
|
7058
7144
|
);
|
|
7059
|
-
|
|
7060
|
-
setupNodePositionWatcher(userAgentStyle, "user-agent");
|
|
7145
|
+
injectStaticStyle(userAgentStyle, fallbackStyle, "user-agent");
|
|
7061
7146
|
const textStyle = createOrUpdateStyle("darkreader--text");
|
|
7062
7147
|
if (theme.useFont || theme.textStroke > 0) {
|
|
7063
7148
|
textStyle.textContent = createTextStyle(theme);
|
|
7064
7149
|
} else {
|
|
7065
7150
|
textStyle.textContent = "";
|
|
7066
7151
|
}
|
|
7067
|
-
|
|
7068
|
-
setupNodePositionWatcher(textStyle, "text");
|
|
7152
|
+
injectStaticStyle(textStyle, userAgentStyle, "text");
|
|
7069
7153
|
const invertStyle = createOrUpdateStyle("darkreader--invert");
|
|
7070
7154
|
if (fixes && Array.isArray(fixes.invert) && fixes.invert.length > 0) {
|
|
7071
7155
|
invertStyle.textContent = [
|
|
@@ -7082,17 +7166,10 @@ function createStaticStyleOverrides() {
|
|
|
7082
7166
|
} else {
|
|
7083
7167
|
invertStyle.textContent = "";
|
|
7084
7168
|
}
|
|
7085
|
-
|
|
7086
|
-
setupNodePositionWatcher(invertStyle, "invert");
|
|
7169
|
+
injectStaticStyle(invertStyle, textStyle, "invert");
|
|
7087
7170
|
const inlineStyle = createOrUpdateStyle("darkreader--inline");
|
|
7088
7171
|
inlineStyle.textContent = getInlineOverrideStyle();
|
|
7089
|
-
|
|
7090
|
-
setupNodePositionWatcher(inlineStyle, "inline");
|
|
7091
|
-
const overrideStyle = createOrUpdateStyle("darkreader--override");
|
|
7092
|
-
overrideStyle.textContent =
|
|
7093
|
-
fixes && fixes.css ? replaceCSSTemplates(fixes.css) : "";
|
|
7094
|
-
document.head.appendChild(overrideStyle);
|
|
7095
|
-
setupNodePositionWatcher(overrideStyle, "override");
|
|
7172
|
+
injectStaticStyle(inlineStyle, invertStyle, "inline");
|
|
7096
7173
|
const variableStyle = createOrUpdateStyle("darkreader--variables");
|
|
7097
7174
|
const selectionColors = theme?.selectionColor
|
|
7098
7175
|
? getSelectionColor(theme)
|
|
@@ -7113,13 +7190,12 @@ function createStaticStyleOverrides() {
|
|
|
7113
7190
|
` --darkreader-selection-text: ${selectionColors?.foregroundColorSelection ?? "initial"};`,
|
|
7114
7191
|
`}`
|
|
7115
7192
|
].join("\n");
|
|
7116
|
-
|
|
7117
|
-
setupNodePositionWatcher(variableStyle, "variables", () =>
|
|
7193
|
+
injectStaticStyle(variableStyle, inlineStyle, "variables", () =>
|
|
7118
7194
|
registerVariablesSheet(variableStyle.sheet)
|
|
7119
7195
|
);
|
|
7120
7196
|
registerVariablesSheet(variableStyle.sheet);
|
|
7121
7197
|
const rootVarsStyle = createOrUpdateStyle("darkreader--root-vars");
|
|
7122
|
-
|
|
7198
|
+
injectStaticStyle(rootVarsStyle, variableStyle, "root-vars");
|
|
7123
7199
|
const enableStyleSheetsProxy = !(fixes && fixes.disableStyleSheetsProxy);
|
|
7124
7200
|
const enableCustomElementRegistryProxy = !(
|
|
7125
7201
|
fixes && fixes.disableCustomElementRegistryProxy
|
|
@@ -7133,6 +7209,10 @@ function createStaticStyleOverrides() {
|
|
|
7133
7209
|
document.head.insertBefore(proxyScript, rootVarsStyle.nextSibling);
|
|
7134
7210
|
proxyScript.remove();
|
|
7135
7211
|
}
|
|
7212
|
+
const overrideStyle = createOrUpdateStyle("darkreader--override");
|
|
7213
|
+
overrideStyle.textContent =
|
|
7214
|
+
fixes && fixes.css ? replaceCSSTemplates(fixes.css) : "";
|
|
7215
|
+
injectStaticStyle(overrideStyle, document.head.lastChild, "override");
|
|
7136
7216
|
}
|
|
7137
7217
|
const shadowRootsWithOverrides = new Set();
|
|
7138
7218
|
function createShadowStaticStyleOverridesInner(root) {
|
|
@@ -7208,7 +7288,8 @@ function replaceCSSTemplates($cssText) {
|
|
|
7208
7288
|
}
|
|
7209
7289
|
function cleanFallbackStyle() {
|
|
7210
7290
|
const fallback =
|
|
7211
|
-
staticStyleMap.get("darkreader--fallback") ||
|
|
7291
|
+
staticStyleMap.get(document.head)?.get("darkreader--fallback") ||
|
|
7292
|
+
staticStyleMap.get(document)?.get("darkreader--fallback") ||
|
|
7212
7293
|
document.querySelector(".darkreader--fallback");
|
|
7213
7294
|
if (fallback) {
|
|
7214
7295
|
fallback.textContent = "";
|
|
@@ -7737,7 +7818,7 @@ function removeDynamicTheme() {
|
|
|
7737
7818
|
selectors.forEach((selector) =>
|
|
7738
7819
|
removeNode(document.head.querySelector(selector))
|
|
7739
7820
|
);
|
|
7740
|
-
staticStyleMap
|
|
7821
|
+
staticStyleMap = new WeakMap();
|
|
7741
7822
|
removeProxy();
|
|
7742
7823
|
}
|
|
7743
7824
|
shadowRootsWithOverrides.forEach((root) => {
|