Repository: darkreader/darkreader
Pull request #3263 (2020-07-28 12:13:28)

fix for praca.pl
Logo invert fix to include menu showing after scrolling down in offer.
Link you can check: https://www.praca.pl/analityk-biznesowy_3527880.html#0dd86a977b6b191a0525323bd50aaafa


Patch:
diff --git a/src/background/extension.ts b/src/background/extension.ts
index 7ba28d1c..81b9731b 100644
--- a/src/background/extension.ts
+++ b/src/background/extension.ts
@@ -9,7 +9,7 @@ import {setWindowTheme, resetWindowTheme} from './window-theme';
 import {getFontList, getCommands, setShortcut, canInjectScript} from './utils/extension-api';
 import {isFirefox} from '../utils/platform';
 import {isInTimeInterval, getDuration, isNightAtLocation} from '../utils/time';
-import {isURLInList, getURLHost, isURLEnabled} from '../utils/url';
+import {isURLInList, getURLHostOrProtocol, isURLEnabled} from '../utils/url';
 import ThemeEngines from '../generators/theme-engines';
 import createCSSFilterStylesheet from '../generators/css-filter';
 import {getDynamicThemeFixesFor} from '../generators/dynamic-theme';
@@ -300,7 +300,7 @@ export class Extension {
         const siteList = isInDarkList ?
             this.user.settings.siteListEnabled.slice() :
             this.user.settings.siteList.slice();
-        const pattern = getURLHost(url);
+        const pattern = getURLHostOrProtocol(url);
         const index = siteList.indexOf(pattern);
         if (index < 0) {
             siteList.push(pattern);
diff --git a/src/config/dark-sites.config b/src/config/dark-sites.config
index e1c7c11d..5127b97c 100644
--- a/src/config/dark-sites.config
+++ b/src/config/dark-sites.config
@@ -176,6 +176,7 @@ editor.method.ac
 egee.io
 eggsy.xyz
 eleaks.to
+ellie-app.com
 elybeatmaker.com
 emanuelemilella.com
 emeraldchat.com/app
diff --git a/src/config/dynamic-theme-fixes.config b/src/config/dynamic-theme-fixes.config
index dd73dcee..6989dd16 100644
--- a/src/config/dynamic-theme-fixes.config
+++ b/src/config/dynamic-theme-fixes.config
@@ -229,6 +229,16 @@ CSS
 
 ================================
 
+alexpage.de
+
+CSS
+#page {
+    background-image: none !important;
+    background-color: var(--darkreader-neutral-background) !important;
+}
+
+================================
+
 aljazeera.com
 
 INVERT
@@ -3710,7 +3720,7 @@ CSS
 praca.pl
 
 INVERT
-.app-header__logo
+img[alt="Praca.pl"]
 
 CSS
 .listing__logo {
@@ -3902,6 +3912,16 @@ canvas
 
 ================================
 
+relive.cc
+
+INVERT
+img[src*="logo-relive"]
+
+IGNORE IMAGE ANALYSIS
+.email-button i
+
+================================
+
 render.githubusercontent.com/view/ipynb
 
 INVERT
@@ -4736,6 +4756,16 @@ div.top_section_bg, div.bottom_section_bg {
 
 ================================
 
+tonsky.me
+
+CSS
+body {
+    background-image: none !important;
+    background-color: var(--darkreader-neutral-background) !important;
+}
+
+================================
+
 translate.google.*
 translate.google.*.*
 
diff --git a/src/inject/dynamic-theme/image.ts b/src/inject/dynamic-theme/image.ts
index dbc2e6bc..604722c8 100644
--- a/src/inject/dynamic-theme/image.ts
+++ b/src/inject/dynamic-theme/image.ts
@@ -1,6 +1,6 @@
 import {getSVGFilterMatrixValue} from '../../generators/svg-filter';
 import {bgFetch} from './network';
-import {getURLHost} from '../../utils/url';
+import {getURLHostOrProtocol} from '../../utils/url';
 import {loadAsDataURL} from '../../utils/network';
 import {FilterConfig} from '../../definitions';
 
@@ -34,7 +34,7 @@ export async function getImageDetails(url: string) {
 }
 
 async function getImageDataURL(url: string) {
-    if (getURLHost(url) === location.host) {
+    if (getURLHostOrProtocol(url) === (location.host || location.protocol)) {
         return await loadAsDataURL(url);
     }
     return await bgFetch({url, responseType: 'data-url'});
diff --git a/src/ui/connect/mock.ts b/src/ui/connect/mock.ts
index 7ad43aea..2a2c1427 100644
--- a/src/ui/connect/mock.ts
+++ b/src/ui/connect/mock.ts
@@ -1,4 +1,4 @@
-import {getURLHost} from '../../utils/url';
+import {getURLHostOrProtocol} from '../../utils/url';
 import {ExtensionData, TabInfo, Theme, UserSettings} from '../../definitions';
 
 export function getMockData(override = {} as Partial<ExtensionData>): ExtensionData {
@@ -7,6 +7,7 @@ export function getMockData(override = {} as Partial<ExtensionData>): ExtensionD
         isReady: true,
         settings: {
             enabled: true,
+            presets: [],
             theme: {
                 mode: 1,
                 brightness: 110,
@@ -97,7 +98,7 @@ export function createConnectorMock() {
             listener(data);
         },
         toggleURL(url) {
-            const pattern = getURLHost(url);
+            const pattern = getURLHostOrProtocol(url);
             const index = data.settings.siteList.indexOf(pattern);
             if (index >= 0) {
                 data.settings.siteList.splice(index, 1, pattern);
diff --git a/src/ui/devtools/components/body.tsx b/src/ui/devtools/components/body.tsx
index b36e6cb8..3887c151 100644
--- a/src/ui/devtools/components/body.tsx
+++ b/src/ui/devtools/components/body.tsx
@@ -5,7 +5,7 @@ import ThemeEngines from '../../../generators/theme-engines';
 import {DEVTOOLS_DOCS_URL} from '../../../utils/links';
 import {isFirefox} from '../../../utils/platform';
 import {ExtWrapper, TabInfo} from '../../../definitions';
-import {isURLInList} from '../../../utils/url';
+import {getCurrentThemePreset} from '../../popup/theme/utils';
 
 type BodyProps = ExtWrapper & {tab: TabInfo};
 
@@ -13,8 +13,7 @@ function Body({data, tab, actions}: BodyProps) {
     const {state, setState} = useState({errorText: null as string});
     let textNode: HTMLTextAreaElement;
     const previewButtonText = data.settings.previewNewDesign ? 'Switch to old design' : 'Preview new design';
-    const custom = data.settings.customThemes.find(({url: urlList}) => isURLInList(tab.url, urlList));
-    const theme = custom ? custom.theme : data.settings.theme;
+    const {theme} = getCurrentThemePreset({data, tab, actions});
 
     const wrapper = (theme.engine === ThemeEngines.staticTheme
         ? {
diff --git a/src/ui/popup/components/custom-settings-toggle/index.tsx b/src/ui/popup/components/custom-settings-toggle/index.tsx
index ae46d507..bd11475d 100644
--- a/src/ui/popup/components/custom-settings-toggle/index.tsx
+++ b/src/ui/popup/components/custom-settings-toggle/index.tsx
@@ -1,22 +1,20 @@
 import {m} from 'malevic';
 import {Button} from '../../../controls';
-import {getURLHost, isURLInList} from '../../../../utils/url';
+import {getURLHostOrProtocol, isURLInList} from '../../../../utils/url';
 import {getLocalMessage} from '../../../../utils/locales';
 import {ExtWrapper, TabInfo} from '../../../../definitions';
 
 export default function CustomSettingsToggle({data, tab, actions}: ExtWrapper & {tab: TabInfo}) {
-    const host = getURLHost(tab.url || '');
+    const host = getURLHostOrProtocol(tab.url);
 
     const isCustom = data.settings.customThemes.some(({url}) => isURLInList(tab.url, url));
 
-    const urlText = (host
-        ? host
-            .split('.')
-            .reduce((elements, part, i) => elements.concat(
-                <wbr />,
-                `${i > 0 ? '.' : ''}${part}`
-            ), [])
-        : 'current site');
+    const urlText = host
+        .split('.')
+        .reduce((elements, part, i) => elements.concat(
+            <wbr />,
+            `${i > 0 ? '.' : ''}${part}`
+        ), []);
 
     return (
         <Button
diff --git a/src/ui/popup/components/site-toggle/index.tsx b/src/ui/popup/components/site-toggle/index.tsx
index d5c32167..23d423dc 100644
--- a/src/ui/popup/components/site-toggle/index.tsx
+++ b/src/ui/popup/components/site-toggle/index.tsx
@@ -1,7 +1,7 @@
 import {m} from 'malevic';
 import CheckmarkIcon from './checkmark-icon';
 import {Button} from '../../../controls';
-import {getURLHost, isURLEnabled, isPDF} from '../../../../utils/url';
+import {getURLHostOrProtocol, isURLEnabled, isPDF} from '../../../../utils/url';
 import {ExtWrapper, TabInfo} from '../../../../definitions';
 
 export default function SiteToggleButton({data, tab, actions}: ExtWrapper & {tab: TabInfo}) {
@@ -19,16 +19,14 @@ export default function SiteToggleButton({data, tab, actions}: ExtWrapper & {tab
     );
     const pdf = isPDF(tab.url);
     const isSiteEnabled = isURLEnabled(tab.url, data.settings, tab);
-    const host = getURLHost(tab.url || '');
+    const host = getURLHostOrProtocol(tab.url);
 
-    const urlText = (host
-        ? host
-            .split('.')
-            .reduce((elements, part, i) => elements.concat(
-                <wbr />,
-                `${i > 0 ? '.' : ''}${part}`
-            ), [])
-        : 'current site');
+    const urlText = host
+        .split('.')
+        .reduce((elements, part, i) => elements.concat(
+            <wbr />,
+            `${i > 0 ? '.' : ''}${part}`
+        ), []);
 
     return (
         <Button
diff --git a/src/ui/popup/manage-settings-page/export-theme.tsx b/src/ui/popup/manage-settings-page/export-theme.tsx
index 737cb16f..48422210 100644
--- a/src/ui/popup/manage-settings-page/export-theme.tsx
+++ b/src/ui/popup/manage-settings-page/export-theme.tsx
@@ -2,12 +2,12 @@ import {m} from 'malevic';
 import {Button} from '../../controls';
 import {saveFile} from '../../utils';
 import ControlGroup from '../control-group';
-import {getURLHost} from '../../../utils/url';
+import {getURLHostOrProtocol} from '../../../utils/url';
 
 export default function ExportTheme() {
     const listener = ({type, data}, sender: chrome.runtime.MessageSender) => {
         if (type === 'export-css-response') {
-            const url = getURLHost(sender.tab.url).replace(/[^a-z0-1\-]/g, '-');
+            const url = getURLHostOrProtocol(sender.tab.url).replace(/[^a-z0-1\-]/g, '-');
             saveFile(`DarkReader-${url}.css`, data);
             chrome.runtime.onMessage.removeListener(listener);
         }
diff --git a/src/ui/popup/theme/preset-picker/index.tsx b/src/ui/popup/theme/preset-picker/index.tsx
index 2283c98a..6de19fb4 100644
--- a/src/ui/popup/theme/preset-picker/index.tsx
+++ b/src/ui/popup/theme/preset-picker/index.tsx
@@ -1,7 +1,7 @@
 import {m} from 'malevic';
 import {getContext} from 'malevic/dom';
 import {ThemePreset} from '../../../../definitions';
-import {isURLInList, isURLMatched, getURLHost} from '../../../../utils/url';
+import {isURLInList, isURLMatched, getURLHostOrProtocol} from '../../../../utils/url';
 import {DropDown, MessageBox} from '../../../controls';
 import {ViewProps} from '../../types';
 import {generateUID} from '../../../../utils/uid';
@@ -46,7 +46,7 @@ function PresetItem(props: ViewProps & {preset: ThemePreset}) {
 const MAX_ALLOWED_PRESETS = 3;
 
 export default function PresetPicker(props: ViewProps) {
-    const host = getURLHost(props.tab.url || '');
+    const host = getURLHostOrProtocol(props.tab.url);
     const preset = props.data.settings.presets.find(
         ({urls}) => isURLInList(props.tab.url, urls)
     );
diff --git a/src/ui/stylesheet-editor/components/body.tsx b/src/ui/stylesheet-editor/components/body.tsx
index e4592adc..cb7b8ea2 100644
--- a/src/ui/stylesheet-editor/components/body.tsx
+++ b/src/ui/stylesheet-editor/components/body.tsx
@@ -1,6 +1,6 @@
 import {m} from 'malevic';
 import {Button} from '../../controls';
-import {getURLHost, isURLInList} from '../../../utils/url';
+import {getURLHostOrProtocol, isURLInList} from '../../../utils/url';
 import {ExtWrapper, TabInfo} from '../../../definitions';
 
 interface BodyProps extends ExtWrapper {
@@ -9,7 +9,7 @@ interface BodyProps extends ExtWrapper {
 
 export default function Body({data, tab, actions}: BodyProps) {
 
-    const host = getURLHost(tab.url);
+    const host = getURLHostOrProtocol(tab.url);
     const custom = data.settings.customThemes.find(({url}) => isURLInList(tab.url, url));
 
     let textNode: HTMLTextAreaElement;
diff --git a/src/utils/url.ts b/src/utils/url.ts
index 7f8590d9..fbae5101 100644
--- a/src/utils/url.ts
+++ b/src/utils/url.ts
@@ -1,8 +1,13 @@
 import {UserSettings} from '../definitions';
 import {isIPV6, compareIPV6} from './ipv6';
 
-export function getURLHost(url: string) {
-    return url.match(/^(.*?\/{2,3})?(.+?)(\/|$)/)[2];
+export function getURLHostOrProtocol($url: string) {
+    const url = new URL($url);
+    if (url.host) {
+        return url.host;
+    } else {
+        return url.protocol;
+    }
 }
 
 export function compareURLPatterns(a: string, b: string) {


Test patch:
diff --git a/tests/utils/url.tests.ts b/tests/utils/url.tests.ts
index bc627c9e..a901737f 100644
--- a/tests/utils/url.tests.ts
+++ b/tests/utils/url.tests.ts
@@ -1,4 +1,4 @@
-import {isURLEnabled, isURLMatched, isPDF} from '../../src/utils/url';
+import {isURLEnabled, isURLMatched, isPDF, getURLHostOrProtocol} from '../../src/utils/url';
 import {UserSettings} from '../../src/definitions';
 
 test('URL is enabled', () => {
@@ -211,3 +211,13 @@ test('URL is enabled', () => {
         {isProtected: false, isInDarkList: false},
     )).toBe(true);
 });
+
+test('Get URL host or protocol', () => {
+    expect(getURLHostOrProtocol('https://www.google.com')).toBe('www.google.com');
+    expect(getURLHostOrProtocol('https://www.google.com/maps')).toBe('www.google.com');
+    expect(getURLHostOrProtocol('http://localhost:8080')).toBe('localhost:8080');
+    expect(getURLHostOrProtocol('about:blank')).toBe('about:');
+    expect(getURLHostOrProtocol('http://user:pass@www.example.org')).toBe('www.example.org');
+    expect(getURLHostOrProtocol('data:text/html,<html>Hello</html>')).toBe('data:');
+    expect(getURLHostOrProtocol('file:///Users/index.html')).toBe('file:');
+});