From 44aeb217d8a3b17cc31be7c341d8e5b3b078c2ce Mon Sep 17 00:00:00 2001 From: SukkaW Date: Mon, 26 Dec 2022 00:12:59 +0800 Subject: [PATCH] Update Reject Filter Parsing --- Build/build-reject-domainset.js | 21 +- Build/lib/parse-filter.js | 269 +++++++++++++----- Build/lib/reject-data-source.js | 61 ++-- Build/worker/build-reject-domainset-worker.js | 5 + List/non_ip/reject.conf | 4 + Source/domainset/reject_sukka.conf | 8 + package.json | 1 + pnpm-lock.yaml | 89 ++++++ 8 files changed, 366 insertions(+), 92 deletions(-) diff --git a/Build/build-reject-domainset.js b/Build/build-reject-domainset.js index 279182fc..151dbbba 100644 --- a/Build/build-reject-domainset.js +++ b/Build/build-reject-domainset.js @@ -40,17 +40,19 @@ const filterRuleWhitelistDomainSets = new Set(PREDEFINED_WHITELIST); // Parse from AdGuard Filters console.time('* Download and process AdBlock Filter Rules'); + + let shouldStop = false; await Promise.all(ADGUARD_FILTERS.map(input => { - const promise = Array.isArray(input) && input.length === 2 - ? processFilterRules(input[0], input[1]) - : processFilterRules(input); + const promise = typeof input === 'string' + ? processFilterRules(input, undefined, false) + : processFilterRules(input[0], input[1] ?? undefined, input[2] ?? false) return promise.then((i) => { if (i) { const { white, black, foundDebugDomain } = i; if (foundDebugDomain) { - process.exit(1); - }; + shouldStop = true; + } white.forEach(i => filterRuleWhitelistDomainSets.add(i)); black.forEach(i => domainSets.add(i)); } else { @@ -61,6 +63,10 @@ const filterRuleWhitelistDomainSets = new Set(PREDEFINED_WHITELIST); console.timeEnd('* Download and process AdBlock Filter Rules'); + if (shouldStop) { + process.exit(1); + } + previousSize = domainSets.size - previousSize; console.log(`Import ${previousSize} rules from adguard filters!`); @@ -246,6 +252,11 @@ function isInWhiteList (domain) { if (domain === white || domain.endsWith(white)) { return true; } + if (white.endsWith(domain)) { + // If a whole domain is in blacklist but a subdomain is in whitelist + // We have no choice but to remove the whole domain from blacklist + return true; + } } return false; diff --git a/Build/lib/parse-filter.js b/Build/lib/parse-filter.js index 824270d1..983539e7 100644 --- a/Build/lib/parse-filter.js +++ b/Build/lib/parse-filter.js @@ -1,4 +1,5 @@ const { fetchWithRetry } = require('./fetch-retry'); +const { NetworkFilter } = require('@cliqz/adblocker'); const { normalizeDomain } = require('./is-domain-loose'); const DEBUG_DOMAIN_TO_FIND = null; // example.com | null @@ -99,9 +100,9 @@ async function processHosts (hostsUrl, includeAllSubDomain = false) { /** * @param {string | URL} filterRulesUrl * @param {(string | URL)[] | undefined} fallbackUrls - * @returns {Promise<{ white: Set, black: Set, foundDebugDomain: boolean }>} + * @returns {Promise<{ white: Set, black: Set, foundDebugDomain: boolean, parseFailed: boolean }>} */ -async function processFilterRules (filterRulesUrl, fallbackUrls) { +async function processFilterRules (filterRulesUrl, fallbackUrls, includeThirdParties = false) { console.time(` - processFilterRules: ${filterRulesUrl}`); /** @type Set */ @@ -109,6 +110,26 @@ async function processFilterRules (filterRulesUrl, fallbackUrls) { /** @type Set */ const blacklistDomainSets = new Set(); + const addToBlackList = (domainToBeAddedToBlack, isSubDomain) => { + if (DEBUG_DOMAIN_TO_FIND && domainToBeAddedToBlack.includes(DEBUG_DOMAIN_TO_FIND)) { + warnOnce(filterRulesUrl.toString(), false, DEBUG_DOMAIN_TO_FIND); + foundDebugDomain = true; + } + + if (isSubDomain && !domainToBeAddedToBlack.startsWith('.')) { + blacklistDomainSets.add(`.${domainToBeAddedToBlack}`); + } else { + blacklistDomainSets.add(domainToBeAddedToBlack); + } + }; + const addToWhiteList = (domainToBeAddedToWhite) => { + if (DEBUG_DOMAIN_TO_FIND && domainToBeAddedToWhite.includes(DEBUG_DOMAIN_TO_FIND)) { + warnOnce(filterRulesUrl.toString(), false, DEBUG_DOMAIN_TO_FIND); + foundDebugDomain = true; + } + whitelistDomainSets.add(domainToBeAddedToWhite); + } + let filterRules; try { /** @type string[] */ @@ -124,117 +145,236 @@ async function processFilterRules (filterRulesUrl, fallbackUrls) { throw e; } - for (let i = 0, len = filterRules.length; i < len; i++) { - const line = filterRules[i]; + let hasParseFailed = false; - const lineStartsWithDoubleVerticalBar = line.startsWith('||'); + for (let i = 0, len = filterRules.length; i < len; i++) { + const line = filterRules[i].trim(); if ( line === '' + // doesn't include + || !line.includes('.') // rule with out dot can not be a domain + // includes || line.includes('#') || line.includes('!') + || line.includes('?') || line.includes('*') - || line.includes('/') || line.includes('=') || line.includes('[') || line.includes('(') - || line.includes('$') && !lineStartsWithDoubleVerticalBar || line.includes(']') || line.includes(')') + || line.includes(',') + || line.includes('~') + || line.includes('&') + || line.includes('%') + || ((line.includes('/') || line.includes(':')) && !line.includes('://')) + // ends with + || line.endsWith('.') + || line.endsWith('-') + || line.endsWith('_') + // special modifier + || line.includes('$popup') + || line.includes('$removeparam') + || line.includes('$popunder') ) { continue; } + const filter = NetworkFilter.parse(line); + if (filter) { + if ( + filter.isElemHide() + || filter.isGenericHide() + || filter.isSpecificHide() + || filter.isRedirect() + || filter.isRedirectRule() + || filter.hasDomains() + || filter.isCSP() // must not be csp rule + || (!filter.fromAny() && !filter.fromDocument()) + ) { + // not supported type + continue; + } + + if ( + filter.hasHostname() // must have + && filter.isPlain() + && (!filter.isRegex()) + && (!filter.isFullRegex()) + ) { + const hostname = filter.getHostname(); + if (hostname) { + if (filter.isException() || filter.isBadFilter()) { + addToWhiteList(hostname); + continue; + } + if (filter.firstParty() === filter.thirdParty()) { + addToBlackList(hostname, true); + continue; + } + if (filter.thirdParty()) { + if (includeThirdParties) { + addToBlackList(hostname, true); + } + continue; + } + if (filter.firstParty()) { + continue; + } + } + } + } + + if (line.includes('$third-party') || line.includes('$frame')) { + continue; + } + const lineEndsWithCaret = line.endsWith('^'); const lineEndsWithCaretVerticalBar = line.endsWith('^|'); - if (lineStartsWithDoubleVerticalBar && line.endsWith('^$badfilter')) { - const _domain = line.replace('||', '').replace('^$badfilter', '').trim(); - const domain = normalizeDomain(_domain); - if (domain) { - if (DEBUG_DOMAIN_TO_FIND && domain.includes(DEBUG_DOMAIN_TO_FIND)) { - warnOnce(filterRulesUrl.toString(), true, DEBUG_DOMAIN_TO_FIND); - foundDebugDomain = true; + if (line.startsWith('@@')) { + if (line.endsWith('$cname')) { + continue; + } + + if ( + (line.startsWith('@@|') || line.startsWith('@@.')) + && ( + lineEndsWithCaret + || lineEndsWithCaretVerticalBar + || line.endsWith('$genericblock') + || line.endsWith('$document') + ) + ) { + const _domain = line + .replace('@@||', '') + .replace('@@|', '') + .replace('@@.', '') + .replace('^|', '') + .replace('^$genericblock', '') + .replace('$genericblock', '') + .replace('^$document', '') + .replace('$document', '') + .replaceAll('^', '') + .trim(); + + const domain = normalizeDomain(_domain); + if (domain) { + addToWhiteList(domain); + } else { + console.warn(' * [parse-filter E0001] (black) invalid domain:', _domain); } - whitelistDomainSets.add(domain); - } else { - console.warn(' * [parse-filter white] ' + _domain + ' is not a valid domain'); + continue; } - } else if (line.startsWith('@@||') + } + + if ( + line.startsWith('||') && ( lineEndsWithCaret || lineEndsWithCaretVerticalBar - || line.endsWith('^$badfilter') - || line.endsWith('^$1p') + || line.endsWith('$cname') ) ) { const _domain = line - .replaceAll('@@||', '') - .replaceAll('^$badfilter', '') - .replaceAll('^$1p', '') - .replaceAll('^|', '') + .replace('||', '') + .replace('^|', '') + .replace('$cname', '') .replaceAll('^', '') .trim(); const domain = normalizeDomain(_domain); - if (domain) { - if (DEBUG_DOMAIN_TO_FIND && domain.includes(DEBUG_DOMAIN_TO_FIND)) { - warnOnce(filterRulesUrl.toString(), true, DEBUG_DOMAIN_TO_FIND); - foundDebugDomain = true; - } - - whitelistDomainSets.add(domain); + addToBlackList(domain, true); } else { - console.warn(' * [parse-filter white] ' + _domain + ' is not a valid domain'); + console.warn(' * [parse-filter E0002] (black) invalid domain:', _domain); } - } else if ( - lineStartsWithDoubleVerticalBar + continue; + } + + const lineStartsWithSingleDot = line.startsWith('.'); + if ( + lineStartsWithSingleDot && ( lineEndsWithCaret || lineEndsWithCaretVerticalBar - || line.endsWith('^$all') - || line.endsWith('^$doc') - || line.endsWith('^$document') ) ) { const _domain = line - .replaceAll('||', '') - .replaceAll('^|', '') - .replaceAll('^$all', '') - .replaceAll('^$document', '') - .replaceAll('^$doc', '') + .replace('^|', '') + .replaceAll('^', '') + .slice(1) + .trim(); + + const domain = normalizeDomain(_domain); + if (domain) { + addToBlackList(domain, true); + } else { + console.warn(' * [parse-filter E0003] (black) invalid domain:', _domain); + } + continue; + } + if ( + ( + line.startsWith('://') + || line.startsWith('http://') + || line.startsWith('https://') + || line.startsWith('|http://') + || line.startsWith('|https://') + ) + && ( + lineEndsWithCaret + || lineEndsWithCaretVerticalBar + ) + ) { + const _domain = line + .replace('|https://', '') + .replace('https://', '') + .replace('|http://', '') + .replace('http://', '') + .replace('://', '') + .replace('^|', '') .replaceAll('^', '') .trim(); const domain = normalizeDomain(_domain); - if (domain) { - if (DEBUG_DOMAIN_TO_FIND && domain.includes(DEBUG_DOMAIN_TO_FIND)) { - warnOnce(filterRulesUrl.toString(), false, DEBUG_DOMAIN_TO_FIND); - foundDebugDomain = true; - } - - blacklistDomainSets.add(`.${domain}`); + addToBlackList(domain, false); + } else { + console.warn(' * [parse-filter E0004] (black) invalid domain:', _domain); } - } else if ( - line.startsWith('://') - && ( - lineEndsWithCaret - || lineEndsWithCaretVerticalBar - ) - ) { - const _domain = `${line.replaceAll('://', '').replaceAll('^|', '').replaceAll('^', '')}`.trim(); + continue; + } + if (!line.startsWith('|') && lineEndsWithCaret) { + const _domain = line.slice(0, -1); const domain = normalizeDomain(_domain); if (domain) { - if (DEBUG_DOMAIN_TO_FIND && domain.includes(DEBUG_DOMAIN_TO_FIND)) { - warnOnce(filterRulesUrl.toString(), false, DEBUG_DOMAIN_TO_FIND); - foundDebugDomain = true; - } - - blacklistDomainSets.add(domain); + addToBlackList(domain, false); + } else { + console.warn(' * [parse-filter E0005] (black) invalid domain:', _domain); } + continue; + } + const tryNormalizeDomain = normalizeDomain(lineStartsWithSingleDot ? line.slice(1) : line); + if ( + tryNormalizeDomain + && ( + lineStartsWithSingleDot + ? tryNormalizeDomain.length === line.length - 1 + : tryNormalizeDomain === line + ) + ) { + addToBlackList(line, true); + continue; + } + + if ( + !line.endsWith('.js') + ) { + hasParseFailed = true; + console.warn(' * [parse-filter E0010] can not parse:', line); } } @@ -243,7 +383,8 @@ async function processFilterRules (filterRulesUrl, fallbackUrls) { return { white: whitelistDomainSets, black: blacklistDomainSets, - foundDebugDomain + foundDebugDomain, + parseFailed: hasParseFailed }; } diff --git a/Build/lib/reject-data-source.js b/Build/lib/reject-data-source.js index 9fb6e703..5a3cd78d 100644 --- a/Build/lib/reject-data-source.js +++ b/Build/lib/reject-data-source.js @@ -15,7 +15,18 @@ const ADGUARD_FILTERS = [ 'https://easylist-downloads.adblockplus.org/easylist.txt', 'https://raw.githubusercontent.com/easylist/easylist/gh-pages/easylist.txt', 'https://secure.fanboy.co.nz/easylist.txt' - ] + ], + true + ], + // Easy Privacy + [ + 'https://easylist.to/easylist/easyprivacy.txt', + [ + 'https://secure.fanboy.co.nz/easyprivacy.txt', + 'https://raw.githubusercontent.com/easylist/easylist/gh-pages/easyprivacy.txt', + 'https://easylist-downloads.adblockplus.org/easyprivacy.txt' + ], + true ], // AdGuard DNS Filter 'https://adguardteam.github.io/AdGuardSDNSFilter/Filters/filter.txt', @@ -27,28 +38,32 @@ const ADGUARD_FILTERS = [ [ 'https://ublockorigin.github.io/uAssetsCDN/filters/filters.txt', 'https://ublockorigin.pages.dev/filters/filters.txt' - ] + ], + false ], [ 'https://ublockorigin.github.io/uAssets/filters/filters-2020.txt', [ 'https://ublockorigin.github.io/uAssetsCDN/filters/filters-2020.txt', 'https://ublockorigin.pages.dev/filters/filters-2020.txt' - ] + ], + false ], [ 'https://ublockorigin.github.io/uAssets/filters/filters-2021.txt', [ 'https://ublockorigin.github.io/uAssetsCDN/filters/filters-2021.txt', 'https://ublockorigin.pages.dev/filters/filters-2021.txt' - ] + ], + false ], [ 'https://ublockorigin.github.io/uAssets/filters/filters-2022.txt', [ 'https://ublockorigin.github.io/uAssetsCDN/filters/filters-2022.txt', 'https://ublockorigin.pages.dev/filters/filters-2022.txt' - ] + ], + false ], // uBlock Origin Badware Risk List [ @@ -56,7 +71,8 @@ const ADGUARD_FILTERS = [ [ 'https://ublockorigin.github.io/uAssetsCDN/filters/badware.txt', 'https://ublockorigin.pages.dev/filters/badware.txt' - ] + ], + false ], // uBlock Origin Privacy List [ @@ -64,7 +80,8 @@ const ADGUARD_FILTERS = [ [ 'https://ublockorigin.github.io/uAssetsCDN/filters/privacy.txt', 'https://ublockorigin.pages.dev/filters/privacy.txt' - ] + ], + false ], // uBlock Origin Resource Abuse [ @@ -72,7 +89,8 @@ const ADGUARD_FILTERS = [ [ 'https://ublockorigin.github.io/uAssetsCDN/filters/resource-abuse.txt', 'https://ublockorigin.pages.dev/filters/resource-abuse.txt' - ] + ], + false ], // uBlock Origin Unbreak [ @@ -80,7 +98,8 @@ const ADGUARD_FILTERS = [ [ 'https://ublockorigin.github.io/uAssetsCDN/filters/unbreak.txt', 'https://ublockorigin.pages.dev/filters/unbreak.txt' - ] + ], + false ], // AdGuard Base Filter 'https://filters.adtidy.org/extension/ublock/filters/2_without_easylist.txt', @@ -99,16 +118,8 @@ const ADGUARD_FILTERS = [ 'https://easylist.to/easylistgermany/easylistgermany.txt', [ 'https://easylist-downloads.adblockplus.org/easylistgermany.txt' - ] - ], - // Easy Privacy - [ - 'https://easylist.to/easylist/easyprivacy.txt', - [ - 'https://secure.fanboy.co.nz/easyprivacy.txt', - 'https://raw.githubusercontent.com/easylist/easylist/gh-pages/easyprivacy.txt', - 'https://easylist-downloads.adblockplus.org/easyprivacy.txt' - ] + ], + false ], // Curben's UrlHaus Malicious URL Blocklist [ @@ -117,7 +128,8 @@ const ADGUARD_FILTERS = [ 'https://urlhaus-filter.pages.dev/urlhaus-filter-agh-online.txt', // Prefer mirror, since malware-filter.gitlab.io has not been updated for a while // 'https://malware-filter.gitlab.io/urlhaus-filter/urlhaus-filter-agh-online.txt' - ] + ], + false ], // Curben's Phishing URL Blocklist [ @@ -126,7 +138,8 @@ const ADGUARD_FILTERS = [ 'https://phishing-filter.pages.dev/phishing-filter-agh.txt', // Prefer mirror, since malware-filter.gitlab.io has not been updated for a while // 'https://malware-filter.gitlab.io/malware-filter/phishing-filter-agh.txt' - ] + ], + false ], // Curben's PUP Domains Blocklist [ @@ -135,7 +148,8 @@ const ADGUARD_FILTERS = [ 'https://pup-filter.pages.dev/pup-filter-agh.txt', // Prefer mirror, since malware-filter.gitlab.io has not been updated for a while // 'https://malware-filter.gitlab.io/malware-filter/pup-filter-agh.txt' - ] + ], + false ], // GameConsoleAdblockList 'https://raw.githubusercontent.com/DandelionSprout/adfilt/master/GameConsoleAdblockList.txt', @@ -147,7 +161,8 @@ const ADGUARD_FILTERS = [ 'https://paulgb.github.io/BarbBlock/blacklists/ublock-origin.txt', // Brave First Party & First Party CNAME 'https://raw.githubusercontent.com/brave/adblock-lists/master/brave-lists/brave-firstparty.txt', - 'https://raw.githubusercontent.com/brave/adblock-lists/master/brave-lists/brave-firstparty-cname.txt' + 'https://raw.githubusercontent.com/brave/adblock-lists/master/brave-lists/brave-firstparty-cname.txt', + 'https://raw.githubusercontent.com/brave/adblock-lists/master/coin-miners.txt' ]; const PREDEFINED_WHITELIST = [ diff --git a/Build/worker/build-reject-domainset-worker.js b/Build/worker/build-reject-domainset-worker.js index ebcda423..3ec77fc2 100644 --- a/Build/worker/build-reject-domainset-worker.js +++ b/Build/worker/build-reject-domainset-worker.js @@ -1,8 +1,11 @@ const Piscina = require('piscina'); +const { isCI } = require('ci-info'); const fullsetDomainStartsWithADot = Piscina.workerData const totalLen = fullsetDomainStartsWithADot.length; +const log = isCI ? () => { } : console.log.bind(console); + module.exports.dedupe = ({ chunk }) => { const chunkLength = chunk.length; const outputToBeRemoved = new Int8Array(chunkLength); @@ -34,6 +37,7 @@ module.exports.dedupe = ({ chunk }) => { if (shouldBeRemoved) { outputToBeRemoved[i] = 1; + log(domainFromInput, domainFromFullSet) break; } } @@ -42,6 +46,7 @@ module.exports.dedupe = ({ chunk }) => { // domainFromInput is now startsWith a "." if (domainFromInput.endsWith(domainFromFullSet)) { outputToBeRemoved[i] = 1; + log(domainFromInput, domainFromFullSet) break; } } diff --git a/List/non_ip/reject.conf b/List/non_ip/reject.conf index 3e3618db..081e9535 100644 --- a/List/non_ip/reject.conf +++ b/List/non_ip/reject.conf @@ -50,6 +50,10 @@ AND,((DOMAIN-KEYWORD,f-log), (DOMAIN-SUFFIX,grammarly.io)) DOMAIN,stun.smartgslb.com AND,((DOMAIN-SUFFIX,prod.hosts.ooklaserver.net), (DOMAIN-KEYWORD,.ad.)) +DOMAIN-KEYWORD,_vmind.qqvideo.tc.qq.com +DOMAIN-KEYWORD,-logging.nextmedia.com +DOMAIN-KEYWORD,-spiky.clevertap-prod.com + # Important: Force add the following domains without whitelisting DOMAIN-SUFFIX,openx.net # DOMAIN-SUFFIX,mmstat.com diff --git a/Source/domainset/reject_sukka.conf b/Source/domainset/reject_sukka.conf index 26a3952b..30a20dbf 100644 --- a/Source/domainset/reject_sukka.conf +++ b/Source/domainset/reject_sukka.conf @@ -15,6 +15,8 @@ optimus-ads.amap.com .rjno1.com .taio.app .headcaptcha.live +# fake pirate bay +.thepiratebay3.com # >> Qihoo 360 hot.m.shouji.360tpcdn.com @@ -565,6 +567,10 @@ adcloud.jp events.jianshu.io .mobileadtrading.com +t.yesware.com +.charlestownwyllie.oaklawnnonantum.com +.auwrtou.cn + # >> Tracking tracking.yorg.app .taginstall.com @@ -618,6 +624,7 @@ analytics.slashdotmedia.com .tagtic.cn sa.holopin.io analytics.infomaniak.com +.prtrackings.com .adjust.io .airbrake.io @@ -957,6 +964,7 @@ videopush.baidu.com .toolbar.baidu.com .tracker.baidu.com .tuijian.baidu.com +.ubmcmm.baidustatic.com # >> Qihoo 360 .stat.360safe.com diff --git a/package.json b/package.json index db9b2bee..7e80bc05 100644 --- a/package.json +++ b/package.json @@ -102,6 +102,7 @@ "author": "", "license": "ISC", "dependencies": { + "@cliqz/adblocker": "^1.25.1", "@sukka/listdir": "^0.2.0", "@vercel/fetch-retry": "^5.1.3", "ci-info": "^3.7.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 32541384..9f747918 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,6 +1,7 @@ lockfileVersion: 5.4 specifiers: + '@cliqz/adblocker': ^1.25.1 '@sukka/listdir': ^0.2.0 '@vercel/fetch-retry': ^5.1.3 ci-info: ^3.7.0 @@ -15,6 +16,7 @@ specifiers: wireit: ^0.9.1 dependencies: + '@cliqz/adblocker': 1.25.1 '@sukka/listdir': 0.2.0 '@vercel/fetch-retry': 5.1.3 ci-info: 3.7.0 @@ -36,6 +38,29 @@ packages: resolution: {integrity: sha512-H71nDOOL8Y7kWRLqf6Sums+01Q5msqBW2KhDUTemh1tvY04eSkSXrK0uj/4mmY0Xr16/3zyZmsrxN7CKuRbNRg==} dev: false + /@cliqz/adblocker-content/1.25.1: + resolution: {integrity: sha512-7gl2VdNPBfj7aPoq34B5miwGcnda/7LCr+BqnpcSOjdLV6jjT2FrNSAKGFvcH23q0HM1IFhYDV6ydTgsdWFCnA==} + dependencies: + '@cliqz/adblocker-extended-selectors': 1.25.1 + dev: false + + /@cliqz/adblocker-extended-selectors/1.25.1: + resolution: {integrity: sha512-4MdMe/YfIok5d8WYVcLR3Ak7vGrmeUV47frgmXEe945luY93vwlzk1NiLYW1JM5Gdm+VePweoS9cJ1/QUTmv+Q==} + dev: false + + /@cliqz/adblocker/1.25.1: + resolution: {integrity: sha512-1C1/ELI94/XewdUj/o1+Q4ziOigMvTZQA05UERfDoKqpJ+0cbrEF/UImrzpX7n+kYsR7xTJvmf+iNM3zS0tfsg==} + dependencies: + '@cliqz/adblocker-content': 1.25.1 + '@cliqz/adblocker-extended-selectors': 1.25.1 + '@remusao/guess-url-type': 1.2.1 + '@remusao/small': 1.2.1 + '@remusao/smaz': 1.9.1 + '@types/chrome': 0.0.197 + '@types/firefox-webext-browser': 94.0.1 + tldts-experimental: 5.7.103 + dev: false + /@nodelib/fs.scandir/2.1.5: resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -57,10 +82,64 @@ packages: fastq: 1.13.0 dev: true + /@remusao/guess-url-type/1.2.1: + resolution: {integrity: sha512-rbOqre2jW8STjheOsOaQHLgYBaBZ9Owbdt8NO7WvNZftJlaG3y/K9oOkl8ZUpuFBisIhmBuMEW6c+YrQl5inRA==} + dev: false + + /@remusao/small/1.2.1: + resolution: {integrity: sha512-7MjoGt0TJMVw1GPKgWq6SJPws1SLsUXQRa43Umht+nkyw2jnpy3WpiLNqGdwo5rHr5Wp9B2W/Pm5RQp656UJdw==} + dev: false + + /@remusao/smaz-compress/1.9.1: + resolution: {integrity: sha512-E2f48TwloQu3r6BdLOGF2aczeH7bJ/32oJGqvzT9SKur0cuUnLcZ7ZXP874E2fwmdE+cXzfC7bKzp79cDnmeyw==} + dependencies: + '@remusao/trie': 1.4.1 + dev: false + + /@remusao/smaz-decompress/1.9.1: + resolution: {integrity: sha512-TfjKKprYe3n47od8auhvJ/Ikj9kQTbDTe71ynKlxslrvvUhlIV3VQSuwYuMWMbdz1fIs0H/fxCN1Z8/H3km6/A==} + dev: false + + /@remusao/smaz/1.9.1: + resolution: {integrity: sha512-e6BLuP8oaXCZ9+v46Is4ilAZ/Vq6YLgmBP204Ixgk1qTjXmqvFYG7+AS7v9nsZdGOy96r9DWGFbbDVgMxwu1rA==} + dependencies: + '@remusao/smaz-compress': 1.9.1 + '@remusao/smaz-decompress': 1.9.1 + dev: false + + /@remusao/trie/1.4.1: + resolution: {integrity: sha512-yvwa+aCyYI/UjeD39BnpMypG8N06l86wIDW1/PAc6ihBRnodIfZDwccxQN3n1t74wduzaz74m4ZMHZnB06567Q==} + dev: false + /@sukka/listdir/0.2.0: resolution: {integrity: sha512-UyVirNhAOXKwjiDehjUaGtpfk0QwNHyiXrlLb/FmWMtI+BGhaEvB9MypSfEAtiiMI3g6QTfG38ayNAorEuz5ow==} dev: false + /@types/chrome/0.0.197: + resolution: {integrity: sha512-m1NfS5bOjaypyqQfaX6CxmJodZVcvj5+Mt/K94EBHkflYjPNmXHAzbxfifdLMa0YM3PDyOxohoTS5ug/e6p5jA==} + dependencies: + '@types/filesystem': 0.0.32 + '@types/har-format': 1.2.10 + dev: false + + /@types/filesystem/0.0.32: + resolution: {integrity: sha512-Yuf4jR5YYMR2DVgwuCiP11s0xuVRyPKmz8vo6HBY3CGdeMj8af93CFZX+T82+VD1+UqHOxTq31lO7MI7lepBtQ==} + dependencies: + '@types/filewriter': 0.0.29 + dev: false + + /@types/filewriter/0.0.29: + resolution: {integrity: sha512-BsPXH/irW0ht0Ji6iw/jJaK8Lj3FJemon2gvEqHKpCdDCeemHa+rI3WBGq5z7cDMZgoLjY40oninGxqk+8NzNQ==} + dev: false + + /@types/firefox-webext-browser/94.0.1: + resolution: {integrity: sha512-I6iHRQJSTZ+gYt2IxdH2RRAMvcUyK8v5Ig7fHQR0IwUNYP7hz9+cziBVIKxLCO6XI7fiyRsNOWObfl3/4Js2Lg==} + dev: false + + /@types/har-format/1.2.10: + resolution: {integrity: sha512-o0J30wqycjF5miWDKYKKzzOU1ZTLuA42HZ4HE7/zqTOc/jTLdQ5NhYWvsRQo45Nfi1KHoRdNhteSI4BAxTF1Pg==} + dev: false + /@vercel/fetch-retry/5.1.3: resolution: {integrity: sha512-UIbFc4VsEZHOr6dWuE+kxY4NxnOLXFMCWm0fSKRRHUEtrIzaJLzHpWk2QskCXTSzFgFvhkLAvSrBK2XZg7NSzg==} peerDependencies: @@ -552,6 +631,16 @@ packages: resolution: {integrity: sha512-EFhrqqb0abo/9KZ4ZxHSF4e8CYKk/SouOLbNUMZUw+5OjC0hUJbFmHXtHNWYGaqnmwjnvdwFQ1a29Tflpz5Ufg==} dev: false + /tldts-core/5.7.103: + resolution: {integrity: sha512-MdSolgnhJwr2SH6a+5KFAYB8znpYdRLoOFTJmrWslsec9Ne/V3DBrw+BbS1YYQJKGTin6U02Y9CSYxnOpg3vwg==} + dev: false + + /tldts-experimental/5.7.103: + resolution: {integrity: sha512-oo9QI0TjXdrlZnDSJMazRJe+nnd0OwXgzRmHcsnyp4k6UxmmlaWEA1iq3RY3EDSKwYEJ+lDnwQeAaGRleU/LEQ==} + dependencies: + tldts-core: 5.7.103 + dev: false + /tldts/5.7.102: resolution: {integrity: sha512-FvqzkTsADAntBc4EPmcmIs4GkjBBtDKZKHJJU6i1TzL9d+ijBearWEgGNoE8YO9T8pEe+szYE+KFMmh6ixexYA==} hasBin: true