/*******************************************************************************

    uBlock Origin - a browser extension to block requests.
    Copyright (C) 2015-2018 Raymond Hill

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see {http://www.gnu.org/licenses/}.

    Home: https://github.com/gorhill/uBlock
*/

/* global uDom */

'use strict';

/******************************************************************************/

(( ) => {

/******************************************************************************/

const showdomButton = uDom.nodeFromId('showdom');

// Don't bother if the browser is not modern enough.
if (
    typeof Map === 'undefined' ||
    Map.polyfill ||
    typeof WeakMap === 'undefined'
) {
    showdomButton.classList.add('disabled');
    return;
}

/******************************************************************************/

const logger = self.logger;
var inspectorConnectionId;
var inspectedTabId = 0;
var inspectedURL = '';
var inspectedHostname = '';
var inspector = uDom.nodeFromId('domInspector');
var domTree = uDom.nodeFromId('domTree');
var uidGenerator = 1;
var filterToIdMap = new Map();

/******************************************************************************/

const messaging = vAPI.messaging;

vAPI.MessagingConnection.addListener(function(msg) {
    if ( msg.from !== 'domInspector' || msg.to !== 'loggerUI' ) { return; }
    switch ( msg.what ) {
    case 'connectionBroken':
        if ( inspectorConnectionId === msg.id ) {
            filterToIdMap.clear();
            logger.removeAllChildren(domTree);
            inspectorConnectionId = undefined;
        }
        injectInspector();
        break;
    case 'connectionMessage':
        if ( msg.payload.what === 'domLayoutFull' ) {
            inspectedURL = msg.payload.url;
            inspectedHostname = msg.payload.hostname;
            renderDOMFull(msg.payload);
        } else if ( msg.payload.what === 'domLayoutIncremental' ) {
            renderDOMIncremental(msg.payload);
        }
        break;
    case 'connectionRequested':
        if ( msg.tabId === undefined || msg.tabId !== inspectedTabId ) {
            return;
        }
        filterToIdMap.clear();
        logger.removeAllChildren(domTree);
        inspectorConnectionId = msg.id;
        return true;
    }
});

/******************************************************************************/

const nodeFromDomEntry = function(entry) {
    var node, value;
    var li = document.createElement('li');
    li.setAttribute('id', entry.nid);
    // expander/collapser
    li.appendChild(document.createElement('span'));
    // selector
    node = document.createElement('code');
    node.textContent = entry.sel;
    li.appendChild(node);
    // descendant count
    value = entry.cnt || 0;
    node = document.createElement('span');
    node.textContent = value !== 0 ? value.toLocaleString() : '';
    node.setAttribute('data-cnt', value);
    li.appendChild(node);
    // cosmetic filter
    if ( entry.filter === undefined ) {
        return li;
    }
    node = document.createElement('code');
    node.classList.add('filter');
    value = filterToIdMap.get(entry.filter);
    if ( value === undefined ) {
        value = uidGenerator.toString();
        filterToIdMap.set(entry.filter, value);
        uidGenerator += 1;
    }
    node.setAttribute('data-filter-id', value);
    node.textContent = entry.filter;
    li.appendChild(node);
    li.classList.add('isCosmeticHide');
    return li;
};

/******************************************************************************/

const appendListItem = function(ul, li) {
    ul.appendChild(li);
    // Ancestor nodes of a node which is affected by a cosmetic filter will
    // be marked as "containing cosmetic filters", for user convenience.
    if ( li.classList.contains('isCosmeticHide') === false ) { return; }
    for (;;) {
        li = li.parentElement.parentElement;
        if ( li === null ) { break; }
        li.classList.add('hasCosmeticHide');
    }
};

/******************************************************************************/

const renderDOMFull = function(response) {
    var domTreeParent = domTree.parentElement;
    var ul = domTreeParent.removeChild(domTree);
    logger.removeAllChildren(domTree);

    filterToIdMap.clear();

    var lvl = 0;
    var entries = response.layout;
    var n = entries.length;
    var li, entry;
    for ( var i = 0; i < n; i++ ) {
        entry = entries[i];
        if ( entry.lvl === lvl ) {
            li = nodeFromDomEntry(entry);
            appendListItem(ul, li);
            continue;
        }
        if ( entry.lvl > lvl ) {
            ul = document.createElement('ul');
            li.appendChild(ul);
            li.classList.add('branch');
            li = nodeFromDomEntry(entry);
            appendListItem(ul, li);
            lvl = entry.lvl;
            continue;
        }
        // entry.lvl < lvl
        while ( entry.lvl < lvl ) {
            ul = li.parentNode;
            li = ul.parentNode;
            ul = li.parentNode;
            lvl -= 1;
        }
        li = nodeFromDomEntry(entry);
        appendListItem(ul, li);
    }
    while ( ul.parentNode !== null ) {
        ul = ul.parentNode;
    }
    ul.firstElementChild.classList.add('show');

    domTreeParent.appendChild(domTree);
};

// https://www.youtube.com/watch?v=IDGNA83mxDo

/******************************************************************************/

const patchIncremental = function(from, delta) {
    var span, cnt;
    var li = from.parentElement.parentElement;
    var patchCosmeticHide = delta >= 0 &&
                            from.classList.contains('isCosmeticHide') &&
                            li.classList.contains('hasCosmeticHide') === false;
    // Include descendants count when removing a node
    if ( delta < 0 ) {
        delta -= countFromNode(from);
    }
    for ( ; li.localName === 'li'; li = li.parentElement.parentElement ) {
        span = li.children[2];
        if ( delta !== 0 ) {
            cnt = countFromNode(li) + delta;
            span.textContent = cnt !== 0 ? cnt.toLocaleString() : '';
            span.setAttribute('data-cnt', cnt);
        }
        if ( patchCosmeticHide ) {
            li.classList.add('hasCosmeticHide');
        }
    }
};

/******************************************************************************/

const renderDOMIncremental = function(response) {
    // Process each journal entry:
    //  1 = node added
    // -1 = node removed
    var journal = response.journal;
    var nodes = new Map(response.nodes);
    var entry, previous, li, ul;
    for ( var i = 0, n = journal.length; i < n; i++ ) {
        entry = journal[i];
        // Remove node
        if ( entry.what === -1 ) {
            li = document.getElementById(entry.nid);
            if ( li === null ) { continue; }
            patchIncremental(li, -1);
            li.parentNode.removeChild(li);
            continue;
        }
        // Modify node
        if ( entry.what === 0 ) {
            // TODO: update selector/filter
            continue;
        }
        // Add node as sibling
        if ( entry.what === 1 && entry.l ) {
            previous = document.getElementById(entry.l);
            // This should not happen
            if ( previous === null ) {
                // throw new Error('No left sibling!?');
                continue;
            }
            ul = previous.parentElement;
            li = nodeFromDomEntry(nodes.get(entry.nid));
            ul.insertBefore(li, previous.nextElementSibling);
            patchIncremental(li, 1);
            continue;
        }
        // Add node as child
        if ( entry.what === 1 && entry.u ) {
            li = document.getElementById(entry.u);
            // This should not happen
            if ( li === null ) {
                // throw new Error('No parent!?');
                continue;
            }
            ul = li.querySelector('ul');
            if ( ul === null ) {
                ul = document.createElement('ul');
                li.appendChild(ul);
                li.classList.add('branch');
            }
            li = nodeFromDomEntry(nodes.get(entry.nid));
            ul.appendChild(li);
            patchIncremental(li, 1);
            continue;
        }
    }
};

// https://www.youtube.com/watch?v=6u2KPtJB9h8

/******************************************************************************/

const countFromNode = function(li) {
    var span = li.children[2];
    var cnt = parseInt(span.getAttribute('data-cnt'), 10);
    return isNaN(cnt) ? 0 : cnt;
};

/******************************************************************************/

const selectorFromNode = function(node) {
    var selector = '';
    var code;
    while ( node !== null ) {
        if ( node.localName === 'li' ) {
            code = node.querySelector('code');
            if ( code !== null ) {
                selector = code.textContent + ' > ' + selector;
                if ( selector.indexOf('#') !== -1 ) {
                    break;
                }
            }
        }
        node = node.parentElement;
    }
    return selector.slice(0, -3);
};

/******************************************************************************/

const selectorFromFilter = function(node) {
    while ( node !== null ) {
        if ( node.localName === 'li' ) {
            var code = node.querySelector('code:nth-of-type(2)');
            if ( code !== null ) {
                return code.textContent;
            }
        }
        node = node.parentElement;
    }
    return '';
};

/******************************************************************************/

const nidFromNode = function(node) {
    var li = node;
    while ( li !== null ) {
        if ( li.localName === 'li' ) {
            return li.id || '';
        }
        li = li.parentElement;
    }
    return '';
};

/******************************************************************************/

const startDialog = (function() {
    let dialog;
    let textarea;
    let hideSelectors = [];
    let unhideSelectors = [];
    let inputTimer;

    const onInputChanged = (function() {
        const parse = function() {
            inputTimer = undefined;
            hideSelectors = [];
            unhideSelectors = [];

            const re = /^([^#]*)(#@?#)(.+)$/;
            for ( let line of textarea.value.split(/\s*\n\s*/) ) {
                line = line.trim();
                if ( line === '' || line.charAt(0) === '!' ) { continue; }
                const matches = re.exec(line);
                if ( matches === null || matches.length !== 4 ) { continue; }
                if ( inspectedHostname.lastIndexOf(matches[1]) === -1 ) {
                    continue;
                }
                if ( matches[2] === '##' ) {
                    hideSelectors.push(matches[3]);
                } else {
                    unhideSelectors.push(matches[3]);
                }
            }

            showCommitted();
        };

        return function parseAsync() {
            if ( inputTimer === undefined ) {
                inputTimer = vAPI.setTimeout(parse, 743);
            }
        };
    })();

    const onClicked = function(ev) {
        var target = ev.target;

        ev.stopPropagation();

        if ( target.id === 'createCosmeticFilters' ) {
            messaging.send('loggerUI', {
                what: 'createUserFilter',
                filters: textarea.value,
            });
            // Force a reload for the new cosmetic filter(s) to take effect
            messaging.send('loggerUI', {
                what: 'reloadTab',
                tabId: inspectedTabId,
            });
            return stop();
        }
    };

    const showCommitted = function() {
        vAPI.MessagingConnection.sendTo(inspectorConnectionId, {
            what: 'showCommitted',
            hide: hideSelectors.join(',\n'),
            unhide: unhideSelectors.join(',\n')
        });
    };

    const showInteractive = function() {
        vAPI.MessagingConnection.sendTo(inspectorConnectionId, {
            what: 'showInteractive',
            hide: hideSelectors.join(',\n'),
            unhide: unhideSelectors.join(',\n')
        });
    };

    const start = function() {
        dialog = logger.modalDialog.create('#cosmeticFilteringDialog', stop);
        textarea = dialog.querySelector('textarea');
        hideSelectors = [];
        for ( const node of domTree.querySelectorAll('code.off') ) {
            if ( node.classList.contains('filter') ) { continue; }
            hideSelectors.push(selectorFromNode(node));
        }
        const taValue = [];
        for ( const selector of hideSelectors ) {
            taValue.push(inspectedHostname + '##' + selector);
        }
        const ids = new Set();
        for ( const node of domTree.querySelectorAll('code.filter.off') ) {
            const id = node.getAttribute('data-filter-id');
            if ( ids.has(id) ) { continue; }
            ids.add(id);
            unhideSelectors.push(node.textContent);
            taValue.push(inspectedHostname + '#@#' + node.textContent);
        }
        textarea.value = taValue.join('\n');
        textarea.addEventListener('input', onInputChanged);
        dialog.addEventListener('click', onClicked, true);
        showCommitted();
        logger.modalDialog.show();
    };

    const stop = function() {
        if ( inputTimer !== undefined ) {
            clearTimeout(inputTimer);
            inputTimer = undefined;
        }
        showInteractive();
        textarea.removeEventListener('input', onInputChanged);
        dialog.removeEventListener('click', onClicked, true);
        dialog = undefined;
        textarea = undefined;
        hideSelectors = [];
        unhideSelectors = [];
    };

    return start;
})();

/******************************************************************************/

const onClicked = function(ev) {
    ev.stopPropagation();

    if ( inspectedTabId === 0 ) { return; }

    var target = ev.target;
    var parent = target.parentElement;

    // Expand/collapse branch
    if (
        target.localName === 'span' &&
        parent instanceof HTMLLIElement &&
        parent.classList.contains('branch') &&
        target === parent.firstElementChild
    ) {
        var state = parent.classList.toggle('show');
        if ( !state ) {
            for ( var node of parent.querySelectorAll('.branch') ) {
                node.classList.remove('show');
            }
        }
        return;
    }

    // Not a node or filter
    if ( target.localName !== 'code' ) { return; }

    // Toggle cosmetic filter
    if ( target.classList.contains('filter') ) {
        vAPI.MessagingConnection.sendTo(inspectorConnectionId, {
            what: 'toggleFilter',
            original: false,
            target: target.classList.toggle('off'),
            selector: selectorFromNode(target),
            filter: selectorFromFilter(target),
            nid: nidFromNode(target)
        });
        uDom('[data-filter-id="' + target.getAttribute('data-filter-id') + '"]', inspector).toggleClass(
            'off',
            target.classList.contains('off')
        );
    }
    // Toggle node
    else {
        vAPI.MessagingConnection.sendTo(inspectorConnectionId, {
            what: 'toggleNodes',
            original: true,
            target: target.classList.toggle('off') === false,
            selector: selectorFromNode(target),
            nid: nidFromNode(target)
        });
    }

    var cantCreate = domTree.querySelector('.off') === null;
    inspector.querySelector('.permatoolbar .revert').classList.toggle('disabled', cantCreate);
    inspector.querySelector('.permatoolbar .commit').classList.toggle('disabled', cantCreate);
};

/******************************************************************************/

const onMouseOver = (function() {
    var mouseoverTarget = null;
    var mouseoverTimer = null;

    var timerHandler = function() {
        mouseoverTimer = null;
        vAPI.MessagingConnection.sendTo(inspectorConnectionId, {
            what: 'highlightOne',
            selector: selectorFromNode(mouseoverTarget),
            nid: nidFromNode(mouseoverTarget),
            scrollTo: true
        });
    };

    return function(ev) {
        if ( inspectedTabId === 0 ) { return; }
        // Convenience: skip real-time highlighting if shift key is pressed.
        if ( ev.shiftKey ) { return; }
        // Find closest `li`
        var target = ev.target;
        while ( target !== null ) {
            if ( target.localName === 'li' ) { break; }
            target = target.parentElement;
        }
        if ( target === mouseoverTarget ) { return; }
        mouseoverTarget = target;
        if ( mouseoverTimer === null ) {
            mouseoverTimer = vAPI.setTimeout(timerHandler, 50);
        }
    };
})();

/******************************************************************************/

const currentTabId = function() {
    if ( showdomButton.classList.contains('active') === false ) { return 0; }
    return logger.tabIdFromPageSelector();
};

/******************************************************************************/

const injectInspector = function() {
    const tabId = currentTabId();
    if ( tabId <= 0 ) { return; }
    inspectedTabId = tabId;
    messaging.send('loggerUI', {
        what: 'scriptlet',
        tabId,
        scriptlet: 'dom-inspector',
    });
};

/******************************************************************************/

const shutdownInspector = function() {
    if ( inspectorConnectionId !== undefined ) {
        vAPI.MessagingConnection.disconnectFrom(inspectorConnectionId);
        inspectorConnectionId = undefined;
    }
    logger.removeAllChildren(domTree);
    inspector.classList.remove('vExpanded');
    inspectedTabId = 0;
};

/******************************************************************************/

const onTabIdChanged = function() {
    const tabId = currentTabId();
    if ( tabId <= 0 ) {
        return toggleOff();
    }
    if ( inspectedTabId !== tabId ) {
        shutdownInspector();
        injectInspector();
    }
};

/******************************************************************************/

const toggleVCompactView = function() {
    var state = inspector.classList.toggle('vExpanded');
    var branches = document.querySelectorAll('#domInspector li.branch');
    for ( var branch of branches ) {
        branch.classList.toggle('show', state);
    }
};

const toggleHCompactView = function() {
    inspector.classList.toggle('hCompact');
};

/******************************************************************************/
/*
var toggleHighlightMode = function() {
    vAPI.MessagingConnection.sendTo(inspectorConnectionId, {
        what: 'highlightMode',
        invert: uDom.nodeFromSelector('#domInspector .permatoolbar .highlightMode').classList.toggle('invert')
    });
};
*/
/******************************************************************************/

const revert = function() {
    uDom('#domTree .off').removeClass('off');
    vAPI.MessagingConnection.sendTo(
        inspectorConnectionId,
        { what: 'resetToggledNodes' }
    );
    inspector.querySelector('.permatoolbar .revert').classList.add('disabled');
    inspector.querySelector('.permatoolbar .commit').classList.add('disabled');
};

/******************************************************************************/

const toggleOn = function() {
    uDom.nodeFromId('inspectors').classList.add('dom');
    window.addEventListener('beforeunload', toggleOff);
    document.addEventListener('tabIdChanged', onTabIdChanged);
    domTree.addEventListener('click', onClicked, true);
    domTree.addEventListener('mouseover', onMouseOver, true);
    uDom.nodeFromSelector('#domInspector .vCompactToggler').addEventListener('click', toggleVCompactView);
    uDom.nodeFromSelector('#domInspector .hCompactToggler').addEventListener('click', toggleHCompactView);
    //uDom.nodeFromSelector('#domInspector .permatoolbar .highlightMode').addEventListener('click', toggleHighlightMode);
    uDom.nodeFromSelector('#domInspector .permatoolbar .revert').addEventListener('click', revert);
    uDom.nodeFromSelector('#domInspector .permatoolbar .commit').addEventListener('click', startDialog);
    injectInspector();
};

/******************************************************************************/

const toggleOff = function() {
    showdomButton.classList.remove('active');
    uDom.nodeFromId('inspectors').classList.remove('dom');
    shutdownInspector();
    window.removeEventListener('beforeunload', toggleOff);
    document.removeEventListener('tabIdChanged', onTabIdChanged);
    domTree.removeEventListener('click', onClicked, true);
    domTree.removeEventListener('mouseover', onMouseOver, true);
    uDom.nodeFromSelector('#domInspector .vCompactToggler').removeEventListener('click', toggleVCompactView);
    uDom.nodeFromSelector('#domInspector .hCompactToggler').removeEventListener('click', toggleHCompactView);
    //uDom.nodeFromSelector('#domInspector .permatoolbar .highlightMode').removeEventListener('click', toggleHighlightMode);
    uDom.nodeFromSelector('#domInspector .permatoolbar .revert').removeEventListener('click', revert);
    uDom.nodeFromSelector('#domInspector .permatoolbar .commit').removeEventListener('click', startDialog);
    inspectedTabId = 0;
};

/******************************************************************************/

const toggle = function() {
    if ( showdomButton.classList.toggle('active') ) {
        toggleOn();
    } else {
        toggleOff();
    }
    logger.resize();
};

/******************************************************************************/

showdomButton.addEventListener('click', toggle);

/******************************************************************************/

})();


keep keep keep keep add keep keep keep keep


uBlock Origin

extension name.

Nareszcie skuteczny bloker charakteryzujący się niskim użyciem procesora i pamięci.

this will be in the Chrome web store: must be 132 characters or less

uBlock₀ – Panel sterowania

English: uBlock₀ — Dashboard

Uwaga! Masz niezapisane zmiany

A warning in the dashboard when navigating away from unsaved changes

Zostań

Label for button to prevent navigating away from unsaved changes

Ignoruj

Label for button to ignore unsaved changes

Ustawienia

appears as tab name in dashboard

Listy filtrów

appears as tab name in dashboard

Moje filtry

appears as tab name in dashboard

Moje reguły

appears as tab name in dashboard

Zaufane witryny

appears as tab name in dashboard

Skróty

appears as tab name in dashboard

uBlock₀ – Rejestrator

Title for the logger window

O rozszerzeniu

appears as tab name in dashboard

Pomoc techniczna

appears as tab name in dashboard

uBlock₀ – Podgląd zasobu

Title for the asset viewer page

Ustawienia zaawansowane

Title for the advanced settings page

Kliknij, aby włączyć/wyłączyć uBlock₀ na tej witrynie.

Kliknij z wciśniętym klawiszem Ctrl, aby włączyć/wyłączyć uBlock₀ tylko na tej stronie.

English: Click: disable/enable uBlock₀ for this site.

Ctrl+click: disable uBlock₀ only on this page.

Kliknij, aby wyłączyć uBlock₀ dla tej witryny.

Kliknij z wciśniętym klawiszem Ctrl, aby wyłączyć uBlock₀ tylko dla tej strony.

Message to be read by screen readers

Kliknij, aby włączyć uBlock₀ dla tej witryny.

Message to be read by screen readers

zablokowane żądania

English: requests blocked

na tej stronie

English: on this page

{{count}} ({{percent}}%)

Example: 15 (13%)

od instalacji

English: since install

lub

English: or

Zablokowane na tej stronie

For the new mobile-friendly popup design

Zablokowane od instalacji

Domeny podłączone

Otwórz panel sterowania

English: Click to open the dashboard

Przejdź do trybu usuwania elementów

Tooltip for the element-zapper icon in the popup panel

Przejdź do trybu zaznaczania elementów

English: Enter element picker mode

Otwórz rejestrator

Tooltip used for the logger icon in the panel

Zgłoś problem z tą stroną

Tooltip used for the 'chat' icon in the panel

Włącz/wyłącz blokowanie wyskakujących okien na tej witrynie

Tooltip for the no-popups per-site switch

Kliknij, aby zablokować wszystkie wyskakujące okna na tej witrynie

Kliknij, aby nie blokować wyskakujących okien na tej witrynie

Włącz/wyłącz blokowanie dużych elementów multimedialnych na tej witrynie

Tooltip for the no-large-media per-site switch

Kliknij, aby zablokować duże elementy multimedialne na tej witrynie

Kliknij, aby nie blokować dużych elementów multimedialnych na tej witrynie

Włącz/wyłącz kosmetyczne filtrowanie na tej witrynie

Tooltip for the no-cosmetic-filtering per-site switch

Kliknij, aby wyłączyć filtrowanie kosmetyczne na tej witrynie

Kliknij, aby włączyć filtrowanie kosmetyczne na tej witrynie

Włącz/wyłącz blokowanie zdalnych czcionek na tej witrynie

Tooltip for the no-remote-fonts per-site switch

Kliknij, aby zablokować zdalne czcionki na tej witrynie

Kliknij, aby nie blokować zdalnych czcionek na tej witrynie

Kliknij, aby wyłączyć JavaScript na tej witrynie

Tooltip for the no-scripting per-site switch

Kliknij, aby JavaScript nie był już wyłączony na tej witrynie

Wyskakujące okna

Caption for the no-popups per-site switch

Duże elementy multimedialne

Caption for the no-large-media per-site switch

Filtrowanie kosmetyczne

Caption for the no-cosmetic-filtering per-site switch

Zdalne czcionki

Caption for the no-remote-fonts per-site switch

JavaScript

Caption for the no-scripting per-site switch

Więcej

Label to be used to show popup panel sections

Mniej

Label to be used to hide popup panel sections

Reguły globalne. W tej kolumnie znajdują się reguły stosowane na wszystkich witrynach.

Tooltip when hovering the top-most cell of the global-rules column.

Reguły lokalne. W tej kolumnie znajdują się reguły stosowane tylko na bieżącej witrynie.
Reguły lokalne zastępują reguły globalne.

Tooltip when hovering the top-most cell of the local-rules column.

Kliknij, aby zastosować zmiany na stałe.

Tooltip when hovering over the padlock in the dynamic filtering pane.

Kliknij, aby odrzucić zmiany.

Tooltip when hovering over the eraser in the dynamic filtering pane.

wszystko

obrazki

domeny zewnętrzne

zewnętrzne CSS/obrazki

zagnieżdżone skrypty

skrypty własne

skrypty z domen zewnętrznych

ramki z domen zewnętrznych

podłączone domeny

appears in popup

{{count}} z {{total}}

appears in popup

Wersja

Example of use: Version 1.26.4

↑: Wyróżnij wiersze zawierające skrypty z domen zewnętrznych

Tooltip shown when hovering small filtering widget in '3rd-party scripts' cell

↑: Wyróżnij wiersze zawierające ramki z domen zewnętrznych

Tooltip shown when hovering small filtering widget in '3rd-party frames' cell

Utwórz

English: Create

Wybierz

English: Pick

Zamknij

English: Quit

Podgląd

Element picker preview mode: will cause the elements matching the current filter to be removed from the page

Filtry sieciowe

English: header for a type of filter in the element picker dialog

Filtry kosmetyczne

English: Cosmetic filters

Klik, Ctrl + klik

English: Click, Ctrl-click

Zablokuj element…

An entry in the browser's contextual menu

Ukrywaj symbole zastępcze zablokowanych elementów

English: Hide placeholders of blocked elements

Wyświetlaj liczbę zablokowanych żądań na ikonie rozszerzenia

English: Show the number of blocked requests on the icon

Nie wyświetlaj dymków podpowiedzi

A checkbox in the Settings pane

Używaj menu kontekstowego, gdzie to możliwe

English: Make use of context menu where appropriate

Interfejs przyjazny osobom z zaburzeniami widzenia kolorów

English: Color-blind friendly

Wygląd

Section for controlling user interface appearance

Motyw

Label for checkbox to enable a custom dark theme

Własny kolor akcentujący

Label for checkbox to pick an accent color

Włącz obsługę zapisu ustawień w chmurze

Jestem zaawansowanym użytkownikiem

Checkbox to let user access advanced, technical features

Wyłącz wstępne pobieranie (by uniknąć połączeń z zablokowanymi zapytaniami sieciowymi)

English:

Wyłącz śledzenie kliknięć odnośników

English:

Zapobiegaj ujawnianiu lokalnego adresu IP poprzez interfejs WebRTC

English:

Działanie domyślne

Te ustawienia mogą być zastąpione przez ustawienia danej witryny

Wyłącz filtrowanie kosmetyczne

Blokuj elementy multimedialne większe niż {{input}} KiB

Blokuj zdalne czcionki

Wyłącz JavaScript

The default state for the per-site no-scripting switch

Blokuj raporty CSP

background information: https://github.com/gorhill/uBlock/issues/3150

Pokaż rzeczywistą nazwę domeny (CNAME)

background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513

Zaawansowane

Section for controlling advanced-user settings

Funkcje odpowiednie tylko dla użytkowników z przygotowaniem technicznym

Description of section controlling advanced-user settings

Ustawienia zaawansowane

For the tooltip of a link which gives access to advanced settings

Ostatnie przywrócenie wykonano:

English: Last restore:

Ostatnią kopię zapasową wykonano:

English: Last backup:

Filtry sieciowe: {{netFilterCount}} + filtry kosmetyczne: {{cosmeticFilterCount}} z:

Appears at the top of the _3rd-party filters_ pane

użytych {{used}} z {{total}}

Appears aside each filter list in the _3rd-party filters_ pane

Automatycznie aktualizuj listy filtrów

A checkbox in the _3rd-party filters_ pane

Zaktualizuj teraz

A button in the in the _3rd-party filters_ pane

Wyczyść całą pamięć podręczną

Przetwarzaj i stosuj filtry kosmetyczne

English: Parse and enforce Adblock+ element hiding filters.

Filtry kosmetyczne służą do ukrywania elementów stron internetowych uważanych za wizualne uciążliwe, które to nie mogą zostać zablokowane za pomocą filtrów żądań sieciowych.

Describes the purpose of the 'Parse and enforce cosmetic filters' feature.

Ignoruj ogólne filtry kosmetyczne

This will cause uBO to ignore all generic cosmetic filters.

Ogólne filtry kosmetyczne, to filtry które mają być zastosowane na wszystkich stronach internetowych. Włącznie tej funkcji zmniejszy obciążenie procesora i pamięci.

Zaleca się włączenie tej funkcji na mniej wydajnych urządzeniach.

Describes the purpose of the 'Ignore generic cosmetic filters' feature.

Zawieś aktywność sieciową do czasu załadowania wszystkich list filtrów

A checkbox in the 'Filter lists' pane

Listy zablokowanych hostów

English: Lists of blocked hosts

Zastosuj zmiany

English: Apply changes

Wbudowane

Header for the uBlock filters section in 'Filter lists pane'

Reklamy

English: Ads

Prywatność

English: Privacy

Domeny ze złośliwym oprogramowaniem

English: Malware domains

Elementy irytujące

The header identifying the filter lists in the category 'annoyances'

Wielofunkcyjne

English: Multipurpose

Regiony, języki

English: Regions, languages

Własne

English: Custom

Importuj…

The label for the checkbox used to import external filter lists

Jeden adres URL listy na linię. Błędne adresy URL będą pomijane.

Short information about how to use the textarea to import external filter lists by URL

Nieaktualna.

used as a tooltip for the out-of-date icon beside a list

zobacz zawartość

used as a tooltip for eye icon beside a list

Zaktualizowano: {{ago}}.
Kliknij, aby wymusić aktualizację.

used as a tooltip for the clock icon beside a list

Aktualizowanie…

used as a tooltip for the spinner icon beside a list

Błąd sieci uniemożliwił aktualizację zasobów.

used as a tooltip for error icon beside a list

W wierszu może być tylko jeden filtr. Filtrem może być nazwa hosta lub filtr kompatybilny z EasyList. Wiersze poprzedzone znakiem <code>!</code> będą pomijane.

Short information about how to create custom filters

Importuj i dołącz

English: Import and append

Eksportuj

English: Export

ublock-statyczne-filtry_{{datetime}}.txt

English: my-ublock-static-filters_{{datetime}}.txt

Zastosuj zmiany

English: Apply changes

Stałe reguły

header

Tymczasowe reguły

header

Przywróć

This will remove all temporary rules

Zatwierdź

This will persist temporary rules

Edytuj

Will enable manual-edit mode (textarea)

Zapisz

Will save manually-edited content and exit manual-edit mode

Odrzuć

Will discard manually-edited content and exit manual-edit mode

Importuj z pliku…

Eksportuj do pliku…

ublock-dynamiczne-reguly_{{datetime}}.txt

default file name to use

Lista reguł dynamicznego filtrowania.

English: List of your dynamic filtering rules.

Składnia reguły: źródło cel typ akcja (pełna dokumentacja).

English: dynamic rule syntax and full documentation.

Sortowanie:

English: label for sort option.

Typ reguły

English: a sort option for list of rules.

Źródło

Miejsce docelowe

Wytyczne zaufanych witryn nakazują, na których stronach uBlock Origin powinien zostać wyłączony. Jeden wpis na linię.

A concise description of the 'Trusted sites' pane.

Importuj i dołącz

English: Import and append

Eksportuj

English: Export

The default filename to use for import/export purpose

Zastosuj zmiany

English: Apply changes

Typ

English: Type

Domena

English: Domain

Adres URL

English: URL

Filtr

English: Filter

Wszystkie

Appears in the logger's tab selector

Bez kart

Pretty name for behind-the-scene network requests

Aktywna karta

Appears in the logger's tab selector

Przeładuj zawartość karty

Tooltip for the reload button in the logger page

Przełącz inspektor DOM

Tooltip for the DOM inspector button in the logger page

Przełącz panel popup

Tooltip for the popup panel button in the logger page

uBlock Origin wiki: Rejestrator (ang.)

Tooltip for the top-right info label in the logger page

Wyczyść rejestr

Tooltip for the eraser in the logger page; used to blank the content of the logger

Pauzuj rejestrowanie (porzuć wszystkie przychodzące dane)

Tooltip for the pause button in the logger page

Wznów rejestrowanie

Tooltip for the play button in the logger page

Przełącz filtrowanie rejestru

Tooltip for the row filterer button in the logger page

filtruj zawartość rejestru

Placeholder string for logger output filtering input field

Opcje filtrowania rejestru

Tooltip for the button to bring up logger output filtering options

Nie

A keyword in the built-in row filtering expression

akcje

A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)

zablokowane

dozwolone

zmodyfikowane

własna domena

domeny zewnętrzne

Szczegóły

Small header to identify the 'Details' pane for a specific logger entry

Filtr

Label to identify a filter field

Lista filtrów

Label to identify a filter list field

Reguła

Label to identify a rule field

Kontekst

Label to identify a context field (typically a hostname)

Kontekst główny

Label to identify a root context field (typically a hostname)

Lokalność

Label to identify a field providing partyness information

Typ

Label to identify the type of an entry

Adres URL

Label to identify the URL of an entry

Reguła URL

Small header to identify the dynamic URL filtering section

Kontekst:

Label for the context selector

Typ:

Label for the type selector

Filtr statyczny

Small header to identify the static filtering section

{{action}} żądania sieciowe {{type}}, których adres URL jest zgodny z: {{url}} {{br}}i pochodzi {{origin}}, {{importance}} filtr znajduje się na liście wyjątków.

Used in the static filtering wizard

Blokuj

Used in the static filtering wizard

Zezwalaj na

Used in the static filtering wizard

typu „{{type}}”

Used in the static filtering wizard

każdego typu

Used in the static filtering wizard

z „{{origin}}”

Used in the static filtering wizard

z dowolnego miejsca

Used in the static filtering wizard

z wyjątkiem, gdy

Used in the static filtering wizard

nawet, jeśli

Used in the static filtering wizard

Filtr statyczny <code>{{filter}}</code> znajdujący się w:

Below this sentence, the filter list(s) in which the filter was found

Filtr statyczny nie został znaleziony w aktualnie włączonych listach filtrów

Message to show when a filter cannot be found in any filter lists

Wpisy rejestru niespełniające wszystkich trzech warunków będą automatycznie porzucane:

Logger setting: A sentence to describe the purpose of the settings below

Zachowuj wpisy z ostatnich {{input}} minut

A logger setting

Zachowuj nie więcej niż {{input}} przeładowań strony na kartę

A logger setting

Zachowuj nie więcej niż {{input}} wpisów na kartę

A logger setting

Użyj {{input}} linie na wpis w widoku poszerzonym

A logger setting

Ukryj kolumny:

Logger settings: a sentence to describe the purpose of the checkboxes below

{{input}} Czas

A label for the time column

{{input}} Filtr/reguła

A label for the filter or rule column

{{input}} Kontekst

A label for the context column

{{input}} Lokalność

A label for the partyness column

Lista

Label for radio-button to pick export format

Tabela

Bez formatowania

Label for radio-button to pick export text format

Markdown

Otwórz

Text for button which open an external webpage in Support pane

Utwórz nowy raport

Znajdź podobne raporty

A clickable link in the filter issue reporter section

Dokumentacja

Header of 'Documentation' section in Support pane

Przeczytaj dokumentację na uBlock/wiki, by nauczyć się obsługi uBlock Origin.

First paragraph of 'Documentation' section in Support pane

Pytania oraz pomoc

Header of 'Questions and support' section in Support pane

Odpowiedzi na pytania oraz inne rodzaje pomocy są udzielane na subreddicie <code>/r/uBlockOrigin</code>.

First paragraph of 'Questions and support' section in Support pane

Problemy z filtrowaniem/błędy w wyświetlaniu stron

Header of 'Filter issues' section in Support pane

Zgłoś problemy z filtrowaniem na poszczególnych stronach na  trackerze błędów uBlockOrigin/uAssets. Wymaga konta GitHub.

First paragraph of 'Filter issues' section in Support pane

<b>Ważne:</b> unikaj innych podobnie działających dodatków razem z uBlock Origin, ponieważ może to powodować problemy z filtrowaniem na poszczególnych stronach.

Second paragraph of 'Filter issues' section in Support pane

Porada: upewnij się, że listy filtrów są aktualne. Rejestrator jest głównym narzędziem do diagnozowania problemów z filtrowaniem.

Third paragraph of 'Filter issues' section in Support pane

Zgłaszanie błędów

Header of 'Bug report' section in Support pane

Zgłoś problemy związane bezpośrednio z uBlock Origin na trackerze błędów uBlockOrigin/uBlock-issue. Wymaga konta GitHub.

First paragraph of 'Bug report' section in Support pane

Informacje pomocne w rozwiązywaniu problemów

Header of 'Troubleshooting Information' section in Support pane

Poniżej znajdują się informacje techniczne które mogą być użyteczne gdy wolontariusze próbują pomóc ci w rozwiązaniu problemu.

First paragraph of 'Troubleshooting Information' section in Support pane

<b>Ważne:</b> potencjalnie prywatne lub wrażliwe informacje są domyślnie ocenzurowane. Ocenzurowanie może utrudniać rozwiązanie problemu.

Second paragraph of 'Troubleshooting Information' section in Support pane

Zgłoś problem z filtrowaniem

Header of 'Report a filter issue' section in Support pane

Aby uniknąć obciążania wolontariuszy zduplikowanymi zgłoszeniami, sprawdź, czy problem nie został już zgłoszony.

A paragraph in the filter issue reporter section

Adres strony internetowej:

Label for the URL of the page

Strona internetowa…

Label for widget to select type of issue

— Wybierz pozycję —

An entry in the widget used to select the type of issue

Wyświetla reklamy lub ich pozostałości

Ma okna dialogowe lub inne niedogodności

Wykrywa uBlock Origin

Ma problemy związane z prywatnością

Działa nieprawidłowo, gdy włączony jest uBlock Origin

Otwiera niepożądane karty lub okna

Oznacz stronę internetową jako „NSFW” („Not Safe For Work (nieodpowiednią w pracy)”)

A checkbox to use for NSFW sites

Ocenzuruj

Text for 'Redact' button

Nie cenzuruj

Text for 'Unredact' button

Polityka prywatności

Link to privacy policy on GitHub (English)

Informacje o wydaniu

Kod źródłowy (GPLv3)

English: Source code (GPLv3)

Współtwórcy

English: Contributors

Kod źródłowy

Link text to source code repo

Tłumaczenia

Link text to translations repo

Listy filtrów

Link text to uBO's own filter lists repo

Zewnętrzne zależności (kompatybilne z GPLv3):

Shown in the About pane

Własne listy filtrów uBO są dobrowolnie hostowane w następujących sieciach CDN:

Shown in the About pane

Losowo wybrana sieć CDN zostanie użyta, gdy lista filtrów będzie wymagała aktualizacji

Shown in the About pane

Utwórz kopię zapasową…

Text for button to create a backup of all settings

English: my-ublock-backup_{{datetime}}.txt

Przywróć kopię z pliku…

English: Restore from file...

Przywróć ustawienia domyślne…

English: Reset to default settings...

Wszystkie twoje ustawienia zostaną zastąpione ustawieniami z kopii stworzonej {{time}}. Po zakończeniu uBlock₀ zostanie uruchomiony ponownie.

Przywrócić ustawienia z kopii zapasowej?

Message asking user to confirm restore

Danych nie można odczytać lub są nieprawidłowe

Message to display when an error occurred during restore

Wszystkie twoje ustawienia zostaną usunięte i uBlock₀ zostanie ponownie uruchomiony.

Czy chcesz przywrócić ustawienia domyślne?

Message asking user to confirm reset

Błąd sieci: {{msg}}

English: Network error: {{msg}}

Dodać następujący URL do twoich list filtrów?

Tytuł: "{{title}}"
URL: {{url}}

No longer used

Subskrybuj

For the button used to subscribe to a filter list

minutę temu

English: a minute ago

{{value}} min. temu

English: {{value}} minutes ago

godzinę temu

English: an hour ago

{{value}} godz. temu

English: {{value}} hours ago

wczoraj

English: a day ago

{{value}} dni temu

English: {{value}} days ago

Panel sterowania

Firefox/Fennec-specific: Show Dashboard

Pokaż rejestrator

Firefox/Fennec-specific: Show Logger

wyłączony

Firefox-specific: appears as 'uBlock₀ (off)'

uBlock Origin zablokował wczytywanie następującej strony:

Used in the strict-blocking page

Powodem zablokowania jest filtr

Used in the strict-blocking page

bez parametrów

label to be used for the parameter-less URL: https://cloud.githubusercontent.com/assets/585534/9832014/bfb1b8f0-593b-11e5-8a27-fba472a5529a.png

Filtr znajduje się na liście:

English: List of filter list names follows

Wstecz

English: Go back

Zamknij to okno

English: Close this window

Wyłącz rygorystyczne blokowanie dla {{hostname}}

English: Disable strict blocking for {{hostname}} ...

Tymczasowo

English: Temporarily

Na stałe

English: Permanently

Eksportuj do chmury

tooltip

Importuj z chmury

tooltip

Importuj z chmury i połącz z aktualnymi ustawieniami

tooltip

Nazwa urządzenia:

used as a prompt for the user to provide a custom device name

Uwaga! Te ustawienia zmieniasz na własne ryzyko.

A warning to users at the top of 'Advanced settings' page

Wyślij

for generic 'Submit' buttons

Zastosuj zmiany

for generic 'Apply changes' buttons

Przywróć

for generic 'Revert' buttons

bajty

Zablokuj element w ramce…

An entry in the browser's contextual menu

Subskrybuj listę filtrów…

Tymczasowo zezwalaj na wyświetlanie dużych elementów multimedialnych

A context menu entry, present when large media elements have been blocked on the current site

Wprowadź skrót

Placeholder string for input field used to capture a keyboard shortcut

Przełącz przewijanie synchroniczne

Tooltip for the button used to lock scrolling between the views in the 'My rules' pane

Kopiuj do schowka

Label for buttons used to copy something to the clipboard

Zaznacz wszystko

Label for buttons used to select all text in editor

Przełącz profil blokowania

Label for keyboard shortcut used to toggle blocking profile

Rozluźnij tryb blokowania

Label for keyboard shortcut used to relax blocking mode (meant to replace 'Toggle blocking profile')

Użycie pamięci dyskowej: {{value}} {{unit}}

In Setting pane, renders as (example): Storage used: 13.2 MB

KB

short for 'kilobytes'

MB

short for 'megabytes'

GB

short for 'gigabytes'

Kliknij, aby załadować

Message used in frame placeholders

Ten wpis musi być ostatni

so we dont need to deal with comma for last entry


/*******************************************************************************

    uBlock Origin - a browser extension to block requests.
    Copyright (C) 2019-present Raymond Hill

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see {http://www.gnu.org/licenses/}.

    Home: https://github.com/gorhill/uBlock
*/

(function() {
    'use strict';
    const signatures = [
        [ 'blockadblock' ],
        [ 'babasbm' ],
        [ /getItem\('babn'\)/ ],
        [
            'getElementById',
            'String.fromCharCode',
            'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',
            'charAt',
            'DOMContentLoaded',
            'AdBlock',
            'addEventListener',
            'doScroll',
            'fromCharCode',
            '<<2|r>>4',
            'sessionStorage',
            'clientWidth',
            'localStorage',
            'Math',
            'random'
        ],
    ];
    const check = function(s) {
        for ( let i = 0; i < signatures.length; i++ ) {
            const tokens = signatures[i];
            let match = 0;
            for ( let j = 0; j < tokens.length; j++ ) {
                const token = tokens[j];
                const pos = token instanceof RegExp
                    ? s.search(token)
                    : s.indexOf(token);
                if ( pos !== -1 ) { match += 1; }
            }
            if ( (match / tokens.length) >= 0.8 ) { return true; }
        }
        return false;
    };
    window.eval = new Proxy(window.eval, {              // jshint ignore: line
        apply: function(target, thisArg, args) {
            const a = args[0];
            if ( typeof a !== 'string' || !check(a) ) {
                return target.apply(thisArg, args);
            }
            if ( document.body ) {
                document.body.style.removeProperty('visibility');
            }
            let el = document.getElementById('babasbmsgx');
            if ( el ) {
                el.parentNode.removeChild(el);
            }
        }
    });
    window.setTimeout = new Proxy(window.setTimeout, {
        apply: function(target, thisArg, args) {
            const a = args[0];
            if (
                typeof a !== 'string' ||
                /\.bab_elementid.$/.test(a) === false
            ) {
                return target.apply(thisArg, args);
            }
        }
    });
})();


Ένας αποτελεσματικός αναστολέας διαφημίσεων: παρόλο το ελαφρύ του αποτύπωμα στη μνήμη και τον επεξεργαστή μπορεί να εφαρμόσει χιλιάδες περισσότερα φίλτρα σε σχέση με άλλους δημοφιλείς blockers.

Απεικονιζόμενη επισκόπηση της αποτελεσματικότητάς του: https://github.com/gorhill/uBlock/wiki/uBlock-vs.-ABP:-efficiency-compared

Χρήση: Το μεγάλο πλήκτρο απενεργοποίησης/ενεργοποίησης στο αναδυόμενο παράθυρο, χρησιμεύει στην εναλλαγή κατάστασης του uBlock για τον τρέχοντα ιστότοπο. Η εφαρμογή της ρύθμισης αυτής γίνεται μόνο για τον τρέχοντα ιστότοπο και δεν επιβάλλεται καθολικά.

***

Ευέλικτος, είναι πολλά περισσότερα από ένας απλός "ad blocker": μπορεί επιπλέον να διαβάζει και να δημιουργεί φίλτρα από αρχεία hosts.

Κατά προεπιλογή, οι λίστες φίλτρων που φορτώνονται και επιβάλλονται είναι οι εξής:

- EasyList
- Λίστα διακομιστών διαφημίσεων του Peter Lowe
- EasyPrivacy
- Κακόβουλοι τομείς

Επιπλέον λίστες είναι διαθέσιμες για να επιλέξετε εάν το επιθυμείτε:

- Ενισχυμένη Ιχνωσική Λίστα του Fanboy
- Αρχείο hosts του Dan Pollock
- Διαφημίσεις και διακομιστές ίχνωσης hpHosts
- MVPS HOSTS
- Spam404
- και πολλές άλλες

Φυσικά, όσο περισσότερα φίλτρα ενεργοποιούνται, τόσο αυξάνεται το αποτύπωμα της μνήμης. Ωστόσο, ακόμη και μετά από την προσθήκη δυο επιπλέον λιστών, του Fanboy και της λίστας διαφημίσεων και διακομιστών ίχνωσης hpHosts, το uBlock₀ συνεχίζει να έχει χαμηλότερο αποτύπωμα μνήμης από άλλους δημοφιλείς αναστολείς.

Επίσης, έχετε υπ'όψην ότι διαλέγοντας μερικές από τις έξτρα λίστες μπορεί να οδηγήσει σε πιθανό σφάλμα στην ιστοσελίδα -- ειδικά εκείνες που κανονικά χρησιμοποιούνται σαν host αρχεία.

***

Χωρίς τις υπάρχουσες λίστες φίλτρων, αυτή η επέκταση δεν έχει καμία αξία. Εάν ποτέ λοιπόν θελήσετε πραγματικά να συνεισφέρετε κάτι, αναλογιστείτε τους ανθρώπους που εργάζονται σκληρά για να διατηρήσουν τις λίστες φίλτρων που χρησιμοποιείτε, οι οποίες διατέθηκαν προς χρήση σε όλους, δωρεάν.

***

Δωρεάν.
Ανοιχτού κώδικα με άδεια δημόσιας χρήσης (GPLv3)
Από τους χρήστες για τους χρήστες.

Συνεισφέροντες @ Github: https://github.com/gorhill/uBlock/graphs/contributors
Συνεισφέροντες @ Crowdin: https://crowdin.net/project/ublock

***

Είναι μια αρκετά πρόωρη έκδοση, κρατήστε το υπόψη κατά την αξιολόγηση.

Αρχείο αλλαγών του έργου:
https://github.com/gorhill/uBlock/releases


keep keep keep keep keep replace keep keep keep keep

.codeMirrorContainer {
    font-size: 12px;
    line-height: 1.25;
    overflow: hidden;
    position: relative;
    }
.CodeMirror {
    background-color: var(--surface-0);
    box-sizing: border-box;
    color: var(--ink-1);
    flex-grow: 1;
    height: 100%;
    width: 100%;
    }
.CodeMirror-cursor {
    border-color: var(--cm-cursor);
    }
.CodeMirror-selected {
    background-color: var(--cm-selection-surface);
    }
.CodeMirror-focused .CodeMirror-selected {
    background-color: var(--cm-selection-focused-surface);
    }
.CodeMirror-foldmarker {
    color: var(--cm-foldmarker-ink);
    font-size: large;
    text-shadow: none;
    }
.CodeMirror-gutters {
    background-color: var(--cm-gutter-surface);
    border-color: var(--cm-gutter-border);
    }
.CodeMirror-line::selection,
.CodeMirror-line > span::selection,
.CodeMirror-line > span > span::selection {
    background-color: var(--cm-selection-focused-surface);
    }
.CodeMirror-linenumber {
    color: var(--cm-gutter-ink);
    }
.CodeMirror-lines {
    padding-bottom: 6rem;
    }
.CodeMirror-matchingbracket {
    color: unset;
    }
.CodeMirror-matchingbracket {
    background-color: var(--cm-matchingbracket) !important;
    color: inherit !important;
    font-weight: bold;
    }

.CodeMirror-search-match {
    background: none;
    background-color: var(--cm-search-match-surface);
    border: 0;
    opacity: 1;
    }

/* For when panels are used */
.codeMirrorContainer > div:not([class^="CodeMirror"]) {
    display: flex;
    flex-direction: column;
    height: 100%;
    }

.codeMirrorContainer.codeMirrorBreakAll .CodeMirror-wrap pre {
    word-break: break-all;
    }

.cm-s-default .cm-comment {
    color: var(--sf-comment-ink);
    }
.cm-s-default .cm-def {
    color: var(--sf-def-ink);
    }
.cm-s-default .cm-directive {
    color: var(--sf-directive-ink);
    font-weight: bold;
    }
.cm-s-default .cm-error {
    color: inherit;
    }
.cm-s-default .cm-error,
.CodeMirror-linebackground.error {
    background-color: var(--sf-error-surface);
    text-decoration: underline var(--sf-error-ink);
    text-underline-position: under;
    }
.cm-s-default .cm-link {
    text-decoration: none;
    }
.cm-s-default .cm-link:hover {
    color: var(--link-ink);
    }
.cm-s-default .cm-keyword {
    color: var(--sf-keyword-ink);
    }
.cm-s-default .cm-negative {
    color: var(--cm-negative);
    }
.cm-s-default .cm-positive {
    color: var(--cm-positive);
    }
.cm-s-default .cm-notice {
    text-underline-position: under;
    text-decoration-color: var(--sf-notice-ink);
    text-decoration-style: solid;
    text-decoration-line: underline;
    }
.cm-s-default .cm-tag {
    color: var(--sf-tag-ink);
    }
.cm-s-default .cm-value { color: var(--sf-value-ink); }
.cm-s-default .cm-variable {
    color: var(--sf-variable-ink);
    }
.cm-s-default .cm-warning {
    background-color: var(--sf-warning-surface);
    text-decoration: underline var(--sf-warning-ink);
    text-underline-position: under;
    }
.cm-s-default .cm-readonly {
    color: var(--sf-readonly-ink);
    }

/* Rules */
.cm-s-default .cm-allowrule {
    color: var(--df-allow-ink);
    font-weight: bold;
    }
.cm-s-default .cm-blockrule {
    color: var(--df-block-ink);
    font-weight: bold;
    }
.cm-s-default .cm-nooprule {
    color: var(--df-noop-ink);
    font-weight: bold;
    }
.cm-s-default .cm-sortkey {
    color: var(--sf-keyword-ink);
    }

.cm-search-widget {
    align-items: center;
    background-color: var(--cm-gutter-surface);
    border-bottom: 1px solid var(--cm-gutter-border);
    cursor: default;
    direction: ltr;
    display: flex;
    flex-shrink: 0;
    justify-content: space-between;
    padding: 0.5em;
    user-select: none;
      -moz-user-select: none;
      -webkit-user-select: none;
    z-index: 1000;
    }
.cm-search-widget-input {
    display: inline-flex;
    flex-grow: 1;
    }
.cm-search-widget .fa-icon {
    fill: var(--cm-gutter-ink);
    font-size: 140%;
    }
.cm-search-widget .fa-icon:not(.fa-icon-ro):hover {
    fill: var(--ink-1);
    }
.cm-search-widget-input input {
    border: 1px solid var(--cm-gutter-ink);
    display: inline-flex;
    flex-grow: 1;
    max-width: 16em;
    }
.cm-search-widget-count {
    align-items: center;
    display: inline-flex;
    flex-grow: 0;
    font-size: 95%;
    min-width: 6em;
    visibility: hidden;
    }
.cm-search-widget[data-query] .cm-search-widget-count:not(:empty) {
    visibility: visible;
    }
.cm-search-widget .cm-search-widget-button:hover {
    color: #000;
    }
.cm-search-widget .sourceURL[href=""] {
    display: none;
    }
.cm-searching.cm-overlay {
    background-color: var(--cm-searching-surface);
    border: 0;
    color: var(--cm-searching-ink);
    }

.CodeMirror-merge {
    border-color: var(--cm-gutter-border);
    }
.CodeMirror-merge-copy,
.CodeMirror-merge-copy-reverse {
    color: var(--cm-merge-copy-ink);
    }
.CodeMirror-merge-l-chunk {
    background-color: var(--cm-merge-chunk-surface);
    }
.CodeMirror-merge-l-chunk-start,
.CodeMirror-merge-l-chunk-end {
    border-color: var(--cm-merge-chunk-border);
    }
.CodeMirror-merge-l-deleted {
    background-image: none;
    }
.CodeMirror-merge-l-inserted {
    background-image: none;
    }
/* This probably needs to be added to CodeMirror repo */
.CodeMirror-merge-gap {
    background-color: var(--cm-gutter-surface);
    border-color: var(--cm-gutter-border);
    vertical-align: top;
    }
.CodeMirror-merge-spacer {
    background-color: var(--cm-merge-chunk-surface);
    }

.CodeMirror-hints {
    z-index: 10000;
    }

/* Must appear after other background color declarations to be sure it
 * overrides them
 * */
.CodeMirror-activeline-background {
    background-color: var(--cm-active-line);
    }


## INSTALL

### Chromium

- Download and unzip `ublock0.chromium.zip` ([latest release desirable](https://github.com/gorhill/uBlock/releases)).
- Rename the unzipped directory to `ublock`
    - When you later update manually, replace the **content** of the `ublock` folder with the **content** of the latest zipped version.
    - This will ensure that all the extension settings will be preserved
    - As long as the extension loads **from same folder path from which it was originally installed**, all your settings will be preserved.
- Go to chromium/chrome *Extensions*.
- Click to check *Developer mode*.
- Click *Load unpacked extension...*.
- In the file selector dialog:
    - Select the directory `ublock` which was created above.
    - Click *Open*.

The extension will now be available in your chromium/chromium-based browser.

Remember that you have to update manually also. For some users, updating manually is actually an advantage because:
- You can update when **you** want
- If ever a new version sucks, you can easily just re-install the previous one

### Firefox

Compatible with Firefox 52 and beyond.

#### For stable release version

This works only if you set `xpinstall.signatures.required` to `false` in `about:config`.[see "Add-on signing in Firefox"](https://support.mozilla.org/en-US/kb/add-on-signing-in-firefox)

- Download `ublock0.firefox.xpi` ([latest release desirable](https://github.com/gorhill/uBlock/releases)).
    - Right-click and choose _"Save As..."_.
- Drag and drop the previously downloaded `ublock0.firefox.xpi` into Firefox

#### For beta version

- Click on `ublock0.firefox.signed.xpi` ([latest release desirable](https://github.com/gorhill/uBlock/releases)).

#### Location of uBO settings

On Linux, the settings are saved in a JSON file located at `~/.mozilla/firefox/[profile name]/browser-extension-data/uBlock0@raymondhill.net/storage.js`.

When you uninstall the extension, Firefox deletes that file, so all your settings are lost when you uninstall.

### Firefox legacy

Compatible with Firefox 24-56, [Pale Moon](https://www.palemoon.org/) and [SeaMonkey](http://www.seamonkey-project.org/).

- Download `ublock0.firefox-legacy.xpi` ([latest release desirable](https://github.com/gorhill/uBlock-for-firefox-legacy/releases)).
    - Right-click and select "Save Link As..."
- Drag and drop the previously downloaded `ublock0.firefox-legacy.xpi` into Firefox

With Firefox 43 and beyond, you may need to toggle the setting `xpinstall.signatures.required` to `false` in `about:config`.[see "Add-on signing in Firefox"](https://support.mozilla.org/en-US/kb/add-on-signing-in-firefox)

Your uBlock Origin settings are kept intact even after you uninstall the addon.

On Linux, the settings are saved in a SQlite file located at `~/.mozilla/firefox/[profile name]/extension-data/ublock0.sqlite`.

On Windows, the settings are saved in a SQlite file located at `%APPDATA%\Mozilla\Firefox\Profiles\[profile name]\extension-data\ublock0.sqlite`.

### Build instructions (for developers)

- Clone [uBlock repo](https://github.com/gorhill/uBlock): `git clone https://github.com/gorhill/uBlock.git`
- Set path to uBlock: `cd uBlock`
- The official version of uBO is in the `master` branch
    - `git checkout master`
- Build the plugin:
    - Chromium: `make chromium`
    - Firefox: `make firefox`
    - NPM package: `make npm`
- Load the result of the build into your browser:
    - Chromium:
        - Navigate to `chrome://extensions/`
        - Check _"Developer mode"_
        - Click _"Load unpacked"_
        - Select `/uBlock/dist/build/uBlock0.chromium/`
    - Firefox:
        - Navigate to `about:debugging#/runtime/this-firefox`
        - Click _"Load Temporary Add-on..."_
        - Select `/uBlock/dist/build/uBlock0.firefox/`


/*******************************************************************************

    uBlock Origin - a browser extension to block requests.
    Copyright (C) 2020-present Raymond Hill

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see {http://www.gnu.org/licenses/}.

    Home: https://github.com/gorhill/uBlock
*/

'use strict';

/******************************************************************************/

(( ) => {
    if ( typeof vAPI !== 'object' ) { return; }

    if ( vAPI.dynamicReloadToken === undefined ) {
        vAPI.dynamicReloadToken = vAPI.randomToken();
    }

    for ( const sheet of Array.from(document.styleSheets) ) {
        let loaded = false;
        try {
            loaded = sheet.rules.length !== 0;
        } catch(ex) {
        }
        if ( loaded ) { continue; }
        const link = sheet.ownerNode || null;
        if ( link === null || link.localName !== 'link' ) { continue; }
        if ( link.hasAttribute(vAPI.dynamicReloadToken) ) { continue; }
        const clone = link.cloneNode(true);
        clone.setAttribute(vAPI.dynamicReloadToken, '');
        link.replaceWith(clone);
    }
})();

/*******************************************************************************

    DO NOT:
    - Remove the following code
    - Add code beyond the following code
    Reason:
    - https://github.com/gorhill/uBlock/pull/3721
    - uBO never uses the return value from injected content scripts

**/

void 0;