darkreader 4.9.118 → 4.9.120
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/darkreader.js +330 -98
- package/darkreader.mjs +326 -98
- package/index.d.ts +8 -0
- package/package.json +22 -22
package/darkreader.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Dark Reader v4.9.
|
|
2
|
+
* Dark Reader v4.9.120
|
|
3
3
|
* https://darkreader.org/
|
|
4
4
|
*/
|
|
5
5
|
|
|
@@ -1010,54 +1010,155 @@ function parse($color) {
|
|
|
1010
1010
|
}
|
|
1011
1011
|
return null;
|
|
1012
1012
|
}
|
|
1013
|
-
|
|
1013
|
+
const C_0 = "0".charCodeAt(0);
|
|
1014
|
+
const C_9 = "9".charCodeAt(0);
|
|
1015
|
+
const C_e = "e".charCodeAt(0);
|
|
1016
|
+
const C_DOT = ".".charCodeAt(0);
|
|
1017
|
+
const C_PLUS = "+".charCodeAt(0);
|
|
1018
|
+
const C_MINUS = "-".charCodeAt(0);
|
|
1019
|
+
const C_SPACE = " ".charCodeAt(0);
|
|
1020
|
+
const C_COMMA = ",".charCodeAt(0);
|
|
1021
|
+
const C_SLASH = "/".charCodeAt(0);
|
|
1022
|
+
const C_PERCENT = "%".charCodeAt(0);
|
|
1023
|
+
function getNumbersFromString(input, range, units) {
|
|
1014
1024
|
const numbers = [];
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
const
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1025
|
+
const searchStart = input.indexOf("(") + 1;
|
|
1026
|
+
const searchEnd = input.length - 1;
|
|
1027
|
+
let numStart = -1;
|
|
1028
|
+
let unitStart = -1;
|
|
1029
|
+
const push = (matchEnd) => {
|
|
1030
|
+
const numEnd = unitStart > -1 ? unitStart : matchEnd;
|
|
1031
|
+
const $num = input.slice(numStart, numEnd);
|
|
1032
|
+
let n = parseFloat($num);
|
|
1033
|
+
const r = range[numbers.length];
|
|
1034
|
+
if (unitStart > -1) {
|
|
1035
|
+
const unit = input.slice(unitStart, matchEnd);
|
|
1036
|
+
const u = units[unit];
|
|
1037
|
+
if (u != null) {
|
|
1038
|
+
n *= r / u;
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
if (r > 1) {
|
|
1042
|
+
n = Math.round(n);
|
|
1043
|
+
}
|
|
1044
|
+
numbers.push(n);
|
|
1045
|
+
numStart = -1;
|
|
1046
|
+
unitStart = -1;
|
|
1047
|
+
};
|
|
1048
|
+
for (let i = searchStart; i < searchEnd; i++) {
|
|
1049
|
+
const c = input.charCodeAt(i);
|
|
1050
|
+
const isNumChar =
|
|
1051
|
+
(c >= C_0 && c <= C_9) ||
|
|
1052
|
+
c === C_DOT ||
|
|
1053
|
+
c === C_PLUS ||
|
|
1054
|
+
c === C_MINUS ||
|
|
1055
|
+
c === C_e;
|
|
1056
|
+
const isDelimiter = c === C_SPACE || c === C_COMMA || c === C_SLASH;
|
|
1057
|
+
if (isNumChar) {
|
|
1058
|
+
if (numStart === -1) {
|
|
1059
|
+
numStart = i;
|
|
1060
|
+
}
|
|
1061
|
+
} else if (numStart > -1) {
|
|
1062
|
+
if (isDelimiter) {
|
|
1063
|
+
push(i);
|
|
1064
|
+
} else if (unitStart === -1) {
|
|
1065
|
+
unitStart = i;
|
|
1066
|
+
}
|
|
1067
|
+
}
|
|
1068
|
+
}
|
|
1069
|
+
if (numStart > -1) {
|
|
1070
|
+
push(searchEnd);
|
|
1033
1071
|
}
|
|
1034
1072
|
return numbers;
|
|
1035
1073
|
}
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
const
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1074
|
+
const rgbRange = [255, 255, 255, 1];
|
|
1075
|
+
const rgbUnits = {"%": 100};
|
|
1076
|
+
function getRGBValues(input) {
|
|
1077
|
+
const CHAR_CODE_0 = 48;
|
|
1078
|
+
const length = input.length;
|
|
1079
|
+
let i = 0;
|
|
1080
|
+
let digitsCount = 0;
|
|
1081
|
+
let digitSequence = false;
|
|
1082
|
+
let floatDigitsCount = -1;
|
|
1083
|
+
let delimiter = C_SPACE;
|
|
1084
|
+
let channel = -1;
|
|
1085
|
+
let result = null;
|
|
1086
|
+
while (i < length) {
|
|
1087
|
+
const c = input.charCodeAt(i);
|
|
1088
|
+
if ((c >= C_0 && c <= C_9) || c === C_DOT) {
|
|
1089
|
+
if (!digitSequence) {
|
|
1090
|
+
digitSequence = true;
|
|
1091
|
+
digitsCount = 0;
|
|
1092
|
+
floatDigitsCount = -1;
|
|
1093
|
+
channel++;
|
|
1094
|
+
if (channel === 3 && result) {
|
|
1095
|
+
result[3] = 0;
|
|
1096
|
+
}
|
|
1097
|
+
if (channel > 3) {
|
|
1098
|
+
return null;
|
|
1099
|
+
}
|
|
1100
|
+
}
|
|
1101
|
+
if (c === C_DOT) {
|
|
1102
|
+
if (floatDigitsCount > 0) {
|
|
1103
|
+
return null;
|
|
1104
|
+
}
|
|
1105
|
+
floatDigitsCount = 0;
|
|
1049
1106
|
} else {
|
|
1050
|
-
|
|
1107
|
+
const d = c - CHAR_CODE_0;
|
|
1108
|
+
if (!result) {
|
|
1109
|
+
result = [0, 0, 0, 1];
|
|
1110
|
+
}
|
|
1111
|
+
if (floatDigitsCount > -1) {
|
|
1112
|
+
floatDigitsCount++;
|
|
1113
|
+
result[channel] += d / 10 ** floatDigitsCount;
|
|
1114
|
+
} else {
|
|
1115
|
+
digitsCount++;
|
|
1116
|
+
if (digitsCount > 3) {
|
|
1117
|
+
return null;
|
|
1118
|
+
}
|
|
1119
|
+
result[channel] = result[channel] * 10 + d;
|
|
1120
|
+
}
|
|
1051
1121
|
}
|
|
1052
|
-
|
|
1053
|
-
|
|
1122
|
+
} else if (c === C_PERCENT) {
|
|
1123
|
+
if (
|
|
1124
|
+
channel < 0 ||
|
|
1125
|
+
channel > 3 ||
|
|
1126
|
+
delimiter !== C_SPACE ||
|
|
1127
|
+
!result
|
|
1128
|
+
) {
|
|
1129
|
+
return null;
|
|
1054
1130
|
}
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1131
|
+
result[channel] =
|
|
1132
|
+
channel < 3
|
|
1133
|
+
? Math.round((result[channel] * 255) / 100)
|
|
1134
|
+
: result[channel] / 100;
|
|
1135
|
+
digitSequence = false;
|
|
1136
|
+
} else {
|
|
1137
|
+
digitSequence = false;
|
|
1138
|
+
if (c === C_SPACE) {
|
|
1139
|
+
if (channel === 0) {
|
|
1140
|
+
delimiter = c;
|
|
1141
|
+
}
|
|
1142
|
+
} else if (c === C_COMMA) {
|
|
1143
|
+
if (channel === -1) {
|
|
1144
|
+
return null;
|
|
1145
|
+
}
|
|
1146
|
+
delimiter = C_COMMA;
|
|
1147
|
+
} else if (c === C_SLASH) {
|
|
1148
|
+
if (channel !== 2 || delimiter !== C_SPACE) {
|
|
1149
|
+
return null;
|
|
1150
|
+
}
|
|
1151
|
+
} else {
|
|
1152
|
+
return null;
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1155
|
+
i++;
|
|
1156
|
+
}
|
|
1157
|
+
if (channel < 2 || channel > 3) {
|
|
1158
|
+
return null;
|
|
1159
|
+
}
|
|
1160
|
+
return result;
|
|
1058
1161
|
}
|
|
1059
|
-
const rgbRange = [255, 255, 255, 1];
|
|
1060
|
-
const rgbUnits = {"%": 100};
|
|
1061
1162
|
function parseRGB($rgb) {
|
|
1062
1163
|
const [r, g, b, a = 1] = getNumbersFromString($rgb, rgbRange, rgbUnits);
|
|
1063
1164
|
if (r == null || g == null || b == null || a == null) {
|
|
@@ -1074,28 +1175,48 @@ function parseHSL($hsl) {
|
|
|
1074
1175
|
}
|
|
1075
1176
|
return hslToRGB({h, s, l, a});
|
|
1076
1177
|
}
|
|
1178
|
+
const C_A = "A".charCodeAt(0);
|
|
1179
|
+
const C_F = "F".charCodeAt(0);
|
|
1180
|
+
const C_a = "a".charCodeAt(0);
|
|
1181
|
+
const C_f = "f".charCodeAt(0);
|
|
1077
1182
|
function parseHex($hex) {
|
|
1078
|
-
const
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1183
|
+
const length = $hex.length;
|
|
1184
|
+
const digitCount = length - 1;
|
|
1185
|
+
const isShort = digitCount === 3 || digitCount === 4;
|
|
1186
|
+
const isLong = digitCount === 6 || digitCount === 8;
|
|
1187
|
+
if (!isShort && !isLong) {
|
|
1188
|
+
return null;
|
|
1189
|
+
}
|
|
1190
|
+
const hex = (i) => {
|
|
1191
|
+
const c = $hex.charCodeAt(i);
|
|
1192
|
+
if (c >= C_A && c <= C_F) {
|
|
1193
|
+
return c + 10 - C_A;
|
|
1087
1194
|
}
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1195
|
+
if (c >= C_a && c <= C_f) {
|
|
1196
|
+
return c + 10 - C_a;
|
|
1197
|
+
}
|
|
1198
|
+
return c - C_0;
|
|
1199
|
+
};
|
|
1200
|
+
let r;
|
|
1201
|
+
let g;
|
|
1202
|
+
let b;
|
|
1203
|
+
let a = 1;
|
|
1204
|
+
if (isShort) {
|
|
1205
|
+
r = hex(1) * 17;
|
|
1206
|
+
g = hex(2) * 17;
|
|
1207
|
+
b = hex(3) * 17;
|
|
1208
|
+
if (digitCount === 4) {
|
|
1209
|
+
a = (hex(4) * 17) / 255;
|
|
1210
|
+
}
|
|
1211
|
+
} else {
|
|
1212
|
+
r = hex(1) * 16 + hex(2);
|
|
1213
|
+
g = hex(3) * 16 + hex(4);
|
|
1214
|
+
b = hex(5) * 16 + hex(6);
|
|
1215
|
+
if (digitCount === 8) {
|
|
1216
|
+
a = (hex(7) * 16 + hex(8)) / 255;
|
|
1096
1217
|
}
|
|
1097
1218
|
}
|
|
1098
|
-
return
|
|
1219
|
+
return {r, g, b, a};
|
|
1099
1220
|
}
|
|
1100
1221
|
function getColorByName($color) {
|
|
1101
1222
|
const n = knownColors.get($color);
|
|
@@ -1877,13 +1998,6 @@ const shorthandVarDepPropRegexps = isSafari
|
|
|
1877
1998
|
})
|
|
1878
1999
|
: null;
|
|
1879
2000
|
function iterateCSSDeclarations(style, iterate) {
|
|
1880
|
-
forEach(style, (property) => {
|
|
1881
|
-
const value = style.getPropertyValue(property).trim();
|
|
1882
|
-
if (!value) {
|
|
1883
|
-
return;
|
|
1884
|
-
}
|
|
1885
|
-
iterate(property, value);
|
|
1886
|
-
});
|
|
1887
2001
|
const cssText = style.cssText;
|
|
1888
2002
|
if (cssText.includes("var(")) {
|
|
1889
2003
|
if (isSafari) {
|
|
@@ -1917,6 +2031,13 @@ function iterateCSSDeclarations(style, iterate) {
|
|
|
1917
2031
|
) {
|
|
1918
2032
|
handleEmptyShorthand("border", style, iterate);
|
|
1919
2033
|
}
|
|
2034
|
+
forEach(style, (property) => {
|
|
2035
|
+
const value = style.getPropertyValue(property).trim();
|
|
2036
|
+
if (!value) {
|
|
2037
|
+
return;
|
|
2038
|
+
}
|
|
2039
|
+
iterate(property, value);
|
|
2040
|
+
});
|
|
1920
2041
|
}
|
|
1921
2042
|
function handleEmptyShorthand(shorthand, style, iterate) {
|
|
1922
2043
|
const parentRule = style.parentRule;
|
|
@@ -2671,13 +2792,56 @@ const imageManager = new AsyncQueue();
|
|
|
2671
2792
|
async function getImageDetails(url) {
|
|
2672
2793
|
return new Promise(async (resolve, reject) => {
|
|
2673
2794
|
try {
|
|
2674
|
-
|
|
2675
|
-
? url
|
|
2676
|
-
: await getDataURL(url);
|
|
2795
|
+
let dataURL = url.startsWith("data:") ? url : await getDataURL(url);
|
|
2677
2796
|
const blob =
|
|
2678
2797
|
tryConvertDataURLToBlobSync(dataURL) ?? (await loadAsBlob(url));
|
|
2679
2798
|
let image;
|
|
2799
|
+
let useViewBox = false;
|
|
2680
2800
|
if (dataURL.startsWith("data:image/svg+xml")) {
|
|
2801
|
+
const commaIndex = dataURL.indexOf(",");
|
|
2802
|
+
if (commaIndex >= 0) {
|
|
2803
|
+
let svgText = dataURL.slice(commaIndex + 1);
|
|
2804
|
+
const encoding = dataURL.slice(0, commaIndex).split(";")[1];
|
|
2805
|
+
if (encoding === "base64") {
|
|
2806
|
+
if (svgText.includes("%")) {
|
|
2807
|
+
svgText = decodeURIComponent(svgText);
|
|
2808
|
+
}
|
|
2809
|
+
svgText = atob(svgText);
|
|
2810
|
+
} else if (svgText.startsWith("%3c")) {
|
|
2811
|
+
svgText = decodeURIComponent(svgText);
|
|
2812
|
+
}
|
|
2813
|
+
if (svgText.startsWith("<svg ")) {
|
|
2814
|
+
const closingIndex = svgText.indexOf(">");
|
|
2815
|
+
const svgOpening = svgText
|
|
2816
|
+
.slice(0, closingIndex + 1)
|
|
2817
|
+
.toLocaleLowerCase();
|
|
2818
|
+
if (
|
|
2819
|
+
svgOpening.includes("viewbox=") &&
|
|
2820
|
+
!svgOpening.includes("width=") &&
|
|
2821
|
+
!svgOpening.includes("height=")
|
|
2822
|
+
) {
|
|
2823
|
+
useViewBox = true;
|
|
2824
|
+
const viewboxIndex = svgOpening.indexOf("viewbox=");
|
|
2825
|
+
const quote = svgOpening[viewboxIndex + 8];
|
|
2826
|
+
const viewboxCloseIndex = svgOpening.indexOf(
|
|
2827
|
+
quote,
|
|
2828
|
+
viewboxIndex + 9
|
|
2829
|
+
);
|
|
2830
|
+
const viewBox = svgOpening
|
|
2831
|
+
.slice(viewboxIndex + 9, viewboxCloseIndex)
|
|
2832
|
+
.split(" ")
|
|
2833
|
+
.map((x) => parseFloat(x));
|
|
2834
|
+
if (
|
|
2835
|
+
viewBox.length === 4 &&
|
|
2836
|
+
!viewBox.some((x) => isNaN(x))
|
|
2837
|
+
) {
|
|
2838
|
+
const width = viewBox[2] - viewBox[0];
|
|
2839
|
+
const height = viewBox[3] - viewBox[1];
|
|
2840
|
+
dataURL = `data:image/svg+xml;base64,${btoa(`<svg width="${width}" height="${height}" ${svgText.slice(5)}`)}`;
|
|
2841
|
+
}
|
|
2842
|
+
}
|
|
2843
|
+
}
|
|
2844
|
+
}
|
|
2681
2845
|
image = await loadImage(dataURL);
|
|
2682
2846
|
} else {
|
|
2683
2847
|
image =
|
|
@@ -2691,6 +2855,7 @@ async function getImageDetails(url) {
|
|
|
2691
2855
|
dataURL: analysis.isLarge ? "" : dataURL,
|
|
2692
2856
|
width: image.width,
|
|
2693
2857
|
height: image.height,
|
|
2858
|
+
useViewBox,
|
|
2694
2859
|
...analysis
|
|
2695
2860
|
});
|
|
2696
2861
|
});
|
|
@@ -2877,13 +3042,16 @@ function onCSPError(err) {
|
|
|
2877
3042
|
}
|
|
2878
3043
|
document.addEventListener("securitypolicyviolation", onCSPError);
|
|
2879
3044
|
const objectURLs = new Set();
|
|
2880
|
-
function getFilteredImageURL({dataURL, width, height}, theme) {
|
|
3045
|
+
function getFilteredImageURL({dataURL, width, height, useViewBox}, theme) {
|
|
2881
3046
|
if (dataURL.startsWith("data:image/svg+xml")) {
|
|
2882
3047
|
dataURL = escapeXML(dataURL);
|
|
2883
3048
|
}
|
|
2884
3049
|
const matrix = getSVGFilterMatrixValue(theme);
|
|
3050
|
+
const size = useViewBox
|
|
3051
|
+
? `viewBox="0 0 ${width} ${height}"`
|
|
3052
|
+
: `width="${width}" height="${height}"`;
|
|
2885
3053
|
const svg = [
|
|
2886
|
-
`<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
|
3054
|
+
`<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" ${size}>`,
|
|
2887
3055
|
"<defs>",
|
|
2888
3056
|
'<filter id="darkreader-image-filter">',
|
|
2889
3057
|
`<feColorMatrix type="matrix" values="${matrix}" />`,
|
|
@@ -2926,7 +3094,11 @@ function tryConvertDataURLToBlobSync(dataURL) {
|
|
|
2926
3094
|
if (encoding !== "base64" || !mediaType) {
|
|
2927
3095
|
return null;
|
|
2928
3096
|
}
|
|
2929
|
-
|
|
3097
|
+
let base64Content = dataURL.substring(commaIndex + 1);
|
|
3098
|
+
if (base64Content.includes("%")) {
|
|
3099
|
+
base64Content = decodeURIComponent(base64Content);
|
|
3100
|
+
}
|
|
3101
|
+
const characters = atob(base64Content);
|
|
2930
3102
|
const bytes = new Uint8Array(characters.length);
|
|
2931
3103
|
for (let i = 0; i < characters.length; i++) {
|
|
2932
3104
|
bytes[i] = characters.charCodeAt(i);
|
|
@@ -2963,6 +3135,12 @@ function cleanImageProcessingCache() {
|
|
|
2963
3135
|
function getPriority(ruleStyle, property) {
|
|
2964
3136
|
return Boolean(ruleStyle && ruleStyle.getPropertyPriority(property));
|
|
2965
3137
|
}
|
|
3138
|
+
const bgPropsToCopy = [
|
|
3139
|
+
"background-clip",
|
|
3140
|
+
"background-position",
|
|
3141
|
+
"background-repeat",
|
|
3142
|
+
"background-size"
|
|
3143
|
+
];
|
|
2966
3144
|
function getModifiableCSSDeclaration(
|
|
2967
3145
|
property,
|
|
2968
3146
|
value,
|
|
@@ -3026,6 +3204,8 @@ function getModifiableCSSDeclaration(
|
|
|
3026
3204
|
);
|
|
3027
3205
|
} else if (property.includes("shadow")) {
|
|
3028
3206
|
modifier = getShadowModifier(value);
|
|
3207
|
+
} else if (bgPropsToCopy.includes(property) && value !== "initial") {
|
|
3208
|
+
modifier = value;
|
|
3029
3209
|
}
|
|
3030
3210
|
if (!modifier) {
|
|
3031
3211
|
return null;
|
|
@@ -4093,9 +4273,7 @@ class VariablesStore {
|
|
|
4093
4273
|
}
|
|
4094
4274
|
this.definedVars.add(varName);
|
|
4095
4275
|
const isColor = Boolean(
|
|
4096
|
-
value
|
|
4097
|
-
value.match(rawRGBCommaRegex) ||
|
|
4098
|
-
parseColorWithCache(value)
|
|
4276
|
+
getRGBValues(value) || parseColorWithCache(value)
|
|
4099
4277
|
);
|
|
4100
4278
|
if (isColor) {
|
|
4101
4279
|
this.unknownColorVars.add(varName);
|
|
@@ -4426,16 +4604,13 @@ const textColorProps = [
|
|
|
4426
4604
|
function isTextColorProperty(property) {
|
|
4427
4605
|
return textColorProps.includes(property);
|
|
4428
4606
|
}
|
|
4429
|
-
const rawRGBSpaceRegex =
|
|
4430
|
-
/^(\d{1,3})\s+(\d{1,3})\s+(\d{1,3})\s*(\/\s*\d+\.?\d*)?$/;
|
|
4431
|
-
const rawRGBCommaRegex = /^(\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})$/;
|
|
4432
4607
|
function parseRawColorValue(input) {
|
|
4433
|
-
const
|
|
4434
|
-
|
|
4435
|
-
|
|
4436
|
-
|
|
4437
|
-
|
|
4438
|
-
|
|
4608
|
+
const v = getRGBValues(input);
|
|
4609
|
+
if (v) {
|
|
4610
|
+
const color =
|
|
4611
|
+
v[3] < 1
|
|
4612
|
+
? `rgb(${v[0]} ${v[1]} ${v[2]} / ${v[3]})`
|
|
4613
|
+
: `rgb(${v[0]} ${v[1]} ${v[2]})`;
|
|
4439
4614
|
return {isRaw: true, color};
|
|
4440
4615
|
}
|
|
4441
4616
|
return {isRaw: false, color: input};
|
|
@@ -4448,7 +4623,9 @@ function handleRawColorValue(input, theme, modifyFunction) {
|
|
|
4448
4623
|
if (isRaw) {
|
|
4449
4624
|
const outputInRGB = parseColorWithCache(outputColor);
|
|
4450
4625
|
return outputInRGB
|
|
4451
|
-
?
|
|
4626
|
+
? Number.isNaN(outputInRGB.a) || outputInRGB.a === 1
|
|
4627
|
+
? `${outputInRGB.r}, ${outputInRGB.g}, ${outputInRGB.b}`
|
|
4628
|
+
: `${outputInRGB.r}, ${outputInRGB.g}, ${outputInRGB.b}, ${outputInRGB.a}`
|
|
4452
4629
|
: outputColor;
|
|
4453
4630
|
}
|
|
4454
4631
|
return outputColor;
|
|
@@ -5466,8 +5643,8 @@ function shouldAnalyzeSVGAsImage(svg) {
|
|
|
5466
5643
|
}
|
|
5467
5644
|
const shouldAnalyze = Boolean(
|
|
5468
5645
|
svg &&
|
|
5469
|
-
|
|
5470
|
-
|
|
5646
|
+
(svg.getAttribute("class")?.includes("logo") ||
|
|
5647
|
+
svg.parentElement?.getAttribute("class")?.includes("logo"))
|
|
5471
5648
|
);
|
|
5472
5649
|
svgAnalysisConditionCache.set(svg, shouldAnalyze);
|
|
5473
5650
|
return shouldAnalyze;
|
|
@@ -5510,6 +5687,7 @@ function getSVGElementRoot(svgElement) {
|
|
|
5510
5687
|
svgNodesRoots.set(svgElement, root);
|
|
5511
5688
|
return root;
|
|
5512
5689
|
}
|
|
5690
|
+
const inlineStringValueCache = new Map();
|
|
5513
5691
|
function overrideInlineStyle(
|
|
5514
5692
|
element,
|
|
5515
5693
|
theme,
|
|
@@ -5537,6 +5715,13 @@ function overrideInlineStyle(
|
|
|
5537
5715
|
}
|
|
5538
5716
|
const unsetProps = new Set(Object.keys(overrides));
|
|
5539
5717
|
function setCustomProp(targetCSSProp, modifierCSSProp, cssVal) {
|
|
5718
|
+
const cachedStringValue = inlineStringValueCache
|
|
5719
|
+
.get(modifierCSSProp)
|
|
5720
|
+
?.get(cssVal);
|
|
5721
|
+
if (cachedStringValue) {
|
|
5722
|
+
setStaticValue(cachedStringValue);
|
|
5723
|
+
return;
|
|
5724
|
+
}
|
|
5540
5725
|
const mod = getModifiableCSSDeclaration(
|
|
5541
5726
|
modifierCSSProp,
|
|
5542
5727
|
cssVal,
|
|
@@ -5602,6 +5787,10 @@ function overrideInlineStyle(
|
|
|
5602
5787
|
typeof mod.value === "function" ? mod.value(theme) : mod.value;
|
|
5603
5788
|
if (typeof value === "string") {
|
|
5604
5789
|
setStaticValue(value);
|
|
5790
|
+
if (!inlineStringValueCache.has(modifierCSSProp)) {
|
|
5791
|
+
inlineStringValueCache.set(modifierCSSProp, new Map());
|
|
5792
|
+
}
|
|
5793
|
+
inlineStringValueCache.get(modifierCSSProp).set(cssVal, value);
|
|
5605
5794
|
} else if (value instanceof Promise) {
|
|
5606
5795
|
setAsyncValue(value, cssVal);
|
|
5607
5796
|
} else if (typeof value === "object") {
|
|
@@ -5676,13 +5865,16 @@ function overrideInlineStyle(
|
|
|
5676
5865
|
let value = element.getAttribute("color");
|
|
5677
5866
|
if (value.match(/^[0-9a-f]{3}$/i) || value.match(/^[0-9a-f]{6}$/i)) {
|
|
5678
5867
|
value = `#${value}`;
|
|
5868
|
+
} else if (value.match(/^#?[0-9a-f]{4}$/i)) {
|
|
5869
|
+
const hex = value.startsWith("#") ? value.substring(1) : value;
|
|
5870
|
+
value = `#${hex}00`;
|
|
5679
5871
|
}
|
|
5680
5872
|
setCustomProp("color", "color", value);
|
|
5681
5873
|
}
|
|
5682
5874
|
if (isSVGElement) {
|
|
5683
5875
|
if (element.hasAttribute("fill")) {
|
|
5684
5876
|
const value = element.getAttribute("fill");
|
|
5685
|
-
if (value !== "none") {
|
|
5877
|
+
if (value !== "none" && value !== "currentColor") {
|
|
5686
5878
|
if (!(element instanceof SVGTextElement)) {
|
|
5687
5879
|
const handleSVGElement = () => {
|
|
5688
5880
|
let isSVGSmall = false;
|
|
@@ -5947,17 +6139,28 @@ function createRAFSheetWatcher(
|
|
|
5947
6139
|
}
|
|
5948
6140
|
|
|
5949
6141
|
const STYLE_SELECTOR = 'style, link[rel*="stylesheet" i]:not([disabled])';
|
|
5950
|
-
|
|
5951
|
-
|
|
6142
|
+
let ignoredCSSURLPatterns = [];
|
|
6143
|
+
function setIgnoredCSSURLs(patterns) {
|
|
6144
|
+
ignoredCSSURLPatterns = patterns || [];
|
|
6145
|
+
}
|
|
6146
|
+
function shouldIgnoreCSSURL(url) {
|
|
6147
|
+
if (!url || ignoredCSSURLPatterns.length === 0) {
|
|
5952
6148
|
return false;
|
|
5953
6149
|
}
|
|
5954
|
-
|
|
5955
|
-
|
|
5956
|
-
|
|
5957
|
-
|
|
5958
|
-
|
|
5959
|
-
|
|
6150
|
+
for (const pattern of ignoredCSSURLPatterns) {
|
|
6151
|
+
if (pattern.startsWith("^")) {
|
|
6152
|
+
if (url.startsWith(pattern.slice(1))) {
|
|
6153
|
+
return true;
|
|
6154
|
+
}
|
|
6155
|
+
} else if (pattern.endsWith("$")) {
|
|
6156
|
+
if (url.endsWith(pattern.slice(0, -1))) {
|
|
6157
|
+
return true;
|
|
6158
|
+
}
|
|
6159
|
+
} else if (url.includes(pattern)) {
|
|
6160
|
+
return true;
|
|
6161
|
+
}
|
|
5960
6162
|
}
|
|
6163
|
+
return false;
|
|
5961
6164
|
}
|
|
5962
6165
|
const hostsBreakingOnSVGStyleOverride = [
|
|
5963
6166
|
"account.containerstore.com",
|
|
@@ -5977,7 +6180,7 @@ function shouldManageStyle(element) {
|
|
|
5977
6180
|
(isFirefox
|
|
5978
6181
|
? !element.href.startsWith("moz-extension://")
|
|
5979
6182
|
: true) &&
|
|
5980
|
-
!
|
|
6183
|
+
!shouldIgnoreCSSURL(element.href))) &&
|
|
5981
6184
|
!element.classList.contains("darkreader") &&
|
|
5982
6185
|
!ignoredMedia.includes(element.media.toLowerCase()) &&
|
|
5983
6186
|
!element.classList.contains("stylus")
|
|
@@ -5994,7 +6197,7 @@ function getManageableStyles(node, results = [], deep = true) {
|
|
|
5994
6197
|
forEach(node.querySelectorAll(STYLE_SELECTOR), (style) =>
|
|
5995
6198
|
getManageableStyles(style, results, false)
|
|
5996
6199
|
);
|
|
5997
|
-
if (deep) {
|
|
6200
|
+
if (deep && (node.children?.length > 0 || node.shadowRoot)) {
|
|
5998
6201
|
iterateShadowHosts(node, (host) =>
|
|
5999
6202
|
getManageableStyles(host.shadowRoot, results, false)
|
|
6000
6203
|
);
|
|
@@ -7120,10 +7323,23 @@ function watchForStylePositions(currentStyles, update, shadowRootDiscovered) {
|
|
|
7120
7323
|
removedStyles,
|
|
7121
7324
|
movedStyles
|
|
7122
7325
|
});
|
|
7326
|
+
const potentialHosts = new Set();
|
|
7123
7327
|
additions.forEach((n) => {
|
|
7328
|
+
if (n.parentElement) {
|
|
7329
|
+
potentialHosts.add(n.parentElement);
|
|
7330
|
+
}
|
|
7331
|
+
if (n.previousElementSibling) {
|
|
7332
|
+
potentialHosts.add(n.previousElementSibling);
|
|
7333
|
+
}
|
|
7124
7334
|
deepObserve(n);
|
|
7125
7335
|
collectUndefinedElements(n);
|
|
7126
7336
|
});
|
|
7337
|
+
potentialHosts.forEach((el) => {
|
|
7338
|
+
if (el.shadowRoot && !observedRoots.has(el)) {
|
|
7339
|
+
subscribeForShadowRootChanges(el);
|
|
7340
|
+
deepObserve(el.shadowRoot);
|
|
7341
|
+
}
|
|
7342
|
+
});
|
|
7127
7343
|
additions.forEach(
|
|
7128
7344
|
(node) => isCustomElement(node) && recordUndefinedElement(node)
|
|
7129
7345
|
);
|
|
@@ -7237,6 +7453,14 @@ function watchForStylePositions(currentStyles, update, shadowRootDiscovered) {
|
|
|
7237
7453
|
});
|
|
7238
7454
|
document.addEventListener("__darkreader__isDefined", handleIsDefined);
|
|
7239
7455
|
collectUndefinedElements(document);
|
|
7456
|
+
addDOMReadyListener(() => {
|
|
7457
|
+
forEach(document.body.children, (el) => {
|
|
7458
|
+
if (el.shadowRoot && !observedRoots.has(el)) {
|
|
7459
|
+
subscribeForShadowRootChanges(el);
|
|
7460
|
+
deepObserve(el.shadowRoot);
|
|
7461
|
+
}
|
|
7462
|
+
});
|
|
7463
|
+
});
|
|
7240
7464
|
}
|
|
7241
7465
|
function resetObservers() {
|
|
7242
7466
|
observers.forEach((o) => o.disconnect());
|
|
@@ -7918,9 +8142,13 @@ function createOrUpdateDynamicThemeInternal(
|
|
|
7918
8142
|
ignoredInlineSelectors = Array.isArray(fixes.ignoreInlineStyle)
|
|
7919
8143
|
? fixes.ignoreInlineStyle
|
|
7920
8144
|
: [];
|
|
8145
|
+
setIgnoredCSSURLs(
|
|
8146
|
+
Array.isArray(fixes.ignoreCSSUrl) ? fixes.ignoreCSSUrl : []
|
|
8147
|
+
);
|
|
7921
8148
|
} else {
|
|
7922
8149
|
ignoredImageAnalysisSelectors = [];
|
|
7923
8150
|
ignoredInlineSelectors = [];
|
|
8151
|
+
setIgnoredCSSURLs([]);
|
|
7924
8152
|
}
|
|
7925
8153
|
if (theme.immediateModify) {
|
|
7926
8154
|
setIsDOMReady(() => {
|
package/index.d.ts
CHANGED
|
@@ -157,6 +157,14 @@ declare namespace DarkReader {
|
|
|
157
157
|
* who are using the Dark Reader API.
|
|
158
158
|
*/
|
|
159
159
|
disableStyleSheetsProxy: boolean;
|
|
160
|
+
/**
|
|
161
|
+
* List of stylesheet URL patterns to ignore.
|
|
162
|
+
* Stylesheets matching these patterns will not be processed by Dark Reader.
|
|
163
|
+
* - Simple string: matches if URL contains the string (e.g., "crisp")
|
|
164
|
+
* - Prefix with ^: matches if URL starts with pattern (e.g., "^https://client.crisp")
|
|
165
|
+
* - Suffix with $: matches if URL ends with pattern (e.g., ".css$")
|
|
166
|
+
*/
|
|
167
|
+
ignoreCSSUrl: string[];
|
|
160
168
|
}
|
|
161
169
|
}
|
|
162
170
|
|