diff --git a/app/static/js/Dark_Reader/darkreader.js b/app/static/js/Dark_Reader/darkreader.js index dd259a22..a2a986a7 100644 --- a/app/static/js/Dark_Reader/darkreader.js +++ b/app/static/js/Dark_Reader/darkreader.js @@ -1,5 +1,5 @@ /** - * Dark Reader v4.7.15 + * Dark Reader v4.9.2 * https://darkreader.org/ */ @@ -7,7 +7,7 @@ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (global = global || self, factory(global.DarkReader = {})); -}(this, function (exports) { 'use strict'; +}(this, (function (exports) { 'use strict'; /*! ***************************************************************************** Copyright (c) Microsoft Corporation. All rights reserved. @@ -72,35 +72,213 @@ } } + function isFirefox() { + return navigator.userAgent.includes('Firefox'); + } + function isMacOS() { + return navigator.platform.toLowerCase().startsWith('mac'); + } + function isDeepSelectorSupported() { + try { + document.querySelector('x /deep/ x'); + return true; + } + catch (err) { + return false; + } + } + function isHostSelectorSupported() { + try { + document.querySelector(':host x'); + return true; + } + catch (err) { + return false; + } + } + function isDefinedSelectorSupported() { + try { + document.querySelector(':defined'); + return true; + } + catch (err) { + return false; + } + } + + function getOKResponse(url, mimeType) { + return __awaiter(this, void 0, void 0, function () { + var response; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4, fetch(url, { + cache: 'force-cache', + credentials: 'omit', + })]; + case 1: + response = _a.sent(); + if (isFirefox() && mimeType === 'text/css' && url.startsWith('moz-extension://') && url.endsWith('.css')) { + return [2, response]; + } + if (mimeType && !response.headers.get('Content-Type').startsWith(mimeType)) { + throw new Error("Mime type mismatch when loading " + url); + } + if (!response.ok) { + throw new Error("Unable to load " + url + " " + response.status + " " + response.statusText); + } + return [2, response]; + } + }); + }); + } + function loadAsDataURL(url, mimeType) { + return __awaiter(this, void 0, void 0, function () { + var response; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4, getOKResponse(url, mimeType)]; + case 1: + response = _a.sent(); + return [4, readResponseAsDataURL(response)]; + case 2: return [2, _a.sent()]; + } + }); + }); + } + function readResponseAsDataURL(response) { + return __awaiter(this, void 0, void 0, function () { + var blob, dataURL; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4, response.blob()]; + case 1: + blob = _a.sent(); + return [4, (new Promise(function (resolve) { + var reader = new FileReader(); + reader.onloadend = function () { return resolve(reader.result); }; + reader.readAsDataURL(blob); + }))]; + case 2: + dataURL = _a.sent(); + return [2, dataURL]; + } + }); + }); + } + + var throwCORSError = function (url) { return __awaiter(void 0, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, Promise.reject(new Error([ + 'Embedded Dark Reader cannot access a cross-origin resource', + url, + 'Overview your URLs and CORS policies or use', + '`DarkReader.setFetchMethod(fetch: (url) => Promise))`.', + 'See if using `DarkReader.setFetchMethod(window.fetch)`', + 'before `DarkReader.enable()` works.' + ].join(' ')))]; + }); + }); }; + var fetcher = throwCORSError; + function setFetchMethod(fetch) { + if (fetch) { + fetcher = fetch; + } + else { + fetcher = throwCORSError; + } + } + function callFetchMethod(url) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4, fetcher(url)]; + case 1: return [2, _a.sent()]; + } + }); + }); + } + if (!window.chrome) { window.chrome = {}; } - if (!window.chrome.runtime) { - window.chrome.runtime = {}; + if (!chrome.runtime) { + chrome.runtime = {}; } - var throwCORSError = function () { - throw new Error('Access to some of your resources was blocked by cross-origin policy'); - }; - if (window.chrome.runtime.sendMessage) { - var nativeSendMessage_1 = window.chrome.runtime.sendMessage; - window.chrome.runtime.sendMessage = function () { + var messageListeners = new Set(); + function sendMessage() { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + return __awaiter(this, void 0, void 0, function () { + var id_1, _a, url, responseType, response, text_1, error_1; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: + if (!(args[0] && args[0].type === 'fetch')) return [3, 8]; + id_1 = args[0].id; + _b.label = 1; + case 1: + _b.trys.push([1, 7, , 8]); + _a = args[0].data, url = _a.url, responseType = _a.responseType; + return [4, callFetchMethod(url)]; + case 2: + response = _b.sent(); + if (!(responseType === 'data-url')) return [3, 4]; + return [4, readResponseAsDataURL(response)]; + case 3: + text_1 = _b.sent(); + return [3, 6]; + case 4: return [4, response.text()]; + case 5: + text_1 = _b.sent(); + _b.label = 6; + case 6: + messageListeners.forEach(function (cb) { return cb({ type: 'fetch-response', data: text_1, error: null, id: id_1 }); }); + return [3, 8]; + case 7: + error_1 = _b.sent(); + console.error(error_1); + messageListeners.forEach(function (cb) { return cb({ type: 'fetch-response', data: null, error: error_1, id: id_1 }); }); + return [3, 8]; + case 8: return [2]; + } + }); + }); + } + function addMessageListener(callback) { + messageListeners.add(callback); + } + if (typeof chrome.runtime.sendMessage === 'function') { + var nativeSendMessage_1 = chrome.runtime.sendMessage; + chrome.runtime.sendMessage = function () { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } - if (args[0] && args[0].type === 'fetch') { - throwCORSError(); - } - nativeSendMessage_1.apply(window.chrome.runtime, args); + sendMessage.apply(void 0, args); + nativeSendMessage_1.apply(chrome.runtime, args); }; } else { - window.chrome.runtime.sendMessage = throwCORSError; + chrome.runtime.sendMessage = sendMessage; } - if (!window.chrome.runtime.onMessage) { - window.chrome.runtime.onMessage = { - addListener: Function.prototype, + if (!chrome.runtime.onMessage) { + chrome.runtime.onMessage = {}; + } + if (typeof chrome.runtime.onMessage.addListener === 'function') { + var nativeAddListener_1 = chrome.runtime.onMessage.addListener; + chrome.runtime.onMessage.addListener = function () { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + addMessageListener.apply(void 0, args); + nativeAddListener_1.apply(chrome.runtime.onMessage, args); }; + } + else { + chrome.runtime.onMessage.addListener = addMessageListener; } var ThemeEngines = { @@ -254,6 +432,145 @@ return result; } + function throttle(callback) { + var pending = false; + var frameId = null; + var lastArgs; + var throttled = (function () { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + lastArgs = args; + if (frameId) { + pending = true; + } + else { + callback.apply(void 0, lastArgs); + frameId = requestAnimationFrame(function () { + frameId = null; + if (pending) { + callback.apply(void 0, lastArgs); + pending = false; + } + }); + } + }); + var cancel = function () { + cancelAnimationFrame(frameId); + pending = false; + frameId = null; + }; + return Object.assign(throttled, { cancel: cancel }); + } + function createAsyncTasksQueue() { + var tasks = []; + var frameId = null; + function runTasks() { + var task; + while (task = tasks.shift()) { + task(); + } + frameId = null; + } + function add(task) { + tasks.push(task); + if (!frameId) { + frameId = requestAnimationFrame(runTasks); + } + } + function cancel() { + tasks.splice(0); + cancelAnimationFrame(frameId); + frameId = null; + } + return { add: add, cancel: cancel }; + } + + function getDuration(time) { + var duration = 0; + if (time.seconds) { + duration += time.seconds * 1000; + } + if (time.minutes) { + duration += time.minutes * 60 * 1000; + } + if (time.hours) { + duration += time.hours * 60 * 60 * 1000; + } + if (time.days) { + duration += time.days * 24 * 60 * 60 * 1000; + } + return duration; + } + + function removeNode(node) { + node && node.parentNode && node.parentNode.removeChild(node); + } + function watchForNodePosition(node, _a) { + var _b = _a.onRestore, onRestore = _b === void 0 ? Function.prototype : _b, _c = _a.watchParent, watchParent = _c === void 0 ? true : _c, _d = _a.watchSibling, watchSibling = _d === void 0 ? false : _d; + var MAX_ATTEMPTS_COUNT = 10; + var ATTEMPTS_INTERVAL = getDuration({ seconds: 10 }); + var prevSibling = node.previousSibling; + var parent = node.parentNode; + if (!parent) { + logWarn('Unable to watch for node position: parent element not found', node, prevSibling); + return { stop: Function.prototype }; + } + var attempts = 0; + var start = null; + var restore = throttle(function () { + attempts++; + var now = Date.now(); + if (start == null) { + start = now; + } + else if (attempts >= MAX_ATTEMPTS_COUNT) { + if (now - start < ATTEMPTS_INTERVAL) { + logWarn('Node position watcher stopped: some script conflicts with Dark Reader and can cause high CPU usage', node, prevSibling); + stop(); + return; + } + start = now; + attempts = 1; + } + if (prevSibling && prevSibling.parentNode !== parent) { + logWarn('Unable to restore node position: sibling was removed', node, prevSibling, parent); + stop(); + return; + } + logWarn('Node was removed, restoring it\'s position', node, prevSibling, parent); + parent.insertBefore(node, prevSibling ? prevSibling.nextSibling : parent.firstChild); + onRestore && onRestore(); + }); + var observer = new MutationObserver(function () { + if ((watchParent && !node.parentNode) || + (watchSibling && node.previousSibling !== prevSibling)) { + restore(); + observer.takeRecords(); + } + }); + var run = function () { + observer.observe(parent, { childList: true }); + }; + var stop = function () { + observer.disconnect(); + }; + run(); + return { run: run, stop: stop }; + } + function iterateShadowNodes(root, iterator) { + var walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT, { + acceptNode: function (node) { + return node.shadowRoot == null ? NodeFilter.FILTER_SKIP : NodeFilter.FILTER_ACCEPT; + } + }, false); + for (var node = (root.shadowRoot ? walker.currentNode : walker.nextNode()); node != null; node = walker.nextNode()) { + iterator(node); + iterateShadowNodes(node.shadowRoot, iterator); + } + } + function hslToRGB(_a) { var h = _a.h, s = _a.s, l = _a.l, _b = _a.a, a = _b === void 0 ? 1 : _b; if (s === 0) { @@ -626,22 +943,6 @@ return result; } - function isFirefox() { - return navigator.userAgent.includes('Firefox'); - } - function isMacOS() { - return navigator.platform.toLowerCase().startsWith('mac'); - } - function isDeepSelectorSupported() { - try { - document.querySelector('x /deep/ x'); - return true; - } - catch (err) { - return false; - } - } - function getMatches(regex, input, group) { if (group === void 0) { group = 0; } var matches = []; @@ -831,7 +1132,7 @@ if (filter.mode === 0) { return modifyColorWithCache(rgb, filter, modifyLightModeHSL); } - return modifyColorWithCache(rgb, __assign({}, filter, { mode: 0 }), modifyBgHSL); + return modifyColorWithCache(rgb, __assign(__assign({}, filter), { mode: 0 }), modifyBgHSL); } function modifyFgHSL(_a) { var h = _a.h, s = _a.s, l = _a.l, a = _a.a; @@ -869,7 +1170,7 @@ if (filter.mode === 0) { return modifyColorWithCache(rgb, filter, modifyLightModeHSL); } - return modifyColorWithCache(rgb, __assign({}, filter, { mode: 0 }), modifyFgHSL); + return modifyColorWithCache(rgb, __assign(__assign({}, filter), { mode: 0 }), modifyFgHSL); } function modifyBorderHSL(_a) { var h = _a.h, s = _a.s, l = _a.l, a = _a.a; @@ -886,7 +1187,7 @@ if (filter.mode === 0) { return modifyColorWithCache(rgb, filter, modifyLightModeHSL); } - return modifyColorWithCache(rgb, __assign({}, filter, { mode: 0 }), modifyBorderHSL); + return modifyColorWithCache(rgb, __assign(__assign({}, filter), { mode: 0 }), modifyBorderHSL); } function modifyShadowColor(rgb, filter) { return modifyBackgroundColor(rgb, filter); @@ -975,49 +1276,6 @@ } }); - function getOKResponse(url) { - return __awaiter(this, void 0, void 0, function () { - var response; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: return [4, fetch(url, { cache: 'force-cache' })]; - case 1: - response = _a.sent(); - if (response.ok) { - return [2, response]; - } - else { - throw new Error("Unable to load " + url + " " + response.status + " " + response.statusText); - } - return [2]; - } - }); - }); - } - function loadAsDataURL(url) { - return __awaiter(this, void 0, void 0, function () { - var response, blob, dataURL; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: return [4, getOKResponse(url)]; - case 1: - response = _a.sent(); - return [4, response.blob()]; - case 2: - blob = _a.sent(); - return [4, (new Promise(function (resolve) { - var reader = new FileReader(); - reader.onloadend = function () { return resolve(reader.result); }; - reader.readAsDataURL(blob); - }))]; - case 3: - dataURL = _a.sent(); - return [2, dataURL]; - } - }); - }); - } - function getImageDetails(url) { return __awaiter(this, void 0, void 0, function () { var dataURL, image, info; @@ -1405,7 +1663,7 @@ var result; if (isDark && isTransparent && filter.mode === 1 && !isLarge && width > 2) { logInfo("Inverting dark image " + imageDetails.src); - var inverted = getFilteredImageDataURL(imageDetails, __assign({}, filter, { sepia: clamp(filter.sepia + 10, 0, 100) })); + var inverted = getFilteredImageDataURL(imageDetails, __assign(__assign({}, filter), { sepia: clamp(filter.sepia + 10, 0, 100) })); result = "url(\"" + inverted + "\")"; } else if (isLight && !isTransparent && filter.mode === 1) { @@ -1420,7 +1678,7 @@ } else if (filter.mode === 0 && isLight && !isLarge) { logInfo("Applying filter to image " + imageDetails.src); - var filtered = getFilteredImageDataURL(imageDetails, __assign({}, filter, { brightness: clamp(filter.brightness - 10, 5, 200), sepia: clamp(filter.sepia + 10, 0, 100) })); + var filtered = getFilteredImageDataURL(imageDetails, __assign(__assign({}, filter), { brightness: clamp(filter.brightness - 10, 5, 200), sepia: clamp(filter.sepia + 10, 0, 100) })); result = "url(\"" + filtered + "\")"; } else { @@ -1573,7 +1831,6 @@ ].join('\n'); }).join('\n'); } - var observer = null; function expand(nodes, selector) { var results = []; nodes.forEach(function (n) { @@ -1586,11 +1843,18 @@ }); return results; } - function watchForInlineStyles(elementStyleDidChange) { - if (observer) { - observer.disconnect(); + var observers = new Map(); + function watchForInlineStyles(elementStyleDidChange, shadowRootDiscovered) { + deepWatchForInlineStyles(document.documentElement, elementStyleDidChange, shadowRootDiscovered); + iterateShadowNodes(document.documentElement, function (node) { + deepWatchForInlineStyles(node.shadowRoot, elementStyleDidChange, shadowRootDiscovered); + }); + } + function deepWatchForInlineStyles(root, elementStyleDidChange, shadowRootDiscovered) { + if (observers.has(root)) { + observers.get(root).disconnect(); } - observer = new MutationObserver(function (mutations) { + var observer = new MutationObserver(function (mutations) { mutations.forEach(function (m) { var createdInlineStyles = expand(Array.from(m.addedNodes), INLINE_STYLE_SELECTOR); if (createdInlineStyles.length > 0) { @@ -1611,8 +1875,18 @@ }); } }); + mutations.forEach(function (m) { + m.addedNodes.forEach(function (added) { + if (added.isConnected) { + iterateShadowNodes(added, function (n) { + shadowRootDiscovered(n.shadowRoot); + deepWatchForInlineStyles(n.shadowRoot, elementStyleDidChange, shadowRootDiscovered); + }); + } + }); + }); }); - observer.observe(document, { + observer.observe(root, { childList: true, subtree: true, attributes: true, @@ -1621,12 +1895,11 @@ return dataAttr; })), }); + observers.set(root, observer); } function stopWatchingForInlineStyles() { - if (observer) { - observer.disconnect(); - observer = null; - } + observers.forEach(function (o) { return o.disconnect(); }); + observers.clear(); } var inlineStyleCache = new WeakMap(); var filterProps = ['brightness', 'contrast', 'grayscale', 'sepia', 'mode']; @@ -1708,7 +1981,7 @@ var metaThemeColorName = 'theme-color'; var metaThemeColorSelector = "meta[name=\"" + metaThemeColorName + "\"]"; var srcMetaThemeColor = null; - var observer$1 = null; + var observer = null; function changeMetaThemeColor(meta, theme) { srcMetaThemeColor = srcMetaThemeColor || meta.content; try { @@ -1725,30 +1998,30 @@ changeMetaThemeColor(meta, theme); } else { - if (observer$1) { - observer$1.disconnect(); + if (observer) { + observer.disconnect(); } - observer$1 = new MutationObserver(function (mutations) { + observer = new MutationObserver(function (mutations) { loop: for (var _i = 0, mutations_1 = mutations; _i < mutations_1.length; _i++) { var m = mutations_1[_i]; for (var _a = 0, _b = Array.from(m.addedNodes); _a < _b.length; _a++) { var node = _b[_a]; if (node instanceof HTMLMetaElement && node.name === metaThemeColorName) { - observer$1.disconnect(); - observer$1 = null; + observer.disconnect(); + observer = null; changeMetaThemeColor(node, theme); break loop; } } } }); - observer$1.observe(document.head, { childList: true }); + observer.observe(document.head, { childList: true }); } } function restoreMetaThemeColor() { - if (observer$1) { - observer$1.disconnect(); - observer$1 = null; + if (observer) { + observer.disconnect(); + observer = null; } var meta = document.querySelector(metaThemeColorSelector); if (meta && srcMetaThemeColor) { @@ -1756,137 +2029,30 @@ } } - function throttle(callback) { - var pending = false; - var frameId = null; - var lastArgs; - var throttled = (function () { - var args = []; - for (var _i = 0; _i < arguments.length; _i++) { - args[_i] = arguments[_i]; - } - lastArgs = args; - if (frameId) { - pending = true; - } - else { - callback.apply(void 0, lastArgs); - frameId = requestAnimationFrame(function () { - frameId = null; - if (pending) { - callback.apply(void 0, lastArgs); - pending = false; - } - }); - } - }); - var cancel = function () { - cancelAnimationFrame(frameId); - pending = false; - frameId = null; - }; - return Object.assign(throttled, { cancel: cancel }); - } - function createAsyncTasksQueue() { - var tasks = []; - var frameId = null; - function runTasks() { - var task; - while (task = tasks.shift()) { - task(); - } - frameId = null; + var STYLE_SELECTOR = (function () { + var selectors = [ + 'html /deep/ link[rel*="stylesheet" i]:not([disabled])', + 'html /deep/ style', + ':host /deep/ link[rel*="stylesheet" i]:not([disabled])', + ':host /deep/ style', + ':host link[rel*="stylesheet" i]:not([disabled])', + ':host style', + ]; + if (!isDeepSelectorSupported()) { + selectors = selectors.map(function (s) { return s.replace('/deep/ ', ''); }); } - function add(task) { - tasks.push(task); - if (!frameId) { - frameId = requestAnimationFrame(runTasks); - } + if (!isHostSelectorSupported()) { + selectors = selectors.filter(function (s) { return !s.startsWith(':host'); }); } - function cancel() { - tasks.splice(0); - cancelAnimationFrame(frameId); - frameId = null; - } - return { add: add, cancel: cancel }; - } - - function getDuration(time) { - var duration = 0; - if (time.seconds) { - duration += time.seconds * 1000; - } - if (time.minutes) { - duration += time.minutes * 60 * 1000; - } - if (time.hours) { - duration += time.hours * 60 * 60 * 1000; - } - if (time.days) { - duration += time.days * 24 * 60 * 60 * 1000; - } - return duration; - } - - function removeNode(node) { - node && node.parentNode && node.parentNode.removeChild(node); - } - function watchForNodePosition(node, onRestore) { - var MAX_ATTEMPTS_COUNT = 10; - var ATTEMPTS_INTERVAL = getDuration({ seconds: 10 }); - var prevSibling = node.previousSibling; - var parent = node.parentElement; - if (!parent) { - logWarn('Unable to watch for node position: parent element not found', node, prevSibling); - return { stop: function () { } }; - } - var attempts = 0; - var start = null; - var restore = throttle(function () { - attempts++; - var now = Date.now(); - if (start == null) { - start = now; - } - else if (attempts >= MAX_ATTEMPTS_COUNT) { - if (now - start < ATTEMPTS_INTERVAL) { - logWarn('Node position watcher stopped: some script conflicts with Dark Reader and can cause high CPU usage', node, prevSibling); - stop(); - return; - } - start = now; - attempts = 1; - } - if ((prevSibling && prevSibling.parentElement !== parent)) { - logWarn('Unable to restore node position: sibling was removed', node, prevSibling, parent); - stop(); - return; - } - logWarn('Node was removed, restoring it\'s position', node, prevSibling, parent); - parent.insertBefore(node, prevSibling ? prevSibling.nextSibling : parent.firstChild); - onRestore && onRestore(); - }); - var observer = new MutationObserver(function () { - if (!node.parentElement) { - restore(); - } - }); - var run = function () { - observer.observe(parent, { childList: true }); - }; - var stop = function () { - observer.disconnect(); - }; - run(); - return { run: run, stop: stop }; - } - - var STYLE_SELECTOR = isDeepSelectorSupported() - ? 'html /deep/ link[rel*="stylesheet" i], html /deep/ style' - : 'html link[rel*="stylesheet" i], html style'; + return selectors.join(', '); + })(); function shouldManageStyle(element) { return (((element instanceof HTMLStyleElement) || - (element instanceof HTMLLinkElement && element.rel && element.rel.toLowerCase().includes('stylesheet'))) && + (element instanceof SVGStyleElement) || + (element instanceof HTMLLinkElement && + element.rel && + element.rel.toLowerCase().includes('stylesheet') && + !element.disabled)) && !element.classList.contains('darkreader') && element.media !== 'print'); } @@ -1934,6 +2100,27 @@ } return safeGetSheetRules(); } + function insertStyle() { + if (corsCopy) { + if (element.nextSibling !== corsCopy) { + element.parentNode.insertBefore(corsCopy, element.nextSibling); + } + if (corsCopy.nextSibling !== syncStyle) { + element.parentNode.insertBefore(syncStyle, corsCopy.nextSibling); + } + } + else if (element.nextSibling !== syncStyle) { + element.parentNode.insertBefore(syncStyle, element.nextSibling); + } + } + function createSyncStyle() { + syncStyle = element instanceof SVGStyleElement ? + document.createElementNS('http://www.w3.org/2000/svg', 'style') : + document.createElement('style'); + syncStyle.classList.add('darkreader'); + syncStyle.classList.add('darkreader--sync'); + syncStyle.media = 'screen'; + } var isLoadingRules = false; var wasLoadingError = false; function getRulesAsync() { @@ -1994,9 +2181,6 @@ case 9: fullCSSText = _a.sent(); corsCopy = createCORSCopy(element, fullCSSText); - if (corsCopy) { - corsCopyPositionWatcher = watchForNodePosition(corsCopy); - } return [3, 11]; case 10: err_2 = _a.sent(); @@ -2004,6 +2188,7 @@ return [3, 11]; case 11: if (corsCopy) { + corsCopyPositionWatcher = watchForNodePosition(corsCopy, { watchParent: true, watchSibling: true }); return [2, corsCopy.sheet.cssRules]; } _a.label = 12; @@ -2043,6 +2228,7 @@ var rulesTextCache = new Map(); var rulesModCache = new Map(); var prevFilterKey = null; + var forceRestore = false; function render(filter, variables) { var rules = getRulesSync(); if (!rules) { @@ -2109,10 +2295,11 @@ rulesModCache.delete(key); }); prevFilterKey = filterKey; - if (!rulesChanged && !filterChanged) { + if (!forceRestore && !rulesChanged && !filterChanged) { return; } renderId++; + forceRestore = false; function setRule(target, index, declarations) { var selector = declarations[0].selector; target.insertRule(selector + " {}", index); @@ -2150,13 +2337,10 @@ selectorGroup.push(decl); }); if (!syncStyle) { - syncStyle = document.createElement('style'); - syncStyle.classList.add('darkreader'); - syncStyle.classList.add('darkreader--sync'); - syncStyle.media = 'screen'; + createSyncStyle(); } syncStylePositionWatcher && syncStylePositionWatcher.stop(); - element.parentNode.insertBefore(syncStyle, corsCopy ? corsCopy.nextSibling : element.nextSibling); + insertStyle(); var sheet = syncStyle.sheet; for (var i = sheet.cssRules.length - 1; i >= 0; i--) { sheet.deleteRule(i); @@ -2189,7 +2373,7 @@ syncStylePositionWatcher.run(); } else { - syncStylePositionWatcher = watchForNodePosition(syncStyle, buildStyleSheet); + syncStylePositionWatcher = watchForNodePosition(syncStyle, { onRestore: buildStyleSheet, watchSibling: true, watchParent: true }); } } function rebuildAsyncRule(key) { @@ -2234,10 +2418,13 @@ }); buildStyleSheet(); } - var rulesCount = null; + var rulesChangeKey = null; var rulesCheckFrameId = null; function safeGetSheetRules() { try { + if (element.sheet == null) { + return null; + } return element.sheet.cssRules; } catch (err) { @@ -2245,15 +2432,22 @@ return null; } } - function subscribeToSheetChanges() { - if (element.sheet && safeGetSheetRules()) { - rulesCount = element.sheet.cssRules.length; + function updateRulesChangeKey() { + var rules = safeGetSheetRules(); + if (rules) { + rulesChangeKey = rules.length; } + } + function didRulesKeyChange() { + var rules = safeGetSheetRules(); + return rules && rules.length !== rulesChangeKey; + } + function subscribeToSheetChanges() { + updateRulesChangeKey(); unsubscribeFromSheetChanges(); var checkForUpdate = function () { - if (element.sheet && safeGetSheetRules() && - element.sheet.cssRules.length !== rulesCount) { - rulesCount = element.sheet.cssRules.length; + if (didRulesKeyChange()) { + updateRulesChangeKey(); update(); } rulesCheckFrameId = requestAnimationFrame(checkForUpdate); @@ -2265,9 +2459,9 @@ } function pause() { observer.disconnect(); + cancelAsyncOperations = true; corsCopyPositionWatcher && corsCopyPositionWatcher.stop(); syncStylePositionWatcher && syncStylePositionWatcher.stop(); - cancelAsyncOperations = true; unsubscribeFromSheetChanges(); } function destroy() { @@ -2281,12 +2475,33 @@ subscribeToSheetChanges(); } } + var maxMoveCount = 10; + var moveCount = 0; + function restore() { + if (!syncStyle) { + return; + } + moveCount++; + if (moveCount > maxMoveCount) { + logWarn('Style sheet was moved multiple times', element); + return; + } + logWarn('Restore style', syncStyle, element); + var shouldRestore = syncStyle.sheet == null || syncStyle.sheet.cssRules.length > 0; + insertStyle(); + if (shouldRestore) { + forceRestore = true; + updateRulesChangeKey(); + update(); + } + } return { details: details, render: render, pause: pause, destroy: destroy, watch: watch, + restore: restore, }; } function linkLoading(link) { @@ -2319,7 +2534,7 @@ return [4, fetch(url)]; case 1: return [4, (_a.sent()).text()]; case 2: return [2, _a.sent()]; - case 3: return [4, bgFetch({ url: url, responseType: 'text' })]; + case 3: return [4, bgFetch({ url: url, responseType: 'text', mimeType: 'text/css' })]; case 4: return [2, _a.sent()]; } }); @@ -2385,7 +2600,7 @@ return cors; } - var observer$2 = null; + var observer$1 = null; function getAllManageableStyles(nodes) { var results = []; Array.from(nodes).forEach(function (node) { @@ -2393,72 +2608,171 @@ if (shouldManageStyle(node)) { results.push(node); } + } + if (node instanceof Element || node instanceof ShadowRoot) { results.push.apply(results, Array.from(node.querySelectorAll(STYLE_SELECTOR)).filter(shouldManageStyle)); } }); return results; } - function iterateShadowNodes(nodes, iterator) { - Array.from(nodes).forEach(function (node) { - if (node instanceof Element) { - if (node.shadowRoot) { - iterator(node); - } - iterateShadowNodes(node.childNodes, iterator); + var undefinedGroups = new Map(); + var elementsDefinitionCallback; + function collectUndefinedElements(root) { + if (!isDefinedSelectorSupported()) { + return; + } + root.querySelectorAll(':not(:defined)') + .forEach(function (el) { + var tag = el.tagName.toLowerCase(); + if (!undefinedGroups.has(tag)) { + undefinedGroups.set(tag, new Set()); + customElementsWhenDefined(tag).then(function () { + if (elementsDefinitionCallback) { + var elements = undefinedGroups.get(tag); + undefinedGroups.delete(tag); + elementsDefinitionCallback(Array.from(elements)); + } + }); + } + undefinedGroups.get(tag).add(el); + }); + } + function customElementsWhenDefined(tag) { + return new Promise(function (resolve) { + if (window.customElements && typeof window.customElements.whenDefined === 'function') { + customElements.whenDefined(tag).then(resolve); + } + else { + var checkIfDefined_1 = function () { + var elements = undefinedGroups.get(tag); + if (elements && elements.size > 0) { + if (elements.values().next().value.matches(':defined')) { + resolve(); + } + else { + requestAnimationFrame(checkIfDefined_1); + } + } + }; + requestAnimationFrame(checkIfDefined_1); } }); } + function watchWhenCustomElementsDefined(callback) { + elementsDefinitionCallback = callback; + } + function unsubscribeFromDefineCustomElements() { + elementsDefinitionCallback = null; + undefinedGroups.clear(); + } var shadowObservers = new Set(); + var nodesShadowObservers = new WeakMap(); + function unsubscribeFromShadowRootChanges() { + shadowObservers.forEach(function (o) { return o.disconnect(); }); + shadowObservers.clear(); + nodesShadowObservers = new WeakMap(); + } function watchForStyleChanges(update) { - if (observer$2) { - observer$2.disconnect(); + if (observer$1) { + observer$1.disconnect(); shadowObservers.forEach(function (o) { return o.disconnect(); }); shadowObservers.clear(); + nodesShadowObservers = new WeakMap(); } function handleMutations(mutations) { - var createdStyles = mutations.reduce(function (nodes, m) { return nodes.concat(getAllManageableStyles(m.addedNodes)); }, []); - var removedStyles = mutations.reduce(function (nodes, m) { return nodes.concat(getAllManageableStyles(m.removedNodes)); }, []); - var updatedStyles = mutations - .filter(function (_a) { - var target = _a.target, type = _a.type; - return type === 'attributes' && shouldManageStyle(target); - }) - .reduce(function (styles, _a) { - var target = _a.target; - styles.push(target); - return styles; - }, []); - if (createdStyles.length + removedStyles.length + updatedStyles.length > 0) { - update({ - created: createdStyles, - updated: updatedStyles, - removed: removedStyles, - }); - } - var allAddedNodes = []; + var createdStyles = new Set(); + var updatedStyles = new Set(); + var removedStyles = new Set(); + var movedStyles = new Set(); + var additions = new Set(); + var deletions = new Set(); + var styleUpdates = new Set(); mutations.forEach(function (m) { - m.addedNodes.forEach(function (n) { - allAddedNodes.push(n); + m.addedNodes.forEach(function (n) { return additions.add(n); }); + m.removedNodes.forEach(function (n) { return deletions.add(n); }); + if (m.type === 'attributes' && shouldManageStyle(m.target)) { + styleUpdates.add(m.target); + } + }); + var styleAdditions = getAllManageableStyles(additions); + var styleDeletions = getAllManageableStyles(deletions); + additions.forEach(function (n) { + iterateShadowNodes(n, function (host) { + var shadowStyles = getAllManageableStyles(host.shadowRoot.children); + if (shadowStyles.length > 0) { + styleAdditions.push.apply(styleAdditions, shadowStyles); + } }); }); - iterateShadowNodes(allAddedNodes, subscribeForShadowRootChanges); + deletions.forEach(function (n) { + iterateShadowNodes(n, function (host) { + var shadowStyles = getAllManageableStyles(host.shadowRoot.children); + if (shadowStyles.length > 0) { + styleDeletions.push.apply(styleDeletions, shadowStyles); + } + }); + }); + styleDeletions.forEach(function (style) { + if (style.isConnected) { + movedStyles.add(style); + } + else { + removedStyles.add(style); + } + }); + styleUpdates.forEach(function (style) { + if (!removedStyles.has(style)) { + updatedStyles.add(style); + } + }); + styleAdditions.forEach(function (style) { + if (!(removedStyles.has(style) || movedStyles.has(style) || updatedStyles.has(style))) { + createdStyles.add(style); + } + }); + if (createdStyles.size + removedStyles.size + updatedStyles.size > 0) { + update({ + created: Array.from(createdStyles), + updated: Array.from(updatedStyles), + removed: Array.from(removedStyles), + moved: Array.from(movedStyles), + }); + } + additions.forEach(function (n) { + if (n.isConnected) { + iterateShadowNodes(n, subscribeForShadowRootChanges); + if (n instanceof Element) { + collectUndefinedElements(n); + } + } + }); } function subscribeForShadowRootChanges(node) { + if (nodesShadowObservers.has(node)) { + return; + } var shadowObserver = new MutationObserver(handleMutations); shadowObserver.observe(node.shadowRoot, mutationObserverOptions); shadowObservers.add(shadowObserver); + nodesShadowObservers.set(node, shadowObserver); } - var mutationObserverOptions = { childList: true, subtree: true, attributes: true, attributeFilter: ['rel'] }; - observer$2 = new MutationObserver(handleMutations); - observer$2.observe(document.documentElement, mutationObserverOptions); - iterateShadowNodes(document.documentElement.children, subscribeForShadowRootChanges); + var mutationObserverOptions = { childList: true, subtree: true, attributes: true, attributeFilter: ['rel', 'disabled'] }; + observer$1 = new MutationObserver(handleMutations); + observer$1.observe(document.documentElement, mutationObserverOptions); + iterateShadowNodes(document.documentElement, subscribeForShadowRootChanges); + watchWhenCustomElementsDefined(function (hosts) { + var newStyles = getAllManageableStyles(hosts.map(function (h) { return h.shadowRoot; })); + update({ created: newStyles, updated: [], removed: [], moved: [] }); + hosts.forEach(function (h) { return subscribeForShadowRootChanges(h); }); + }); + collectUndefinedElements(document); } function stopWatchingForStyleChanges() { - if (observer$2) { - observer$2.disconnect(); - observer$2 = null; - shadowObservers.forEach(function (o) { return o.disconnect(); }); - shadowObservers.clear(); + if (observer$1) { + observer$1.disconnect(); + observer$1 = null; + unsubscribeFromShadowRootChanges(); + unsubscribeFromDefineCustomElements(); } } @@ -2467,8 +2781,9 @@ var filter = null; var fixes = null; var isIFrame = null; - function createOrUpdateStyle(className) { - var style = (document.head || document).querySelector("." + className); + function createOrUpdateStyle(className, root) { + if (root === void 0) { root = document.head || document; } + var style = root.querySelector("." + className); if (!style) { style = document.createElement('style'); style.classList.add('darkreader'); @@ -2480,7 +2795,7 @@ var stylePositionWatchers = new Map(); function setupStylePositionWatcher(node, alias) { stylePositionWatchers.has(alias) && stylePositionWatchers.get(alias).stop(); - stylePositionWatchers.set(alias, watchForNodePosition(node)); + stylePositionWatchers.set(alias, watchForNodePosition(node, { watchParent: true, watchSibling: false })); } function stopStylePositionWatchers() { Array.from(stylePositionWatchers.values()).forEach(function (watcher) { return watcher.stop(); }); @@ -2509,7 +2824,7 @@ if (fixes && Array.isArray(fixes.invert) && fixes.invert.length > 0) { invertStyle.textContent = [ fixes.invert.join(', ') + " {", - " filter: " + getCSSFilterValue(__assign({}, filter, { contrast: filter.mode === 0 ? filter.contrast : clamp(filter.contrast - 10, 0, 100) })) + " !important;", + " filter: " + getCSSFilterValue(__assign(__assign({}, filter), { contrast: filter.mode === 0 ? filter.contrast : clamp(filter.contrast - 10, 0, 100) })) + " !important;", '}', ].join('\n'); } @@ -2526,6 +2841,13 @@ overrideStyle.textContent = fixes && fixes.css ? replaceCSSTemplates(fixes.css) : ''; setupStylePositionWatcher(overrideStyle, 'override'); } + var shadowRootsWithOverrides = new Set(); + function createShadowStaticStyleOverrides(root) { + var inlineStyle = createOrUpdateStyle('darkreader--inline', root); + root.insertBefore(inlineStyle, root.firstChild); + inlineStyle.textContent = getInlineOverrideStyle(); + shadowRootsWithOverrides.add(root); + } function replaceCSSTemplates($cssText) { return $cssText.replace(/\${(.+?)}/g, function (m0, $color) { try { @@ -2547,7 +2869,14 @@ function createDynamicStyleOverrides() { cancelRendering(); updateVariables(getElementCSSVariables(document.documentElement)); - var newManagers = Array.from(document.querySelectorAll(STYLE_SELECTOR)) + var allStyles = Array.from(document.querySelectorAll(STYLE_SELECTOR)); + iterateShadowNodes(document.documentElement, function (node) { + var shadowStyles = node.shadowRoot.querySelectorAll(STYLE_SELECTOR); + if (shadowStyles.length > 0) { + allStyles.push.apply(allStyles, Array.from(shadowStyles)); + } + }); + var newManagers = Array.from(allStyles) .filter(function (style) { return !styleManagers.has(style) && shouldManageStyle(style); }) .map(function (style) { return createManager(style); }); var newVariables = newManagers @@ -2573,6 +2902,13 @@ } newManagers.forEach(function (manager) { return manager.watch(); }); var inlineStyleElements = Array.from(document.querySelectorAll(INLINE_STYLE_SELECTOR)); + iterateShadowNodes(document.documentElement, function (node) { + var elements = node.shadowRoot.querySelectorAll(INLINE_STYLE_SELECTOR); + if (elements.length > 0) { + createShadowStaticStyleOverrides(node.shadowRoot); + inlineStyleElements.push.apply(inlineStyleElements, Array.from(elements)); + } + }); inlineStyleElements.forEach(function (el) { return overrideInlineStyle(el, filter); }); } var loadingStylesCounter = 0; @@ -2682,14 +3018,14 @@ } function watchForUpdates() { watchForStyleChanges(function (_a) { - var created = _a.created, updated = _a.updated, removed = _a.removed; - var createdStyles = new Set(created); - var movedStyles = new Set(removed.filter(function (style) { return createdStyles.has(style); })); - removed - .filter(function (style) { return !movedStyles.has(style); }) - .forEach(function (style) { return removeManager(style); }); - var newManagers = Array.from(new Set(created.concat(updated))) - .filter(function (style) { return !styleManagers.has(style); }) + var created = _a.created, updated = _a.updated, removed = _a.removed, moved = _a.moved; + var stylesToRemove = removed; + var stylesToManage = created.concat(updated).concat(moved) + .filter(function (style) { return !styleManagers.has(style); }); + var stylesToRestore = moved + .filter(function (style) { return styleManagers.has(style); }); + stylesToRemove.forEach(function (style) { return removeManager(style); }); + var newManagers = stylesToManage .map(function (style) { return createManager(style); }); var newVariables = newManagers .map(function (manager) { return manager.details(); }) @@ -2706,6 +3042,7 @@ throttledRenderAllStyles(); } newManagers.forEach(function (manager) { return manager.watch(); }); + stylesToRestore.forEach(function (style) { return styleManagers.get(style).restore(); }); }); watchForInlineStyles(function (element) { overrideInlineStyle(element, filter); @@ -2716,6 +3053,12 @@ throttledRenderAllStyles(); } } + }, function (root) { + var inlineStyleElements = root.querySelectorAll(INLINE_STYLE_SELECTOR); + if (inlineStyleElements.length > 0) { + createShadowStaticStyleOverrides(root); + inlineStyleElements.forEach(function (el) { return overrideInlineStyle(el, filter); }); + } }); document.addEventListener('readystatechange', onReadyStateChange); } @@ -2759,6 +3102,10 @@ removeNode(document.head.querySelector('.darkreader--inline')); removeNode(document.head.querySelector('.darkreader--override')); } + shadowRootsWithOverrides.forEach(function (root) { + removeNode(root.querySelector('.darkreader--inline')); + }); + shadowRootsWithOverrides.clear(); Array.from(styleManagers.keys()).forEach(function (el) { return removeManager(el); }); Array.from(document.querySelectorAll('.darkreader')).forEach(removeNode); } @@ -2781,22 +3128,60 @@ engine: ThemeEngines.dynamicTheme, stylesheet: '', }; - function enable(themeOptions, fixes, isIFrame) { + var isIFrame$1 = (function () { + try { + return window.self !== window.top; + } + catch (err) { + console.warn(err); + return true; + } + })(); + function enable(themeOptions, fixes) { + if (themeOptions === void 0) { themeOptions = {}; } if (fixes === void 0) { fixes = null; } - if (isIFrame === void 0) { isIFrame = false; } - var theme = __assign({}, defaultTheme, themeOptions); + var theme = __assign(__assign({}, defaultTheme), themeOptions); if (theme.engine !== ThemeEngines.dynamicTheme) { throw new Error('Theme engine is not supported'); } - createOrUpdateDynamicTheme(theme, fixes, isIFrame); + createOrUpdateDynamicTheme(theme, fixes, isIFrame$1); } function disable() { removeDynamicTheme(); - } + } + var darkScheme = matchMedia('(prefers-color-scheme: dark)'); + var store = { + themeOptions: null, + fixes: null, + }; + function handleColorScheme() { + if (darkScheme.matches) { + enable(store.themeOptions, store.fixes); + } + else { + disable(); + } + } + function auto(themeOptions, fixes) { + if (themeOptions === void 0) { themeOptions = {}; } + if (fixes === void 0) { fixes = null; } + if (themeOptions) { + store = { themeOptions: themeOptions, fixes: fixes }; + handleColorScheme(); + darkScheme.addListener(handleColorScheme); + } + else { + darkScheme.removeListener(handleColorScheme); + disable(); + } + } + var setFetchMethod$1 = setFetchMethod; + exports.auto = auto; exports.disable = disable; exports.enable = enable; + exports.setFetchMethod = setFetchMethod$1; Object.defineProperty(exports, '__esModule', { value: true }); -})); +})));