diff --git a/.eslintrc.js b/.eslintrc.js index 1d4fff01c96c..75099666e607 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,4 +1,10 @@ -module.exports = { +/** @type {import('eslint').Linter.Config} */ +const config = {overrides: []}; + +// Source code (TS, JSX, JS) +config.overrides.push({ + files: ['{src,tasks,tests}/**/*.{ts,tsx,js,jsx}', '.*.js', 'index.d.ts'], + excludedFiles: ['darkreader.js'], parser: '@typescript-eslint/parser', plugins: ['@typescript-eslint', 'local'], extends: ['plugin:@typescript-eslint/recommended', 'plugin:import/recommended', 'plugin:import/typescript'], @@ -163,4 +169,62 @@ module.exports = { } }, ], -}; +}); + +// Bundled JS + +config.overrides.push({ + files: ['darkreader.js', 'build/debug/chrome/**/*.js'], + env: {browser: true}, + extends: ['plugin:compat/recommended'], + parserOptions: { + ecmaVersion: 2019, + sourceType: 'module' + }, + settings: { + polyfills: [ + 'navigator.deviceMemory', + 'navigator.userAgentData', + ], + }, + overrides: [ + + // API (modern clients) + { + files: ['darkreader.js'], + rules: { + + // Compatibility check + 'compat/compat': ['error', [ + '>0.5% and supports es5 and supports promises and supports url', + 'not Explorer > 0', + ].join(', ')] + }, + }, + + // Extension (non-mobile browsers based on Firefox or Chromium) + { + files: ['build/debug/chrome/**/*.js'], + rules: { + + // Compatibility check + 'compat/compat': ['error', [ + '> 0.5% and supports es5', + 'Firefox ESR', + 'last 2 FirefoxAndroid versions', + 'not Explorer > 0', + 'not Safari > 0', + 'not iOS > 0', + 'not ChromeAndroid > 0', + 'not OperaMini all', + ].join(', ')] + }, + }, + ], +}); + +// Ignore temporarily since it's taking forever. +// It seems to be importing typescript or something. +config.ignorePatterns = ['tests/project/tsconf.tests.ts']; + +module.exports = config; diff --git a/.github/ISSUE_TEMPLATE/broken-website.md b/.github/ISSUE_TEMPLATE/broken-website.md index d5ae36b97850..af1022ffdae0 100644 --- a/.github/ISSUE_TEMPLATE/broken-website.md +++ b/.github/ISSUE_TEMPLATE/broken-website.md @@ -7,21 +7,15 @@ assignees: '' --- - - - # Broken Website Report ## Website Address @@ -33,14 +27,10 @@ assignees: '' Here is an example: - Go to example.com. - Hover over the example button. -- Notice that when hovering over the example button, it does not change color. --> -## Expected Behavior - - -## Actual Behavior - +## Problematic Observation + ## Screenshots @@ -56,4 +46,4 @@ Here is an example: - Dark Reader Version: ## Additional Context - \ No newline at end of file + diff --git a/.github/ISSUE_TEMPLATE/bug-report.md b/.github/ISSUE_TEMPLATE/bug-report.md index f8b6303ea846..77ef61ee106e 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.md +++ b/.github/ISSUE_TEMPLATE/bug-report.md @@ -7,39 +7,29 @@ assignees: '' --- - - # Bug Report +## Website Address + + ## Bug Description -## Website Address - - ## Steps To Reproduce - - ## Expected Behavior @@ -62,4 +52,4 @@ Here is an example: - Dark Reader Version: ## Additional Context - \ No newline at end of file + diff --git a/.github/workflows/test-browser.yml b/.github/workflows/test-browser.yml new file mode 100644 index 000000000000..0803765d6259 --- /dev/null +++ b/.github/workflows/test-browser.yml @@ -0,0 +1,85 @@ +name: Run browser tests in Karma +on: + + # Runs for pushes and pull requests, + # but don't run these when only some config is changed. + push: + branches: + - master + paths-ignore: + - 'src/config/*' + pull_request: + branches: + - master + types: + - opened + - synchronize + - reopened + - ready_for_review + paths-ignore: + - 'src/config/**' + + workflow_dispatch: +jobs: + test-browser: + name: Run browser tests + strategy: + matrix: + include: + + # Extended support releases + - channel: esr + firefox: latest-esr + + # Stable releases + - channel: stable + chrome: stable + firefox: latest + coverage: true + + # Beta releases + - channel: beta + chrome: beta + firefox: latest-beta + + runs-on: ubuntu-latest + + steps: + - name: Check out code + uses: actions/checkout@v2 + + - name: Install Chrome + if: ${{ matrix.chrome }} + uses: browser-actions/setup-chrome@latest + with: + chrome-version: ${{ matrix.chrome }} + - name: Configure Karma with path to Chrome executable + if: ${{ matrix.chrome }} + run: | + chrome --version + { echo CHROME_BIN="$(which chrome)"; echo CHROME_TEST=1; } | tee -a "$GITHUB_ENV" + + - name: Install Firefox + if: ${{ matrix.firefox }} + uses: browser-actions/setup-firefox@latest + with: + firefox-version: ${{ matrix.firefox }} + - name: Configure Karma with path to Firefox executable + if: ${{ matrix.firefox }} + run: | + firefox --version + { echo FIREFOX_BIN="$(which firefox)"; echo FIREFOX_TEST=1; } | tee -a "$GITHUB_ENV" + + - name: Node.js setup + uses: actions/setup-node@v2 + with: + node-version: ${{ matrix.node }} + cache: npm + - name: Track Node and NPM version + run: node --version && npm --version + + - name: Install application dependencies + run: npm ci + + - name: Run tests + run: npm run test:inject -- --ci diff --git a/.github/workflows/test-code.yml b/.github/workflows/test-code.yml new file mode 100644 index 000000000000..1b941d6b2828 --- /dev/null +++ b/.github/workflows/test-code.yml @@ -0,0 +1,55 @@ +name: Run code tests on Pull Request or Push +on: + + # Runs for pushes and pull requests, + # but don't run these when only some config is changed. + push: + branches: + - master + paths-ignore: + - 'src/config/*' + pull_request: + branches: + - master + types: + - opened + - synchronize + - reopened + - ready_for_review + paths-ignore: + - 'src/config/**' + + workflow_dispatch: +jobs: + test: + name: Run tests + runs-on: ubuntu-latest + steps: + - name: Clone repository + uses: actions/checkout@v2 + + - name: Set up Node.js + uses: actions/setup-node@v2 + with: + node-version: 15.x + + - name: Verify NPM version + run: npm --version + + - name: Set up npm cache + uses: actions/cache@v2 + with: + path: ~/.npm + key: ${{ runner.os }}-${{ hashFiles('package-lock.json') }} + restore-keys: | + ${{ runner.OS }}-${{ hashFiles('package-lock.json') }} + ${{ runner.OS }} + + - name: Install npm dependencies + run: npm ci + + - name: Lint code for code-style errors + run: npm run lint + + - name: Check for compatibility issues + run: npm run lint:bundle diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 03a547ab9056..f713063aea18 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,4 +1,4 @@ -name: Run tests on Pull Request or Push +name: Run config tests on Pull Request or Push on: push: branches: @@ -23,8 +23,11 @@ jobs: - name: Set up Node.js uses: actions/setup-node@v2 with: - node-version: 14.x - + node-version: 15.x + + - name: Verify NPM version + run: npm --version + - name: Set up npm cache uses: actions/cache@v2 with: @@ -39,6 +42,3 @@ jobs: - name: Run test against code run: npm run test:ci - - - name: Lint code for code-style errors - run: npm run lint diff --git a/.gitignore b/.gitignore index 57568961811e..31138007e3f7 100644 --- a/.gitignore +++ b/.gitignore @@ -18,8 +18,13 @@ tests/inject/coverage/ #----------------------------------- .idea/ .vscode/ +.log/ *.code-workspace # Cache files #----------------------------------- .eslintcache + +# V8 Profiler logs +#----------------------------------- +isolate-*-v8.log diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000000..169ff7196938 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,180 @@ +## Unreleased + +- Don't manage styles that have a empty `href` attribute. +- Use `navigator.UserAgentData` when possible. +- Add a `` detector, to disable Dark Reader when detected (only dynamic theme). + +## 4.9.52 (June 28, 2022) + +- Correctly handle escaped characters in CSS `url(...)` values. + +## 4.9.51 (May 27, 2022) + +Dynamic mode improvements: + +- Fixed CSS imports that contain `url(...)` and end with `screen`. +- Send network responses to correct frames in tabs. +- Improved `calc(...)` color handling by using [Shunting Yard algorithm](https://en.wikipedia.org/wiki/Shunting_yard_algorithm). + +New translations: + +- Malay translation. +- Telugu translation. + +Other: + +- UI improvements. +- Users' fixes for websites. + +## 4.9.50 (May 1, 2022) + +- Fix working in Firefox Nightly 101. +- Users' fixes for websites. + +## 4.9.48 (Apr 18, 2022) + +- Fix PDF inversion when Auto-detect dark theme option was enabled. +- Fix Jira's background. +- User's settings validation. +- Users' fixes for websites. + +## 4.9.47 (Mar 14, 2022) + +- Users' fixes for websites. + +## 4.9.46 (Mar 10, 2022) + +- v5 Preview: Auto-detect dark theme on websites. +- v5 Preview: Option for running dark theme on hidden tabs immediately. +- Dynamic mode bug fixes. +- Translation improvements. +- Users' fixes for websites. + +## 4.9.45 (Feb 5, 2022) + +- Revert reducing brightness for images (due to some performance issues). +- Users' fixes for websites. + +## 4.9.44 (Feb 4, 2022) + +- Dynamic mode improvements. +- v5 preview: Ability to automate dark/light scheme. +- Users' fixes for websites. + +## 4.9.43 (Dec 7, 2021) + +- Dynamic mode bug fixes. +- Users' fixes for websites. + +## 4.9.42 (Nov 6, 2021) + +- Fixed slow performance on some websites. +- Fixed broken UI for some users. +- Users' fixes for websites. + +## 4.9.41 (Nov 5, 2021) + +- Fixed white flash when page starts loading. +- Users' fixes for websites. + +## 4.9.40 (Nov 3, 2021) + +- Dynamic mode fixes. +- Filipino translation (thanks to @IverCoder). +- Serbian translation (thanks to Nemanja @nebocoder). +- Users' fixes for websites. + +## 4.9.39 (Oct 1, 2021) + +- Fixed settings not being saved. +- Fixed not working popup for some users. +- Dynamic mode performance improvements. +- v5 Preview design update. +- Users' fixes for websites. + +## 4.9.37.1 (Sep 23, 2021) + +- Fixed error when applying settings after some time. +- Users' fixes for websites. + +## 4.9.36 (Sep 21, 2021) + +- Fixed regression bugs after 4.9.35 release (hotkeys, Dev Tools, sunrise/sunset). +- Users' fixes for websites. + +## 4.9.35 (Sep 19, 2021) + +- Preparing the app for work in non-persistent background context. +- Dynamic mode bug fixes and performance improvements. +- Users' fixes for websites. + +## 4.9.34 (Jul 7, 2021) + +- Dynamic mode bug fixes and performance improvements. +- Minor UI improvements. +- Users' fixes for websites. + +## 4.9.33 (May 28, 2021) + +- Fixed disability to switch on sites in Global Dark List. +- Bug fixes. +- Users' fixes for websites. + +## 4.9.32 (Apr 21, 2021) + +- Dynamic mode bug fixes. +- Users' fixes for websites. + +## 4.9.31 (Apr 5, 2021) + +- Fixed performance bottleneck for websites with CSS variables. +- Users' fixes for websites. + +## 4.9.30 (Apr 1, 2021) + +- Improved CSS Variables support. +- Dynamic mode bug fixes. +- Fixed toggle shortcut keys for PDFs. +- Users' fixes for websites. + +## 4.9.29 (Feb 22, 2021) + +- Users' fixes for websites. + +## 4.9.27 (Jan 21, 2021) + +- Dynamic mode improvements. +- Thunderbird support. +- Users' fixes for websites. +- Users' translation improvements. + +## 4.9.26 (Nov 26, 2020) + +- Dynamic mode bug fixes. +- Users' fixes for websites. + +## 4.9.25 (Nov 25, 2020) + +- Dynamic mode bug fixes. +- Users' fixes for websites. + +## 4.9.24 (Nov 19, 2020) + +- Dynamic mode fixes and performance improvements. +- Updates for Dutch translation. +- Users' fixes for websites. +- Reduced assets size. + +## 4.9.23 (Oct 26, 2020) + +- Fixed missing images on some websites. + +## 4.9.22 (Oct 26, 2020) + +- Fixed high CPU usage caused by conflict with some websites. +- Dynamic mode bug fixes. +- Users' fixes for websites. + +## 4.9.21 (Sep 26, 2020) + +- Fixed wrongly displaying pages where the extension is disabled. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c490029c504c..0137e79d0efc 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -86,11 +86,11 @@ IGNORE IMAGE ANALYSIS ``` | Rule | Description | Notes / Examples | -|-|-|-| -| `INVERT` | Inverts specified elements. | **Dynamic Mode**: INVERT only for dark images that are invisible on dark backgrounds. | -| `CSS` | Adds custom CSS to a web page. | `!important` keyword should be specified for each CSS property to prevent overrides by other stylesheets.
**Dynamic mode** supports `${COLOR}` template, where `COLOR` is a color value before the inversion.
*Example*: `${white}` will become `${black}` in dark mode. | -| `IGNORE INLINE STYLE` | Prevents inline style analysis of matched elements. | *Example*: `

` element's style attribute will not be changed. | -| `IGNORE IMAGE ANALYSIS` | Prevents background images from being analyzed for matched selectors. | | +|---|---|---| +| **INVERT** | Inverts specified elements. | **Dynamic Mode**: INVERT only for dark images that are invisible on dark backgrounds. | +| **CSS** | Adds custom CSS to a web page. | `!important` keyword should be specified for each CSS property to prevent overrides by other stylesheets.
**Dynamic mode** supports `${COLOR}` template, where `COLOR` is a color value before the inversion.
*Example*: `${white}` will become `${black}` in dark mode. | +| **IGNORE INLINE STYLE** | Prevents inline style analysis of matched elements. | *Example*: `

` element's style attribute will not be changed. | +| **IGNORE IMAGE ANALYSIS** | Prevents background images from being analyzed for matched selectors. | | ## Adding a new color scheme @@ -132,13 +132,12 @@ CSS ``` Here is a full table of available CSS variables: - | Variable | Description | Use | -|-|-|-| -| `--darkreader-neutral-background` | Neutral background color that corresponds to the user's settings. | Mostly used for elements that have a wrong background color | -| `--darkreader-neutral-text` | Neutral text color that corresponds to the user's settings. | Used for elements with a wrong text color | -| `--darkreader-selection-background` | The text color setting defined by the user. | The user's Text Color setting | -| `--darkreader-selection-text` | The background color setting defined by the user. | The user's Background Color setting | +|---|---|---| +| **`--darkreader-neutral-background`** | Neutral background color that
corresponds to the user's settings. | Mostly used for elements that have
a wrong background color | +| **`--darkreader-neutral-text`** | Neutral text color that
corresponds to the user's settings. | Used for elements with a wrong text color | +| **`--darkreader-selection-background`** | The text color setting
defined by the user. | The user's Text Color setting | +| **`--darkreader-selection-text`** | The background color setting
defined by the user. | The user's Background Color setting | ## Fixes for Filter and Filter+ mode @@ -196,7 +195,7 @@ It will after making any code changes, the project will be automatically recompi ## Tips -For editing the code you can use any text editor or web IDE (like [Visual Studio Code](https://code.visualstudio.com), [Atom](https://atom.io/), or [WebStorm](https://www.jetbrains.com/webstorm/)). +For editing the code you can use any text editor or web IDE (like [Visual Studio Code](https://code.visualstudio.com), or [WebStorm](https://www.jetbrains.com/webstorm/)). **Please preserve code style** (whitespaces etc). This can automatically be done by executing `npm run code-style`. diff --git a/README.md b/README.md index d5e20992f24e..3f2dc5a7f36d 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@

Dark Reader's mascot

-

Dark Reader analyzes web pages and aims to reduce the eyestrain while you browse the web.

+

Dark Reader analyzes web pages and aims to reduce eyestrain while browsing the web.


Chrome Web Store Firefox Add-ons Apple App Store Edge Addons Thunderbird

Dark Reader


-

Dark Reader is an open-source MIT-licensed browser extension that is designed to analyze web pages. Based on its analysis, Dark Reader will generate a dark mode that aims to reduce the eyestrain of the user. Dark Reader is feature-rich and can be configured in many ways throughout the UI.

+

Dark Reader is an open-source MIT-licensed browser extension designed to analyze web pages. Dark Reader will generate a dark mode that aims to reduce the eyestrain of the user. Dark Reader is feature-rich and is customizable in many ways throughout the UI.



@@ -22,12 +22,12 @@ Read more about contributing to Dark Reader in [CONTRIBUTING.md](https://github. You can install the extension from a file. Install [Node.js LTS](https://nodejs.org/en/). Download the source code (or check out from git). -Open terminal in the root folder and run: +Open the terminal in the root folder and run: -- `npm install` -- `npm run build` +- `npm install` +- `npm run build` -This will generate a `build/release/darkreader-chrome.zip` file that is useable in a Chromium-based browser and also a `build/release/darkreader-firefox.xpi` file that is useable in Firefox. +This will create a `build/release/darkreader-chrome.zip` file for use in a Chromium-based browser and a `build/release/darkreader-firefox.xpi` file for use in Firefox. ## Using Dark Reader for a website @@ -90,39 +90,39 @@ const CSS = await collectCSS(); const isEnabled = isDarkReaderEnabled(); ``` -Be aware, that darkreader will add the `chrome` object onto the `window` object, these are to stub certain functions that -the code will use. They originate from the webextension-api. +Be aware that darkreader will add the `chrome` object onto the `window` object. These are to stub certain functions that the code will use. They originate from the webextension-api. ## Site fixes -Automatically syncing the site fixes to every Dark Reader user was disabled because the GitHub team doesn't allow using GitHub as a CDN. Storing these files and making requests to other resources would be expensive and look suspicious. As such, changes are included with each new Dark Reader release. +Automatically syncing the site fixes to every Dark Reader user was disabled because the GitHub team does not allow using GitHub as a CDN. The storage of these files would be expensive, and making requests to other resources would look suspicious. Each new release of Dark Reader will include these changes. -However, this can be enabled by the following steps: +However, this can be enabled using the following steps: - Click on the Dark Reader icon. - Click on the Dev tools button (in the bottom-right corner). - Click on the Preview new design button. -- Enable the `Synchronize site fixes` setting, under `Settings -> Manage Settings`. +- Enable the `Synchronize site fixes` setting under `Settings -> Manage Settings`.

Contributors


-

Dark Reader exists thanks to all the people who have contributed to Dark Reader!

+

Thank you to all our contributors! Dark Reader exists thanks to you.



Backers


-

Thank you to all our generous backers! Support Dark Reader by Becoming a backer

+

Thank you to all our generous backers! Support Dark Reader by becoming a backer.



Sponsors

-

Does your company use Dark Reader? Ask your manager or the marketing team if your company would be interested in supporting our project. By supporting this project, it will allow the maintainers to dedicate more time for maintenance and new features for everyone. Also, your company's logo will show on GitHub - who doesn't want a little extra exposure? Here's the info.

- -

Thank you to our wonderful sponsors!

+

Does your company use Dark Reader? Ask your manager or the marketing team if your company would be interested in supporting our project. Your support will allow the maintainers to dedicate more time to maintenance and creating new features for everyone. Also, your company's logo will show on GitHub. Who doesn't want a little extra exposure? Here's the info.

+

Thank you to all our wonderful sponsors!

+
+
diff --git a/SECURITY.md b/SECURITY.md index c9f400ef31c0..911c3393bc3c 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -10,18 +10,17 @@ Latest version is supported. | Version | Supported | | --------- | ------------------ | -| 4.9.33 | :white_check_mark: | -| < 4.9.33 | :x: | +| 4.9.43 | :white_check_mark: | +| < 4.9.43 | :x: | ## Reporting a Vulnerability -In case there is a vulnerability left behind, immediately notify -to ; unless you can fix it yourself, -in which case open a pull request on -. - -Alexander Shutau, owner +In case there is a vulnerability, please immediately notify +. -"Gusted" William Zijl, maintainer +If you can fix it yourself, please also open a pull request at +. -Erkin Alp Güney, security policy author +Alexander Shutau, owner +"Gusted" William Zijl, maintainer +Erkin Alp Güney, security policy author diff --git a/docs/color-schemes-drconf.spec b/docs/color-schemes-drconf.spec index eb4ba364d372..cdc6fd29ee29 100644 --- a/docs/color-schemes-drconf.spec +++ b/docs/color-schemes-drconf.spec @@ -4,11 +4,11 @@ which doesn't really follow the standard for other files. Spec: - A section is a unique defined colorscheme following the syntax rules. - The file must begin with a section, with the name of "Default" which has both a light and dark variant. -- A seperator must be placed between new sections, the seperator is `'='.repeat(32)`. -- A new line must be placed before and after the seperator. -- All but not the first section should start with a new line(this is the same new line after the seperator). -- The first keywoard in the section(after the possible new line) should be a unique colorscheme name. -- After 2 new lines of the first keywoard should either be "DARK" or "LIGHT", at least 1 variant should be defined. +- A separator must be placed between new sections, the separator is `'='.repeat(32)`. +- A new line must be placed before and after the separator. +- All but not the first section should start with a new line(this is the same new line after the separator). +- The first keyword in the section(after the possible new line) should be a unique colorscheme name. +- After 2 new lines of the first keyword should either be "DARK" or "LIGHT", at least 1 variant should be defined. - If a color scheme has both variants the order should start with "DARK" and then "LIGHT" for consistency. - Within the variants a background color and text color can be defined, both are required. - The syntax of defining background-color and text color should be `{background,text}: #6-or-3-length-hex-color` each on a new line. diff --git a/index.d.ts b/index.d.ts index 573e7f1697f7..332a07370401 100644 --- a/index.d.ts +++ b/index.d.ts @@ -150,6 +150,13 @@ declare namespace DarkReader { * Mostly used for wrongly inverted background-images */ ignoreImageAnalysis: string[]; + + /** + * A toggle to disable the proxying of `document.styleSheets`. + * This is a API-Exclusive option, as it can break legitmate websites, + * who are using the Dark Reader API. + */ + disableStyleSheetsProxy: boolean; } } diff --git a/package-lock.json b/package-lock.json index 659e9accc822..6e1fccb25ca1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,59 +1,62 @@ { "name": "darkreader", - "version": "4.9.42", + "version": "4.9.52", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "darkreader", - "version": "4.9.42", + "version": "4.9.49", "license": "MIT", "devDependencies": { - "@rollup/plugin-node-resolve": "13.0.6", - "@rollup/plugin-replace": "3.0.0", - "@rollup/pluginutils": "4.1.1", - "@types/chrome": "0.0.162", - "@types/jasmine": "3.10.1", - "@types/jest": "27.0.2", - "@types/karma": "6.3.1", - "@types/node": "16.11.6", + "@rollup/plugin-node-resolve": "13.1.3", + "@rollup/plugin-replace": "4.0.0", + "@rollup/plugin-typescript": "8.3.1", + "@rollup/pluginutils": "4.2.0", + "@types/chrome": "0.0.180", + "@types/eslint": "8.4.1", + "@types/jasmine": "4.0.0", + "@types/jest": "27.4.1", + "@types/karma": "6.3.3", + "@types/karma-coverage": "2.0.1", + "@types/node": "17.0.23", "@types/offscreencanvas": "2019.6.4", - "@typescript-eslint/eslint-plugin": "5.3.0", - "@typescript-eslint/parser": "5.3.0", - "chokidar": "3.5.2", - "eslint": "8.1.0", - "eslint-plugin-import": "2.25.2", + "@typescript-eslint/eslint-plugin": "5.16.0", + "@typescript-eslint/parser": "5.16.0", + "chokidar": "3.5.3", + "eslint": "8.11.0", + "eslint-plugin-compat": "4.0.2", + "eslint-plugin-import": "2.25.4", "eslint-plugin-local": "1.0.0", - "fs-extra": "10.0.0", - "globby": "11.0.4", - "jasmine-core": "3.10.1", - "jest": "27.3.1", - "karma": "6.3.7", - "karma-chrome-launcher": "3.1.0", - "karma-coverage": "2.0.3", + "get-stream": "6.0.1", + "globby": "13.1.1", + "jasmine-core": "4.0.1", + "jest": "27.5.1", + "jest-extended": "2.0.0", + "karma": "6.3.17", + "karma-chrome-launcher": "3.1.1", + "karma-coverage": "2.2.0", "karma-firefox-launcher": "2.1.2", "karma-jasmine": "4.0.1", - "karma-rollup-preprocessor": "7.0.7", + "karma-rollup-preprocessor": "7.0.8", "karma-safari-launcher": "1.0.0", + "karma-spec-reporter": "0.0.33", "less": "4.1.2", - "malevic": "0.18.6", - "prettier": "2.4.1", - "puppeteer-core": "10.4.0", - "rollup": "2.59.0", + "malevic": "0.19.1", + "prettier": "2.6.1", + "puppeteer-core": "13.5.1", + "rollup": "2.70.1", "rollup-plugin-istanbul2": "2.0.2", - "rollup-plugin-typescript2": "0.31.1", - "ts-jest": "27.0.7", - "ts-node": "10.4.0", - "tsconfig-paths": "3.11.0", + "ts-jest": "27.1.4", "tslib": "2.3.1", - "typescript": "4.4.4", - "web-ext": "6.5.0", - "ws": "8.2.3", + "typescript": "4.6.3", + "web-ext": "6.8.0", + "ws": "8.5.0", "yazl": "2.5.1" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/darkreader" + "url": "https://opencollective.com/darkreader/donate" } }, "node_modules/@babel/code-frame": { @@ -230,9 +233,9 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz", - "integrity": "sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz", + "integrity": "sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA==", "dev": true, "engines": { "node": ">=6.9.0" @@ -539,12 +542,12 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.16.0.tgz", - "integrity": "sha512-Xv6mEXqVdaqCBfJFyeab0fH2DnUoMsDmhamxsSi4j8nLd4Vtw213WMJr55xxqipC/YVWyPY3K0blJncPYji+dQ==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.16.7.tgz", + "integrity": "sha512-YhUIJHHGkqPgEcMYkPCKTyGUdoGKWtopIycQyjJH8OjvRgOYsXsaKehLVPScKJWAULPxMa4N1vCe6szREFlZ7A==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" @@ -614,25 +617,13 @@ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true }, - "node_modules/@cspotcode/source-map-consumer": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz", - "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==", - "dev": true, - "engines": { - "node": ">= 12" - } - }, - "node_modules/@cspotcode/source-map-support": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz", - "integrity": "sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==", + "node_modules/@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", "dev": true, - "dependencies": { - "@cspotcode/source-map-consumer": "0.8.0" - }, "engines": { - "node": ">=12" + "node": ">=0.1.90" } }, "node_modules/@devicefarmer/adbkit": { @@ -693,18 +684,18 @@ "dev": true }, "node_modules/@eslint/eslintrc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.0.3.tgz", - "integrity": "sha512-DHI1wDPoKCBPoLZA3qDR91+3te/wDSc1YhKg3jR8NxKKRJq2hwHwcWv31cSwSYvIBrmbENoYMWcenW8uproQqg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.1.tgz", + "integrity": "sha512-bxvbYnBPN1Gibwyp6NrpnFzA3YtRL3BBAyEAFVIpNTm2Rn4Vy87GA5M4aSn3InRrlsbX5N0GW7XIx+U4SAEKdQ==", "dev": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.0.0", + "espree": "^9.3.1", "globals": "^13.9.0", - "ignore": "^4.0.6", + "ignore": "^5.2.0", "import-fresh": "^3.2.1", - "js-yaml": "^3.13.1", + "js-yaml": "^4.1.0", "minimatch": "^3.0.4", "strip-json-comments": "^3.1.1" }, @@ -712,52 +703,13 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/@eslint/eslintrc/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/@eslint/eslintrc/node_modules/debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@eslint/eslintrc/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, "node_modules/@humanwhocodes/config-array": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.6.0.tgz", - "integrity": "sha512-JQlEKbcgEUjBFhLIF4iqM7u/9lwgHRBcpHrmUNCALK0Q3amXN6lxdoXLnF0sm11E9VqTmBALR87IlUg1bZ8A9A==", + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.2.tgz", + "integrity": "sha512-UXOuFCGcwciWckOpmfKDq/GyhlTf9pN/BzG//x8p8zTOFEcGuA68ANXheFS0AGvy3qgZqLBUkMs7hqzqCKOVwA==", "dev": true, "dependencies": { - "@humanwhocodes/object-schema": "^1.2.0", + "@humanwhocodes/object-schema": "^1.2.1", "debug": "^4.1.1", "minimatch": "^3.0.4" }, @@ -766,9 +718,9 @@ } }, "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.0.tgz", - "integrity": "sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true }, "node_modules/@istanbuljs/load-nyc-config": { @@ -828,16 +780,16 @@ } }, "node_modules/@jest/console": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-27.3.1.tgz", - "integrity": "sha512-RkFNWmv0iui+qsOr/29q9dyfKTTT5DCuP31kUwg7rmOKPT/ozLeGLKJKVIiOfbiKyleUZKIrHwhmiZWVe8IMdw==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-27.5.1.tgz", + "integrity": "sha512-kZ/tNpS3NXn0mlXXXPNuDZnb4c0oZ20r4K5eemM2k30ZC3G0T02nXUvyhf5YdbXWHPEJLc9qGLxEZ216MdL+Zg==", "dev": true, "dependencies": { - "@jest/types": "^27.2.5", + "@jest/types": "^27.5.1", "@types/node": "*", "chalk": "^4.0.0", - "jest-message-util": "^27.3.1", - "jest-util": "^27.3.1", + "jest-message-util": "^27.5.1", + "jest-util": "^27.5.1", "slash": "^3.0.0" }, "engines": { @@ -845,35 +797,35 @@ } }, "node_modules/@jest/core": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-27.3.1.tgz", - "integrity": "sha512-DMNE90RR5QKx0EA+wqe3/TNEwiRpOkhshKNxtLxd4rt3IZpCt+RSL+FoJsGeblRZmqdK4upHA/mKKGPPRAifhg==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-27.5.1.tgz", + "integrity": "sha512-AK6/UTrvQD0Cd24NSqmIA6rKsu0tKIxfiCducZvqxYdmMisOYAsdItspT+fQDQYARPf8XgjAFZi0ogW2agH5nQ==", "dev": true, "dependencies": { - "@jest/console": "^27.3.1", - "@jest/reporters": "^27.3.1", - "@jest/test-result": "^27.3.1", - "@jest/transform": "^27.3.1", - "@jest/types": "^27.2.5", + "@jest/console": "^27.5.1", + "@jest/reporters": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "emittery": "^0.8.1", "exit": "^0.1.2", - "graceful-fs": "^4.2.4", - "jest-changed-files": "^27.3.0", - "jest-config": "^27.3.1", - "jest-haste-map": "^27.3.1", - "jest-message-util": "^27.3.1", - "jest-regex-util": "^27.0.6", - "jest-resolve": "^27.3.1", - "jest-resolve-dependencies": "^27.3.1", - "jest-runner": "^27.3.1", - "jest-runtime": "^27.3.1", - "jest-snapshot": "^27.3.1", - "jest-util": "^27.3.1", - "jest-validate": "^27.3.1", - "jest-watcher": "^27.3.1", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^27.5.1", + "jest-config": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-resolve-dependencies": "^27.5.1", + "jest-runner": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "jest-watcher": "^27.5.1", "micromatch": "^4.0.4", "rimraf": "^3.0.0", "slash": "^3.0.0", @@ -892,77 +844,77 @@ } }, "node_modules/@jest/environment": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.3.1.tgz", - "integrity": "sha512-BCKCj4mOVLme6Tanoyc9k0ultp3pnmuyHw73UHRPeeZxirsU/7E3HC4le/VDb/SMzE1JcPnto+XBKFOcoiJzVw==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.5.1.tgz", + "integrity": "sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA==", "dev": true, "dependencies": { - "@jest/fake-timers": "^27.3.1", - "@jest/types": "^27.2.5", + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", "@types/node": "*", - "jest-mock": "^27.3.0" + "jest-mock": "^27.5.1" }, "engines": { "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, "node_modules/@jest/fake-timers": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.3.1.tgz", - "integrity": "sha512-M3ZFgwwlqJtWZ+QkBG5NmC23A9w+A6ZxNsO5nJxJsKYt4yguBd3i8TpjQz5NfCX91nEve1KqD9RA2Q+Q1uWqoA==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.5.1.tgz", + "integrity": "sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ==", "dev": true, "dependencies": { - "@jest/types": "^27.2.5", + "@jest/types": "^27.5.1", "@sinonjs/fake-timers": "^8.0.1", "@types/node": "*", - "jest-message-util": "^27.3.1", - "jest-mock": "^27.3.0", - "jest-util": "^27.3.1" + "jest-message-util": "^27.5.1", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1" }, "engines": { "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, "node_modules/@jest/globals": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-27.3.1.tgz", - "integrity": "sha512-Q651FWiWQAIFiN+zS51xqhdZ8g9b88nGCobC87argAxA7nMfNQq0Q0i9zTfQYgLa6qFXk2cGANEqfK051CZ8Pg==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-27.5.1.tgz", + "integrity": "sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q==", "dev": true, "dependencies": { - "@jest/environment": "^27.3.1", - "@jest/types": "^27.2.5", - "expect": "^27.3.1" + "@jest/environment": "^27.5.1", + "@jest/types": "^27.5.1", + "expect": "^27.5.1" }, "engines": { "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, "node_modules/@jest/reporters": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-27.3.1.tgz", - "integrity": "sha512-m2YxPmL9Qn1emFVgZGEiMwDntDxRRQ2D58tiDQlwYTg5GvbFOKseYCcHtn0WsI8CG4vzPglo3nqbOiT8ySBT/w==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-27.5.1.tgz", + "integrity": "sha512-cPXh9hWIlVJMQkVk84aIvXuBB4uQQmFqZiacloFuGiP3ah1sbCxCosidXFDfqG8+6fO1oR2dTJTlsOy4VFmUfw==", "dev": true, "dependencies": { "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^27.3.1", - "@jest/test-result": "^27.3.1", - "@jest/transform": "^27.3.1", - "@jest/types": "^27.2.5", + "@jest/console": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", "@types/node": "*", "chalk": "^4.0.0", "collect-v8-coverage": "^1.0.0", "exit": "^0.1.2", "glob": "^7.1.2", - "graceful-fs": "^4.2.4", + "graceful-fs": "^4.2.9", "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^4.0.3", + "istanbul-lib-instrument": "^5.1.0", "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.0.2", - "jest-haste-map": "^27.3.1", - "jest-resolve": "^27.3.1", - "jest-util": "^27.3.1", - "jest-worker": "^27.3.1", + "istanbul-reports": "^3.1.3", + "jest-haste-map": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", "slash": "^3.0.0", "source-map": "^0.6.0", "string-length": "^4.0.1", @@ -982,13 +934,13 @@ } }, "node_modules/@jest/source-map": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-27.0.6.tgz", - "integrity": "sha512-Fek4mi5KQrqmlY07T23JRi0e7Z9bXTOOD86V/uS0EIW4PClvPDqZOyFlLpNJheS6QI0FNX1CgmPjtJ4EA/2M+g==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-27.5.1.tgz", + "integrity": "sha512-y9NIHUYF3PJRlHk98NdC/N1gl88BL08aQQgu4k4ZopQkCw9t9cV8mtl3TV8b/YCB8XaVTFrmUTAJvjsntDireg==", "dev": true, "dependencies": { "callsites": "^3.0.0", - "graceful-fs": "^4.2.4", + "graceful-fs": "^4.2.9", "source-map": "^0.6.0" }, "engines": { @@ -996,13 +948,13 @@ } }, "node_modules/@jest/test-result": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.3.1.tgz", - "integrity": "sha512-mLn6Thm+w2yl0opM8J/QnPTqrfS4FoXsXF2WIWJb2O/GBSyResL71BRuMYbYRsGt7ELwS5JGcEcGb52BNrumgg==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.5.1.tgz", + "integrity": "sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag==", "dev": true, "dependencies": { - "@jest/console": "^27.3.1", - "@jest/types": "^27.2.5", + "@jest/console": "^27.5.1", + "@jest/types": "^27.5.1", "@types/istanbul-lib-coverage": "^2.0.0", "collect-v8-coverage": "^1.0.0" }, @@ -1011,38 +963,38 @@ } }, "node_modules/@jest/test-sequencer": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-27.3.1.tgz", - "integrity": "sha512-siySLo07IMEdSjA4fqEnxfIX8lB/lWYsBPwNFtkOvsFQvmBrL3yj3k3uFNZv/JDyApTakRpxbKLJ3CT8UGVCrA==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-27.5.1.tgz", + "integrity": "sha512-LCheJF7WB2+9JuCS7VB/EmGIdQuhtqjRNI9A43idHv3E4KltCTsPsLxvdaubFHSYwY/fNjMWjl6vNRhDiN7vpQ==", "dev": true, "dependencies": { - "@jest/test-result": "^27.3.1", - "graceful-fs": "^4.2.4", - "jest-haste-map": "^27.3.1", - "jest-runtime": "^27.3.1" + "@jest/test-result": "^27.5.1", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-runtime": "^27.5.1" }, "engines": { "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, "node_modules/@jest/transform": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.3.1.tgz", - "integrity": "sha512-3fSvQ02kuvjOI1C1ssqMVBKJpZf6nwoCiSu00zAKh5nrp3SptNtZy/8s5deayHnqxhjD9CWDJ+yqQwuQ0ZafXQ==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.5.1.tgz", + "integrity": "sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==", "dev": true, "dependencies": { "@babel/core": "^7.1.0", - "@jest/types": "^27.2.5", - "babel-plugin-istanbul": "^6.0.0", + "@jest/types": "^27.5.1", + "babel-plugin-istanbul": "^6.1.1", "chalk": "^4.0.0", "convert-source-map": "^1.4.0", "fast-json-stable-stringify": "^2.0.0", - "graceful-fs": "^4.2.4", - "jest-haste-map": "^27.3.1", - "jest-regex-util": "^27.0.6", - "jest-util": "^27.3.1", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-util": "^27.5.1", "micromatch": "^4.0.4", - "pirates": "^4.0.1", + "pirates": "^4.0.4", "slash": "^3.0.0", "source-map": "^0.6.1", "write-file-atomic": "^3.0.0" @@ -1052,9 +1004,9 @@ } }, "node_modules/@jest/types": { - "version": "27.2.5", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.2.5.tgz", - "integrity": "sha512-nmuM4VuDtCZcY+eTpw+0nvstwReMsjPoj7ZR80/BbixulhLaiX+fbv8oeLW8WZlJMcsGQsTmMKT/iTZu1Uy/lQ==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", "dev": true, "dependencies": { "@types/istanbul-lib-coverage": "^2.0.0", @@ -1068,9 +1020,9 @@ } }, "node_modules/@mdn/browser-compat-data": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-4.0.5.tgz", - "integrity": "sha512-KPSNaHUl5aikqsQU7LpBntFzaPbhm5OJxD88Wv00OKDc4wudyid2wDFqLeb7VcYT9x5bND8PPFloWdK5DY0pHA==", + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-4.1.12.tgz", + "integrity": "sha512-y3Ntio6hb5+m6asxcA3nnIN6URjAFMji2EZZVYGd2Ag5On4mmvPhMnXdiIScCMXgHjFX+5qXuKaojLLhJHZPAg==", "dev": true }, "node_modules/@nodelib/fs.scandir": { @@ -1109,9 +1061,9 @@ } }, "node_modules/@rollup/plugin-node-resolve": { - "version": "13.0.6", - "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-13.0.6.tgz", - "integrity": "sha512-sFsPDMPd4gMqnh2gS0uIxELnoRUp5kBl5knxD2EO0778G1oOJv4G1vyT2cpWz75OU2jDVcXhjVUuTAczGyFNKA==", + "version": "13.1.3", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-13.1.3.tgz", + "integrity": "sha512-BdxNk+LtmElRo5d06MGY4zoepyrXX1tkzX2hrnPEZ53k78GuOMWLqmJDGIIOPwVRIFZrLQOo+Yr6KtCuLIA0AQ==", "dev": true, "dependencies": { "@rollup/pluginutils": "^3.1.0", @@ -1152,9 +1104,9 @@ "dev": true }, "node_modules/@rollup/plugin-replace": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-3.0.0.tgz", - "integrity": "sha512-3c7JCbMuYXM4PbPWT4+m/4Y6U60SgsnDT/cCyAyUKwFHg7pTSfsSQzIpETha3a3ig6OdOKzZz87D9ZXIK3qsDg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-4.0.0.tgz", + "integrity": "sha512-+rumQFiaNac9y64OHtkHGmdjm7us9bo1PlbgQfdihQtuNxzjpaB064HbRnewUOggLQxVCCyINfStkgmBeQpv1g==", "dev": true, "dependencies": { "@rollup/pluginutils": "^3.1.0", @@ -1187,10 +1139,51 @@ "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", "dev": true }, + "node_modules/@rollup/plugin-typescript": { + "version": "8.3.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-8.3.1.tgz", + "integrity": "sha512-84rExe3ICUBXzqNX48WZV2Jp3OddjTMX97O2Py6D1KJaGSwWp0mDHXj+bCGNJqWHIEKDIT2U0sDjhP4czKi6cA==", + "dev": true, + "dependencies": { + "@rollup/pluginutils": "^3.1.0", + "resolve": "^1.17.0" + }, + "engines": { + "node": ">=8.0.0" + }, + "peerDependencies": { + "rollup": "^2.14.0", + "tslib": "*", + "typescript": ">=3.7.0" + } + }, + "node_modules/@rollup/plugin-typescript/node_modules/@rollup/pluginutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", + "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", + "dev": true, + "dependencies": { + "@types/estree": "0.0.39", + "estree-walker": "^1.0.1", + "picomatch": "^2.2.2" + }, + "engines": { + "node": ">= 8.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0" + } + }, + "node_modules/@rollup/plugin-typescript/node_modules/estree-walker": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", + "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", + "dev": true + }, "node_modules/@rollup/pluginutils": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.1.1.tgz", - "integrity": "sha512-clDjivHqWGXi7u+0d2r2sBi4Ie6VLEAzWMIkvJLnDmxoOhBYOTfzGbOQBA32THHm11/LiJbd01tJUpJsbshSWQ==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.0.tgz", + "integrity": "sha512-2WUyJNRkyH5p487pGnn4tWAsxhEFKN/pT8CMgHshd5H+IXkOnKvKZwsz5ZWz+YCXkleZRAU5kwbfgF8CPfDRqA==", "dev": true, "dependencies": { "estree-walker": "^2.0.1", @@ -1220,14 +1213,23 @@ } }, "node_modules/@sinonjs/fake-timers": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-8.0.1.tgz", - "integrity": "sha512-AU7kwFxreVd6OAXcAFlKSmZquiRUU0FvYm44k1Y1QbK7Co4m0aqfGMhjykIeQp/H6rcl+nFmj0zfdUcGVs9Dew==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz", + "integrity": "sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==", "dev": true, "dependencies": { "@sinonjs/commons": "^1.7.0" } }, + "node_modules/@socket.io/base64-arraybuffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@socket.io/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", + "integrity": "sha512-dOlCBKnDw4iShaIsH/bxujKTM18+2TOAsYz+KSc11Am38H4q5Xw8Bbz97ZYdrVNM+um3p7w86Bvvmcn9q+5+eQ==", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/@szmarczak/http-timer": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", @@ -1249,44 +1251,10 @@ "node": ">= 6" } }, - "node_modules/@ts-type/package-dts": { - "version": "1.0.53", - "resolved": "https://registry.npmjs.org/@ts-type/package-dts/-/package-dts-1.0.53.tgz", - "integrity": "sha512-P8bMcjqaUsaBbXOCxBtzT4/pvhQSHTMc91WrpErVfB52zpNRVw2evOYWMe6q3c087+wpvITB7HtppYDnQe1RwA==", - "dev": true, - "dependencies": { - "@types/semver": "^7.3.9", - "ts-type": "^1.2.40" - } - }, - "node_modules/@tsconfig/node10": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz", - "integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==", - "dev": true - }, - "node_modules/@tsconfig/node12": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz", - "integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==", - "dev": true - }, - "node_modules/@tsconfig/node14": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz", - "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==", - "dev": true - }, - "node_modules/@tsconfig/node16": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz", - "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==", - "dev": true - }, "node_modules/@types/babel__core": { - "version": "7.1.16", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.16.tgz", - "integrity": "sha512-EAEHtisTMM+KaKwfWdC3oyllIqswlznXCIVCt7/oRNrh+DhgT4UEBNC/jlADNjvw7UnfbcdkGQcPVZ1xYiLcrQ==", + "version": "7.1.18", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.18.tgz", + "integrity": "sha512-S7unDjm/C7z2A2R9NzfKCK1I+BAALDtxEmsJBwlB3EzNfb929ykjL++1CK9LO++EIp2fQrC8O+BwjKvz6UeDyQ==", "dev": true, "dependencies": { "@babel/parser": "^7.1.0", @@ -1297,9 +1265,9 @@ } }, "node_modules/@types/babel__generator": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.3.tgz", - "integrity": "sha512-/GWCmzJWqV7diQW54smJZzWbSFf4QYtF71WCKhcx6Ru/tFyQIY2eiiITcCAeuPbNSvT9YCGkVMqqvSk2Z0mXiA==", + "version": "7.6.4", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", + "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", "dev": true, "dependencies": { "@babel/types": "^7.0.0" @@ -1324,17 +1292,10 @@ "@babel/types": "^7.3.0" } }, - "node_modules/@types/bluebird": { - "version": "3.5.36", - "resolved": "https://registry.npmjs.org/@types/bluebird/-/bluebird-3.5.36.tgz", - "integrity": "sha512-HBNx4lhkxN7bx6P0++W8E289foSu8kO8GCk2unhuVggO+cE7rh9DhZUyPhUxNRG9m+5B5BTKxZQ5ZP92x/mx9Q==", - "dev": true, - "peer": true - }, "node_modules/@types/chrome": { - "version": "0.0.162", - "resolved": "https://registry.npmjs.org/@types/chrome/-/chrome-0.0.162.tgz", - "integrity": "sha512-DiMo9SrOhkb49bXPRke41Nvd9rgDgxn/mqyZ5gQnU+ST3H/vcnnvtwCkpuUl7O9FwoUwECfMSZiBTXuK8sMSwQ==", + "version": "0.0.180", + "resolved": "https://registry.npmjs.org/@types/chrome/-/chrome-0.0.180.tgz", + "integrity": "sha512-A/CuuKAaHq2CHEpYBAtl0lp2ib7TTXK7VjJI4q+c+1U/HDvZLJ8IlsdEDzzHdvkNdh36bGONxrMnO9YZrKqbAw==", "dev": true, "dependencies": { "@types/filesystem": "*", @@ -1381,6 +1342,16 @@ "@types/node": "*" } }, + "node_modules/@types/eslint": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.1.tgz", + "integrity": "sha512-GE44+DNEyxxh2Kc6ro/VkIj+9ma0pO0bwv9+uHSyBrikYOHr8zYcdPvnBOp1aw8s+CjRvuSx7CyWqRrNFQ59mA==", + "dev": true, + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, "node_modules/@types/estree": { "version": "0.0.39", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", @@ -1388,9 +1359,9 @@ "dev": true }, "node_modules/@types/filesystem": { - "version": "0.0.30", - "resolved": "https://registry.npmjs.org/@types/filesystem/-/filesystem-0.0.30.tgz", - "integrity": "sha512-NCoRgmGmLpTT9VFL6Bb6z0jQuqI3d0E5FGl7M0JOv/J5RQYo9s5aOItPYnpckx9MbYQk1APLXcF8f20Vqnf2yA==", + "version": "0.0.32", + "resolved": "https://registry.npmjs.org/@types/filesystem/-/filesystem-0.0.32.tgz", + "integrity": "sha512-Yuf4jR5YYMR2DVgwuCiP11s0xuVRyPKmz8vo6HBY3CGdeMj8af93CFZX+T82+VD1+UqHOxTq31lO7MI7lepBtQ==", "dev": true, "dependencies": { "@types/filewriter": "*" @@ -1427,6 +1398,12 @@ "integrity": "sha512-IG8AE1m2pWtPqQ7wXhFhy6Q59bwwnLwO36v5Rit2FrbXCIp8Sk8E2PfUCreyrdo17STwFSKDAkitVuVYbpEHvQ==", "dev": true }, + "node_modules/@types/istanbul": { + "version": "0.4.30", + "resolved": "https://registry.npmjs.org/@types/istanbul/-/istanbul-0.4.30.tgz", + "integrity": "sha512-+hQU4fh2G96ze78uI5/V6+SRDZD1UnVrFn23i2eDetwfbBq3s0/zYP92xj/3qyvVMM3WnvS88N56zjz+HmL04A==", + "dev": true + }, "node_modules/@types/istanbul-lib-coverage": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz", @@ -1452,18 +1429,18 @@ } }, "node_modules/@types/jasmine": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-3.10.1.tgz", - "integrity": "sha512-So26woGjM6F9b2julbJlXdcPdyhwteZzEX2EbFmreuJBamPVVdp6w4djywUG9TmcwjiC+ECAe+RSSBgYEOgEqQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-4.0.0.tgz", + "integrity": "sha512-KvhqNz4NaONk7cfp4E9x+uXOUp7x4H2Zeyb4yXnw2vIuxD5YfSi1767x+aF7z54elhZcC0OH9/78/WL6+5jcDg==", "dev": true }, "node_modules/@types/jest": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-27.0.2.tgz", - "integrity": "sha512-4dRxkS/AFX0c5XW6IPMNOydLn2tEhNhJV7DnYK+0bjoJZ+QTmfucBlihX7aoEsh/ocYtkLC73UbnBXBXIxsULA==", + "version": "27.4.1", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-27.4.1.tgz", + "integrity": "sha512-23iPJADSmicDVrWk+HT58LMJtzLAnB2AgIzplQuq/bSrGaxCrlvRFjGbXmamnnk/mAmCdLStiGqggu28ocUyiw==", "dev": true, "dependencies": { - "jest-diff": "^27.0.0", + "jest-matcher-utils": "^27.0.0", "pretty-format": "^27.0.0" } }, @@ -1480,14 +1457,23 @@ "dev": true }, "node_modules/@types/karma": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/@types/karma/-/karma-6.3.1.tgz", - "integrity": "sha512-t7hSJ8oWrgzrJV0nBqqMrDnQFft/W3WCPOfSi2aOq7rUPARLC8XpZfbsQ+mfYaNk18v1XqkBU12uirp1ISJVAA==", + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/@types/karma/-/karma-6.3.3.tgz", + "integrity": "sha512-nRMec4mTCt+tkpRqh5/pAxmnjzEgAaalIq7mdfLFH88gSRC8+bxejLiSjHMMT/vHIhJHqg4GPIGCnCFbwvDRww==", "dev": true, - "license": "MIT", "dependencies": { "@types/node": "*", - "log4js": "^6.2.1" + "log4js": "^6.4.1" + } + }, + "node_modules/@types/karma-coverage": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/karma-coverage/-/karma-coverage-2.0.1.tgz", + "integrity": "sha512-A5aJSn2IVJAy6XJl3zC8xAk78pqcj1dSAc9s0QPj3jnsmEpK5cGKmCTVVD7CYX8iEFk0C+IuSiS5YPVbacreSg==", + "dev": true, + "dependencies": { + "@types/istanbul": "*", + "@types/karma": "*" } }, "node_modules/@types/minimatch": { @@ -1497,9 +1483,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "16.11.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.6.tgz", - "integrity": "sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w==", + "version": "17.0.23", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.23.tgz", + "integrity": "sha512-UxDxWn7dl97rKVeVS61vErvw086aCYhDLyvRQZ5Rk65rZKepaFdm53GeqXaKBuOhED4e9uWq34IC3TdSdJJ2Gw==", "dev": true }, "node_modules/@types/offscreencanvas": { @@ -1509,9 +1495,9 @@ "dev": true }, "node_modules/@types/prettier": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.4.1.tgz", - "integrity": "sha512-Fo79ojj3vdEZOHg3wR9ksAMRz4P3S5fDB5e/YWZiFnyFQI1WY2Vftu9XoXVVtJfxB7Bpce/QTqWSSntkz2Znrw==", + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.4.4.tgz", + "integrity": "sha512-ReVR2rLTV1kvtlWFyuot+d1pkpG2Fw/XKE3PDAdj57rbM97ttSp9JZ2UsP+2EHTylra9cUf6JA7tGwW1INzUrA==", "dev": true }, "node_modules/@types/resolve": { @@ -1523,12 +1509,6 @@ "@types/node": "*" } }, - "node_modules/@types/semver": { - "version": "7.3.9", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.9.tgz", - "integrity": "sha512-L/TMpyURfBkf+o/526Zb6kd/tchUP3iBDEPjqjb+U2MAJhVRxxrmr2fwpe08E7QsV7YLcpq0tUaQ9O9x97ZIxQ==", - "dev": true - }, "node_modules/@types/stack-utils": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", @@ -1560,13 +1540,14 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.3.0.tgz", - "integrity": "sha512-ARUEJHJrq85aaiCqez7SANeahDsJTD3AEua34EoQN9pHS6S5Bq9emcIaGGySt/4X2zSi+vF5hAH52sEen7IO7g==", + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.16.0.tgz", + "integrity": "sha512-SJoba1edXvQRMmNI505Uo4XmGbxCK9ARQpkvOd00anxzri9RNQk0DDCxD+LIl+jYhkzOJiOMMKYEHnHEODjdCw==", "dev": true, "dependencies": { - "@typescript-eslint/experimental-utils": "5.3.0", - "@typescript-eslint/scope-manager": "5.3.0", + "@typescript-eslint/scope-manager": "5.16.0", + "@typescript-eslint/type-utils": "5.16.0", + "@typescript-eslint/utils": "5.16.0", "debug": "^4.3.2", "functional-red-black-tree": "^1.0.1", "ignore": "^5.1.8", @@ -1591,65 +1572,15 @@ } } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { - "version": "5.1.8", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", - "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/@typescript-eslint/experimental-utils": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.3.0.tgz", - "integrity": "sha512-NFVxYTjKj69qB0FM+piah1x3G/63WB8vCBMnlnEHUsiLzXSTWb9FmFn36FD9Zb4APKBLY3xRArOGSMQkuzTF1w==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.3.0", - "@typescript-eslint/types": "5.3.0", - "@typescript-eslint/typescript-estree": "5.3.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "*" - } - }, "node_modules/@typescript-eslint/parser": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.3.0.tgz", - "integrity": "sha512-rKu/yAReip7ovx8UwOAszJVO5MgBquo8WjIQcp1gx4pYQCwYzag+I5nVNHO4MqyMkAo0gWt2gWUi+36gWAVKcw==", + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.16.0.tgz", + "integrity": "sha512-fkDq86F0zl8FicnJtdXakFs4lnuebH6ZADDw6CYQv0UZeIjHvmEw87m9/29nk2Dv5Lmdp0zQ3zDQhiMWQf/GbA==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.3.0", - "@typescript-eslint/types": "5.3.0", - "@typescript-eslint/typescript-estree": "5.3.0", + "@typescript-eslint/scope-manager": "5.16.0", + "@typescript-eslint/types": "5.16.0", + "@typescript-eslint/typescript-estree": "5.16.0", "debug": "^4.3.2" }, "engines": { @@ -1668,31 +1599,32 @@ } } }, - "node_modules/@typescript-eslint/parser/node_modules/debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "node_modules/@typescript-eslint/scope-manager": { + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.16.0.tgz", + "integrity": "sha512-P+Yab2Hovg8NekLIR/mOElCDPyGgFZKhGoZA901Yax6WR6HVeGLbsqJkZ+Cvk5nts/dAlFKm8PfL43UZnWdpIQ==", "dev": true, "dependencies": { - "ms": "2.1.2" + "@typescript-eslint/types": "5.16.0", + "@typescript-eslint/visitor-keys": "5.16.0" }, "engines": { - "node": ">=6.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.3.0.tgz", - "integrity": "sha512-22Uic9oRlTsPppy5Tcwfj+QET5RWEnZ5414Prby465XxQrQFZ6nnm5KnXgnsAJefG4hEgMnaxTB3kNEyjdjj6A==", + "node_modules/@typescript-eslint/type-utils": { + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.16.0.tgz", + "integrity": "sha512-SKygICv54CCRl1Vq5ewwQUJV/8padIWvPgCxlWPGO/OgQLCijY9G7lDu6H+mqfQtbzDNlVjzVWQmeqbLMBLEwQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.3.0", - "@typescript-eslint/visitor-keys": "5.3.0" + "@typescript-eslint/utils": "5.16.0", + "debug": "^4.3.2", + "tsutils": "^3.21.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1700,12 +1632,20 @@ "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, "node_modules/@typescript-eslint/types": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.3.0.tgz", - "integrity": "sha512-fce5pG41/w8O6ahQEhXmMV+xuh4+GayzqEogN24EK+vECA3I6pUwKuLi5QbXO721EMitpQne5VKXofPonYlAQg==", + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.16.0.tgz", + "integrity": "sha512-oUorOwLj/3/3p/HFwrp6m/J2VfbLC8gjW5X3awpQJ/bSG+YRGFS4dpsvtQ8T2VNveV+LflQHjlLvB6v0R87z4g==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1716,13 +1656,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.3.0.tgz", - "integrity": "sha512-FJ0nqcaUOpn/6Z4Jwbtf+o0valjBLkqc3MWkMvrhA2TvzFXtcclIM8F4MBEmYa2kgcI8EZeSAzwoSrIC8JYkug==", + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.16.0.tgz", + "integrity": "sha512-SE4VfbLWUZl9MR+ngLSARptUv2E8brY0luCdgmUevU6arZRY/KxYoLI/3V/yxaURR8tLRN7bmZtJdgmzLHI6pQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.3.0", - "@typescript-eslint/visitor-keys": "5.3.0", + "@typescript-eslint/types": "5.16.0", + "@typescript-eslint/visitor-keys": "5.16.0", "debug": "^4.3.2", "globby": "^11.0.4", "is-glob": "^4.0.3", @@ -1742,60 +1682,18 @@ } } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.3.0.tgz", - "integrity": "sha512-oVIAfIQuq0x2TFDNLVavUn548WL+7hdhxYn+9j3YdJJXB7mH9dAmZNJsPDa7Jc+B9WGqoiex7GUDbyMxV0a/aw==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.3.0", - "eslint-visitor-keys": "^3.0.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@yarn-tool/resolve-package": { - "version": "1.0.38", - "resolved": "https://registry.npmjs.org/@yarn-tool/resolve-package/-/resolve-package-1.0.38.tgz", - "integrity": "sha512-WmYM/Znh/vPQw7PBfbH2PmZSrzCF0AfGMfpA4z3SbNa2UUcdpqq9yD9pYKcHY1FP3yjMB7KwcVD8mhojROXCQQ==", - "dev": true, - "dependencies": { - "@ts-type/package-dts": "^1.0.53", - "pkg-dir": "< 6 >= 5", - "tslib": "^2.3.1", - "upath2": "^3.1.10" - } - }, - "node_modules/@yarn-tool/resolve-package/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "node_modules/@typescript-eslint/typescript-estree/node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dev": true, "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" }, "engines": { "node": ">=10" @@ -1804,61 +1702,45 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@yarn-tool/resolve-package/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "node_modules/@typescript-eslint/utils": { + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.16.0.tgz", + "integrity": "sha512-iYej2ER6AwmejLWMWzJIHy3nPJeGDuCqf8Jnb+jAQVoPpmWzwQOfa9hWVB8GIQE5gsCv/rfN4T+AYb/V06WseQ==", "dev": true, "dependencies": { - "p-locate": "^5.0.0" + "@types/json-schema": "^7.0.9", + "@typescript-eslint/scope-manager": "5.16.0", + "@typescript-eslint/types": "5.16.0", + "@typescript-eslint/typescript-estree": "5.16.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0" }, "engines": { - "node": ">=10" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@yarn-tool/resolve-package/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/@yarn-tool/resolve-package/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "node_modules/@typescript-eslint/visitor-keys": { + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.16.0.tgz", + "integrity": "sha512-jqxO8msp5vZDhikTwq9ubyMHqZ67UIvawohr4qF3KhlpL7gzSjOd+8471H3nh5LyABkaI85laEKKU8SnGUK5/g==", "dev": true, "dependencies": { - "p-limit": "^3.0.2" + "@typescript-eslint/types": "5.16.0", + "eslint-visitor-keys": "^3.0.0" }, "engines": { - "node": ">=10" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@yarn-tool/resolve-package/node_modules/pkg-dir": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz", - "integrity": "sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==", - "dev": true, - "dependencies": { - "find-up": "^5.0.0" - }, - "engines": { - "node": ">=10" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, "node_modules/abab": { @@ -1881,9 +1763,9 @@ } }, "node_modules/acorn": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.5.0.tgz", - "integrity": "sha512-yXbYeFy+jUuYd3/CDcg2NkIYE991XYX/bje7LmjJigUciaeO1JR4XxXgCIV1/Zc/dRuFEyw1L0pbA+qynJkW5Q==", + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", + "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -1933,41 +1815,41 @@ } }, "node_modules/addons-linter": { - "version": "3.20.0", - "resolved": "https://registry.npmjs.org/addons-linter/-/addons-linter-3.20.0.tgz", - "integrity": "sha512-rHaahIZ34HSL1D7ZYCMs/QQPOp0pAnsOMqtNSy/zDSrkgVtlCQvSeMpx1a3ZnE2pGRVHjMIO506KWUmrN1lPRw==", + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/addons-linter/-/addons-linter-4.14.0.tgz", + "integrity": "sha512-TH3/PMS4Dd0Jf3kXW7DLXseHZcD7ZbnfnQAztkrP4YC0HQKQVZJ+lGOuDOGUtVQDMwC/eEdvHvZoRnHDer5qkg==", "dev": true, "dependencies": { - "@mdn/browser-compat-data": "4.0.5", + "@mdn/browser-compat-data": "4.1.12", "addons-moz-compare": "1.2.0", - "addons-scanner-utils": "5.0.0", + "addons-scanner-utils": "6.3.0", "ajv": "6.12.6", "ajv-merge-patch": "4.1.0", "chalk": "4.1.2", "cheerio": "1.0.0-rc.10", - "columnify": "1.5.4", - "common-tags": "1.8.0", + "columnify": "1.6.0", + "common-tags": "1.8.2", "deepmerge": "4.2.2", - "dispensary": "0.62.0", - "eslint": "7.32.0", - "eslint-plugin-no-unsanitized": "3.1.5", - "eslint-visitor-keys": "3.0.0", - "espree": "9.0.0", + "eslint": "8.11.0", + "eslint-plugin-no-unsanitized": "4.0.1", + "eslint-visitor-keys": "3.3.0", + "espree": "9.3.1", "esprima": "4.0.1", "fluent-syntax": "0.13.0", "glob": "7.2.0", - "image-size": "1.0.0", + "image-size": "1.0.1", "is-mergeable-object": "1.1.1", "jed": "1.1.1", "os-locale": "5.0.0", - "pino": "6.13.3", - "postcss": "8.3.9", + "pino": "7.9.1", + "postcss": "8.4.12", "relaxed-json": "1.0.3", "semver": "7.3.5", - "source-map-support": "0.5.20", + "sha.js": "2.4.11", + "source-map-support": "0.5.21", "tosource": "1.0.0", "upath": "2.0.1", - "yargs": "17.2.1", + "yargs": "17.4.0", "yauzl": "2.10.0" }, "bin": { @@ -1977,231 +1859,10 @@ "node": ">=12.21.0" } }, - "node_modules/addons-linter/node_modules/@babel/code-frame": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", - "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", - "dev": true, - "dependencies": { - "@babel/highlight": "^7.10.4" - } - }, - "node_modules/addons-linter/node_modules/@eslint/eslintrc": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", - "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==", - "dev": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.1.1", - "espree": "^7.3.0", - "globals": "^13.9.0", - "ignore": "^4.0.6", - "import-fresh": "^3.2.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/addons-linter/node_modules/@eslint/eslintrc/node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/addons-linter/node_modules/@eslint/eslintrc/node_modules/espree": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", - "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", - "dev": true, - "dependencies": { - "acorn": "^7.4.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^1.3.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/addons-linter/node_modules/@humanwhocodes/config-array": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", - "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==", - "dev": true, - "dependencies": { - "@humanwhocodes/object-schema": "^1.2.0", - "debug": "^4.1.1", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/addons-linter/node_modules/acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/addons-linter/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/addons-linter/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/addons-linter/node_modules/eslint": { - "version": "7.32.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", - "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==", - "dev": true, - "dependencies": { - "@babel/code-frame": "7.12.11", - "@eslint/eslintrc": "^0.4.3", - "@humanwhocodes/config-array": "^0.5.0", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.0.1", - "doctrine": "^3.0.0", - "enquirer": "^2.3.5", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^2.1.0", - "eslint-visitor-keys": "^2.0.0", - "espree": "^7.3.1", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^5.1.2", - "globals": "^13.6.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^3.13.1", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.0.4", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "progress": "^2.0.0", - "regexpp": "^3.1.0", - "semver": "^7.2.1", - "strip-ansi": "^6.0.0", - "strip-json-comments": "^3.1.0", - "table": "^6.0.9", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/addons-linter/node_modules/eslint-plugin-no-unsanitized": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/eslint-plugin-no-unsanitized/-/eslint-plugin-no-unsanitized-3.1.5.tgz", - "integrity": "sha512-s/6w++p1590h/H/dE2Wo660bOkaM/3OEK14Y7xm1UT0bafxkKw1Cq0ksjxkxLdH/WWd014DlsLKuD6CyNrR2Dw==", - "dev": true, - "peerDependencies": { - "eslint": "^5 || ^6 || ^7" - } - }, - "node_modules/addons-linter/node_modules/eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^1.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/addons-linter/node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/addons-linter/node_modules/eslint/node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/addons-linter/node_modules/eslint/node_modules/espree": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", - "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", - "dev": true, - "dependencies": { - "acorn": "^7.4.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^1.3.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/addons-linter/node_modules/eslint/node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/addons-linter/node_modules/image-size": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.0.0.tgz", - "integrity": "sha512-JLJ6OwBfO1KcA+TvJT+v8gbE6iWbj24LyDNFgFEN0lzegn6cC6a/p3NIDaepMsJjQjlUWqIC7wJv8lBFxPNjcw==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.0.1.tgz", + "integrity": "sha512-VAwkvNSNGClRw9mDHhc5Efax8PLlsOGcUTh0T/LIriC8vPA3U5PdqXWqkz406MoYHMKW8Uf9gWr05T/rYB44kQ==", "dev": true, "dependencies": { "queue": "6.0.2" @@ -2213,37 +1874,33 @@ "node": ">=12.0.0" } }, - "node_modules/addons-linter/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, "node_modules/addons-linter/node_modules/yargs": { - "version": "17.2.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.2.1.tgz", - "integrity": "sha512-XfR8du6ua4K6uLGm5S6fA+FIJom/MdJcFNVY8geLlp2v8GYbOXD4EB1tPNZsRn4vBzKGMgb5DRZMeWuFc2GO8Q==", + "version": "17.4.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.4.0.tgz", + "integrity": "sha512-WJudfrk81yWFSOkZYpAZx4Nt7V4xp7S/uJkX0CnxovMCt1wCE8LNftPpNuF9X/u9gN5nsD7ycYtRcDf2pL3UiA==", "dev": true, "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", - "string-width": "^4.2.0", + "string-width": "^4.2.3", "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" + "yargs-parser": "^21.0.0" }, "engines": { "node": ">=12" } }, + "node_modules/addons-linter/node_modules/yargs-parser": { + "version": "21.0.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.1.tgz", + "integrity": "sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==", + "dev": true, + "engines": { + "node": ">=12" + } + }, "node_modules/addons-moz-compare": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/addons-moz-compare/-/addons-moz-compare-1.2.0.tgz", @@ -2251,13 +1908,13 @@ "dev": true }, "node_modules/addons-scanner-utils": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/addons-scanner-utils/-/addons-scanner-utils-5.0.0.tgz", - "integrity": "sha512-uENKmGryUeR07I1c8RonDZY/bkAG+zKfZ3T61JFusgY5wiARQJ5+8hI33m8sctXxPopjfxiIjHsG/g7cQzn4Yw==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/addons-scanner-utils/-/addons-scanner-utils-6.3.0.tgz", + "integrity": "sha512-sD4U7TX/NFDUYVheydrcpHH9xG3E0eVBFDn1RuUkGpqRyay3SsOU75Pl2lWAbCmeE0Mh9inU1Fwl7Mm1VRWkZw==", "dev": true, "dependencies": { "@types/yauzl": "2.9.2", - "common-tags": "1.8.0", + "common-tags": "1.8.2", "first-chunk-stream": "3.0.0", "strip-bom-stream": "4.0.0", "upath": "2.0.1", @@ -2265,9 +1922,9 @@ }, "peerDependencies": { "@types/download": "8.0.1", - "body-parser": "1.19.0", + "body-parser": "1.19.1", "download": "8.0.0", - "express": "4.17.1", + "express": "4.17.2", "safe-compare": "1.1.4" } }, @@ -2330,15 +1987,6 @@ "string-width": "^4.1.0" } }, - "node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/ansi-escapes": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", @@ -2430,13 +2078,7 @@ "peer": true, "engines": { "node": ">=4" - } - }, - "node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true + } }, "node_modules/argparse": { "version": "2.0.1", @@ -2453,12 +2095,6 @@ "node": ">=8" } }, - "node_modules/array-filter": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-0.0.1.tgz", - "integrity": "sha1-fajPLiZijtcygDWB/SH2fKzS7uw=", - "dev": true - }, "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", @@ -2485,18 +2121,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/array-map": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/array-map/-/array-map-0.0.0.tgz", - "integrity": "sha1-iKK6tz0c97zVwbEYoAP2b2ZfpmI=", - "dev": true - }, - "node_modules/array-reduce": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/array-reduce/-/array-reduce-0.0.0.tgz", - "integrity": "sha1-FziZ0//Rx9k4PkR5Ul2+J4yrXys=", - "dev": true - }, "node_modules/array-union": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", @@ -2533,9 +2157,9 @@ } }, "node_modules/asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", "dev": true, "dependencies": { "safer-buffer": "~2.1.0" @@ -2550,15 +2174,21 @@ "node": ">=0.8" } }, - "node_modules/astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "node_modules/ast-metadata-inferer": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/ast-metadata-inferer/-/ast-metadata-inferer-0.7.0.tgz", + "integrity": "sha512-OkMLzd8xelb3gmnp6ToFvvsHLtS6CbagTkFQvQ+ZYFe3/AIl9iKikNR9G7pY3GfOR/2Xc222hwBjzI7HLkE76Q==", "dev": true, - "engines": { - "node": ">=8" + "dependencies": { + "@mdn/browser-compat-data": "^3.3.14" } }, + "node_modules/ast-metadata-inferer/node_modules/@mdn/browser-compat-data": { + "version": "3.3.14", + "resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-3.3.14.tgz", + "integrity": "sha512-n2RC9d6XatVbWFdHLimzzUJxJ1KY8LdjqrW6YvGPiRmsHkhOUx74/Ct10x5Yo7bC/Jvqx7cDEW8IMPv/+vwEzA==", + "dev": true + }, "node_modules/async": { "version": "0.2.10", "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", @@ -2605,18 +2235,18 @@ "dev": true }, "node_modules/babel-jest": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-27.3.1.tgz", - "integrity": "sha512-SjIF8hh/ir0peae2D6S6ZKRhUy7q/DnpH7k/V6fT4Bgs/LXXUztOpX4G2tCgq8mLo5HA9mN6NmlFMeYtKmIsTQ==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-27.5.1.tgz", + "integrity": "sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg==", "dev": true, "dependencies": { - "@jest/transform": "^27.3.1", - "@jest/types": "^27.2.5", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.0.0", - "babel-preset-jest": "^27.2.0", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^27.5.1", "chalk": "^4.0.0", - "graceful-fs": "^4.2.4", + "graceful-fs": "^4.2.9", "slash": "^3.0.0" }, "engines": { @@ -2642,35 +2272,10 @@ "node": ">=8" } }, - "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.1.0.tgz", - "integrity": "sha512-czwUz525rkOFDJxfKK6mYfIs9zBKILyrZQxjz3ABhjQXhbhFsSbo1HW/BFcsDnfJYJWA6thRR5/TUY2qs5W99Q==", - "dev": true, - "dependencies": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/babel-plugin-istanbul/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/babel-plugin-jest-hoist": { - "version": "27.2.0", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.2.0.tgz", - "integrity": "sha512-TOux9khNKdi64mW+0OIhcmbAn75tTlzKhxmiNXevQaPbrBYK7YKjP1jl6NHTJ6XR5UgUrJbCnWlKVnJn29dfjw==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.5.1.tgz", + "integrity": "sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ==", "dev": true, "dependencies": { "@babel/template": "^7.3.3", @@ -2706,12 +2311,12 @@ } }, "node_modules/babel-preset-jest": { - "version": "27.2.0", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-27.2.0.tgz", - "integrity": "sha512-z7MgQ3peBwN5L5aCqBKnF6iqdlvZvFUQynEhu0J+X9nHLU72jO3iY331lcYrg+AssJ8q7xsv5/3AICzVmJ/wvg==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-27.5.1.tgz", + "integrity": "sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag==", "dev": true, "dependencies": { - "babel-plugin-jest-hoist": "^27.2.0", + "babel-plugin-jest-hoist": "^27.5.1", "babel-preset-current-node-syntax": "^1.0.0" }, "engines": { @@ -2727,15 +2332,6 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, - "node_modules/base64-arraybuffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.1.tgz", - "integrity": "sha512-vFIUq7FdLtjZMhATwDul5RZWv2jpXQ09Pd6jcVEOvIsqCWTRFD/ONHNfyOS8dA/Ippi5dsIgpyKWKZaAKZltbA==", - "dev": true, - "engines": { - "node": ">= 0.6.0" - } - }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -2801,21 +2397,21 @@ "dev": true }, "node_modules/body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.1.tgz", + "integrity": "sha512-8ljfQi5eBk8EJfECMrgqNGWPEY5jWP+1IzkzkGdFFEwFQZZyaZ21UqdaHktgiMlH0xLHqIFtE/u2OYE5dOtViA==", "dev": true, "dependencies": { - "bytes": "3.1.0", + "bytes": "3.1.1", "content-type": "~1.0.4", "debug": "2.6.9", "depd": "~1.1.2", - "http-errors": "1.7.2", + "http-errors": "1.8.1", "iconv-lite": "0.4.24", "on-finished": "~2.3.0", - "qs": "6.7.0", - "raw-body": "2.4.0", - "type-is": "~1.6.17" + "qs": "6.9.6", + "raw-body": "2.4.2", + "type-is": "~1.6.18" }, "engines": { "node": ">= 0.8" @@ -2905,16 +2501,16 @@ "dev": true }, "node_modules/browserslist": { - "version": "4.16.6", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.6.tgz", - "integrity": "sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ==", + "version": "4.20.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.0.tgz", + "integrity": "sha512-bnpOoa+DownbciXj0jVGENf8VYQnE2LNWomhYuCsMmmx9Jd9lwq0WXODuwpSsp8AVdKM2/HorrzxAfbKvWTByQ==", "dev": true, "dependencies": { - "caniuse-lite": "^1.0.30001219", - "colorette": "^1.2.2", - "electron-to-chromium": "^1.3.723", + "caniuse-lite": "^1.0.30001313", + "electron-to-chromium": "^1.4.76", "escalade": "^3.1.1", - "node-releases": "^1.1.71" + "node-releases": "^2.0.2", + "picocolors": "^1.0.0" }, "bin": { "browserslist": "cli.js" @@ -3049,9 +2645,9 @@ } }, "node_modules/bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.1.tgz", + "integrity": "sha512-dWe4nWO/ruEOY7HkUJ5gFt1DCFV9zPRoJr8pV0/ASQermOZjtq8jMjOprC0Kd10GLN+l7xaUPvxzJFWtxGu8Fg==", "dev": true, "engines": { "node": ">= 0.8" @@ -3125,9 +2721,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001228", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001228.tgz", - "integrity": "sha512-QQmLOGJ3DEgokHbMSA8cj2a+geXqmnpyOFT0lhQV6P3/YOJvGDEwoedcwxEQ30gJIwIIunHIicunJ2rzK5gB2A==", + "version": "1.0.30001314", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001314.tgz", + "integrity": "sha512-0zaSO+TnCHtHJIbpLroX7nsD+vYuOVjl3uzFbJO1wMVbuveJA0RK2WcQA9ZUIOiO0/ArMiMgHJLxfEZhQiC0kw==", "dev": true, "funding": { "type": "opencollective", @@ -3203,10 +2799,16 @@ } }, "node_modules/chokidar": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", - "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -3230,9 +2832,9 @@ "dev": true }, "node_modules/chrome-launcher": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/chrome-launcher/-/chrome-launcher-0.14.0.tgz", - "integrity": "sha512-W//HpflaW6qBGrmuskup7g+XJZN6w03ko9QSIe5CtcTal2u0up5SeReK3Ll1Why4Ey8dPkv8XSodZyHPnGbVHQ==", + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/chrome-launcher/-/chrome-launcher-0.15.0.tgz", + "integrity": "sha512-ZQqX5kb9H0+jy1OqLnWampfocrtSZaGl7Ny3F9GRha85o4odbL8x55paUzh51UC7cEmZ5obp3H2Mm70uC2PpRA==", "dev": true, "dependencies": { "@types/node": "*", @@ -3240,6 +2842,9 @@ "is-wsl": "^2.2.0", "lighthouse-logger": "^1.0.0" }, + "bin": { + "print-chrome-path": "bin/print-chrome-path.js" + }, "engines": { "node": ">=12.13.0" } @@ -3343,12 +2948,6 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/colorette": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", - "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==", - "dev": true - }, "node_modules/colors": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", @@ -3359,34 +2958,16 @@ } }, "node_modules/columnify": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/columnify/-/columnify-1.5.4.tgz", - "integrity": "sha1-Rzfd8ce2mop8NAVweC6UfuyOeLs=", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/columnify/-/columnify-1.6.0.tgz", + "integrity": "sha512-lomjuFZKfM6MSAnV9aCZC9sc0qGbmZdfygNv+nCpqVkSKdCxCklLtd16O0EILGkImHw9ZpHkAnHaB+8Zxq5W6Q==", "dev": true, "dependencies": { - "strip-ansi": "^3.0.0", + "strip-ansi": "^6.0.1", "wcwidth": "^1.0.0" - } - }, - "node_modules/columnify/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/columnify/node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "dependencies": { - "ansi-regex": "^2.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=8.0.0" } }, "node_modules/combined-stream": { @@ -3408,20 +2989,14 @@ "dev": true }, "node_modules/common-tags": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.0.tgz", - "integrity": "sha512-6P6g0uetGpW/sdyUy/iQQCbFF0kWVMSIVSyYz7Zgjcgh8mgw8PQzDNZeyZ5DQ2gM7LBoZPHmnjz8rUthkBG5tw==", + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", + "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", "dev": true, "engines": { "node": ">=4.0.0" } }, - "node_modules/commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true - }, "node_modules/component-emitter": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", @@ -3521,18 +3096,39 @@ "dev": true }, "node_modules/content-disposition": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", - "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", "dev": true, "peer": true, "dependencies": { - "safe-buffer": "5.1.2" + "safe-buffer": "5.2.1" }, "engines": { "node": ">= 0.6" } }, + "node_modules/content-disposition/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "peer": true + }, "node_modules/content-type": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", @@ -3577,9 +3173,9 @@ } }, "node_modules/core-js": { - "version": "3.18.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.18.0.tgz", - "integrity": "sha512-WJeQqq6jOYgVgg4NrXKL0KLQhi0CT4ZOCvFL+3CQ5o7I6J8HkT5wd53EadMfqTDp1so/MT1J+w2ujhWcCJtN7w==", + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.21.0.tgz", + "integrity": "sha512-YUdI3fFu4TF/2WykQ2xzSiTQdldLB4KVuL9WeAy5XONZYt5Cun/fpQvctoKbCgvPhmzADeesTk/j2Rdx77AcKQ==", "dev": true, "hasInstallScript": true, "funding": { @@ -3606,11 +3202,14 @@ "node": ">= 0.10" } }, - "node_modules/create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true + "node_modules/cross-fetch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", + "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", + "dev": true, + "dependencies": { + "node-fetch": "2.6.7" + } }, "node_modules/cross-spawn": { "version": "7.0.3", @@ -3636,16 +3235,16 @@ } }, "node_modules/css-select": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.1.3.tgz", - "integrity": "sha512-gT3wBNd9Nj49rAbmtFHj1cljIAOLYSX1nZ8CB7TBO3INYckygm5B7LISU/szY//YmdiSLbJvDLOx9VnMVpMBxA==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.2.1.tgz", + "integrity": "sha512-/aUslKhzkTNCQUB2qTX84lVmfia9NyjP3WpDGtj/WxhwBzWBYUV3DgUpurHTme8UTPcPlAD1DJ+b0nN/t50zDQ==", "dev": true, "dependencies": { "boolbase": "^1.0.0", - "css-what": "^5.0.0", - "domhandler": "^4.2.0", - "domutils": "^2.6.0", - "nth-check": "^2.0.0" + "css-what": "^5.1.0", + "domhandler": "^4.3.0", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" }, "funding": { "url": "https://github.com/sponsors/fb55" @@ -3720,9 +3319,9 @@ } }, "node_modules/date-format": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/date-format/-/date-format-3.0.0.tgz", - "integrity": "sha512-eyTcpKOcamdhWJXj56DpQMo1ylSQpcGtGKXcU0Tb97+K56/CF5amAqqqNj0+KvA0iw2ynxtHWFsPDSClCxe48w==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.3.tgz", + "integrity": "sha512-7P3FyqDcfeznLZp2b+OMitV9Sz2lUnsT87WaTat9nVwqsBkTzPG3lPLNwW3en6F4pHUiWzr6vb8CLhjdK9bcxQ==", "dev": true, "engines": { "node": ">=4.0" @@ -3735,9 +3334,9 @@ "dev": true }, "node_modules/debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", "dev": true, "dependencies": { "ms": "2.1.2" @@ -4175,9 +3774,9 @@ } }, "node_modules/devtools-protocol": { - "version": "0.0.901419", - "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.901419.tgz", - "integrity": "sha512-4INMPwNm9XRpBukhNbF7OB6fNTTCaI8pzy/fXg0xQzAy5h3zL1P8xT3QazgKqBrb/hAYwIBizqDBZ7GtJE74QQ==", + "version": "0.0.969999", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.969999.tgz", + "integrity": "sha512-6GfzuDWU0OFAuOvBokXpXPLxjOJ5DZ157Ue3sGQQM3LgAamb8m0R0ruSfN0DDu+XG5XJgT50i6zZ/0o8RglreQ==", "dev": true }, "node_modules/di": { @@ -4186,19 +3785,10 @@ "integrity": "sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=", "dev": true }, - "node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, "node_modules/diff-sequences": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.0.6.tgz", - "integrity": "sha512-ag6wfpBFyNXZ0p8pcuIDS//D8H062ZQJ3fzYxjpmeKjnz8W4pekL3AI8VohmyZmsWW2PWaHgjsmqR6L13101VQ==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", + "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==", "dev": true, "engines": { "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" @@ -4216,50 +3806,6 @@ "node": ">=8" } }, - "node_modules/dispensary": { - "version": "0.62.0", - "resolved": "https://registry.npmjs.org/dispensary/-/dispensary-0.62.0.tgz", - "integrity": "sha512-x8vqPX7owhzDp3Y6t/iOuTuNoWx5hlZKITlzlybETsZoY05cYDubGpwt0soLfRLAWLuxX1lq0lTc/vXtk/CDCw==", - "dev": true, - "dependencies": { - "async": "~3.2.0", - "natural-compare-lite": "~1.4.0", - "pino": "~6.11.0", - "request": "~2.88.0", - "sha.js": "~2.4.4", - "source-map-support": "~0.5.4", - "yargs": "~16.2.0" - }, - "bin": { - "dispensary": "bin/dispensary" - }, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/dispensary/node_modules/async": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.2.tgz", - "integrity": "sha512-H0E+qZaDEfx/FY4t7iLRv1W2fFI6+pyCeTw1uN20AQPiwqwM6ojPxHxdLv4z8hi2DtnW9BOckSspLucW7pIE5g==", - "dev": true - }, - "node_modules/dispensary/node_modules/pino": { - "version": "6.11.3", - "resolved": "https://registry.npmjs.org/pino/-/pino-6.11.3.tgz", - "integrity": "sha512-drPtqkkSf0ufx2gaea3TryFiBHdNIdXKf5LN0hTM82SXI4xVIve2wLwNg92e1MT6m3jASLu6VO7eGY6+mmGeyw==", - "dev": true, - "dependencies": { - "fast-redact": "^3.0.0", - "fast-safe-stringify": "^2.0.7", - "flatstr": "^1.0.12", - "pino-std-serializers": "^3.1.0", - "quick-format-unescaped": "^4.0.3", - "sonic-boom": "^1.0.2" - }, - "bin": { - "pino": "bin.js" - } - }, "node_modules/doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -4332,9 +3878,9 @@ } }, "node_modules/domhandler": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.2.2.tgz", - "integrity": "sha512-PzE9aBMsdZO8TK4BnuJwH0QT41wgMbRzuZrHUcpYncEjmQazq8QEaBWgLG7ZyC/DAZKEgglpIA6j4Qn/HmxS3w==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", "dev": true, "dependencies": { "domelementtype": "^2.2.0" @@ -4452,6 +3998,18 @@ "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", "dev": true }, + "node_modules/duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + } + }, "node_modules/ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", @@ -4478,9 +4036,9 @@ "dev": true }, "node_modules/electron-to-chromium": { - "version": "1.3.735", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.735.tgz", - "integrity": "sha512-cp7MWzC3NseUJV2FJFgaiesdrS+A8ZUjX5fLAxdRlcaPDkaPGFplX930S5vf84yqDp4LjuLdKouWuVOTwUfqHQ==", + "version": "1.4.77", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.77.tgz", + "integrity": "sha512-fiDxw8mO9Ph1Z0bjX2sFTPpi0J0QkOiwOJF+5Q0J0baNc/F9lLePAvDPlnoxvbUYYMizqrKPeotRRkJ9LtxAew==", "dev": true }, "node_modules/emittery": { @@ -4520,9 +4078,9 @@ } }, "node_modules/engine.io": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.0.0.tgz", - "integrity": "sha512-Ui7yl3JajEIaACg8MOUwWvuuwU7jepZqX3BKs1ho7NQRuP4LhN4XIykXhp8bEy+x/DhA0LBZZXYSCkZDqrwMMg==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.1.1.tgz", + "integrity": "sha512-AyMc20q8JUUdvKd46+thc9o7yCZ6iC6MoBCChG5Z1XmFMpp+2+y/oKvwpZTUJB0KCjxScw1dV9c2h5pjiYBLuQ==", "dev": true, "dependencies": { "@types/cookie": "^0.4.1", @@ -4541,27 +4099,36 @@ } }, "node_modules/engine.io-parser": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.1.tgz", - "integrity": "sha512-j4p3WwJrG2k92VISM0op7wiq60vO92MlF3CRGxhKHy9ywG1/Dkc72g0dXeDQ+//hrcDn8gqQzoEkdO9FN0d9AA==", + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.3.tgz", + "integrity": "sha512-BtQxwF27XUNnSafQLvDi0dQ8s3i6VgzSoQMJacpIcGNrlUdfHSKbgm3jmjCVvQluGzqwujQMPAoMai3oYSTurg==", "dev": true, "dependencies": { - "base64-arraybuffer": "~1.0.1" + "@socket.io/base64-arraybuffer": "~1.0.2" }, "engines": { "node": ">=10.0.0" } }, - "node_modules/enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "node_modules/engine.io/node_modules/ws": { + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", + "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==", "dev": true, - "dependencies": { - "ansi-colors": "^4.1.1" - }, "engines": { - "node": ">=8.6" + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } } }, "node_modules/ent": { @@ -4783,24 +4350,23 @@ } }, "node_modules/eslint": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.1.0.tgz", - "integrity": "sha512-JZvNneArGSUsluHWJ8g8MMs3CfIEzwaLx9KyH4tZ2i+R2/rPWzL8c0zg3rHdwYVpN/1sB9gqnjHwz9HoeJpGHw==", + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.11.0.tgz", + "integrity": "sha512-/KRpd9mIRg2raGxHRGwW9ZywYNAClZrHjdueHcrVDuO3a6bj83eoTirCCk0M0yPwOjWYKHwRVRid+xK4F/GHgA==", "dev": true, "dependencies": { - "@eslint/eslintrc": "^1.0.3", - "@humanwhocodes/config-array": "^0.6.0", + "@eslint/eslintrc": "^1.2.1", + "@humanwhocodes/config-array": "^0.9.2", "ajv": "^6.10.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.3.2", "doctrine": "^3.0.0", - "enquirer": "^2.3.5", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^6.0.0", + "eslint-scope": "^7.1.1", "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.0.0", - "espree": "^9.0.0", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.3.1", "esquery": "^1.4.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -4808,7 +4374,7 @@ "functional-red-black-tree": "^1.0.1", "glob-parent": "^6.0.1", "globals": "^13.6.0", - "ignore": "^4.0.6", + "ignore": "^5.2.0", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", @@ -4819,10 +4385,8 @@ "minimatch": "^3.0.4", "natural-compare": "^1.4.0", "optionator": "^0.9.1", - "progress": "^2.0.0", "regexpp": "^3.2.0", - "semver": "^7.2.1", - "strip-ansi": "^6.0.0", + "strip-ansi": "^6.0.1", "strip-json-comments": "^3.1.0", "text-table": "^0.2.0", "v8-compile-cache": "^2.0.3" @@ -4857,14 +4421,13 @@ } }, "node_modules/eslint-module-utils": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.1.tgz", - "integrity": "sha512-fjoetBXQZq2tSTWZ9yWVl2KuFrTZZH3V+9iD1V1RfpDgxzJR+mPd/KZmMiA8gbPqdBzpNiEHOuT7IYEWxrH0zQ==", + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.2.tgz", + "integrity": "sha512-zquepFnWCY2ISMFwD/DqzaM++H+7PDzOpUvotJWm/y1BAFt5R4oeULgdrTejKqLkz7MA/tgstsUMNYc7wNdTrg==", "dev": true, "dependencies": { "debug": "^3.2.7", - "find-up": "^2.1.0", - "pkg-dir": "^2.0.0" + "find-up": "^2.1.0" }, "engines": { "node": ">=4" @@ -4946,22 +4509,93 @@ "node": ">=4" } }, - "node_modules/eslint-module-utils/node_modules/pkg-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", - "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "node_modules/eslint-plugin-compat": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-compat/-/eslint-plugin-compat-4.0.2.tgz", + "integrity": "sha512-xqvoO54CLTVaEYGMzhu35Wzwk/As7rCvz/2dqwnFiWi0OJccEtGIn+5qq3zqIu9nboXlpdBN579fZcItC73Ycg==", "dev": true, "dependencies": { - "find-up": "^2.1.0" + "@mdn/browser-compat-data": "^4.1.5", + "ast-metadata-inferer": "^0.7.0", + "browserslist": "^4.16.8", + "caniuse-lite": "^1.0.30001304", + "core-js": "^3.16.2", + "find-up": "^5.0.0", + "lodash.memoize": "4.1.2", + "semver": "7.3.5" }, "engines": { - "node": ">=4" + "node": ">=9.x" + }, + "peerDependencies": { + "eslint": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/eslint-plugin-compat/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint-plugin-compat/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint-plugin-compat/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint-plugin-compat/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/eslint-plugin-import": { - "version": "2.25.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.25.2.tgz", - "integrity": "sha512-qCwQr9TYfoBHOFcVGKY9C9unq05uOxxdklmBXLVvcwo68y5Hta6/GzCZEMx2zQiu0woKNEER0LE7ZgaOfBU14g==", + "version": "2.25.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.25.4.tgz", + "integrity": "sha512-/KJBASVFxpu0xg1kIBn9AUa8hQVnszpwgE7Ld0lKAlx7Ie87yzEzCgSkekt+le/YVhiaosO4Y14GDAOc41nfxA==", "dev": true, "dependencies": { "array-includes": "^3.1.4", @@ -4969,14 +4603,14 @@ "debug": "^2.6.9", "doctrine": "^2.1.0", "eslint-import-resolver-node": "^0.3.6", - "eslint-module-utils": "^2.7.0", + "eslint-module-utils": "^2.7.2", "has": "^1.0.3", - "is-core-module": "^2.7.0", + "is-core-module": "^2.8.0", "is-glob": "^4.0.3", "minimatch": "^3.0.4", "object.values": "^1.1.5", "resolve": "^1.20.0", - "tsconfig-paths": "^3.11.0" + "tsconfig-paths": "^3.12.0" }, "engines": { "node": ">=4" @@ -5018,6 +4652,15 @@ "integrity": "sha1-8MBwEclf7EK/tNkJ3rtuoDXzsqQ=", "dev": true }, + "node_modules/eslint-plugin-no-unsanitized": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-no-unsanitized/-/eslint-plugin-no-unsanitized-4.0.1.tgz", + "integrity": "sha512-y/lAMWnPPC7RYuUdxlEL/XiCL8FehN9h9s3Kjqbp/Kv0i9NZs+IXSC2kS546Fa4Bumwy31HlVS/OdWX0Kxb5Xg==", + "dev": true, + "peerDependencies": { + "eslint": "^6 || ^7 || ^8" + } + }, "node_modules/eslint-scope": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", @@ -5059,29 +4702,12 @@ } }, "node_modules/eslint-visitor-keys": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.0.0.tgz", - "integrity": "sha512-mJOZa35trBTb3IyRmo8xmKBZlxf+N7OnUl4+ZhJHs/r+0770Wh/LEACE2pqMGMe27G/4y8P2bYGk4J70IC5k1Q==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/eslint/node_modules/debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", + "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/eslint/node_modules/escape-string-regexp": { @@ -5097,9 +4723,9 @@ } }, "node_modules/eslint/node_modules/eslint-scope": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-6.0.0.tgz", - "integrity": "sha512-uRDL9MWmQCkaFus8RF5K9/L/2fn+80yoW3jkD53l4shjCh26fCtvJGasxjUqP5OT87SYTxCVA3BwTUzuELx9kA==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", + "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", "dev": true, "dependencies": { "esrecurse": "^4.3.0", @@ -5131,14 +4757,14 @@ } }, "node_modules/espree": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.0.0.tgz", - "integrity": "sha512-r5EQJcYZ2oaGbeR0jR0fFVijGOcwai07/690YRXLINuhmVeRY4UKSAsQPe/0BNuDgwP7Ophoc1PRsr2E3tkbdQ==", + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.1.tgz", + "integrity": "sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ==", "dev": true, "dependencies": { - "acorn": "^8.5.0", + "acorn": "^8.7.0", "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^3.0.0" + "eslint-visitor-keys": "^3.3.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -5233,13 +4859,6 @@ "node": ">= 0.6" } }, - "node_modules/event-to-promise": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/event-to-promise/-/event-to-promise-0.8.0.tgz", - "integrity": "sha1-S4TxF3K28l93Uvx02XFTGsb1tiY=", - "deprecated": "Use promise-toolbox/fromEvent instead", - "dev": true - }, "node_modules/eventemitter3": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", @@ -5269,18 +4888,6 @@ "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/execa/node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/exit": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", @@ -5291,47 +4898,33 @@ } }, "node_modules/expect": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/expect/-/expect-27.3.1.tgz", - "integrity": "sha512-MrNXV2sL9iDRebWPGOGFdPQRl2eDQNu/uhxIMShjjx74T6kC6jFIkmQ6OqXDtevjGUkyB2IT56RzDBqXf/QPCg==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/expect/-/expect-27.5.1.tgz", + "integrity": "sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==", "dev": true, "dependencies": { - "@jest/types": "^27.2.5", - "ansi-styles": "^5.0.0", - "jest-get-type": "^27.3.1", - "jest-matcher-utils": "^27.3.1", - "jest-message-util": "^27.3.1", - "jest-regex-util": "^27.0.6" + "@jest/types": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1" }, "engines": { "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/expect/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/express": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", - "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.2.tgz", + "integrity": "sha512-oxlxJxcQlYwqPWKVJJtvQiwHgosH/LrLSPA+H4UxpyvSS6jC5aH+5MoHFM+KABgTOt0APue4w66Ha8jCUo9QGg==", "dev": true, "peer": true, "dependencies": { "accepts": "~1.3.7", "array-flatten": "1.1.1", - "body-parser": "1.19.0", - "content-disposition": "0.5.3", + "body-parser": "1.19.1", + "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.4.0", + "cookie": "0.4.1", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "~1.1.2", @@ -5345,13 +4938,13 @@ "on-finished": "~2.3.0", "parseurl": "~1.3.3", "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.5", - "qs": "6.7.0", + "proxy-addr": "~2.0.7", + "qs": "6.9.6", "range-parser": "~1.2.1", - "safe-buffer": "5.1.2", - "send": "0.17.1", - "serve-static": "1.14.1", - "setprototypeof": "1.1.1", + "safe-buffer": "5.2.1", + "send": "0.17.2", + "serve-static": "1.14.2", + "setprototypeof": "1.2.0", "statuses": "~1.5.0", "type-is": "~1.6.18", "utils-merge": "1.0.1", @@ -5361,16 +4954,6 @@ "node": ">= 0.10.0" } }, - "node_modules/express/node_modules/cookie": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", - "dev": true, - "peer": true, - "engines": { - "node": ">= 0.6" - } - }, "node_modules/express/node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -5388,6 +4971,27 @@ "dev": true, "peer": true }, + "node_modules/express/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "peer": true + }, "node_modules/ext-list": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/ext-list/-/ext-list-2.2.2.tgz", @@ -5441,6 +5045,21 @@ "@types/yauzl": "^2.9.1" } }, + "node_modules/extract-zip/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", @@ -5457,9 +5076,9 @@ "dev": true }, "node_modules/fast-glob": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", - "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", + "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", @@ -5469,7 +5088,7 @@ "micromatch": "^4.0.4" }, "engines": { - "node": ">=8" + "node": ">=8.6.0" } }, "node_modules/fast-json-patch": { @@ -5503,26 +5122,14 @@ "dev": true }, "node_modules/fast-redact": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.0.2.tgz", - "integrity": "sha512-YN+CYfCVRVMUZOUPeinHNKgytM1wPI/C/UCLEi56EsY2dwwvI00kIJHJoI7pMVqGoMew8SMZ2SSfHKHULHXDsg==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.1.1.tgz", + "integrity": "sha512-odVmjC8x8jNeMZ3C+rPMESzXVSEU8tSWSHv9HFxP2mm89G/1WwqhrerJDQm9Zus8X6aoRgQDThKqptdNA6bt+A==", "dev": true, "engines": { "node": ">=6" } }, - "node_modules/fast-safe-stringify": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", - "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", - "dev": true - }, - "node_modules/fastify-warning": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/fastify-warning/-/fastify-warning-0.2.0.tgz", - "integrity": "sha512-s1EQguBw/9qtc1p/WTY4eq9WMRIACkj+HTcOIK1in4MV5aFaQC9ZCIt0dJ7pr5bIf4lPpHvAtP2ywpTNgs7hqw==", - "dev": true - }, "node_modules/fastq": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", @@ -5642,23 +5249,6 @@ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true }, - "node_modules/find-cache-dir": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", - "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==", - "dev": true, - "dependencies": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/avajs/find-cache-dir?sponsor=1" - } - }, "node_modules/find-up": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", @@ -5673,9 +5263,9 @@ } }, "node_modules/firefox-profile": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/firefox-profile/-/firefox-profile-4.2.1.tgz", - "integrity": "sha512-KyA5ruS7V1nXpaHlJrKPW1jkoc9bq/WKquaKuca/ETembuxcBQPEPpxAp0biwjQCPf3sBslN/heZLdfa5Eotzg==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/firefox-profile/-/firefox-profile-4.2.2.tgz", + "integrity": "sha512-3kI17Xl9dL9AeRkpV1yahsJ+UbekkPtlQswKrIsTY1NLgxtEOR4R19rjGGz5+7/rP8Jt6fvxHk+Bai9R6Eai3w==", "dev": true, "dependencies": { "adm-zip": "~0.5.x", @@ -5734,16 +5324,10 @@ "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/flatstr": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/flatstr/-/flatstr-1.0.12.tgz", - "integrity": "sha512-4zPxDyhCyiN2wIAtSLI6gc82/EjqZc1onI4Mz/l0pWrAlsSfYH/2ZIcU+e3oA2wDwbzIWNKwa23F8rh6+DRWkw==", - "dev": true - }, "node_modules/flatted": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.1.tgz", - "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==", + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", "dev": true }, "node_modules/fluent-syntax": { @@ -5756,9 +5340,9 @@ } }, "node_modules/follow-redirects": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz", - "integrity": "sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg==", + "version": "1.14.8", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.8.tgz", + "integrity": "sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==", "dev": true, "funding": [ { @@ -5908,13 +5492,13 @@ "dev": true }, "node_modules/fx-runner": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fx-runner/-/fx-runner-1.1.0.tgz", - "integrity": "sha512-v/Eo69DDFW30zPdvjCYVXddjVvLy2xGeRbg0S18bPd8kEc0q9VsDoDkjyOxY5lTZsAqcQGy0OWjs3HCfRVBNSg==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fx-runner/-/fx-runner-1.2.0.tgz", + "integrity": "sha512-/zR9BmHF8h4OaVJ+fHHJBv/5FdPV9mjOAPIscQZbAijm7Aa15Ls/P8UBHD5OKU5jwu2niTxkkzzHKITE7oCMoQ==", "dev": true, "dependencies": { "commander": "2.9.0", - "shell-quote": "1.6.1", + "shell-quote": "1.7.3", "spawn-sync": "1.0.15", "when": "3.7.7", "which": "1.2.4", @@ -5997,15 +5581,12 @@ } }, "node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", "dev": true, - "dependencies": { - "pump": "^3.0.0" - }, "engines": { - "node": ">=8" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -6105,32 +5686,34 @@ } }, "node_modules/globby": { - "version": "11.0.4", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz", - "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==", + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-13.1.1.tgz", + "integrity": "sha512-XMzoDZbGZ37tufiv7g0N4F/zp3zkwdFtVbV3EHsVl1KQr4RPLfNoT068/97RPshz2J5xYNEjLKKBKaGHifBd3Q==", "dev": true, "dependencies": { - "array-union": "^2.1.0", "dir-glob": "^3.0.1", - "fast-glob": "^3.1.1", - "ignore": "^5.1.4", - "merge2": "^1.3.0", - "slash": "^3.0.0" + "fast-glob": "^3.2.11", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^4.0.0" }, "engines": { - "node": ">=10" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/globby/node_modules/ignore": { - "version": "5.1.8", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", - "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "node_modules/globby/node_modules/slash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", "dev": true, "engines": { - "node": ">= 4" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/got": { @@ -6183,9 +5766,9 @@ } }, "node_modules/graceful-fs": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", - "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==", + "version": "4.2.9", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", + "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==", "dev": true }, "node_modules/graceful-readlink": { @@ -6357,27 +5940,21 @@ "peer": true }, "node_modules/http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", "dev": true, "dependencies": { "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" + "toidentifier": "1.0.1" }, "engines": { "node": ">= 0.6" } }, - "node_modules/http-errors/node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - }, "node_modules/http-proxy": { "version": "1.18.1", "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", @@ -6476,9 +6053,9 @@ ] }, "node_modules/ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", "dev": true, "engines": { "node": ">= 4" @@ -6529,9 +6106,9 @@ } }, "node_modules/import-local": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.0.3.tgz", - "integrity": "sha512-bE9iaUY3CXH8Cwfan/abDKAxe1KGT9kyGsBPqf6DMK/z0a2OzAsrukeYNgIH6cH5Xr452jb1TUL8rSfCLjZ9uA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", "dev": true, "dependencies": { "pkg-dir": "^4.2.0", @@ -6542,6 +6119,9 @@ }, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/imurmurhash": { @@ -7108,14 +6688,15 @@ } }, "node_modules/istanbul-lib-instrument": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", - "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.1.0.tgz", + "integrity": "sha512-czwUz525rkOFDJxfKK6mYfIs9zBKILyrZQxjz3ABhjQXhbhFsSbo1HW/BFcsDnfJYJWA6thRR5/TUY2qs5W99Q==", "dev": true, "dependencies": { - "@babel/core": "^7.7.5", + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-coverage": "^3.2.0", "semver": "^6.3.0" }, "engines": { @@ -7146,9 +6727,9 @@ } }, "node_modules/istanbul-lib-source-maps": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz", - "integrity": "sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", "dev": true, "dependencies": { "debug": "^4.1.1", @@ -7156,13 +6737,13 @@ "source-map": "^0.6.1" }, "engines": { - "node": ">=8" + "node": ">=10" } }, "node_modules/istanbul-reports": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.0.2.tgz", - "integrity": "sha512-9tZvz7AiR3PEDNGiV9vIouQ/EAcqMXFmkcA1CDFTwOB98OZVDL0PH9glHotf5Ugp6GCOTypfzGWI/OqjWNCRUw==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.3.tgz", + "integrity": "sha512-x9LtDVtfm/t1GFiLl3NffC7hz+I1ragvgX1P/Lg1NlIagifZDKUkuuaAxH/qpwj2IuEfD8G2Bs/UKp+sZ/pKkg==", "dev": true, "dependencies": { "html-escaper": "^2.0.0", @@ -7187,9 +6768,9 @@ } }, "node_modules/jasmine-core": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.10.1.tgz", - "integrity": "sha512-ooZWSDVAdh79Rrj4/nnfklL3NQVra0BcuhcuWoAwwi+znLDoUeH87AFfeX8s+YeYi6xlv5nveRyaA1v7CintfA==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-4.0.1.tgz", + "integrity": "sha512-w+JDABxQCkxbGGxg+a2hUVZyqUS2JKngvIyLGu/xiw2ZwgsoSB0iiecLQsQORSeaKQ6iGrCyWG86RfNDuoA7Lg==", "dev": true }, "node_modules/jed": { @@ -7199,14 +6780,14 @@ "dev": true }, "node_modules/jest": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/jest/-/jest-27.3.1.tgz", - "integrity": "sha512-U2AX0AgQGd5EzMsiZpYt8HyZ+nSVIh5ujQ9CPp9EQZJMjXIiSZpJNweZl0swatKRoqHWgGKM3zaSwm4Zaz87ng==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest/-/jest-27.5.1.tgz", + "integrity": "sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ==", "dev": true, "dependencies": { - "@jest/core": "^27.3.1", + "@jest/core": "^27.5.1", "import-local": "^3.0.2", - "jest-cli": "^27.3.1" + "jest-cli": "^27.5.1" }, "bin": { "jest": "bin/jest.js" @@ -7224,12 +6805,12 @@ } }, "node_modules/jest-changed-files": { - "version": "27.3.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-27.3.0.tgz", - "integrity": "sha512-9DJs9garMHv4RhylUMZgbdCJ3+jHSkpL9aaVKp13xtXAD80qLTLrqcDZL1PHA9dYA0bCI86Nv2BhkLpLhrBcPg==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-27.5.1.tgz", + "integrity": "sha512-buBLMiByfWGCoMsLLzGUUSpAmIAGnbR2KJoMN10ziLhOLvP4e0SlypHnAel8iqQXTrcbmfEY9sSqae5sgUsTvw==", "dev": true, "dependencies": { - "@jest/types": "^27.2.5", + "@jest/types": "^27.5.1", "execa": "^5.0.0", "throat": "^6.0.1" }, @@ -7238,27 +6819,27 @@ } }, "node_modules/jest-circus": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-27.3.1.tgz", - "integrity": "sha512-v1dsM9II6gvXokgqq6Yh2jHCpfg7ZqV4jWY66u7npz24JnhP3NHxI0sKT7+ZMQ7IrOWHYAaeEllOySbDbWsiXw==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-27.5.1.tgz", + "integrity": "sha512-D95R7x5UtlMA5iBYsOHFFbMD/GVA4R/Kdq15f7xYWUfWHBto9NYRsOvnSauTgdF+ogCpJ4tyKOXhUifxS65gdw==", "dev": true, "dependencies": { - "@jest/environment": "^27.3.1", - "@jest/test-result": "^27.3.1", - "@jest/types": "^27.2.5", + "@jest/environment": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", "@types/node": "*", "chalk": "^4.0.0", "co": "^4.6.0", "dedent": "^0.7.0", - "expect": "^27.3.1", + "expect": "^27.5.1", "is-generator-fn": "^2.0.0", - "jest-each": "^27.3.1", - "jest-matcher-utils": "^27.3.1", - "jest-message-util": "^27.3.1", - "jest-runtime": "^27.3.1", - "jest-snapshot": "^27.3.1", - "jest-util": "^27.3.1", - "pretty-format": "^27.3.1", + "jest-each": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1", "slash": "^3.0.0", "stack-utils": "^2.0.3", "throat": "^6.0.1" @@ -7268,21 +6849,21 @@ } }, "node_modules/jest-cli": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-27.3.1.tgz", - "integrity": "sha512-WHnCqpfK+6EvT62me6WVs8NhtbjAS4/6vZJnk7/2+oOr50cwAzG4Wxt6RXX0hu6m1169ZGMlhYYUNeKBXCph/Q==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-27.5.1.tgz", + "integrity": "sha512-Hc6HOOwYq4/74/c62dEE3r5elx8wjYqxY0r0G/nFrLDPMFRu6RA/u8qINOIkvhxG7mMQ5EJsOGfRpI8L6eFUVw==", "dev": true, "dependencies": { - "@jest/core": "^27.3.1", - "@jest/test-result": "^27.3.1", - "@jest/types": "^27.2.5", + "@jest/core": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", "chalk": "^4.0.0", "exit": "^0.1.2", - "graceful-fs": "^4.2.4", + "graceful-fs": "^4.2.9", "import-local": "^3.0.2", - "jest-config": "^27.3.1", - "jest-util": "^27.3.1", - "jest-validate": "^27.3.1", + "jest-config": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", "prompts": "^2.0.1", "yargs": "^16.2.0" }, @@ -7302,32 +6883,35 @@ } }, "node_modules/jest-config": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-27.3.1.tgz", - "integrity": "sha512-KY8xOIbIACZ/vdYCKSopL44I0xboxC751IX+DXL2+Wx6DKNycyEfV3rryC3BPm5Uq/BBqDoMrKuqLEUNJmMKKg==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-27.5.1.tgz", + "integrity": "sha512-5sAsjm6tGdsVbW9ahcChPAFCk4IlkQUknH5AvKjuLTSlcO/wCZKyFdn7Rg0EkC+OGgWODEy2hDpWB1PgzH0JNA==", "dev": true, "dependencies": { - "@babel/core": "^7.1.0", - "@jest/test-sequencer": "^27.3.1", - "@jest/types": "^27.2.5", - "babel-jest": "^27.3.1", + "@babel/core": "^7.8.0", + "@jest/test-sequencer": "^27.5.1", + "@jest/types": "^27.5.1", + "babel-jest": "^27.5.1", "chalk": "^4.0.0", "ci-info": "^3.2.0", "deepmerge": "^4.2.2", "glob": "^7.1.1", - "graceful-fs": "^4.2.4", - "jest-circus": "^27.3.1", - "jest-environment-jsdom": "^27.3.1", - "jest-environment-node": "^27.3.1", - "jest-get-type": "^27.3.1", - "jest-jasmine2": "^27.3.1", - "jest-regex-util": "^27.0.6", - "jest-resolve": "^27.3.1", - "jest-runner": "^27.3.1", - "jest-util": "^27.3.1", - "jest-validate": "^27.3.1", + "graceful-fs": "^4.2.9", + "jest-circus": "^27.5.1", + "jest-environment-jsdom": "^27.5.1", + "jest-environment-node": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-jasmine2": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-runner": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", "micromatch": "^4.0.4", - "pretty-format": "^27.3.1" + "parse-json": "^5.2.0", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" }, "engines": { "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" @@ -7342,30 +6926,30 @@ } }, "node_modules/jest-config/node_modules/ci-info": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.2.0.tgz", - "integrity": "sha512-dVqRX7fLUm8J6FgHJ418XuIgDLZDkYcDFTeL6TA2gt5WlIZUQrrH6EZrNClwT/H0FateUsZkGIOPRrLbP+PR9A==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", + "integrity": "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==", "dev": true }, "node_modules/jest-diff": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.3.1.tgz", - "integrity": "sha512-PCeuAH4AWUo2O5+ksW4pL9v5xJAcIKPUPfIhZBcG1RKv/0+dvaWTQK1Nrau8d67dp65fOqbeMdoil+6PedyEPQ==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", + "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", "dev": true, "dependencies": { "chalk": "^4.0.0", - "diff-sequences": "^27.0.6", - "jest-get-type": "^27.3.1", - "pretty-format": "^27.3.1" + "diff-sequences": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" }, "engines": { "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, "node_modules/jest-docblock": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-27.0.6.tgz", - "integrity": "sha512-Fid6dPcjwepTFraz0YxIMCi7dejjJ/KL9FBjPYhBp4Sv1Y9PdhImlKZqYU555BlN4TQKaTc+F2Av1z+anVyGkA==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-27.5.1.tgz", + "integrity": "sha512-rl7hlABeTsRYxKiUfpHrQrG4e2obOiTQWfMEH3PxPjOtdsfLQO4ReWSZaQ7DETm4xu07rl4q/h4zcKXyU0/OzQ==", "dev": true, "dependencies": { "detect-newline": "^3.0.0" @@ -7375,33 +6959,33 @@ } }, "node_modules/jest-each": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-27.3.1.tgz", - "integrity": "sha512-E4SwfzKJWYcvOYCjOxhZcxwL+AY0uFMvdCOwvzgutJiaiodFjkxQQDxHm8FQBeTqDnSmKsQWn7ldMRzTn2zJaQ==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-27.5.1.tgz", + "integrity": "sha512-1Ff6p+FbhT/bXQnEouYy00bkNSY7OUpfIcmdl8vZ31A1UUaurOLPA8a8BbJOF2RDUElwJhmeaV7LnagI+5UwNQ==", "dev": true, "dependencies": { - "@jest/types": "^27.2.5", + "@jest/types": "^27.5.1", "chalk": "^4.0.0", - "jest-get-type": "^27.3.1", - "jest-util": "^27.3.1", - "pretty-format": "^27.3.1" + "jest-get-type": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1" }, "engines": { "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, "node_modules/jest-environment-jsdom": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-27.3.1.tgz", - "integrity": "sha512-3MOy8qMzIkQlfb3W1TfrD7uZHj+xx8Olix5vMENkj5djPmRqndMaXtpnaZkxmxM+Qc3lo+yVzJjzuXbCcZjAlg==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-27.5.1.tgz", + "integrity": "sha512-TFBvkTC1Hnnnrka/fUb56atfDtJ9VMZ94JkjTbggl1PEpwrYtUBKMezB3inLmWqQsXYLcMwNoDQwoBTAvFfsfw==", "dev": true, "dependencies": { - "@jest/environment": "^27.3.1", - "@jest/fake-timers": "^27.3.1", - "@jest/types": "^27.2.5", + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", "@types/node": "*", - "jest-mock": "^27.3.0", - "jest-util": "^27.3.1", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1", "jsdom": "^16.6.0" }, "engines": { @@ -7409,47 +6993,63 @@ } }, "node_modules/jest-environment-node": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.3.1.tgz", - "integrity": "sha512-T89F/FgkE8waqrTSA7/ydMkcc52uYPgZZ6q8OaZgyiZkJb5QNNCF6oPZjH9IfPFfcc9uBWh1574N0kY0pSvTXw==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.5.1.tgz", + "integrity": "sha512-Jt4ZUnxdOsTGwSRAfKEnE6BcwsSPNOijjwifq5sDFSA2kesnXTvNqKHYgM0hDq3549Uf/KzdXNYn4wMZJPlFLw==", "dev": true, "dependencies": { - "@jest/environment": "^27.3.1", - "@jest/fake-timers": "^27.3.1", - "@jest/types": "^27.2.5", + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", "@types/node": "*", - "jest-mock": "^27.3.0", - "jest-util": "^27.3.1" + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1" }, "engines": { "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, + "node_modules/jest-extended": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/jest-extended/-/jest-extended-2.0.0.tgz", + "integrity": "sha512-6AgjJQVaBEKGSK3FH90kOiRUWJsbzn9NWtW0pjGkAFIdH0oPilfkV/gHPJdVvJeBiqT3jMHw8TUg9pUGC1azDg==", + "dev": true, + "dependencies": { + "jest-diff": "^27.2.5", + "jest-get-type": "^27.0.6" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + }, + "peerDependencies": { + "jest": ">=27.2.5" + } + }, "node_modules/jest-get-type": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.3.1.tgz", - "integrity": "sha512-+Ilqi8hgHSAdhlQ3s12CAVNd8H96ZkQBfYoXmArzZnOfAtVAJEiPDBirjByEblvG/4LPJmkL+nBqPO3A1YJAEg==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", + "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==", "dev": true, "engines": { "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, "node_modules/jest-haste-map": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.3.1.tgz", - "integrity": "sha512-lYfNZIzwPccDJZIyk9Iz5iQMM/MH56NIIcGj7AFU1YyA4ewWFBl8z+YPJuSCRML/ee2cCt2y3W4K3VXPT6Nhzg==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.5.1.tgz", + "integrity": "sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==", "dev": true, "dependencies": { - "@jest/types": "^27.2.5", + "@jest/types": "^27.5.1", "@types/graceful-fs": "^4.1.2", "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", - "graceful-fs": "^4.2.4", - "jest-regex-util": "^27.0.6", - "jest-serializer": "^27.0.6", - "jest-util": "^27.3.1", - "jest-worker": "^27.3.1", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^27.5.1", + "jest-serializer": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", "micromatch": "^4.0.4", "walker": "^1.0.7" }, @@ -7461,28 +7061,27 @@ } }, "node_modules/jest-jasmine2": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-27.3.1.tgz", - "integrity": "sha512-WK11ZUetDQaC09w4/j7o4FZDUIp+4iYWH/Lik34Pv7ukL+DuXFGdnmmi7dT58J2ZYKFB5r13GyE0z3NPeyJmsg==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-27.5.1.tgz", + "integrity": "sha512-jtq7VVyG8SqAorDpApwiJJImd0V2wv1xzdheGHRGyuT7gZm6gG47QEskOlzsN1PG/6WNaCo5pmwMHDf3AkG2pQ==", "dev": true, "dependencies": { - "@babel/traverse": "^7.1.0", - "@jest/environment": "^27.3.1", - "@jest/source-map": "^27.0.6", - "@jest/test-result": "^27.3.1", - "@jest/types": "^27.2.5", + "@jest/environment": "^27.5.1", + "@jest/source-map": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", "@types/node": "*", "chalk": "^4.0.0", "co": "^4.6.0", - "expect": "^27.3.1", + "expect": "^27.5.1", "is-generator-fn": "^2.0.0", - "jest-each": "^27.3.1", - "jest-matcher-utils": "^27.3.1", - "jest-message-util": "^27.3.1", - "jest-runtime": "^27.3.1", - "jest-snapshot": "^27.3.1", - "jest-util": "^27.3.1", - "pretty-format": "^27.3.1", + "jest-each": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1", "throat": "^6.0.1" }, "engines": { @@ -7490,46 +7089,46 @@ } }, "node_modules/jest-leak-detector": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-27.3.1.tgz", - "integrity": "sha512-78QstU9tXbaHzwlRlKmTpjP9k4Pvre5l0r8Spo4SbFFVy/4Abg9I6ZjHwjg2QyKEAMg020XcjP+UgLZIY50yEg==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-27.5.1.tgz", + "integrity": "sha512-POXfWAMvfU6WMUXftV4HolnJfnPOGEu10fscNCA76KBpRRhcMN2c8d3iT2pxQS3HLbA+5X4sOUPzYO2NUyIlHQ==", "dev": true, "dependencies": { - "jest-get-type": "^27.3.1", - "pretty-format": "^27.3.1" + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" }, "engines": { "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, "node_modules/jest-matcher-utils": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.3.1.tgz", - "integrity": "sha512-hX8N7zXS4k+8bC1Aj0OWpGb7D3gIXxYvPNK1inP5xvE4ztbz3rc4AkI6jGVaerepBnfWB17FL5lWFJT3s7qo8w==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz", + "integrity": "sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==", "dev": true, "dependencies": { "chalk": "^4.0.0", - "jest-diff": "^27.3.1", - "jest-get-type": "^27.3.1", - "pretty-format": "^27.3.1" + "jest-diff": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" }, "engines": { "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, "node_modules/jest-message-util": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.3.1.tgz", - "integrity": "sha512-bh3JEmxsTZ/9rTm0jQrPElbY2+y48Rw2t47uMfByNyUVR+OfPh4anuyKsGqsNkXk/TI4JbLRZx+7p7Hdt6q1yg==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", + "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", "dev": true, "dependencies": { "@babel/code-frame": "^7.12.13", - "@jest/types": "^27.2.5", + "@jest/types": "^27.5.1", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", - "graceful-fs": "^4.2.4", + "graceful-fs": "^4.2.9", "micromatch": "^4.0.4", - "pretty-format": "^27.3.1", + "pretty-format": "^27.5.1", "slash": "^3.0.0", "stack-utils": "^2.0.3" }, @@ -7538,12 +7137,12 @@ } }, "node_modules/jest-mock": { - "version": "27.3.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.3.0.tgz", - "integrity": "sha512-ziZiLk0elZOQjD08bLkegBzv5hCABu/c8Ytx45nJKkysQwGaonvmTxwjLqEA4qGdasq9o2I8/HtdGMNnVsMTGw==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz", + "integrity": "sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==", "dev": true, "dependencies": { - "@jest/types": "^27.2.5", + "@jest/types": "^27.5.1", "@types/node": "*" }, "engines": { @@ -7568,27 +7167,27 @@ } }, "node_modules/jest-regex-util": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.0.6.tgz", - "integrity": "sha512-SUhPzBsGa1IKm8hx2F4NfTGGp+r7BXJ4CulsZ1k2kI+mGLG+lxGrs76veN2LF/aUdGosJBzKgXmNCw+BzFqBDQ==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", + "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==", "dev": true, "engines": { "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, "node_modules/jest-resolve": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.3.1.tgz", - "integrity": "sha512-Dfzt25CFSPo3Y3GCbxynRBZzxq9AdyNN+x/v2IqYx6KVT5Z6me2Z/PsSGFSv3cOSUZqJ9pHxilao/I/m9FouLw==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.5.1.tgz", + "integrity": "sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw==", "dev": true, "dependencies": { - "@jest/types": "^27.2.5", + "@jest/types": "^27.5.1", "chalk": "^4.0.0", - "graceful-fs": "^4.2.4", - "jest-haste-map": "^27.3.1", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", "jest-pnp-resolver": "^1.2.2", - "jest-util": "^27.3.1", - "jest-validate": "^27.3.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", "resolve": "^1.20.0", "resolve.exports": "^1.1.0", "slash": "^3.0.0" @@ -7598,45 +7197,44 @@ } }, "node_modules/jest-resolve-dependencies": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-27.3.1.tgz", - "integrity": "sha512-X7iLzY8pCiYOnvYo2YrK3P9oSE8/3N2f4pUZMJ8IUcZnT81vlSonya1KTO9ZfKGuC+svE6FHK/XOb8SsoRUV1A==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-27.5.1.tgz", + "integrity": "sha512-QQOOdY4PE39iawDn5rzbIePNigfe5B9Z91GDD1ae/xNDlu9kaat8QQ5EKnNmVWPV54hUdxCVwwj6YMgR2O7IOg==", "dev": true, "dependencies": { - "@jest/types": "^27.2.5", - "jest-regex-util": "^27.0.6", - "jest-snapshot": "^27.3.1" + "@jest/types": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-snapshot": "^27.5.1" }, "engines": { "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, "node_modules/jest-runner": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-27.3.1.tgz", - "integrity": "sha512-r4W6kBn6sPr3TBwQNmqE94mPlYVn7fLBseeJfo4E2uCTmAyDFm2O5DYAQAFP7Q3YfiA/bMwg8TVsciP7k0xOww==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-27.5.1.tgz", + "integrity": "sha512-g4NPsM4mFCOwFKXO4p/H/kWGdJp9V8kURY2lX8Me2drgXqG7rrZAx5kv+5H7wtt/cdFIjhqYx1HrlqWHaOvDaQ==", "dev": true, "dependencies": { - "@jest/console": "^27.3.1", - "@jest/environment": "^27.3.1", - "@jest/test-result": "^27.3.1", - "@jest/transform": "^27.3.1", - "@jest/types": "^27.2.5", + "@jest/console": "^27.5.1", + "@jest/environment": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", "@types/node": "*", "chalk": "^4.0.0", "emittery": "^0.8.1", - "exit": "^0.1.2", - "graceful-fs": "^4.2.4", - "jest-docblock": "^27.0.6", - "jest-environment-jsdom": "^27.3.1", - "jest-environment-node": "^27.3.1", - "jest-haste-map": "^27.3.1", - "jest-leak-detector": "^27.3.1", - "jest-message-util": "^27.3.1", - "jest-resolve": "^27.3.1", - "jest-runtime": "^27.3.1", - "jest-util": "^27.3.1", - "jest-worker": "^27.3.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^27.5.1", + "jest-environment-jsdom": "^27.5.1", + "jest-environment-node": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-leak-detector": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", "source-map-support": "^0.5.6", "throat": "^6.0.1" }, @@ -7645,84 +7243,78 @@ } }, "node_modules/jest-runtime": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.3.1.tgz", - "integrity": "sha512-qtO6VxPbS8umqhEDpjA4pqTkKQ1Hy4ZSi9mDVeE9Za7LKBo2LdW2jmT+Iod3XFaJqINikZQsn2wEi0j9wPRbLg==", - "dev": true, - "dependencies": { - "@jest/console": "^27.3.1", - "@jest/environment": "^27.3.1", - "@jest/globals": "^27.3.1", - "@jest/source-map": "^27.0.6", - "@jest/test-result": "^27.3.1", - "@jest/transform": "^27.3.1", - "@jest/types": "^27.2.5", - "@types/yargs": "^16.0.0", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.5.1.tgz", + "integrity": "sha512-o7gxw3Gf+H2IGt8fv0RiyE1+r83FJBRruoA+FXrlHw6xEyBsU8ugA6IPfTdVyA0w8HClpbK+DGJxH59UrNMx8A==", + "dev": true, + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/globals": "^27.5.1", + "@jest/source-map": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", "chalk": "^4.0.0", "cjs-module-lexer": "^1.0.0", "collect-v8-coverage": "^1.0.0", "execa": "^5.0.0", - "exit": "^0.1.2", "glob": "^7.1.3", - "graceful-fs": "^4.2.4", - "jest-haste-map": "^27.3.1", - "jest-message-util": "^27.3.1", - "jest-mock": "^27.3.0", - "jest-regex-util": "^27.0.6", - "jest-resolve": "^27.3.1", - "jest-snapshot": "^27.3.1", - "jest-util": "^27.3.1", - "jest-validate": "^27.3.1", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-mock": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", "slash": "^3.0.0", - "strip-bom": "^4.0.0", - "yargs": "^16.2.0" + "strip-bom": "^4.0.0" }, "engines": { "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, "node_modules/jest-serializer": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.0.6.tgz", - "integrity": "sha512-PtGdVK9EGC7dsaziskfqaAPib6wTViY3G8E5wz9tLVPhHyiDNTZn/xjZ4khAw+09QkoOVpn7vF5nPSN6dtBexA==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.5.1.tgz", + "integrity": "sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==", "dev": true, "dependencies": { "@types/node": "*", - "graceful-fs": "^4.2.4" + "graceful-fs": "^4.2.9" }, "engines": { "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, "node_modules/jest-snapshot": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-27.3.1.tgz", - "integrity": "sha512-APZyBvSgQgOT0XumwfFu7X3G5elj6TGhCBLbBdn3R1IzYustPGPE38F51dBWMQ8hRXa9je0vAdeVDtqHLvB6lg==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-27.5.1.tgz", + "integrity": "sha512-yYykXI5a0I31xX67mgeLw1DZ0bJB+gpq5IpSuCAoyDi0+BhgU/RIrL+RTzDmkNTchvDFWKP8lp+w/42Z3us5sA==", "dev": true, "dependencies": { "@babel/core": "^7.7.2", "@babel/generator": "^7.7.2", - "@babel/parser": "^7.7.2", "@babel/plugin-syntax-typescript": "^7.7.2", "@babel/traverse": "^7.7.2", "@babel/types": "^7.0.0", - "@jest/transform": "^27.3.1", - "@jest/types": "^27.2.5", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", "@types/babel__traverse": "^7.0.4", "@types/prettier": "^2.1.5", "babel-preset-current-node-syntax": "^1.0.0", "chalk": "^4.0.0", - "expect": "^27.3.1", - "graceful-fs": "^4.2.4", - "jest-diff": "^27.3.1", - "jest-get-type": "^27.3.1", - "jest-haste-map": "^27.3.1", - "jest-matcher-utils": "^27.3.1", - "jest-message-util": "^27.3.1", - "jest-resolve": "^27.3.1", - "jest-util": "^27.3.1", + "expect": "^27.5.1", + "graceful-fs": "^4.2.9", + "jest-diff": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-util": "^27.5.1", "natural-compare": "^1.4.0", - "pretty-format": "^27.3.1", + "pretty-format": "^27.5.1", "semver": "^7.3.2" }, "engines": { @@ -7730,16 +7322,16 @@ } }, "node_modules/jest-util": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.3.1.tgz", - "integrity": "sha512-8fg+ifEH3GDryLQf/eKZck1DEs2YuVPBCMOaHQxVVLmQwl/CDhWzrvChTX4efLZxGrw+AA0mSXv78cyytBt/uw==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", "dev": true, "dependencies": { - "@jest/types": "^27.2.5", + "@jest/types": "^27.5.1", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", - "graceful-fs": "^4.2.4", + "graceful-fs": "^4.2.9", "picomatch": "^2.2.3" }, "engines": { @@ -7753,26 +7345,26 @@ "dev": true }, "node_modules/jest-validate": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-27.3.1.tgz", - "integrity": "sha512-3H0XCHDFLA9uDII67Bwi1Vy7AqwA5HqEEjyy934lgVhtJ3eisw6ShOF1MDmRPspyikef5MyExvIm0/TuLzZ86Q==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-27.5.1.tgz", + "integrity": "sha512-thkNli0LYTmOI1tDB3FI1S1RTp/Bqyd9pTarJwL87OIBFuqEb5Apv5EaApEudYg4g86e3CT6kM0RowkhtEnCBQ==", "dev": true, "dependencies": { - "@jest/types": "^27.2.5", + "@jest/types": "^27.5.1", "camelcase": "^6.2.0", "chalk": "^4.0.0", - "jest-get-type": "^27.3.1", + "jest-get-type": "^27.5.1", "leven": "^3.1.0", - "pretty-format": "^27.3.1" + "pretty-format": "^27.5.1" }, "engines": { "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, "node_modules/jest-validate/node_modules/camelcase": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", - "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true, "engines": { "node": ">=10" @@ -7782,17 +7374,17 @@ } }, "node_modules/jest-watcher": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-27.3.1.tgz", - "integrity": "sha512-9/xbV6chABsGHWh9yPaAGYVVKurWoP3ZMCv6h+O1v9/+pkOroigs6WzZ0e9gLP/njokUwM7yQhr01LKJVMkaZA==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-27.5.1.tgz", + "integrity": "sha512-z676SuD6Z8o8qbmEGhoEUFOM1+jfEiL3DXHK/xgEiG2EyNYfFG60jluWcupY6dATjfEsKQuibReS1djInQnoVw==", "dev": true, "dependencies": { - "@jest/test-result": "^27.3.1", - "@jest/types": "^27.2.5", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", - "jest-util": "^27.3.1", + "jest-util": "^27.5.1", "string-length": "^4.0.1" }, "engines": { @@ -7800,9 +7392,9 @@ } }, "node_modules/jest-worker": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.3.1.tgz", - "integrity": "sha512-ks3WCzsiZaOPJl/oMsDjaf0TRiSv7ctNgs0FqRr2nARsovz6AWWy4oLElwcquGSz692DzgZQrCLScPNs5YlC4g==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", "dev": true, "dependencies": { "@types/node": "*", @@ -7899,9 +7491,9 @@ } }, "node_modules/jsdom/node_modules/ws": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.5.tgz", - "integrity": "sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w==", + "version": "7.5.7", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz", + "integrity": "sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==", "dev": true, "engines": { "node": ">=8.3.0" @@ -7953,9 +7545,9 @@ "dev": true }, "node_modules/json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", "dev": true }, "node_modules/json-schema-traverse": { @@ -8003,12 +7595,6 @@ "graceful-fs": "^4.1.6" } }, - "node_modules/jsonify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", - "dev": true - }, "node_modules/jsonwebtoken": { "version": "8.5.1", "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", @@ -8041,18 +7627,18 @@ } }, "node_modules/jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", + "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", "dev": true, - "engines": [ - "node >=0.6.0" - ], "dependencies": { "assert-plus": "1.0.0", "extsprintf": "1.3.0", - "json-schema": "0.2.3", + "json-schema": "0.4.0", "verror": "1.10.0" + }, + "engines": { + "node": ">=0.6.0" } }, "node_modules/jszip": { @@ -8113,15 +7699,15 @@ } }, "node_modules/karma": { - "version": "6.3.7", - "resolved": "https://registry.npmjs.org/karma/-/karma-6.3.7.tgz", - "integrity": "sha512-EEkswZhOx3EFt1ELlVECeOXHONbHSGw6fkbeMxvCSkLD77X38Kb1d/Oup2Re9ep/tSoa1He3YIBf3Hp+9EsKtg==", + "version": "6.3.17", + "resolved": "https://registry.npmjs.org/karma/-/karma-6.3.17.tgz", + "integrity": "sha512-2TfjHwrRExC8yHoWlPBULyaLwAFmXmxQrcuFImt/JsAsSZu1uOWTZ1ZsWjqQtWpHLiatJOHL5jFjXSJIgCd01g==", "dev": true, "dependencies": { + "@colors/colors": "1.5.0", "body-parser": "^1.19.0", "braces": "^3.0.2", "chokidar": "^3.5.1", - "colors": "^1.4.0", "connect": "^3.7.0", "di": "^0.0.1", "dom-serialize": "^2.2.1", @@ -8130,9 +7716,10 @@ "http-proxy": "^1.18.1", "isbinaryfile": "^4.0.8", "lodash": "^4.17.21", - "log4js": "^6.3.0", + "log4js": "^6.4.1", "mime": "^2.5.2", "minimatch": "^3.0.4", + "mkdirp": "^0.5.5", "qjobs": "^1.2.0", "range-parser": "^1.2.1", "rimraf": "^3.0.2", @@ -8150,9 +7737,9 @@ } }, "node_modules/karma-chrome-launcher": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-3.1.0.tgz", - "integrity": "sha512-3dPs/n7vgz1rxxtynpzZTvb9y/GIaW8xjAwcIGttLbycqoFtI7yo1NGnQi6oFTherRE+GIhCAHZC4vEqWGhNvg==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-3.1.1.tgz", + "integrity": "sha512-hsIglcq1vtboGPAN+DGCISCFOxW+ZVnIqhDQcCMqqCp+4dmJ0Qpq5QAjkbA0X2L9Mi6OBkHi2Srrbmm7pUKkzQ==", "dev": true, "dependencies": { "which": "^1.2.1" @@ -8171,16 +7758,16 @@ } }, "node_modules/karma-coverage": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/karma-coverage/-/karma-coverage-2.0.3.tgz", - "integrity": "sha512-atDvLQqvPcLxhED0cmXYdsPMCQuh6Asa9FMZW1bhNqlVEhJoB9qyZ2BY1gu7D/rr5GLGb5QzYO4siQskxaWP/g==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/karma-coverage/-/karma-coverage-2.2.0.tgz", + "integrity": "sha512-gPVdoZBNDZ08UCzdMHHhEImKrw1+PAOQOIiffv1YsvxFhBjqvo/SVXNk4tqn1SYqX0BJZT6S/59zgxiBe+9OuA==", "dev": true, "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^4.0.1", + "istanbul-lib-coverage": "^3.2.0", + "istanbul-lib-instrument": "^5.1.0", "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.1", + "istanbul-reports": "^3.0.5", "minimatch": "^3.0.4" }, "engines": { @@ -8212,10 +7799,16 @@ "karma": "*" } }, + "node_modules/karma-jasmine/node_modules/jasmine-core": { + "version": "3.99.0", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.99.0.tgz", + "integrity": "sha512-+ZDaJlEfRopINQqgE+hvzRyDIQDeKfqqTvF8RzXsvU1yE3pBDRud2+Qfh9WvGgRpuzqxyQJVI6Amy5XQ11r/3w==", + "dev": true + }, "node_modules/karma-rollup-preprocessor": { - "version": "7.0.7", - "resolved": "https://registry.npmjs.org/karma-rollup-preprocessor/-/karma-rollup-preprocessor-7.0.7.tgz", - "integrity": "sha512-Y1QwsTCiCBp8sSALZdqmqry/mWIWIy0V6zonUIpy+0/D/Kpb2XZvR+JZrWfacQvcvKQdZFJvg6EwlnKtjepu3Q==", + "version": "7.0.8", + "resolved": "https://registry.npmjs.org/karma-rollup-preprocessor/-/karma-rollup-preprocessor-7.0.8.tgz", + "integrity": "sha512-WiuBCS9qsatJuR17dghiTARBZ7LF+ml+eb7qJXhw7IbsdY0lTWELDRQC/93J9i6636CsAXVBL3VJF4WtaFLZzA==", "dev": true, "dependencies": { "chokidar": "^3.3.1", @@ -8237,6 +7830,30 @@ "karma": ">=0.9" } }, + "node_modules/karma-spec-reporter": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/karma-spec-reporter/-/karma-spec-reporter-0.0.33.tgz", + "integrity": "sha512-xRVevDUkiIVhKbDQ3CmeGEpyzA4b3HeVl95Sx5yJAvurpdKUSYF6ZEbQOqKJ7vrtDniABV1hyFez9KX9+7ruBA==", + "dev": true, + "dependencies": { + "colors": "1.4.0" + }, + "peerDependencies": { + "karma": ">=0.9" + } + }, + "node_modules/karma/node_modules/mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, "node_modules/keyv": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.0.0.tgz", @@ -8374,13 +7991,13 @@ } }, "node_modules/lighthouse-logger": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/lighthouse-logger/-/lighthouse-logger-1.2.0.tgz", - "integrity": "sha512-wzUvdIeJZhRsG6gpZfmSCfysaxNEr43i+QT+Hie94wvHDKFLi4n7C2GqZ4sTC+PH5b5iktmXJvU87rWvhP3lHw==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/lighthouse-logger/-/lighthouse-logger-1.3.0.tgz", + "integrity": "sha512-BbqAKApLb9ywUli+0a+PcV04SyJ/N1q/8qgCNe6U97KbPCS1BTksEuHFLYdvc8DltuhfxIUBqDZsC0bBGtl3lA==", "dev": true, "dependencies": { - "debug": "^2.6.8", - "marky": "^1.2.0" + "debug": "^2.6.9", + "marky": "^1.2.2" } }, "node_modules/lighthouse-logger/node_modules/debug": { @@ -8422,12 +8039,6 @@ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, - "node_modules/lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", - "dev": true - }, "node_modules/lodash.includes": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", @@ -8482,34 +8093,22 @@ "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=", "dev": true }, - "node_modules/lodash.truncate": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", - "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", - "dev": true - }, "node_modules/log4js": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.3.0.tgz", - "integrity": "sha512-Mc8jNuSFImQUIateBFwdOQcmC6Q5maU0VVvdC2R6XMb66/VnT+7WS4D/0EeNMZu1YODmJe5NIn2XftCzEocUgw==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.4.1.tgz", + "integrity": "sha512-iUiYnXqAmNKiIZ1XSAitQ4TmNs8CdZYTAWINARF3LjnsLN8tY5m0vRwd6uuWj/yNY0YHxeZodnbmxKFUOM2rMg==", "dev": true, "dependencies": { - "date-format": "^3.0.0", - "debug": "^4.1.1", - "flatted": "^2.0.1", - "rfdc": "^1.1.4", - "streamroller": "^2.2.4" + "date-format": "^4.0.3", + "debug": "^4.3.3", + "flatted": "^3.2.4", + "rfdc": "^1.3.0", + "streamroller": "^3.0.2" }, "engines": { "node": ">=8.0" } }, - "node_modules/log4js/node_modules/flatted": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", - "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", - "dev": true - }, "node_modules/lowercase-keys": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", @@ -8580,9 +8179,9 @@ } }, "node_modules/malevic": { - "version": "0.18.6", - "resolved": "https://registry.npmjs.org/malevic/-/malevic-0.18.6.tgz", - "integrity": "sha512-Um4XRYJpVDhKjRRteiuHdDmcNbI5gX7URsXC6G+5Tk0Dai2W2RB39kg5C/M32IezNPudT+YsgApBh8JG6fIWrA==", + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/malevic/-/malevic-0.19.1.tgz", + "integrity": "sha512-Om8ryj2MufYydPSNM6DbBYQCCPlp5mgtOrrgQKw6tCZwUIXPFsyfM3d5S/2RIEAsQDYYZpIctM+SX55Fkv5r4w==", "dev": true }, "node_modules/map-age-cleaner": { @@ -8744,9 +8343,9 @@ } }, "node_modules/minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", "dev": true }, "node_modules/mkdirp": { @@ -8761,10 +8360,16 @@ "node": ">=10" } }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "dev": true + }, "node_modules/moment": { - "version": "2.29.1", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", - "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==", + "version": "2.29.2", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.2.tgz", + "integrity": "sha512-UgzG4rvxYpN15jgCmVJwac49h9ly9NurikMWGPdVxm8GZD6XjkKPxDTjQQ43gtGgnV3X0cAyWDdP2Wexoquifg==", "dev": true, "optional": true, "engines": { @@ -8873,9 +8478,9 @@ "optional": true }, "node_modules/nanoid": { - "version": "3.1.30", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.30.tgz", - "integrity": "sha512-zJpuPDwOv8D2zq2WRoMe1HsfZthVewpel9CAvTfc/2mBD1uUT/agc5f7GHGWXlYkFvi1mVxe4IjvP2HNrop7nQ==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", + "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==", "dev": true, "bin": { "nanoid": "bin/nanoid.cjs" @@ -8890,12 +8495,6 @@ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, - "node_modules/natural-compare-lite": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", - "integrity": "sha1-F7CVgZiJef3a/gIB6TG6kzyWy7Q=", - "dev": true - }, "node_modules/ncp": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz", @@ -8944,12 +8543,45 @@ } }, "node_modules/node-fetch": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", - "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==", + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", "dev": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, "engines": { "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-fetch/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", + "dev": true + }, + "node_modules/node-fetch/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=", + "dev": true + }, + "node_modules/node-fetch/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "dev": true, + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" } }, "node_modules/node-forge": { @@ -8964,22 +8596,13 @@ "node_modules/node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=", - "dev": true - }, - "node_modules/node-modules-regexp": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz", - "integrity": "sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } + "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=", + "dev": true }, "node_modules/node-releases": { - "version": "1.1.72", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.72.tgz", - "integrity": "sha512-LLUo+PpH3dU6XizX3iVoubUNheF/owjXCZZ5yACDxNnPtgFuludV1ZL3ayK1kVep42Rmm0+R9/Y60NQbZ2bifw==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.2.tgz", + "integrity": "sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg==", "dev": true }, "node_modules/normalize-path": { @@ -9123,6 +8746,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/on-exit-leak-free": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-0.2.0.tgz", + "integrity": "sha512-dqaz3u44QbRXQooZLTUKU41ZrzYrcvLISVgbrzbyCMxpmSLJvZ3ZamIJIZ29P6OhZIkNIQKosdeM6t1LYbA9hg==", + "dev": true + }, "node_modules/on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", @@ -9232,6 +8861,21 @@ "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, + "node_modules/os-locale/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/os-locale/node_modules/human-signals": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", @@ -9402,6 +9046,21 @@ "node": ">=8" } }, + "node_modules/package-json/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/package-json/node_modules/got": { "version": "9.6.0", "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", @@ -9556,15 +9215,6 @@ "node": ">=0.10.0" } }, - "node_modules/path-is-network-drive": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/path-is-network-drive/-/path-is-network-drive-1.0.10.tgz", - "integrity": "sha512-D6kJYPUSKGZBpTM2nv10sOWNdC056p4JDx0y7ARe6gop0aXXm5G86Gn/SyKvaf0Ce8c9Guctf+J+qoFmzuhDQg==", - "dev": true, - "dependencies": { - "tslib": "^2.3.1" - } - }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -9580,15 +9230,6 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, - "node_modules/path-strip-sep": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-strip-sep/-/path-strip-sep-1.0.7.tgz", - "integrity": "sha512-9xDVZPblHde4lTuTDnwqBKr9LTbPZW+Iae63ho500+BpEiZe3X6wvLInHgbB6FSMtwCTvztljw3k2zcNDNESzg==", - "dev": true, - "dependencies": { - "tslib": "^2.3.1" - } - }, "node_modules/path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", @@ -9618,9 +9259,9 @@ "dev": true }, "node_modules/picocolors": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", - "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", "dev": true }, "node_modules/picomatch": { @@ -9668,37 +9309,47 @@ } }, "node_modules/pino": { - "version": "6.13.3", - "resolved": "https://registry.npmjs.org/pino/-/pino-6.13.3.tgz", - "integrity": "sha512-tJy6qVgkh9MwNgqX1/oYi3ehfl2Y9H0uHyEEMsBe74KinESIjdMrMQDWpcZPpPicg3VV35d/GLQZmo4QgU2Xkg==", + "version": "7.9.1", + "resolved": "https://registry.npmjs.org/pino/-/pino-7.9.1.tgz", + "integrity": "sha512-28+D7c5orCoScdcWtiPXrCA9tdVosBWrYQgVtPdYTyiuTt6u/+rbEtpJR+dtVG8k1flhv0H2f0XSkgGm+TdjqQ==", "dev": true, "dependencies": { "fast-redact": "^3.0.0", - "fast-safe-stringify": "^2.0.8", - "fastify-warning": "^0.2.0", - "flatstr": "^1.0.12", - "pino-std-serializers": "^3.1.0", + "on-exit-leak-free": "^0.2.0", + "pino-abstract-transport": "v0.5.0", + "pino-std-serializers": "^4.0.0", + "process-warning": "^1.0.0", "quick-format-unescaped": "^4.0.3", - "sonic-boom": "^1.0.2" + "real-require": "^0.1.0", + "safe-stable-stringify": "^2.1.0", + "sonic-boom": "^2.2.1", + "thread-stream": "^0.13.0" }, "bin": { "pino": "bin.js" } }, + "node_modules/pino-abstract-transport": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-0.5.0.tgz", + "integrity": "sha512-+KAgmVeqXYbTtU2FScx1XS3kNyfZ5TrXY07V96QnUSFqo2gAqlvmaxH67Lj7SWazqsMabf+58ctdTcBgnOLUOQ==", + "dev": true, + "dependencies": { + "duplexify": "^4.1.2", + "split2": "^4.0.0" + } + }, "node_modules/pino-std-serializers": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-3.2.0.tgz", - "integrity": "sha512-EqX4pwDPrt3MuOAAUBMU0Tk5kR/YcCM5fNPEzgCO2zJ5HfX0vbiH9HbJglnyeQsN96Kznae6MWD47pZB5avTrg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-4.0.0.tgz", + "integrity": "sha512-cK0pekc1Kjy5w9V2/n+8MkZwusa6EyyxfeQCB799CQRhRt/CqYKiWs5adeu8Shve2ZNffvfC/7J64A2PJo1W/Q==", "dev": true }, "node_modules/pirates": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.1.tgz", - "integrity": "sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.4.tgz", + "integrity": "sha512-ZIrVPH+A52Dw84R0L3/VS9Op04PuQ2SEoJL6bkshmiTic/HldyW9Tf7oH5mhJZBK7NmDx27vSMrYEXPXclpDKw==", "dev": true, - "dependencies": { - "node-modules-regexp": "^1.0.0" - }, "engines": { "node": ">= 6" } @@ -9716,21 +9367,27 @@ } }, "node_modules/postcss": { - "version": "8.3.9", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.3.9.tgz", - "integrity": "sha512-f/ZFyAKh9Dnqytx5X62jgjhhzttjZS7hMsohcI7HEI5tjELX/HxCy3EFhsRxyzGvrzFF+82XPvCS8T9TFleVJw==", + "version": "8.4.12", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.12.tgz", + "integrity": "sha512-lg6eITwYe9v6Hr5CncVbK70SoioNQIq81nsaG86ev5hAidQvmOeETBqs7jm43K2F5/Ley3ytDtriImV6TpNiSg==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + } + ], "dependencies": { - "nanoid": "^3.1.28", - "picocolors": "^0.2.1", - "source-map-js": "^0.6.2" + "nanoid": "^3.3.1", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" }, "engines": { "node": "^10 || ^12 || >=14" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" } }, "node_modules/prelude-ls": { @@ -9752,24 +9409,26 @@ } }, "node_modules/prettier": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.4.1.tgz", - "integrity": "sha512-9fbDAXSBcc6Bs1mZrDYb3XKzDLm4EXXL9sC1LqKP5rZkT6KRr/rf9amVUcODVXgguK/isJz0d0hP72WeaKWsvA==", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.6.1.tgz", + "integrity": "sha512-8UVbTBYGwN37Bs9LERmxCPjdvPxlEowx2urIL6urHzdb3SDq4B/Z6xLFCblrSnE4iKWcS6ziJ3aOYrc1kz/E2A==", "dev": true, "bin": { "prettier": "bin-prettier.js" }, "engines": { "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" } }, "node_modules/pretty-format": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.3.1.tgz", - "integrity": "sha512-DR/c+pvFc52nLimLROYjnXPtolawm+uWDxr4FjuLDLUn+ktWnSN851KoHwHzzqq6rfCOjkzN8FLgDrSub6UDuA==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", "dev": true, "dependencies": { - "@jest/types": "^27.2.5", "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", "react-is": "^17.0.1" @@ -9796,6 +9455,12 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, + "node_modules/process-warning": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-1.0.0.tgz", + "integrity": "sha512-du4wfLyj4yCZq1VupnVSZmRsPJsNuxoDQFdCFHLaYiEbFBD7QE0a+I4D7hOxrVnh78QE/YipFAj9lXHiXocV+Q==", + "dev": true + }, "node_modules/progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", @@ -9805,6 +9470,18 @@ "node": ">=0.4.0" } }, + "node_modules/promise-toolbox": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/promise-toolbox/-/promise-toolbox-0.20.0.tgz", + "integrity": "sha512-VXF6waqUheD19yOU7zxsXhw/HCKlXqXwUc4jM8mchtBqZFNA+GHA7dbJsQDLHP4IUpQuTLpCQRd0lCr5z4CqXQ==", + "dev": true, + "dependencies": { + "make-error": "^1.3.2" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/prompts": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", @@ -9883,68 +9560,28 @@ } }, "node_modules/puppeteer-core": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-10.4.0.tgz", - "integrity": "sha512-KU8zyb7AIOqNjLCN3wkrFXxh+EVaG+zrs2P03ATNjc3iwSxHsu5/EvZiREpQ/IJiT9xfQbDVgKcsvRuzLCxglQ==", + "version": "13.5.1", + "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-13.5.1.tgz", + "integrity": "sha512-dobVqWjV34ilyfQHR3BBnCYaekBYTi5MgegEYBRYd3s3uFy8jUpZEEWbaFjG9ETm+LGzR5Lmr0aF6LLuHtiuCg==", "dev": true, "dependencies": { - "debug": "4.3.1", - "devtools-protocol": "0.0.901419", + "cross-fetch": "3.1.5", + "debug": "4.3.3", + "devtools-protocol": "0.0.969999", "extract-zip": "2.0.1", "https-proxy-agent": "5.0.0", - "node-fetch": "2.6.1", "pkg-dir": "4.2.0", - "progress": "2.0.1", + "progress": "2.0.3", "proxy-from-env": "1.1.0", "rimraf": "3.0.2", - "tar-fs": "2.0.0", - "unbzip2-stream": "1.3.3", - "ws": "7.4.6" + "tar-fs": "2.1.1", + "unbzip2-stream": "1.4.3", + "ws": "8.5.0" }, "engines": { "node": ">=10.18.1" } }, - "node_modules/puppeteer-core/node_modules/progress": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.1.tgz", - "integrity": "sha512-OE+a6vzqazc+K6LxJrX5UPyKFvGnL5CYmq2jFGNIBWHpc4QyE49/YOumcrpQFJpfejmvRtbJzgO1zPmMCqlbBg==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/puppeteer-core/node_modules/unbzip2-stream": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.3.3.tgz", - "integrity": "sha512-fUlAF7U9Ah1Q6EieQ4x4zLNejrRvDWUYmxXUpN3uziFYCHapjWFaCAnreY9bGgxzaMCFAPPpYNng57CypwJVhg==", - "dev": true, - "dependencies": { - "buffer": "^5.2.1", - "through": "^2.3.8" - } - }, - "node_modules/puppeteer-core/node_modules/ws": { - "version": "7.4.6", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", - "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", - "dev": true, - "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, "node_modules/qjobs": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz", @@ -9955,12 +9592,15 @@ } }, "node_modules/qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "version": "6.9.6", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.6.tgz", + "integrity": "sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ==", "dev": true, "engines": { "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/query-string": { @@ -10023,13 +9663,13 @@ } }, "node_modules/raw-body": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", - "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.2.tgz", + "integrity": "sha512-RPMAFUJP19WIet/99ngh6Iv8fzAbqum4Li7AD6DtGaW2RpMB/11xDoalPiJMTbu6I3hkbMVkATvZrqb9EEqeeQ==", "dev": true, "dependencies": { - "bytes": "3.1.0", - "http-errors": "1.7.2", + "bytes": "3.1.1", + "http-errors": "1.8.1", "iconv-lite": "0.4.24", "unpipe": "1.0.0" }, @@ -10099,6 +9739,15 @@ "node": ">=8.10.0" } }, + "node_modules/real-require": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.1.0.tgz", + "integrity": "sha512-r/H9MzAWtrv8aSVjPCMFpDMl5q66GqtmmRkRjpHTsp4zBAa+snZyiQNlMONiUmEJcsnaw0wCauJ2GWODr/aFkg==", + "dev": true, + "engines": { + "node": ">= 12.13.0" + } + }, "node_modules/regenerator-runtime": { "version": "0.13.7", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", @@ -10106,9 +9755,9 @@ "dev": true }, "node_modules/regexp.prototype.flags": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz", - "integrity": "sha512-JiBdRBq91WlY7uRJ0ds7R+dU02i6LKi8r3BuQhNXn+kmeLN+EfHhfjqMRis1zJxnlu88hq/4dx0P2OP3APRTOA==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.1.tgz", + "integrity": "sha512-pMR7hBVUUGI7PMA37m2ofIdQCsomVnas+Jn5UPGAHQ+/LlwKm/aTLJHdasmHRzlfeZwHiAOaRSo2rbBDm3nNUQ==", "dev": true, "dependencies": { "call-bind": "^1.0.2", @@ -10291,9 +9940,9 @@ } }, "node_modules/request/node_modules/qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", + "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", "dev": true, "engines": { "node": ">=0.6" @@ -10331,15 +9980,6 @@ "node": ">=0.10.0" } }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", @@ -10439,9 +10079,9 @@ } }, "node_modules/rollup": { - "version": "2.59.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.59.0.tgz", - "integrity": "sha512-l7s90JQhCQ6JyZjKgo7Lq1dKh2RxatOM+Jr6a9F7WbS9WgKbocyUSeLmZl8evAse7y96Ae98L2k1cBOwWD8nHw==", + "version": "2.70.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.70.1.tgz", + "integrity": "sha512-CRYsI5EuzLbXdxC6RnYhOuRdtz4bhejPMSWjsFLfVM/7w/85n2szZv6yExqUXsBdz5KT8eoubeyDUDjhLHEslA==", "dev": true, "bin": { "rollup": "dist/bin/rollup" @@ -10502,62 +10142,6 @@ "semver": "bin/semver.js" } }, - "node_modules/rollup-plugin-typescript2": { - "version": "0.31.1", - "resolved": "https://registry.npmjs.org/rollup-plugin-typescript2/-/rollup-plugin-typescript2-0.31.1.tgz", - "integrity": "sha512-sklqXuQwQX+stKi4kDfEkneVESPi3YM/2S899vfRdF9Yi40vcC50Oq4A4cSZJNXsAQE/UsBZl5fAOsBLziKmjw==", - "dev": true, - "dependencies": { - "@rollup/pluginutils": "^4.1.0", - "@yarn-tool/resolve-package": "^1.0.36", - "find-cache-dir": "^3.3.1", - "fs-extra": "8.1.0", - "resolve": "1.20.0", - "tslib": "2.2.0" - }, - "peerDependencies": { - "rollup": ">=1.26.3", - "typescript": ">=2.4.0" - } - }, - "node_modules/rollup-plugin-typescript2/node_modules/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/rollup-plugin-typescript2/node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "dev": true, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/rollup-plugin-typescript2/node_modules/tslib": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz", - "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==", - "dev": true - }, - "node_modules/rollup-plugin-typescript2/node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true, - "engines": { - "node": ">= 4.0.0" - } - }, "node_modules/rollup-pluginutils": { "version": "2.8.2", "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", @@ -10619,6 +10203,15 @@ "dev": true, "optional": true }, + "node_modules/safe-stable-stringify": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.3.1.tgz", + "integrity": "sha512-kYBSfT+troD9cDA85VDnHZ1rpHC50O0g1e6WlGHVCz/g+JS+9WKLj+XwFYyR8UbrZN8ll9HUpDAAddY58MGisg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -10694,9 +10287,9 @@ } }, "node_modules/send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", - "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "version": "0.17.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz", + "integrity": "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==", "dev": true, "peer": true, "dependencies": { @@ -10707,9 +10300,9 @@ "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "0.5.2", - "http-errors": "~1.7.2", + "http-errors": "1.8.1", "mime": "1.6.0", - "ms": "2.1.1", + "ms": "2.1.3", "on-finished": "~2.3.0", "range-parser": "~1.2.1", "statuses": "~1.5.0" @@ -10749,23 +10342,23 @@ } }, "node_modules/send/node_modules/ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true, "peer": true }, "node_modules/serve-static": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", - "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.2.tgz", + "integrity": "sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==", "dev": true, "peer": true, "dependencies": { "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.17.1" + "send": "0.17.2" }, "engines": { "node": ">= 0.8.0" @@ -10781,9 +10374,9 @@ } }, "node_modules/setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", "dev": true }, "node_modules/sha.js": { @@ -10821,16 +10414,10 @@ } }, "node_modules/shell-quote": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.6.1.tgz", - "integrity": "sha1-9HgZSczkAmlxJ0MOo7PFR29IF2c=", - "dev": true, - "dependencies": { - "array-filter": "~0.0.0", - "array-map": "~0.0.0", - "array-reduce": "~0.0.0", - "jsonify": "~0.0.0" - } + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz", + "integrity": "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==", + "dev": true }, "node_modules/shellwords": { "version": "0.1.1", @@ -10853,20 +10440,20 @@ } }, "node_modules/sign-addon": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/sign-addon/-/sign-addon-3.9.0.tgz", - "integrity": "sha512-a8IzM3jNPSHcf2wSkhLgME4QrIe+rKTb8y/qYwGGzby5ktODAH+WBsKIgGZ9p5d2mpppPwbNEsA+YzcL117bbA==", + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/sign-addon/-/sign-addon-3.11.0.tgz", + "integrity": "sha512-fcK2WzkMb8e8E9kvuccy+mrBTT81iR+1CowHLU594Elr4E9E9zZFr3itGlL0OoXcRouKmvt7rpXzoARu++tXRQ==", "dev": true, "dependencies": { - "common-tags": "1.8.0", - "core-js": "3.18.0", + "common-tags": "1.8.2", + "core-js": "3.21.0", "deepcopy": "2.1.0", "es6-error": "4.1.1", "es6-promisify": "7.0.0", "jsonwebtoken": "8.5.1", "mz": "2.7.0", "request": "2.88.2", - "source-map-support": "0.5.20", + "source-map-support": "0.5.21", "stream-to-promise": "3.0.0" } }, @@ -10891,34 +10478,17 @@ "node": ">=8" } }, - "node_modules/slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, "node_modules/socket.io": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.3.1.tgz", - "integrity": "sha512-HC5w5Olv2XZ0XJ4gOLGzzHEuOCfj3G0SmoW3jLHYYh34EVsIr3EkW9h6kgfW+K3TFEcmYy8JcPWe//KUkBp5jA==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.4.1.tgz", + "integrity": "sha512-s04vrBswdQBUmuWJuuNTmXUVJhP0cVky8bBDhdkf8y0Ptsu7fKU2LuLbts9g+pdmAdyMMn8F/9Mf1/wbtUN0fg==", "dev": true, "dependencies": { "accepts": "~1.3.4", "base64id": "~2.0.0", "debug": "~4.3.2", - "engine.io": "~6.0.0", - "socket.io-adapter": "~2.3.2", + "engine.io": "~6.1.0", + "socket.io-adapter": "~2.3.3", "socket.io-parser": "~4.0.4" }, "engines": { @@ -10926,9 +10496,9 @@ } }, "node_modules/socket.io-adapter": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.3.2.tgz", - "integrity": "sha512-PBZpxUPYjmoogY0aoaTmo1643JelsaS1CiAwNjRVdrI0X9Seuc19Y2Wife8k88avW6haG8cznvwbubAZwH4Mtg==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.3.3.tgz", + "integrity": "sha512-Qd/iwn3VskrpNO60BeRyCyr8ZWw9CPZyitW4AQwmRZ8zCiyDiL+znRnWX6tDHXnWn1sJrM1+b6Mn6wEDJJ4aYQ==", "dev": true }, "node_modules/socket.io-parser": { @@ -10945,31 +10515,13 @@ "node": ">=10.0.0" } }, - "node_modules/socket.io/node_modules/debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, "node_modules/sonic-boom": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-1.4.1.tgz", - "integrity": "sha512-LRHh/A8tpW7ru89lrlkU4AszXt1dbwSjVWguGrmlxE7tawVmDBlI1PILMkXAxJTwqhgsEeTHzj36D5CmHgQmNg==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-2.6.0.tgz", + "integrity": "sha512-6xYZFRmDEtxGqfOKcDQ4cPLrNa0SPEDI+wlzDAHowXE6YV42NeXqg9mP2KkiM8JVu3lHfZ2iQKYlGOz+kTpphg==", "dev": true, "dependencies": { - "atomic-sleep": "^1.0.0", - "flatstr": "^1.0.12" + "atomic-sleep": "^1.0.0" } }, "node_modules/sort-keys": { @@ -11021,18 +10573,18 @@ } }, "node_modules/source-map-js": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-0.6.2.tgz", - "integrity": "sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/source-map-support": { - "version": "0.5.20", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.20.tgz", - "integrity": "sha512-n1lZZ8Ve4ksRqizaBQgxXDgKwttHDhyfQjA6YZZn8+AroHbsIz+JjwxQDxbp+7y5OYCI8t1Yk7etjD9CRd2hIw==", + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, "dependencies": { "buffer-from": "^1.0.0", @@ -11068,6 +10620,15 @@ "node": "*" } }, + "node_modules/split2": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.1.0.tgz", + "integrity": "sha512-VBiJxFkxiXRlUIeyMQi8s4hgvKCSjtknJv/LVYbrgALPwf5zSKmEwV9Lst25AkvMDnvxODugjdl6KZgwKM1WYQ==", + "dev": true, + "engines": { + "node": ">= 10.x" + } + }, "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -11075,9 +10636,9 @@ "dev": true }, "node_modules/sshpk": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", + "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", "dev": true, "dependencies": { "asn1": "~0.2.3", @@ -11120,6 +10681,12 @@ "node": ">= 0.6" } }, + "node_modules/stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", + "dev": true + }, "node_modules/stream-to-array": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/stream-to-array/-/stream-to-array-2.3.0.tgz", @@ -11136,66 +10703,25 @@ "dev": true, "dependencies": { "any-promise": "~1.3.0", - "end-of-stream": "~1.4.1", - "stream-to-array": "~2.3.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/streamroller": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-2.2.4.tgz", - "integrity": "sha512-OG79qm3AujAM9ImoqgWEY1xG4HX+Lw+yY6qZj9R1K2mhF5bEmQ849wvrb+4vt4jLMLzwXttJlQbOdPOQVRv7DQ==", - "dev": true, - "dependencies": { - "date-format": "^2.1.0", - "debug": "^4.1.1", - "fs-extra": "^8.1.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/streamroller/node_modules/date-format": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/date-format/-/date-format-2.1.0.tgz", - "integrity": "sha512-bYQuGLeFxhkxNOF3rcMtiZxvCBAquGzZm6oWA1oZ0g2THUzivaRhv8uOhdr19LmoobSOLoIAxeUK2RdbM8IFTA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/streamroller/node_modules/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/streamroller/node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "dev": true, - "optionalDependencies": { - "graceful-fs": "^4.1.6" + "end-of-stream": "~1.4.1", + "stream-to-array": "~2.3.0" + }, + "engines": { + "node": ">= 10" } }, - "node_modules/streamroller/node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "node_modules/streamroller": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.0.2.tgz", + "integrity": "sha512-ur6y5S5dopOaRXBuRIZ1u6GC5bcEXHRZKgfBjfCglMhmIf+roVCECjvkEYzNQOXIN2/JPnkMPW/8B3CZoKaEPA==", "dev": true, + "dependencies": { + "date-format": "^4.0.3", + "debug": "^4.1.1", + "fs-extra": "^10.0.0" + }, "engines": { - "node": ">= 4.0.0" + "node": ">=8.0" } }, "node_modules/strict-uri-encode": { @@ -11421,67 +10947,16 @@ "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", "dev": true }, - "node_modules/table": { - "version": "6.7.2", - "resolved": "https://registry.npmjs.org/table/-/table-6.7.2.tgz", - "integrity": "sha512-UFZK67uvyNivLeQbVtkiUs8Uuuxv24aSL4/Vil2PJVtMgU8Lx0CYkP12uCGa3kjyQzOSgV1+z9Wkb82fCGsO0g==", - "dev": true, - "dependencies": { - "ajv": "^8.0.1", - "lodash.clonedeep": "^4.5.0", - "lodash.truncate": "^4.4.2", - "slice-ansi": "^4.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/table/node_modules/ajv": { - "version": "8.6.3", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.3.tgz", - "integrity": "sha512-SMJOdDP6LqTkD0Uq8qLi+gMwSt0imXLSV080qFVwJCpH9U6Mb+SUGHAXM0KNbcBPguytWyvFxcHgMLe2D2XSpw==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/table/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, "node_modules/tar-fs": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.0.0.tgz", - "integrity": "sha512-vaY0obB6Om/fso8a8vakQBzwholQ7v5+uy+tF3Ozvxv1KNezmVQAiWtcNmMHFSFPqL3dJA8ha6gdtFbfX9mcxA==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", "dev": true, "dependencies": { "chownr": "^1.1.1", - "mkdirp": "^0.5.1", + "mkdirp-classic": "^0.5.2", "pump": "^3.0.0", - "tar-stream": "^2.0.0" - } - }, - "node_modules/tar-fs/node_modules/mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "dependencies": { - "minimist": "^1.2.5" - }, - "bin": { - "mkdirp": "bin/cmd.js" + "tar-stream": "^2.1.4" } }, "node_modules/tar-stream": { @@ -11557,6 +11032,15 @@ "node": ">=0.8" } }, + "node_modules/thread-stream": { + "version": "0.13.2", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-0.13.2.tgz", + "integrity": "sha512-woZFt0cLFkPdhsa+IGpRo1jiSouaHxMIljzTgt30CMjBWoUYbbcHqnunW5Yv+BXko9H05MVIcxMipI3Jblallw==", + "dev": true, + "dependencies": { + "real-require": "^0.1.0" + } + }, "node_modules/throat": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.1.tgz", @@ -11635,9 +11119,9 @@ } }, "node_modules/toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", "dev": true, "engines": { "node": ">=0.6" @@ -11711,9 +11195,9 @@ } }, "node_modules/ts-jest": { - "version": "27.0.7", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-27.0.7.tgz", - "integrity": "sha512-O41shibMqzdafpuP+CkrOL7ykbmLh+FqQrXEmV9CydQ5JBk0Sj0uAEF5TNNe94fZWKm3yYvWa/IbyV4Yg1zK2Q==", + "version": "27.1.4", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-27.1.4.tgz", + "integrity": "sha512-qjkZlVPWVctAezwsOD1OPzbZ+k7zA5z3oxII4dGdZo5ggX/PL7kvwTM0pXTr10fAtbiVpJaL3bWd502zAhpgSQ==", "dev": true, "dependencies": { "bs-logger": "0.x", @@ -11747,85 +11231,16 @@ }, "babel-jest": { "optional": true - } - } - }, - "node_modules/ts-node": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.4.0.tgz", - "integrity": "sha512-g0FlPvvCXSIO1JDF6S232P5jPYqBkRL9qly81ZgAOSU7rwI0stphCgd2kLiCrU9DjQCrJMWEqcNSjQL02s6d8A==", - "dev": true, - "dependencies": { - "@cspotcode/source-map-support": "0.7.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "yn": "3.1.1" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" - }, - "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true }, - "@swc/wasm": { + "esbuild": { "optional": true } } }, - "node_modules/ts-node/node_modules/acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/ts-toolbelt": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/ts-toolbelt/-/ts-toolbelt-8.4.0.tgz", - "integrity": "sha512-hnGJXIgC49ZuF5g5oDthoge8t4cvT0dYg2pYO5C6yV/HmUUy1koooU2U/5K2N+Uw++hcXQpJAToLRa+GRp28Sg==", - "dev": true, - "peer": true - }, - "node_modules/ts-type": { - "version": "1.2.40", - "resolved": "https://registry.npmjs.org/ts-type/-/ts-type-1.2.40.tgz", - "integrity": "sha512-Ux5e7Frys5pX7w8gYchEd0KfhG1H5puXOQC8yOBgMJ1aEwDSypeHLwxIUpKjecni1IGwtLI3JrxCVZaQO9JKmw==", - "dev": true, - "dependencies": { - "tslib": "^2.3.0", - "typedarray-dts": "^1.0.0" - }, - "peerDependencies": { - "@types/bluebird": "*", - "@types/node": "*", - "ts-toolbelt": "^8.0.7" - } - }, "node_modules/tsconfig-paths": { - "version": "3.11.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.11.0.tgz", - "integrity": "sha512-7ecdYDnIdmv639mmDwslG6KQg1Z9STTz1j7Gcz0xa+nshh/gKDAHcPxRbWOsA3SPp0tXP2leTcY9Kw+NAkfZzA==", + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.12.0.tgz", + "integrity": "sha512-e5adrnOYT6zqVnWqZu7i/BQ3BnhzvGbjEjejFXO20lKIKpwTaupkCPgEfv4GZK1IBciJUEhYs3J3p75FdaTFVg==", "dev": true, "dependencies": { "@types/json5": "^0.0.29", @@ -11952,12 +11367,6 @@ "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", "dev": true }, - "node_modules/typedarray-dts": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typedarray-dts/-/typedarray-dts-1.0.0.tgz", - "integrity": "sha512-Ka0DBegjuV9IPYFT1h0Qqk5U4pccebNIJCGl8C5uU7xtOs+jpJvKGAY4fHGK25hTmXZOEUl9Cnsg5cS6K/b5DA==", - "dev": true - }, "node_modules/typedarray-to-buffer": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", @@ -11968,9 +11377,9 @@ } }, "node_modules/typescript": { - "version": "4.4.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.4.tgz", - "integrity": "sha512-DqGhF5IKoBl8WNf8C1gu8q0xZSInh9j1kJJMqT3a94w1JzVaBU4EXOSMrz9yDqMT0xt3selp83fuFMQ0uzv6qA==", + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz", + "integrity": "sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -12019,7 +11428,6 @@ "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", "dev": true, - "peer": true, "dependencies": { "buffer": "^5.2.1", "through": "^2.3.8" @@ -12065,21 +11473,6 @@ "yarn": "*" } }, - "node_modules/upath2": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/upath2/-/upath2-3.1.10.tgz", - "integrity": "sha512-7ph3GzTaVbQX+oIoMsGtM+9BAWQr+6Mn28TJKPu28+yGpZ+J4am590CPDBlDG0zyuo9T9T7o21ciqNzwIp/q0A==", - "dev": true, - "dependencies": { - "lodash": "^4.17.21", - "path-is-network-drive": "^1.0.10", - "path-strip-sep": "^1.0.7", - "tslib": "^2.3.1" - }, - "peerDependencies": { - "@types/node": "*" - } - }, "node_modules/update-notifier": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-5.1.0.tgz", @@ -12170,9 +11563,9 @@ "dev": true }, "node_modules/v8-to-istanbul": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.0.tgz", - "integrity": "sha512-/PRhfd8aTNp9Ggr62HPzXg2XasNFGy5PBt0Rp04du7/8GNNSgxFL6WBTkgMKSL9bFjH+8kKEG3f37FmxiTqUUA==", + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz", + "integrity": "sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w==", "dev": true, "dependencies": { "@types/istanbul-lib-coverage": "^2.0.1", @@ -12277,24 +11670,23 @@ } }, "node_modules/web-ext": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/web-ext/-/web-ext-6.5.0.tgz", - "integrity": "sha512-71DE73YkxKEyiy1O5Ei5Uy1ZCT0tOPriPWIkH3g+mpnd52Gr1u2buexpq2upATekhc1Mu87d9EmRqXg2Kqhszw==", + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/web-ext/-/web-ext-6.8.0.tgz", + "integrity": "sha512-qZ3a4YVs0Vdqet44QRZEcNUQznkrfhsAkSOnZp57O4T4A9Bo3pamePSBeRqdPdJv9GF8ntKG84o3eV0MrEvLbw==", "dev": true, "dependencies": { "@babel/runtime": "7.13.9", "@devicefarmer/adbkit": "2.11.3", - "addons-linter": "3.20.0", + "addons-linter": "4.14.0", "bunyan": "1.8.15", "camelcase": "6.2.0", - "chrome-launcher": "0.14.0", + "chrome-launcher": "0.15.0", "debounce": "1.2.0", "decamelize": "5.0.0", "es6-error": "4.1.1", - "event-to-promise": "0.8.0", - "firefox-profile": "4.2.1", + "firefox-profile": "4.2.2", "fs-extra": "9.1.0", - "fx-runner": "1.1.0", + "fx-runner": "1.2.0", "import-fresh": "3.3.0", "mkdirp": "1.0.4", "multimatch": "5.0.0", @@ -12302,7 +11694,8 @@ "node-notifier": "9.0.0", "open": "7.4.2", "parse-json": "5.2.0", - "sign-addon": "3.9.0", + "promise-toolbox": "0.20.0", + "sign-addon": "3.11.0", "source-map-support": "0.5.20", "strip-bom": "4.0.0", "strip-json-comments": "3.1.1", @@ -12368,6 +11761,16 @@ "which": "^2.0.2" } }, + "node_modules/web-ext/node_modules/source-map-support": { + "version": "0.5.20", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.20.tgz", + "integrity": "sha512-n1lZZ8Ve4ksRqizaBQgxXDgKwttHDhyfQjA6YZZn8+AroHbsIz+JjwxQDxbp+7y5OYCI8t1Yk7etjD9CRd2hIw==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, "node_modules/web-ext/node_modules/ws": { "version": "7.4.6", "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", @@ -12527,9 +11930,9 @@ } }, "node_modules/ws": { - "version": "8.2.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", - "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", + "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", "dev": true, "engines": { "node": ">=10.0.0" @@ -12661,15 +12064,6 @@ "buffer-crc32": "~0.2.3" } }, - "node_modules/yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", @@ -12855,9 +12249,9 @@ } }, "@babel/helper-plugin-utils": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz", - "integrity": "sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz", + "integrity": "sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA==", "dev": true }, "@babel/helper-replace-supers": { @@ -13097,12 +12491,12 @@ } }, "@babel/plugin-syntax-typescript": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.16.0.tgz", - "integrity": "sha512-Xv6mEXqVdaqCBfJFyeab0fH2DnUoMsDmhamxsSi4j8nLd4Vtw213WMJr55xxqipC/YVWyPY3K0blJncPYji+dQ==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.16.7.tgz", + "integrity": "sha512-YhUIJHHGkqPgEcMYkPCKTyGUdoGKWtopIycQyjJH8OjvRgOYsXsaKehLVPScKJWAULPxMa4N1vCe6szREFlZ7A==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.7" } }, "@babel/runtime": { @@ -13165,21 +12559,12 @@ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true }, - "@cspotcode/source-map-consumer": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz", - "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==", + "@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", "dev": true }, - "@cspotcode/source-map-support": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz", - "integrity": "sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==", - "dev": true, - "requires": { - "@cspotcode/source-map-consumer": "0.8.0" - } - }, "@devicefarmer/adbkit": { "version": "2.11.3", "resolved": "https://registry.npmjs.org/@devicefarmer/adbkit/-/adbkit-2.11.3.tgz", @@ -13228,67 +12613,37 @@ } }, "@eslint/eslintrc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.0.3.tgz", - "integrity": "sha512-DHI1wDPoKCBPoLZA3qDR91+3te/wDSc1YhKg3jR8NxKKRJq2hwHwcWv31cSwSYvIBrmbENoYMWcenW8uproQqg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.1.tgz", + "integrity": "sha512-bxvbYnBPN1Gibwyp6NrpnFzA3YtRL3BBAyEAFVIpNTm2Rn4Vy87GA5M4aSn3InRrlsbX5N0GW7XIx+U4SAEKdQ==", "dev": true, "requires": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.0.0", + "espree": "^9.3.1", "globals": "^13.9.0", - "ignore": "^4.0.6", + "ignore": "^5.2.0", "import-fresh": "^3.2.1", - "js-yaml": "^3.13.1", + "js-yaml": "^4.1.0", "minimatch": "^3.0.4", "strip-json-comments": "^3.1.1" - }, - "dependencies": { - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - } } }, "@humanwhocodes/config-array": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.6.0.tgz", - "integrity": "sha512-JQlEKbcgEUjBFhLIF4iqM7u/9lwgHRBcpHrmUNCALK0Q3amXN6lxdoXLnF0sm11E9VqTmBALR87IlUg1bZ8A9A==", + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.2.tgz", + "integrity": "sha512-UXOuFCGcwciWckOpmfKDq/GyhlTf9pN/BzG//x8p8zTOFEcGuA68ANXheFS0AGvy3qgZqLBUkMs7hqzqCKOVwA==", "dev": true, "requires": { - "@humanwhocodes/object-schema": "^1.2.0", + "@humanwhocodes/object-schema": "^1.2.1", "debug": "^4.1.1", "minimatch": "^3.0.4" } }, "@humanwhocodes/object-schema": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.0.tgz", - "integrity": "sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true }, "@istanbuljs/load-nyc-config": { @@ -13338,49 +12693,49 @@ "dev": true }, "@jest/console": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-27.3.1.tgz", - "integrity": "sha512-RkFNWmv0iui+qsOr/29q9dyfKTTT5DCuP31kUwg7rmOKPT/ozLeGLKJKVIiOfbiKyleUZKIrHwhmiZWVe8IMdw==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-27.5.1.tgz", + "integrity": "sha512-kZ/tNpS3NXn0mlXXXPNuDZnb4c0oZ20r4K5eemM2k30ZC3G0T02nXUvyhf5YdbXWHPEJLc9qGLxEZ216MdL+Zg==", "dev": true, "requires": { - "@jest/types": "^27.2.5", + "@jest/types": "^27.5.1", "@types/node": "*", "chalk": "^4.0.0", - "jest-message-util": "^27.3.1", - "jest-util": "^27.3.1", + "jest-message-util": "^27.5.1", + "jest-util": "^27.5.1", "slash": "^3.0.0" } }, "@jest/core": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-27.3.1.tgz", - "integrity": "sha512-DMNE90RR5QKx0EA+wqe3/TNEwiRpOkhshKNxtLxd4rt3IZpCt+RSL+FoJsGeblRZmqdK4upHA/mKKGPPRAifhg==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-27.5.1.tgz", + "integrity": "sha512-AK6/UTrvQD0Cd24NSqmIA6rKsu0tKIxfiCducZvqxYdmMisOYAsdItspT+fQDQYARPf8XgjAFZi0ogW2agH5nQ==", "dev": true, "requires": { - "@jest/console": "^27.3.1", - "@jest/reporters": "^27.3.1", - "@jest/test-result": "^27.3.1", - "@jest/transform": "^27.3.1", - "@jest/types": "^27.2.5", + "@jest/console": "^27.5.1", + "@jest/reporters": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "emittery": "^0.8.1", "exit": "^0.1.2", - "graceful-fs": "^4.2.4", - "jest-changed-files": "^27.3.0", - "jest-config": "^27.3.1", - "jest-haste-map": "^27.3.1", - "jest-message-util": "^27.3.1", - "jest-regex-util": "^27.0.6", - "jest-resolve": "^27.3.1", - "jest-resolve-dependencies": "^27.3.1", - "jest-runner": "^27.3.1", - "jest-runtime": "^27.3.1", - "jest-snapshot": "^27.3.1", - "jest-util": "^27.3.1", - "jest-validate": "^27.3.1", - "jest-watcher": "^27.3.1", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^27.5.1", + "jest-config": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-resolve-dependencies": "^27.5.1", + "jest-runner": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "jest-watcher": "^27.5.1", "micromatch": "^4.0.4", "rimraf": "^3.0.0", "slash": "^3.0.0", @@ -13388,68 +12743,68 @@ } }, "@jest/environment": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.3.1.tgz", - "integrity": "sha512-BCKCj4mOVLme6Tanoyc9k0ultp3pnmuyHw73UHRPeeZxirsU/7E3HC4le/VDb/SMzE1JcPnto+XBKFOcoiJzVw==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.5.1.tgz", + "integrity": "sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA==", "dev": true, "requires": { - "@jest/fake-timers": "^27.3.1", - "@jest/types": "^27.2.5", + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", "@types/node": "*", - "jest-mock": "^27.3.0" + "jest-mock": "^27.5.1" } }, "@jest/fake-timers": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.3.1.tgz", - "integrity": "sha512-M3ZFgwwlqJtWZ+QkBG5NmC23A9w+A6ZxNsO5nJxJsKYt4yguBd3i8TpjQz5NfCX91nEve1KqD9RA2Q+Q1uWqoA==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.5.1.tgz", + "integrity": "sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ==", "dev": true, "requires": { - "@jest/types": "^27.2.5", + "@jest/types": "^27.5.1", "@sinonjs/fake-timers": "^8.0.1", "@types/node": "*", - "jest-message-util": "^27.3.1", - "jest-mock": "^27.3.0", - "jest-util": "^27.3.1" + "jest-message-util": "^27.5.1", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1" } }, "@jest/globals": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-27.3.1.tgz", - "integrity": "sha512-Q651FWiWQAIFiN+zS51xqhdZ8g9b88nGCobC87argAxA7nMfNQq0Q0i9zTfQYgLa6qFXk2cGANEqfK051CZ8Pg==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-27.5.1.tgz", + "integrity": "sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q==", "dev": true, "requires": { - "@jest/environment": "^27.3.1", - "@jest/types": "^27.2.5", - "expect": "^27.3.1" + "@jest/environment": "^27.5.1", + "@jest/types": "^27.5.1", + "expect": "^27.5.1" } }, "@jest/reporters": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-27.3.1.tgz", - "integrity": "sha512-m2YxPmL9Qn1emFVgZGEiMwDntDxRRQ2D58tiDQlwYTg5GvbFOKseYCcHtn0WsI8CG4vzPglo3nqbOiT8ySBT/w==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-27.5.1.tgz", + "integrity": "sha512-cPXh9hWIlVJMQkVk84aIvXuBB4uQQmFqZiacloFuGiP3ah1sbCxCosidXFDfqG8+6fO1oR2dTJTlsOy4VFmUfw==", "dev": true, "requires": { "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^27.3.1", - "@jest/test-result": "^27.3.1", - "@jest/transform": "^27.3.1", - "@jest/types": "^27.2.5", + "@jest/console": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", "@types/node": "*", "chalk": "^4.0.0", "collect-v8-coverage": "^1.0.0", "exit": "^0.1.2", "glob": "^7.1.2", - "graceful-fs": "^4.2.4", + "graceful-fs": "^4.2.9", "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^4.0.3", + "istanbul-lib-instrument": "^5.1.0", "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.0.2", - "jest-haste-map": "^27.3.1", - "jest-resolve": "^27.3.1", - "jest-util": "^27.3.1", - "jest-worker": "^27.3.1", + "istanbul-reports": "^3.1.3", + "jest-haste-map": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", "slash": "^3.0.0", "source-map": "^0.6.0", "string-length": "^4.0.1", @@ -13458,67 +12813,67 @@ } }, "@jest/source-map": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-27.0.6.tgz", - "integrity": "sha512-Fek4mi5KQrqmlY07T23JRi0e7Z9bXTOOD86V/uS0EIW4PClvPDqZOyFlLpNJheS6QI0FNX1CgmPjtJ4EA/2M+g==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-27.5.1.tgz", + "integrity": "sha512-y9NIHUYF3PJRlHk98NdC/N1gl88BL08aQQgu4k4ZopQkCw9t9cV8mtl3TV8b/YCB8XaVTFrmUTAJvjsntDireg==", "dev": true, "requires": { "callsites": "^3.0.0", - "graceful-fs": "^4.2.4", + "graceful-fs": "^4.2.9", "source-map": "^0.6.0" } }, "@jest/test-result": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.3.1.tgz", - "integrity": "sha512-mLn6Thm+w2yl0opM8J/QnPTqrfS4FoXsXF2WIWJb2O/GBSyResL71BRuMYbYRsGt7ELwS5JGcEcGb52BNrumgg==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.5.1.tgz", + "integrity": "sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag==", "dev": true, "requires": { - "@jest/console": "^27.3.1", - "@jest/types": "^27.2.5", + "@jest/console": "^27.5.1", + "@jest/types": "^27.5.1", "@types/istanbul-lib-coverage": "^2.0.0", "collect-v8-coverage": "^1.0.0" } }, "@jest/test-sequencer": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-27.3.1.tgz", - "integrity": "sha512-siySLo07IMEdSjA4fqEnxfIX8lB/lWYsBPwNFtkOvsFQvmBrL3yj3k3uFNZv/JDyApTakRpxbKLJ3CT8UGVCrA==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-27.5.1.tgz", + "integrity": "sha512-LCheJF7WB2+9JuCS7VB/EmGIdQuhtqjRNI9A43idHv3E4KltCTsPsLxvdaubFHSYwY/fNjMWjl6vNRhDiN7vpQ==", "dev": true, "requires": { - "@jest/test-result": "^27.3.1", - "graceful-fs": "^4.2.4", - "jest-haste-map": "^27.3.1", - "jest-runtime": "^27.3.1" + "@jest/test-result": "^27.5.1", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-runtime": "^27.5.1" } }, "@jest/transform": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.3.1.tgz", - "integrity": "sha512-3fSvQ02kuvjOI1C1ssqMVBKJpZf6nwoCiSu00zAKh5nrp3SptNtZy/8s5deayHnqxhjD9CWDJ+yqQwuQ0ZafXQ==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.5.1.tgz", + "integrity": "sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==", "dev": true, "requires": { "@babel/core": "^7.1.0", - "@jest/types": "^27.2.5", - "babel-plugin-istanbul": "^6.0.0", + "@jest/types": "^27.5.1", + "babel-plugin-istanbul": "^6.1.1", "chalk": "^4.0.0", "convert-source-map": "^1.4.0", "fast-json-stable-stringify": "^2.0.0", - "graceful-fs": "^4.2.4", - "jest-haste-map": "^27.3.1", - "jest-regex-util": "^27.0.6", - "jest-util": "^27.3.1", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-util": "^27.5.1", "micromatch": "^4.0.4", - "pirates": "^4.0.1", + "pirates": "^4.0.4", "slash": "^3.0.0", "source-map": "^0.6.1", "write-file-atomic": "^3.0.0" } }, "@jest/types": { - "version": "27.2.5", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.2.5.tgz", - "integrity": "sha512-nmuM4VuDtCZcY+eTpw+0nvstwReMsjPoj7ZR80/BbixulhLaiX+fbv8oeLW8WZlJMcsGQsTmMKT/iTZu1Uy/lQ==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", "dev": true, "requires": { "@types/istanbul-lib-coverage": "^2.0.0", @@ -13529,9 +12884,9 @@ } }, "@mdn/browser-compat-data": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-4.0.5.tgz", - "integrity": "sha512-KPSNaHUl5aikqsQU7LpBntFzaPbhm5OJxD88Wv00OKDc4wudyid2wDFqLeb7VcYT9x5bND8PPFloWdK5DY0pHA==", + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-4.1.12.tgz", + "integrity": "sha512-y3Ntio6hb5+m6asxcA3nnIN6URjAFMji2EZZVYGd2Ag5On4mmvPhMnXdiIScCMXgHjFX+5qXuKaojLLhJHZPAg==", "dev": true }, "@nodelib/fs.scandir": { @@ -13561,9 +12916,9 @@ } }, "@rollup/plugin-node-resolve": { - "version": "13.0.6", - "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-13.0.6.tgz", - "integrity": "sha512-sFsPDMPd4gMqnh2gS0uIxELnoRUp5kBl5knxD2EO0778G1oOJv4G1vyT2cpWz75OU2jDVcXhjVUuTAczGyFNKA==", + "version": "13.1.3", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-13.1.3.tgz", + "integrity": "sha512-BdxNk+LtmElRo5d06MGY4zoepyrXX1tkzX2hrnPEZ53k78GuOMWLqmJDGIIOPwVRIFZrLQOo+Yr6KtCuLIA0AQ==", "dev": true, "requires": { "@rollup/pluginutils": "^3.1.0", @@ -13594,9 +12949,9 @@ } }, "@rollup/plugin-replace": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-3.0.0.tgz", - "integrity": "sha512-3c7JCbMuYXM4PbPWT4+m/4Y6U60SgsnDT/cCyAyUKwFHg7pTSfsSQzIpETha3a3ig6OdOKzZz87D9ZXIK3qsDg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-4.0.0.tgz", + "integrity": "sha512-+rumQFiaNac9y64OHtkHGmdjm7us9bo1PlbgQfdihQtuNxzjpaB064HbRnewUOggLQxVCCyINfStkgmBeQpv1g==", "dev": true, "requires": { "@rollup/pluginutils": "^3.1.0", @@ -13622,10 +12977,39 @@ } } }, + "@rollup/plugin-typescript": { + "version": "8.3.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-8.3.1.tgz", + "integrity": "sha512-84rExe3ICUBXzqNX48WZV2Jp3OddjTMX97O2Py6D1KJaGSwWp0mDHXj+bCGNJqWHIEKDIT2U0sDjhP4czKi6cA==", + "dev": true, + "requires": { + "@rollup/pluginutils": "^3.1.0", + "resolve": "^1.17.0" + }, + "dependencies": { + "@rollup/pluginutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", + "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", + "dev": true, + "requires": { + "@types/estree": "0.0.39", + "estree-walker": "^1.0.1", + "picomatch": "^2.2.2" + } + }, + "estree-walker": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", + "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", + "dev": true + } + } + }, "@rollup/pluginutils": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.1.1.tgz", - "integrity": "sha512-clDjivHqWGXi7u+0d2r2sBi4Ie6VLEAzWMIkvJLnDmxoOhBYOTfzGbOQBA32THHm11/LiJbd01tJUpJsbshSWQ==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.0.tgz", + "integrity": "sha512-2WUyJNRkyH5p487pGnn4tWAsxhEFKN/pT8CMgHshd5H+IXkOnKvKZwsz5ZWz+YCXkleZRAU5kwbfgF8CPfDRqA==", "dev": true, "requires": { "estree-walker": "^2.0.1", @@ -13649,14 +13033,20 @@ } }, "@sinonjs/fake-timers": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-8.0.1.tgz", - "integrity": "sha512-AU7kwFxreVd6OAXcAFlKSmZquiRUU0FvYm44k1Y1QbK7Co4m0aqfGMhjykIeQp/H6rcl+nFmj0zfdUcGVs9Dew==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz", + "integrity": "sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==", "dev": true, "requires": { "@sinonjs/commons": "^1.7.0" } }, + "@socket.io/base64-arraybuffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@socket.io/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", + "integrity": "sha512-dOlCBKnDw4iShaIsH/bxujKTM18+2TOAsYz+KSc11Am38H4q5Xw8Bbz97ZYdrVNM+um3p7w86Bvvmcn9q+5+eQ==", + "dev": true + }, "@szmarczak/http-timer": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", @@ -13672,44 +13062,10 @@ "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", "dev": true }, - "@ts-type/package-dts": { - "version": "1.0.53", - "resolved": "https://registry.npmjs.org/@ts-type/package-dts/-/package-dts-1.0.53.tgz", - "integrity": "sha512-P8bMcjqaUsaBbXOCxBtzT4/pvhQSHTMc91WrpErVfB52zpNRVw2evOYWMe6q3c087+wpvITB7HtppYDnQe1RwA==", - "dev": true, - "requires": { - "@types/semver": "^7.3.9", - "ts-type": "^1.2.40" - } - }, - "@tsconfig/node10": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz", - "integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==", - "dev": true - }, - "@tsconfig/node12": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz", - "integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==", - "dev": true - }, - "@tsconfig/node14": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz", - "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==", - "dev": true - }, - "@tsconfig/node16": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz", - "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==", - "dev": true - }, "@types/babel__core": { - "version": "7.1.16", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.16.tgz", - "integrity": "sha512-EAEHtisTMM+KaKwfWdC3oyllIqswlznXCIVCt7/oRNrh+DhgT4UEBNC/jlADNjvw7UnfbcdkGQcPVZ1xYiLcrQ==", + "version": "7.1.18", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.18.tgz", + "integrity": "sha512-S7unDjm/C7z2A2R9NzfKCK1I+BAALDtxEmsJBwlB3EzNfb929ykjL++1CK9LO++EIp2fQrC8O+BwjKvz6UeDyQ==", "dev": true, "requires": { "@babel/parser": "^7.1.0", @@ -13720,9 +13076,9 @@ } }, "@types/babel__generator": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.3.tgz", - "integrity": "sha512-/GWCmzJWqV7diQW54smJZzWbSFf4QYtF71WCKhcx6Ru/tFyQIY2eiiITcCAeuPbNSvT9YCGkVMqqvSk2Z0mXiA==", + "version": "7.6.4", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", + "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", "dev": true, "requires": { "@babel/types": "^7.0.0" @@ -13747,17 +13103,10 @@ "@babel/types": "^7.3.0" } }, - "@types/bluebird": { - "version": "3.5.36", - "resolved": "https://registry.npmjs.org/@types/bluebird/-/bluebird-3.5.36.tgz", - "integrity": "sha512-HBNx4lhkxN7bx6P0++W8E289foSu8kO8GCk2unhuVggO+cE7rh9DhZUyPhUxNRG9m+5B5BTKxZQ5ZP92x/mx9Q==", - "dev": true, - "peer": true - }, "@types/chrome": { - "version": "0.0.162", - "resolved": "https://registry.npmjs.org/@types/chrome/-/chrome-0.0.162.tgz", - "integrity": "sha512-DiMo9SrOhkb49bXPRke41Nvd9rgDgxn/mqyZ5gQnU+ST3H/vcnnvtwCkpuUl7O9FwoUwECfMSZiBTXuK8sMSwQ==", + "version": "0.0.180", + "resolved": "https://registry.npmjs.org/@types/chrome/-/chrome-0.0.180.tgz", + "integrity": "sha512-A/CuuKAaHq2CHEpYBAtl0lp2ib7TTXK7VjJI4q+c+1U/HDvZLJ8IlsdEDzzHdvkNdh36bGONxrMnO9YZrKqbAw==", "dev": true, "requires": { "@types/filesystem": "*", @@ -13804,6 +13153,16 @@ "@types/node": "*" } }, + "@types/eslint": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.1.tgz", + "integrity": "sha512-GE44+DNEyxxh2Kc6ro/VkIj+9ma0pO0bwv9+uHSyBrikYOHr8zYcdPvnBOp1aw8s+CjRvuSx7CyWqRrNFQ59mA==", + "dev": true, + "requires": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, "@types/estree": { "version": "0.0.39", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", @@ -13811,9 +13170,9 @@ "dev": true }, "@types/filesystem": { - "version": "0.0.30", - "resolved": "https://registry.npmjs.org/@types/filesystem/-/filesystem-0.0.30.tgz", - "integrity": "sha512-NCoRgmGmLpTT9VFL6Bb6z0jQuqI3d0E5FGl7M0JOv/J5RQYo9s5aOItPYnpckx9MbYQk1APLXcF8f20Vqnf2yA==", + "version": "0.0.32", + "resolved": "https://registry.npmjs.org/@types/filesystem/-/filesystem-0.0.32.tgz", + "integrity": "sha512-Yuf4jR5YYMR2DVgwuCiP11s0xuVRyPKmz8vo6HBY3CGdeMj8af93CFZX+T82+VD1+UqHOxTq31lO7MI7lepBtQ==", "dev": true, "requires": { "@types/filewriter": "*" @@ -13850,6 +13209,12 @@ "integrity": "sha512-IG8AE1m2pWtPqQ7wXhFhy6Q59bwwnLwO36v5Rit2FrbXCIp8Sk8E2PfUCreyrdo17STwFSKDAkitVuVYbpEHvQ==", "dev": true }, + "@types/istanbul": { + "version": "0.4.30", + "resolved": "https://registry.npmjs.org/@types/istanbul/-/istanbul-0.4.30.tgz", + "integrity": "sha512-+hQU4fh2G96ze78uI5/V6+SRDZD1UnVrFn23i2eDetwfbBq3s0/zYP92xj/3qyvVMM3WnvS88N56zjz+HmL04A==", + "dev": true + }, "@types/istanbul-lib-coverage": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz", @@ -13875,18 +13240,18 @@ } }, "@types/jasmine": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-3.10.1.tgz", - "integrity": "sha512-So26woGjM6F9b2julbJlXdcPdyhwteZzEX2EbFmreuJBamPVVdp6w4djywUG9TmcwjiC+ECAe+RSSBgYEOgEqQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-4.0.0.tgz", + "integrity": "sha512-KvhqNz4NaONk7cfp4E9x+uXOUp7x4H2Zeyb4yXnw2vIuxD5YfSi1767x+aF7z54elhZcC0OH9/78/WL6+5jcDg==", "dev": true }, "@types/jest": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-27.0.2.tgz", - "integrity": "sha512-4dRxkS/AFX0c5XW6IPMNOydLn2tEhNhJV7DnYK+0bjoJZ+QTmfucBlihX7aoEsh/ocYtkLC73UbnBXBXIxsULA==", + "version": "27.4.1", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-27.4.1.tgz", + "integrity": "sha512-23iPJADSmicDVrWk+HT58LMJtzLAnB2AgIzplQuq/bSrGaxCrlvRFjGbXmamnnk/mAmCdLStiGqggu28ocUyiw==", "dev": true, "requires": { - "jest-diff": "^27.0.0", + "jest-matcher-utils": "^27.0.0", "pretty-format": "^27.0.0" } }, @@ -13903,13 +13268,23 @@ "dev": true }, "@types/karma": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/@types/karma/-/karma-6.3.1.tgz", - "integrity": "sha512-t7hSJ8oWrgzrJV0nBqqMrDnQFft/W3WCPOfSi2aOq7rUPARLC8XpZfbsQ+mfYaNk18v1XqkBU12uirp1ISJVAA==", + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/@types/karma/-/karma-6.3.3.tgz", + "integrity": "sha512-nRMec4mTCt+tkpRqh5/pAxmnjzEgAaalIq7mdfLFH88gSRC8+bxejLiSjHMMT/vHIhJHqg4GPIGCnCFbwvDRww==", "dev": true, "requires": { "@types/node": "*", - "log4js": "^6.2.1" + "log4js": "^6.4.1" + } + }, + "@types/karma-coverage": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/karma-coverage/-/karma-coverage-2.0.1.tgz", + "integrity": "sha512-A5aJSn2IVJAy6XJl3zC8xAk78pqcj1dSAc9s0QPj3jnsmEpK5cGKmCTVVD7CYX8iEFk0C+IuSiS5YPVbacreSg==", + "dev": true, + "requires": { + "@types/istanbul": "*", + "@types/karma": "*" } }, "@types/minimatch": { @@ -13919,9 +13294,9 @@ "dev": true }, "@types/node": { - "version": "16.11.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.6.tgz", - "integrity": "sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w==", + "version": "17.0.23", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.23.tgz", + "integrity": "sha512-UxDxWn7dl97rKVeVS61vErvw086aCYhDLyvRQZ5Rk65rZKepaFdm53GeqXaKBuOhED4e9uWq34IC3TdSdJJ2Gw==", "dev": true }, "@types/offscreencanvas": { @@ -13931,9 +13306,9 @@ "dev": true }, "@types/prettier": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.4.1.tgz", - "integrity": "sha512-Fo79ojj3vdEZOHg3wR9ksAMRz4P3S5fDB5e/YWZiFnyFQI1WY2Vftu9XoXVVtJfxB7Bpce/QTqWSSntkz2Znrw==", + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.4.4.tgz", + "integrity": "sha512-ReVR2rLTV1kvtlWFyuot+d1pkpG2Fw/XKE3PDAdj57rbM97ttSp9JZ2UsP+2EHTylra9cUf6JA7tGwW1INzUrA==", "dev": true }, "@types/resolve": { @@ -13945,12 +13320,6 @@ "@types/node": "*" } }, - "@types/semver": { - "version": "7.3.9", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.9.tgz", - "integrity": "sha512-L/TMpyURfBkf+o/526Zb6kd/tchUP3iBDEPjqjb+U2MAJhVRxxrmr2fwpe08E7QsV7YLcpq0tUaQ9O9x97ZIxQ==", - "dev": true - }, "@types/stack-utils": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", @@ -13982,99 +13351,69 @@ } }, "@typescript-eslint/eslint-plugin": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.3.0.tgz", - "integrity": "sha512-ARUEJHJrq85aaiCqez7SANeahDsJTD3AEua34EoQN9pHS6S5Bq9emcIaGGySt/4X2zSi+vF5hAH52sEen7IO7g==", + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.16.0.tgz", + "integrity": "sha512-SJoba1edXvQRMmNI505Uo4XmGbxCK9ARQpkvOd00anxzri9RNQk0DDCxD+LIl+jYhkzOJiOMMKYEHnHEODjdCw==", "dev": true, "requires": { - "@typescript-eslint/experimental-utils": "5.3.0", - "@typescript-eslint/scope-manager": "5.3.0", + "@typescript-eslint/scope-manager": "5.16.0", + "@typescript-eslint/type-utils": "5.16.0", + "@typescript-eslint/utils": "5.16.0", "debug": "^4.3.2", "functional-red-black-tree": "^1.0.1", "ignore": "^5.1.8", "regexpp": "^3.2.0", "semver": "^7.3.5", "tsutils": "^3.21.0" - }, - "dependencies": { - "debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "ignore": { - "version": "5.1.8", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", - "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", - "dev": true - } } }, - "@typescript-eslint/experimental-utils": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.3.0.tgz", - "integrity": "sha512-NFVxYTjKj69qB0FM+piah1x3G/63WB8vCBMnlnEHUsiLzXSTWb9FmFn36FD9Zb4APKBLY3xRArOGSMQkuzTF1w==", + "@typescript-eslint/parser": { + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.16.0.tgz", + "integrity": "sha512-fkDq86F0zl8FicnJtdXakFs4lnuebH6ZADDw6CYQv0UZeIjHvmEw87m9/29nk2Dv5Lmdp0zQ3zDQhiMWQf/GbA==", "dev": true, "requires": { - "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.3.0", - "@typescript-eslint/types": "5.3.0", - "@typescript-eslint/typescript-estree": "5.3.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" + "@typescript-eslint/scope-manager": "5.16.0", + "@typescript-eslint/types": "5.16.0", + "@typescript-eslint/typescript-estree": "5.16.0", + "debug": "^4.3.2" } }, - "@typescript-eslint/parser": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.3.0.tgz", - "integrity": "sha512-rKu/yAReip7ovx8UwOAszJVO5MgBquo8WjIQcp1gx4pYQCwYzag+I5nVNHO4MqyMkAo0gWt2gWUi+36gWAVKcw==", + "@typescript-eslint/scope-manager": { + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.16.0.tgz", + "integrity": "sha512-P+Yab2Hovg8NekLIR/mOElCDPyGgFZKhGoZA901Yax6WR6HVeGLbsqJkZ+Cvk5nts/dAlFKm8PfL43UZnWdpIQ==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.3.0", - "@typescript-eslint/types": "5.3.0", - "@typescript-eslint/typescript-estree": "5.3.0", - "debug": "^4.3.2" - }, - "dependencies": { - "debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - } + "@typescript-eslint/types": "5.16.0", + "@typescript-eslint/visitor-keys": "5.16.0" } }, - "@typescript-eslint/scope-manager": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.3.0.tgz", - "integrity": "sha512-22Uic9oRlTsPppy5Tcwfj+QET5RWEnZ5414Prby465XxQrQFZ6nnm5KnXgnsAJefG4hEgMnaxTB3kNEyjdjj6A==", + "@typescript-eslint/type-utils": { + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.16.0.tgz", + "integrity": "sha512-SKygICv54CCRl1Vq5ewwQUJV/8padIWvPgCxlWPGO/OgQLCijY9G7lDu6H+mqfQtbzDNlVjzVWQmeqbLMBLEwQ==", "dev": true, "requires": { - "@typescript-eslint/types": "5.3.0", - "@typescript-eslint/visitor-keys": "5.3.0" + "@typescript-eslint/utils": "5.16.0", + "debug": "^4.3.2", + "tsutils": "^3.21.0" } }, "@typescript-eslint/types": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.3.0.tgz", - "integrity": "sha512-fce5pG41/w8O6ahQEhXmMV+xuh4+GayzqEogN24EK+vECA3I6pUwKuLi5QbXO721EMitpQne5VKXofPonYlAQg==", + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.16.0.tgz", + "integrity": "sha512-oUorOwLj/3/3p/HFwrp6m/J2VfbLC8gjW5X3awpQJ/bSG+YRGFS4dpsvtQ8T2VNveV+LflQHjlLvB6v0R87z4g==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.3.0.tgz", - "integrity": "sha512-FJ0nqcaUOpn/6Z4Jwbtf+o0valjBLkqc3MWkMvrhA2TvzFXtcclIM8F4MBEmYa2kgcI8EZeSAzwoSrIC8JYkug==", + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.16.0.tgz", + "integrity": "sha512-SE4VfbLWUZl9MR+ngLSARptUv2E8brY0luCdgmUevU6arZRY/KxYoLI/3V/yxaURR8tLRN7bmZtJdgmzLHI6pQ==", "dev": true, "requires": { - "@typescript-eslint/types": "5.3.0", - "@typescript-eslint/visitor-keys": "5.3.0", + "@typescript-eslint/types": "5.16.0", + "@typescript-eslint/visitor-keys": "5.16.0", "debug": "^4.3.2", "globby": "^11.0.4", "is-glob": "^4.0.3", @@ -14082,85 +13421,44 @@ "tsutils": "^3.21.0" }, "dependencies": { - "debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dev": true, "requires": { - "ms": "2.1.2" + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" } } } }, - "@typescript-eslint/visitor-keys": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.3.0.tgz", - "integrity": "sha512-oVIAfIQuq0x2TFDNLVavUn548WL+7hdhxYn+9j3YdJJXB7mH9dAmZNJsPDa7Jc+B9WGqoiex7GUDbyMxV0a/aw==", + "@typescript-eslint/utils": { + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.16.0.tgz", + "integrity": "sha512-iYej2ER6AwmejLWMWzJIHy3nPJeGDuCqf8Jnb+jAQVoPpmWzwQOfa9hWVB8GIQE5gsCv/rfN4T+AYb/V06WseQ==", "dev": true, "requires": { - "@typescript-eslint/types": "5.3.0", - "eslint-visitor-keys": "^3.0.0" + "@types/json-schema": "^7.0.9", + "@typescript-eslint/scope-manager": "5.16.0", + "@typescript-eslint/types": "5.16.0", + "@typescript-eslint/typescript-estree": "5.16.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0" } }, - "@yarn-tool/resolve-package": { - "version": "1.0.38", - "resolved": "https://registry.npmjs.org/@yarn-tool/resolve-package/-/resolve-package-1.0.38.tgz", - "integrity": "sha512-WmYM/Znh/vPQw7PBfbH2PmZSrzCF0AfGMfpA4z3SbNa2UUcdpqq9yD9pYKcHY1FP3yjMB7KwcVD8mhojROXCQQ==", + "@typescript-eslint/visitor-keys": { + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.16.0.tgz", + "integrity": "sha512-jqxO8msp5vZDhikTwq9ubyMHqZ67UIvawohr4qF3KhlpL7gzSjOd+8471H3nh5LyABkaI85laEKKU8SnGUK5/g==", "dev": true, "requires": { - "@ts-type/package-dts": "^1.0.53", - "pkg-dir": "< 6 >= 5", - "tslib": "^2.3.1", - "upath2": "^3.1.10" - }, - "dependencies": { - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - } - }, - "locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "requires": { - "p-locate": "^5.0.0" - } - }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - }, - "p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "requires": { - "p-limit": "^3.0.2" - } - }, - "pkg-dir": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz", - "integrity": "sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==", - "dev": true, - "requires": { - "find-up": "^5.0.0" - } - } + "@typescript-eslint/types": "5.16.0", + "eslint-visitor-keys": "^3.0.0" } }, "abab": { @@ -14180,9 +13478,9 @@ } }, "acorn": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.5.0.tgz", - "integrity": "sha512-yXbYeFy+jUuYd3/CDcg2NkIYE991XYX/bje7LmjJigUciaeO1JR4XxXgCIV1/Zc/dRuFEyw1L0pbA+qynJkW5Q==", + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", + "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", "dev": true }, "acorn-globals": { @@ -14217,253 +13515,73 @@ "dev": true }, "addons-linter": { - "version": "3.20.0", - "resolved": "https://registry.npmjs.org/addons-linter/-/addons-linter-3.20.0.tgz", - "integrity": "sha512-rHaahIZ34HSL1D7ZYCMs/QQPOp0pAnsOMqtNSy/zDSrkgVtlCQvSeMpx1a3ZnE2pGRVHjMIO506KWUmrN1lPRw==", + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/addons-linter/-/addons-linter-4.14.0.tgz", + "integrity": "sha512-TH3/PMS4Dd0Jf3kXW7DLXseHZcD7ZbnfnQAztkrP4YC0HQKQVZJ+lGOuDOGUtVQDMwC/eEdvHvZoRnHDer5qkg==", "dev": true, "requires": { - "@mdn/browser-compat-data": "4.0.5", + "@mdn/browser-compat-data": "4.1.12", "addons-moz-compare": "1.2.0", - "addons-scanner-utils": "5.0.0", + "addons-scanner-utils": "6.3.0", "ajv": "6.12.6", "ajv-merge-patch": "4.1.0", "chalk": "4.1.2", "cheerio": "1.0.0-rc.10", - "columnify": "1.5.4", - "common-tags": "1.8.0", + "columnify": "1.6.0", + "common-tags": "1.8.2", "deepmerge": "4.2.2", - "dispensary": "0.62.0", - "eslint": "7.32.0", - "eslint-plugin-no-unsanitized": "3.1.5", - "eslint-visitor-keys": "3.0.0", - "espree": "9.0.0", + "eslint": "8.11.0", + "eslint-plugin-no-unsanitized": "4.0.1", + "eslint-visitor-keys": "3.3.0", + "espree": "9.3.1", "esprima": "4.0.1", "fluent-syntax": "0.13.0", "glob": "7.2.0", - "image-size": "1.0.0", + "image-size": "1.0.1", "is-mergeable-object": "1.1.1", "jed": "1.1.1", "os-locale": "5.0.0", - "pino": "6.13.3", - "postcss": "8.3.9", + "pino": "7.9.1", + "postcss": "8.4.12", "relaxed-json": "1.0.3", "semver": "7.3.5", - "source-map-support": "0.5.20", + "sha.js": "2.4.11", + "source-map-support": "0.5.21", "tosource": "1.0.0", "upath": "2.0.1", - "yargs": "17.2.1", + "yargs": "17.4.0", "yauzl": "2.10.0" }, "dependencies": { - "@babel/code-frame": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", - "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", - "dev": true, - "requires": { - "@babel/highlight": "^7.10.4" - } - }, - "@eslint/eslintrc": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", - "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==", - "dev": true, - "requires": { - "ajv": "^6.12.4", - "debug": "^4.1.1", - "espree": "^7.3.0", - "globals": "^13.9.0", - "ignore": "^4.0.6", - "import-fresh": "^3.2.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", - "strip-json-comments": "^3.1.1" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true - }, - "espree": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", - "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", - "dev": true, - "requires": { - "acorn": "^7.4.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^1.3.0" - } - } - } - }, - "@humanwhocodes/config-array": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", - "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==", - "dev": true, - "requires": { - "@humanwhocodes/object-schema": "^1.2.0", - "debug": "^4.1.1", - "minimatch": "^3.0.4" - } - }, - "acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, - "eslint": { - "version": "7.32.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", - "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==", - "dev": true, - "requires": { - "@babel/code-frame": "7.12.11", - "@eslint/eslintrc": "^0.4.3", - "@humanwhocodes/config-array": "^0.5.0", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.0.1", - "doctrine": "^3.0.0", - "enquirer": "^2.3.5", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^2.1.0", - "eslint-visitor-keys": "^2.0.0", - "espree": "^7.3.1", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^5.1.2", - "globals": "^13.6.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^3.13.1", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.0.4", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "progress": "^2.0.0", - "regexpp": "^3.1.0", - "semver": "^7.2.1", - "strip-ansi": "^6.0.0", - "strip-json-comments": "^3.1.0", - "table": "^6.0.9", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true - }, - "espree": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", - "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", - "dev": true, - "requires": { - "acorn": "^7.4.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^1.3.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true - } - } - } - } - }, - "eslint-plugin-no-unsanitized": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/eslint-plugin-no-unsanitized/-/eslint-plugin-no-unsanitized-3.1.5.tgz", - "integrity": "sha512-s/6w++p1590h/H/dE2Wo660bOkaM/3OEK14Y7xm1UT0bafxkKw1Cq0ksjxkxLdH/WWd014DlsLKuD6CyNrR2Dw==", - "dev": true, - "requires": {} - }, - "eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^1.1.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true - } - } - }, "image-size": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.0.0.tgz", - "integrity": "sha512-JLJ6OwBfO1KcA+TvJT+v8gbE6iWbj24LyDNFgFEN0lzegn6cC6a/p3NIDaepMsJjQjlUWqIC7wJv8lBFxPNjcw==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.0.1.tgz", + "integrity": "sha512-VAwkvNSNGClRw9mDHhc5Efax8PLlsOGcUTh0T/LIriC8vPA3U5PdqXWqkz406MoYHMKW8Uf9gWr05T/rYB44kQ==", "dev": true, "requires": { "queue": "6.0.2" } }, - "js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, "yargs": { - "version": "17.2.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.2.1.tgz", - "integrity": "sha512-XfR8du6ua4K6uLGm5S6fA+FIJom/MdJcFNVY8geLlp2v8GYbOXD4EB1tPNZsRn4vBzKGMgb5DRZMeWuFc2GO8Q==", + "version": "17.4.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.4.0.tgz", + "integrity": "sha512-WJudfrk81yWFSOkZYpAZx4Nt7V4xp7S/uJkX0CnxovMCt1wCE8LNftPpNuF9X/u9gN5nsD7ycYtRcDf2pL3UiA==", "dev": true, "requires": { "cliui": "^7.0.2", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", - "string-width": "^4.2.0", + "string-width": "^4.2.3", "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" + "yargs-parser": "^21.0.0" } + }, + "yargs-parser": { + "version": "21.0.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.1.tgz", + "integrity": "sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==", + "dev": true } } }, @@ -14474,13 +13592,13 @@ "dev": true }, "addons-scanner-utils": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/addons-scanner-utils/-/addons-scanner-utils-5.0.0.tgz", - "integrity": "sha512-uENKmGryUeR07I1c8RonDZY/bkAG+zKfZ3T61JFusgY5wiARQJ5+8hI33m8sctXxPopjfxiIjHsG/g7cQzn4Yw==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/addons-scanner-utils/-/addons-scanner-utils-6.3.0.tgz", + "integrity": "sha512-sD4U7TX/NFDUYVheydrcpHH9xG3E0eVBFDn1RuUkGpqRyay3SsOU75Pl2lWAbCmeE0Mh9inU1Fwl7Mm1VRWkZw==", "dev": true, "requires": { "@types/yauzl": "2.9.2", - "common-tags": "1.8.0", + "common-tags": "1.8.2", "first-chunk-stream": "3.0.0", "strip-bom-stream": "4.0.0", "upath": "2.0.1", @@ -14533,12 +13651,6 @@ "string-width": "^4.1.0" } }, - "ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true - }, "ansi-escapes": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", @@ -14606,12 +13718,6 @@ } } }, - "arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true - }, "argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -14624,12 +13730,6 @@ "integrity": "sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==", "dev": true }, - "array-filter": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-0.0.1.tgz", - "integrity": "sha1-fajPLiZijtcygDWB/SH2fKzS7uw=", - "dev": true - }, "array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", @@ -14650,18 +13750,6 @@ "is-string": "^1.0.7" } }, - "array-map": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/array-map/-/array-map-0.0.0.tgz", - "integrity": "sha1-iKK6tz0c97zVwbEYoAP2b2ZfpmI=", - "dev": true - }, - "array-reduce": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/array-reduce/-/array-reduce-0.0.0.tgz", - "integrity": "sha1-FziZ0//Rx9k4PkR5Ul2+J4yrXys=", - "dev": true - }, "array-union": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", @@ -14686,9 +13774,9 @@ "dev": true }, "asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", "dev": true, "requires": { "safer-buffer": "~2.1.0" @@ -14700,11 +13788,22 @@ "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", "dev": true }, - "astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true + "ast-metadata-inferer": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/ast-metadata-inferer/-/ast-metadata-inferer-0.7.0.tgz", + "integrity": "sha512-OkMLzd8xelb3gmnp6ToFvvsHLtS6CbagTkFQvQ+ZYFe3/AIl9iKikNR9G7pY3GfOR/2Xc222hwBjzI7HLkE76Q==", + "dev": true, + "requires": { + "@mdn/browser-compat-data": "^3.3.14" + }, + "dependencies": { + "@mdn/browser-compat-data": { + "version": "3.3.14", + "resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-3.3.14.tgz", + "integrity": "sha512-n2RC9d6XatVbWFdHLimzzUJxJ1KY8LdjqrW6YvGPiRmsHkhOUx74/Ct10x5Yo7bC/Jvqx7cDEW8IMPv/+vwEzA==", + "dev": true + } + } }, "async": { "version": "0.2.10", @@ -14743,18 +13842,18 @@ "dev": true }, "babel-jest": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-27.3.1.tgz", - "integrity": "sha512-SjIF8hh/ir0peae2D6S6ZKRhUy7q/DnpH7k/V6fT4Bgs/LXXUztOpX4G2tCgq8mLo5HA9mN6NmlFMeYtKmIsTQ==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-27.5.1.tgz", + "integrity": "sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg==", "dev": true, "requires": { - "@jest/transform": "^27.3.1", - "@jest/types": "^27.2.5", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.0.0", - "babel-preset-jest": "^27.2.0", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^27.5.1", "chalk": "^4.0.0", - "graceful-fs": "^4.2.4", + "graceful-fs": "^4.2.9", "slash": "^3.0.0" } }, @@ -14769,33 +13868,12 @@ "@istanbuljs/schema": "^0.1.2", "istanbul-lib-instrument": "^5.0.4", "test-exclude": "^6.0.0" - }, - "dependencies": { - "istanbul-lib-instrument": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.1.0.tgz", - "integrity": "sha512-czwUz525rkOFDJxfKK6mYfIs9zBKILyrZQxjz3ABhjQXhbhFsSbo1HW/BFcsDnfJYJWA6thRR5/TUY2qs5W99Q==", - "dev": true, - "requires": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" - } - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } } }, "babel-plugin-jest-hoist": { - "version": "27.2.0", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.2.0.tgz", - "integrity": "sha512-TOux9khNKdi64mW+0OIhcmbAn75tTlzKhxmiNXevQaPbrBYK7YKjP1jl6NHTJ6XR5UgUrJbCnWlKVnJn29dfjw==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.5.1.tgz", + "integrity": "sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ==", "dev": true, "requires": { "@babel/template": "^7.3.3", @@ -14825,12 +13903,12 @@ } }, "babel-preset-jest": { - "version": "27.2.0", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-27.2.0.tgz", - "integrity": "sha512-z7MgQ3peBwN5L5aCqBKnF6iqdlvZvFUQynEhu0J+X9nHLU72jO3iY331lcYrg+AssJ8q7xsv5/3AICzVmJ/wvg==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-27.5.1.tgz", + "integrity": "sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag==", "dev": true, "requires": { - "babel-plugin-jest-hoist": "^27.2.0", + "babel-plugin-jest-hoist": "^27.5.1", "babel-preset-current-node-syntax": "^1.0.0" } }, @@ -14840,12 +13918,6 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, - "base64-arraybuffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.1.tgz", - "integrity": "sha512-vFIUq7FdLtjZMhATwDul5RZWv2jpXQ09Pd6jcVEOvIsqCWTRFD/ONHNfyOS8dA/Ippi5dsIgpyKWKZaAKZltbA==", - "dev": true - }, "base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -14891,21 +13963,21 @@ "dev": true }, "body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.1.tgz", + "integrity": "sha512-8ljfQi5eBk8EJfECMrgqNGWPEY5jWP+1IzkzkGdFFEwFQZZyaZ21UqdaHktgiMlH0xLHqIFtE/u2OYE5dOtViA==", "dev": true, "requires": { - "bytes": "3.1.0", + "bytes": "3.1.1", "content-type": "~1.0.4", "debug": "2.6.9", "depd": "~1.1.2", - "http-errors": "1.7.2", + "http-errors": "1.8.1", "iconv-lite": "0.4.24", "on-finished": "~2.3.0", - "qs": "6.7.0", - "raw-body": "2.4.0", - "type-is": "~1.6.17" + "qs": "6.9.6", + "raw-body": "2.4.2", + "type-is": "~1.6.18" }, "dependencies": { "debug": { @@ -14981,16 +14053,16 @@ "dev": true }, "browserslist": { - "version": "4.16.6", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.6.tgz", - "integrity": "sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ==", + "version": "4.20.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.0.tgz", + "integrity": "sha512-bnpOoa+DownbciXj0jVGENf8VYQnE2LNWomhYuCsMmmx9Jd9lwq0WXODuwpSsp8AVdKM2/HorrzxAfbKvWTByQ==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30001219", - "colorette": "^1.2.2", - "electron-to-chromium": "^1.3.723", + "caniuse-lite": "^1.0.30001313", + "electron-to-chromium": "^1.4.76", "escalade": "^3.1.1", - "node-releases": "^1.1.71" + "node-releases": "^2.0.2", + "picocolors": "^1.0.0" } }, "bs-logger": { @@ -15083,9 +14155,9 @@ } }, "bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.1.tgz", + "integrity": "sha512-dWe4nWO/ruEOY7HkUJ5gFt1DCFV9zPRoJr8pV0/ASQermOZjtq8jMjOprC0Kd10GLN+l7xaUPvxzJFWtxGu8Fg==", "dev": true }, "cacheable-request": { @@ -15143,9 +14215,9 @@ "dev": true }, "caniuse-lite": { - "version": "1.0.30001228", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001228.tgz", - "integrity": "sha512-QQmLOGJ3DEgokHbMSA8cj2a+geXqmnpyOFT0lhQV6P3/YOJvGDEwoedcwxEQ30gJIwIIunHIicunJ2rzK5gB2A==", + "version": "1.0.30001314", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001314.tgz", + "integrity": "sha512-0zaSO+TnCHtHJIbpLroX7nsD+vYuOVjl3uzFbJO1wMVbuveJA0RK2WcQA9ZUIOiO0/ArMiMgHJLxfEZhQiC0kw==", "dev": true }, "caseless": { @@ -15199,9 +14271,9 @@ } }, "chokidar": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", - "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", "dev": true, "requires": { "anymatch": "~3.1.2", @@ -15221,9 +14293,9 @@ "dev": true }, "chrome-launcher": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/chrome-launcher/-/chrome-launcher-0.14.0.tgz", - "integrity": "sha512-W//HpflaW6qBGrmuskup7g+XJZN6w03ko9QSIe5CtcTal2u0up5SeReK3Ll1Why4Ey8dPkv8XSodZyHPnGbVHQ==", + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/chrome-launcher/-/chrome-launcher-0.15.0.tgz", + "integrity": "sha512-ZQqX5kb9H0+jy1OqLnWampfocrtSZaGl7Ny3F9GRha85o4odbL8x55paUzh51UC7cEmZ5obp3H2Mm70uC2PpRA==", "dev": true, "requires": { "@types/node": "*", @@ -15311,12 +14383,6 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "colorette": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", - "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==", - "dev": true - }, "colors": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", @@ -15324,30 +14390,13 @@ "dev": true }, "columnify": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/columnify/-/columnify-1.5.4.tgz", - "integrity": "sha1-Rzfd8ce2mop8NAVweC6UfuyOeLs=", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/columnify/-/columnify-1.6.0.tgz", + "integrity": "sha512-lomjuFZKfM6MSAnV9aCZC9sc0qGbmZdfygNv+nCpqVkSKdCxCklLtd16O0EILGkImHw9ZpHkAnHaB+8Zxq5W6Q==", "dev": true, "requires": { - "strip-ansi": "^3.0.0", + "strip-ansi": "^6.0.1", "wcwidth": "^1.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - } } }, "combined-stream": { @@ -15366,15 +14415,9 @@ "dev": true }, "common-tags": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.0.tgz", - "integrity": "sha512-6P6g0uetGpW/sdyUy/iQQCbFF0kWVMSIVSyYz7Zgjcgh8mgw8PQzDNZeyZ5DQ2gM7LBoZPHmnjz8rUthkBG5tw==", - "dev": true - }, - "commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", + "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", "dev": true }, "component-emitter": { @@ -15471,13 +14514,22 @@ } }, "content-disposition": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", - "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", "dev": true, "peer": true, "requires": { - "safe-buffer": "5.1.2" + "safe-buffer": "5.2.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "peer": true + } } }, "content-type": { @@ -15518,9 +14570,9 @@ } }, "core-js": { - "version": "3.18.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.18.0.tgz", - "integrity": "sha512-WJeQqq6jOYgVgg4NrXKL0KLQhi0CT4ZOCvFL+3CQ5o7I6J8HkT5wd53EadMfqTDp1so/MT1J+w2ujhWcCJtN7w==", + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.21.0.tgz", + "integrity": "sha512-YUdI3fFu4TF/2WykQ2xzSiTQdldLB4KVuL9WeAy5XONZYt5Cun/fpQvctoKbCgvPhmzADeesTk/j2Rdx77AcKQ==", "dev": true }, "core-util-is": { @@ -15539,11 +14591,14 @@ "vary": "^1" } }, - "create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true + "cross-fetch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", + "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", + "dev": true, + "requires": { + "node-fetch": "2.6.7" + } }, "cross-spawn": { "version": "7.0.3", @@ -15563,16 +14618,16 @@ "dev": true }, "css-select": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.1.3.tgz", - "integrity": "sha512-gT3wBNd9Nj49rAbmtFHj1cljIAOLYSX1nZ8CB7TBO3INYckygm5B7LISU/szY//YmdiSLbJvDLOx9VnMVpMBxA==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.2.1.tgz", + "integrity": "sha512-/aUslKhzkTNCQUB2qTX84lVmfia9NyjP3WpDGtj/WxhwBzWBYUV3DgUpurHTme8UTPcPlAD1DJ+b0nN/t50zDQ==", "dev": true, "requires": { "boolbase": "^1.0.0", - "css-what": "^5.0.0", - "domhandler": "^4.2.0", - "domutils": "^2.6.0", - "nth-check": "^2.0.0" + "css-what": "^5.1.0", + "domhandler": "^4.3.0", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" } }, "css-what": { @@ -15631,9 +14686,9 @@ } }, "date-format": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/date-format/-/date-format-3.0.0.tgz", - "integrity": "sha512-eyTcpKOcamdhWJXj56DpQMo1ylSQpcGtGKXcU0Tb97+K56/CF5amAqqqNj0+KvA0iw2ynxtHWFsPDSClCxe48w==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.3.tgz", + "integrity": "sha512-7P3FyqDcfeznLZp2b+OMitV9Sz2lUnsT87WaTat9nVwqsBkTzPG3lPLNwW3en6F4pHUiWzr6vb8CLhjdK9bcxQ==", "dev": true }, "debounce": { @@ -15643,9 +14698,9 @@ "dev": true }, "debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", "dev": true, "requires": { "ms": "2.1.2" @@ -16000,9 +15055,9 @@ "dev": true }, "devtools-protocol": { - "version": "0.0.901419", - "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.901419.tgz", - "integrity": "sha512-4INMPwNm9XRpBukhNbF7OB6fNTTCaI8pzy/fXg0xQzAy5h3zL1P8xT3QazgKqBrb/hAYwIBizqDBZ7GtJE74QQ==", + "version": "0.0.969999", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.969999.tgz", + "integrity": "sha512-6GfzuDWU0OFAuOvBokXpXPLxjOJ5DZ157Ue3sGQQM3LgAamb8m0R0ruSfN0DDu+XG5XJgT50i6zZ/0o8RglreQ==", "dev": true }, "di": { @@ -16011,16 +15066,10 @@ "integrity": "sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=", "dev": true }, - "diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true - }, "diff-sequences": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.0.6.tgz", - "integrity": "sha512-ag6wfpBFyNXZ0p8pcuIDS//D8H062ZQJ3fzYxjpmeKjnz8W4pekL3AI8VohmyZmsWW2PWaHgjsmqR6L13101VQ==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", + "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==", "dev": true }, "dir-glob": { @@ -16032,43 +15081,6 @@ "path-type": "^4.0.0" } }, - "dispensary": { - "version": "0.62.0", - "resolved": "https://registry.npmjs.org/dispensary/-/dispensary-0.62.0.tgz", - "integrity": "sha512-x8vqPX7owhzDp3Y6t/iOuTuNoWx5hlZKITlzlybETsZoY05cYDubGpwt0soLfRLAWLuxX1lq0lTc/vXtk/CDCw==", - "dev": true, - "requires": { - "async": "~3.2.0", - "natural-compare-lite": "~1.4.0", - "pino": "~6.11.0", - "request": "~2.88.0", - "sha.js": "~2.4.4", - "source-map-support": "~0.5.4", - "yargs": "~16.2.0" - }, - "dependencies": { - "async": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.2.tgz", - "integrity": "sha512-H0E+qZaDEfx/FY4t7iLRv1W2fFI6+pyCeTw1uN20AQPiwqwM6ojPxHxdLv4z8hi2DtnW9BOckSspLucW7pIE5g==", - "dev": true - }, - "pino": { - "version": "6.11.3", - "resolved": "https://registry.npmjs.org/pino/-/pino-6.11.3.tgz", - "integrity": "sha512-drPtqkkSf0ufx2gaea3TryFiBHdNIdXKf5LN0hTM82SXI4xVIve2wLwNg92e1MT6m3jASLu6VO7eGY6+mmGeyw==", - "dev": true, - "requires": { - "fast-redact": "^3.0.0", - "fast-safe-stringify": "^2.0.7", - "flatstr": "^1.0.12", - "pino-std-serializers": "^3.1.0", - "quick-format-unescaped": "^4.0.3", - "sonic-boom": "^1.0.2" - } - } - } - }, "doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -16125,9 +15137,9 @@ } }, "domhandler": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.2.2.tgz", - "integrity": "sha512-PzE9aBMsdZO8TK4BnuJwH0QT41wgMbRzuZrHUcpYncEjmQazq8QEaBWgLG7ZyC/DAZKEgglpIA6j4Qn/HmxS3w==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", "dev": true, "requires": { "domelementtype": "^2.2.0" @@ -16219,6 +15231,18 @@ "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", "dev": true }, + "duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "dev": true, + "requires": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + } + }, "ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", @@ -16245,9 +15269,9 @@ "dev": true }, "electron-to-chromium": { - "version": "1.3.735", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.735.tgz", - "integrity": "sha512-cp7MWzC3NseUJV2FJFgaiesdrS+A8ZUjX5fLAxdRlcaPDkaPGFplX930S5vf84yqDp4LjuLdKouWuVOTwUfqHQ==", + "version": "1.4.77", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.77.tgz", + "integrity": "sha512-fiDxw8mO9Ph1Z0bjX2sFTPpi0J0QkOiwOJF+5Q0J0baNc/F9lLePAvDPlnoxvbUYYMizqrKPeotRRkJ9LtxAew==", "dev": true }, "emittery": { @@ -16278,9 +15302,9 @@ } }, "engine.io": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.0.0.tgz", - "integrity": "sha512-Ui7yl3JajEIaACg8MOUwWvuuwU7jepZqX3BKs1ho7NQRuP4LhN4XIykXhp8bEy+x/DhA0LBZZXYSCkZDqrwMMg==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.1.1.tgz", + "integrity": "sha512-AyMc20q8JUUdvKd46+thc9o7yCZ6iC6MoBCChG5Z1XmFMpp+2+y/oKvwpZTUJB0KCjxScw1dV9c2h5pjiYBLuQ==", "dev": true, "requires": { "@types/cookie": "^0.4.1", @@ -16293,24 +15317,24 @@ "debug": "~4.3.1", "engine.io-parser": "~5.0.0", "ws": "~8.2.3" + }, + "dependencies": { + "ws": { + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", + "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==", + "dev": true, + "requires": {} + } } }, - "engine.io-parser": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.1.tgz", - "integrity": "sha512-j4p3WwJrG2k92VISM0op7wiq60vO92MlF3CRGxhKHy9ywG1/Dkc72g0dXeDQ+//hrcDn8gqQzoEkdO9FN0d9AA==", - "dev": true, - "requires": { - "base64-arraybuffer": "~1.0.1" - } - }, - "enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "engine.io-parser": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.3.tgz", + "integrity": "sha512-BtQxwF27XUNnSafQLvDi0dQ8s3i6VgzSoQMJacpIcGNrlUdfHSKbgm3jmjCVvQluGzqwujQMPAoMai3oYSTurg==", "dev": true, "requires": { - "ansi-colors": "^4.1.1" + "@socket.io/base64-arraybuffer": "~1.0.2" } }, "ent": { @@ -16480,24 +15504,23 @@ } }, "eslint": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.1.0.tgz", - "integrity": "sha512-JZvNneArGSUsluHWJ8g8MMs3CfIEzwaLx9KyH4tZ2i+R2/rPWzL8c0zg3rHdwYVpN/1sB9gqnjHwz9HoeJpGHw==", + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.11.0.tgz", + "integrity": "sha512-/KRpd9mIRg2raGxHRGwW9ZywYNAClZrHjdueHcrVDuO3a6bj83eoTirCCk0M0yPwOjWYKHwRVRid+xK4F/GHgA==", "dev": true, "requires": { - "@eslint/eslintrc": "^1.0.3", - "@humanwhocodes/config-array": "^0.6.0", + "@eslint/eslintrc": "^1.2.1", + "@humanwhocodes/config-array": "^0.9.2", "ajv": "^6.10.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.3.2", "doctrine": "^3.0.0", - "enquirer": "^2.3.5", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^6.0.0", + "eslint-scope": "^7.1.1", "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.0.0", - "espree": "^9.0.0", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.3.1", "esquery": "^1.4.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -16505,7 +15528,7 @@ "functional-red-black-tree": "^1.0.1", "glob-parent": "^6.0.1", "globals": "^13.6.0", - "ignore": "^4.0.6", + "ignore": "^5.2.0", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", @@ -16516,24 +15539,13 @@ "minimatch": "^3.0.4", "natural-compare": "^1.4.0", "optionator": "^0.9.1", - "progress": "^2.0.0", "regexpp": "^3.2.0", - "semver": "^7.2.1", - "strip-ansi": "^6.0.0", + "strip-ansi": "^6.0.1", "strip-json-comments": "^3.1.0", "text-table": "^0.2.0", "v8-compile-cache": "^2.0.3" }, "dependencies": { - "debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, "escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -16541,9 +15553,9 @@ "dev": true }, "eslint-scope": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-6.0.0.tgz", - "integrity": "sha512-uRDL9MWmQCkaFus8RF5K9/L/2fn+80yoW3jkD53l4shjCh26fCtvJGasxjUqP5OT87SYTxCVA3BwTUzuELx9kA==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", + "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", "dev": true, "requires": { "esrecurse": "^4.3.0", @@ -16589,14 +15601,13 @@ } }, "eslint-module-utils": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.1.tgz", - "integrity": "sha512-fjoetBXQZq2tSTWZ9yWVl2KuFrTZZH3V+9iD1V1RfpDgxzJR+mPd/KZmMiA8gbPqdBzpNiEHOuT7IYEWxrH0zQ==", + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.2.tgz", + "integrity": "sha512-zquepFnWCY2ISMFwD/DqzaM++H+7PDzOpUvotJWm/y1BAFt5R4oeULgdrTejKqLkz7MA/tgstsUMNYc7wNdTrg==", "dev": true, "requires": { "debug": "^3.2.7", - "find-up": "^2.1.0", - "pkg-dir": "^2.0.0" + "find-up": "^2.1.0" }, "dependencies": { "debug": { @@ -16656,22 +15667,68 @@ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", "dev": true + } + } + }, + "eslint-plugin-compat": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-compat/-/eslint-plugin-compat-4.0.2.tgz", + "integrity": "sha512-xqvoO54CLTVaEYGMzhu35Wzwk/As7rCvz/2dqwnFiWi0OJccEtGIn+5qq3zqIu9nboXlpdBN579fZcItC73Ycg==", + "dev": true, + "requires": { + "@mdn/browser-compat-data": "^4.1.5", + "ast-metadata-inferer": "^0.7.0", + "browserslist": "^4.16.8", + "caniuse-lite": "^1.0.30001304", + "core-js": "^3.16.2", + "find-up": "^5.0.0", + "lodash.memoize": "4.1.2", + "semver": "7.3.5" + }, + "dependencies": { + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } }, - "pkg-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", - "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "requires": { + "p-locate": "^5.0.0" + } + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "requires": { - "find-up": "^2.1.0" + "p-limit": "^3.0.2" } } } }, "eslint-plugin-import": { - "version": "2.25.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.25.2.tgz", - "integrity": "sha512-qCwQr9TYfoBHOFcVGKY9C9unq05uOxxdklmBXLVvcwo68y5Hta6/GzCZEMx2zQiu0woKNEER0LE7ZgaOfBU14g==", + "version": "2.25.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.25.4.tgz", + "integrity": "sha512-/KJBASVFxpu0xg1kIBn9AUa8hQVnszpwgE7Ld0lKAlx7Ie87yzEzCgSkekt+le/YVhiaosO4Y14GDAOc41nfxA==", "dev": true, "requires": { "array-includes": "^3.1.4", @@ -16679,14 +15736,14 @@ "debug": "^2.6.9", "doctrine": "^2.1.0", "eslint-import-resolver-node": "^0.3.6", - "eslint-module-utils": "^2.7.0", + "eslint-module-utils": "^2.7.2", "has": "^1.0.3", - "is-core-module": "^2.7.0", + "is-core-module": "^2.8.0", "is-glob": "^4.0.3", "minimatch": "^3.0.4", "object.values": "^1.1.5", "resolve": "^1.20.0", - "tsconfig-paths": "^3.11.0" + "tsconfig-paths": "^3.12.0" }, "dependencies": { "debug": { @@ -16721,6 +15778,13 @@ "integrity": "sha1-8MBwEclf7EK/tNkJ3rtuoDXzsqQ=", "dev": true }, + "eslint-plugin-no-unsanitized": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-no-unsanitized/-/eslint-plugin-no-unsanitized-4.0.1.tgz", + "integrity": "sha512-y/lAMWnPPC7RYuUdxlEL/XiCL8FehN9h9s3Kjqbp/Kv0i9NZs+IXSC2kS546Fa4Bumwy31HlVS/OdWX0Kxb5Xg==", + "dev": true, + "requires": {} + }, "eslint-scope": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", @@ -16749,20 +15813,20 @@ } }, "eslint-visitor-keys": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.0.0.tgz", - "integrity": "sha512-mJOZa35trBTb3IyRmo8xmKBZlxf+N7OnUl4+ZhJHs/r+0770Wh/LEACE2pqMGMe27G/4y8P2bYGk4J70IC5k1Q==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", + "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", "dev": true }, "espree": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.0.0.tgz", - "integrity": "sha512-r5EQJcYZ2oaGbeR0jR0fFVijGOcwai07/690YRXLINuhmVeRY4UKSAsQPe/0BNuDgwP7Ophoc1PRsr2E3tkbdQ==", + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.1.tgz", + "integrity": "sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ==", "dev": true, "requires": { - "acorn": "^8.5.0", + "acorn": "^8.7.0", "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^3.0.0" + "eslint-visitor-keys": "^3.3.0" } }, "esprima": { @@ -16830,12 +15894,6 @@ "dev": true, "peer": true }, - "event-to-promise": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/event-to-promise/-/event-to-promise-0.8.0.tgz", - "integrity": "sha1-S4TxF3K28l93Uvx02XFTGsb1tiY=", - "dev": true - }, "eventemitter3": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", @@ -16857,14 +15915,6 @@ "onetime": "^5.1.2", "signal-exit": "^3.0.3", "strip-final-newline": "^2.0.0" - }, - "dependencies": { - "get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true - } } }, "exit": { @@ -16874,40 +15924,30 @@ "dev": true }, "expect": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/expect/-/expect-27.3.1.tgz", - "integrity": "sha512-MrNXV2sL9iDRebWPGOGFdPQRl2eDQNu/uhxIMShjjx74T6kC6jFIkmQ6OqXDtevjGUkyB2IT56RzDBqXf/QPCg==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/expect/-/expect-27.5.1.tgz", + "integrity": "sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==", "dev": true, "requires": { - "@jest/types": "^27.2.5", - "ansi-styles": "^5.0.0", - "jest-get-type": "^27.3.1", - "jest-matcher-utils": "^27.3.1", - "jest-message-util": "^27.3.1", - "jest-regex-util": "^27.0.6" - }, - "dependencies": { - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - } + "@jest/types": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1" } }, "express": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", - "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.2.tgz", + "integrity": "sha512-oxlxJxcQlYwqPWKVJJtvQiwHgosH/LrLSPA+H4UxpyvSS6jC5aH+5MoHFM+KABgTOt0APue4w66Ha8jCUo9QGg==", "dev": true, "peer": true, "requires": { "accepts": "~1.3.7", "array-flatten": "1.1.1", - "body-parser": "1.19.0", - "content-disposition": "0.5.3", + "body-parser": "1.19.1", + "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.4.0", + "cookie": "0.4.1", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "~1.1.2", @@ -16921,26 +15961,19 @@ "on-finished": "~2.3.0", "parseurl": "~1.3.3", "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.5", - "qs": "6.7.0", + "proxy-addr": "~2.0.7", + "qs": "6.9.6", "range-parser": "~1.2.1", - "safe-buffer": "5.1.2", - "send": "0.17.1", - "serve-static": "1.14.1", - "setprototypeof": "1.1.1", + "safe-buffer": "5.2.1", + "send": "0.17.2", + "serve-static": "1.14.2", + "setprototypeof": "1.2.0", "statuses": "~1.5.0", "type-is": "~1.6.18", "utils-merge": "1.0.1", "vary": "~1.1.2" }, "dependencies": { - "cookie": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", - "dev": true, - "peer": true - }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -16957,6 +15990,13 @@ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true, "peer": true + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "peer": true } } }, @@ -16997,6 +16037,17 @@ "debug": "^4.1.1", "get-stream": "^5.1.0", "yauzl": "^2.10.0" + }, + "dependencies": { + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + } } }, "extsprintf": { @@ -17012,9 +16063,9 @@ "dev": true }, "fast-glob": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", - "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", + "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", "dev": true, "requires": { "@nodelib/fs.stat": "^2.0.2", @@ -17054,21 +16105,9 @@ "dev": true }, "fast-redact": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.0.2.tgz", - "integrity": "sha512-YN+CYfCVRVMUZOUPeinHNKgytM1wPI/C/UCLEi56EsY2dwwvI00kIJHJoI7pMVqGoMew8SMZ2SSfHKHULHXDsg==", - "dev": true - }, - "fast-safe-stringify": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", - "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", - "dev": true - }, - "fastify-warning": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/fastify-warning/-/fastify-warning-0.2.0.tgz", - "integrity": "sha512-s1EQguBw/9qtc1p/WTY4eq9WMRIACkj+HTcOIK1in4MV5aFaQC9ZCIt0dJ7pr5bIf4lPpHvAtP2ywpTNgs7hqw==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.1.1.tgz", + "integrity": "sha512-odVmjC8x8jNeMZ3C+rPMESzXVSEU8tSWSHv9HFxP2mm89G/1WwqhrerJDQm9Zus8X6aoRgQDThKqptdNA6bt+A==", "dev": true }, "fastq": { @@ -17174,17 +16213,6 @@ } } }, - "find-cache-dir": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", - "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==", - "dev": true, - "requires": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - } - }, "find-up": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", @@ -17196,9 +16224,9 @@ } }, "firefox-profile": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/firefox-profile/-/firefox-profile-4.2.1.tgz", - "integrity": "sha512-KyA5ruS7V1nXpaHlJrKPW1jkoc9bq/WKquaKuca/ETembuxcBQPEPpxAp0biwjQCPf3sBslN/heZLdfa5Eotzg==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/firefox-profile/-/firefox-profile-4.2.2.tgz", + "integrity": "sha512-3kI17Xl9dL9AeRkpV1yahsJ+UbekkPtlQswKrIsTY1NLgxtEOR4R19rjGGz5+7/rP8Jt6fvxHk+Bai9R6Eai3w==", "dev": true, "requires": { "adm-zip": "~0.5.x", @@ -17244,16 +16272,10 @@ "rimraf": "^3.0.2" } }, - "flatstr": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/flatstr/-/flatstr-1.0.12.tgz", - "integrity": "sha512-4zPxDyhCyiN2wIAtSLI6gc82/EjqZc1onI4Mz/l0pWrAlsSfYH/2ZIcU+e3oA2wDwbzIWNKwa23F8rh6+DRWkw==", - "dev": true - }, "flatted": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.1.tgz", - "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==", + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", "dev": true }, "fluent-syntax": { @@ -17263,9 +16285,9 @@ "dev": true }, "follow-redirects": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz", - "integrity": "sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg==", + "version": "1.14.8", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.8.tgz", + "integrity": "sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==", "dev": true }, "forever-agent": { @@ -17381,13 +16403,13 @@ "dev": true }, "fx-runner": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fx-runner/-/fx-runner-1.1.0.tgz", - "integrity": "sha512-v/Eo69DDFW30zPdvjCYVXddjVvLy2xGeRbg0S18bPd8kEc0q9VsDoDkjyOxY5lTZsAqcQGy0OWjs3HCfRVBNSg==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fx-runner/-/fx-runner-1.2.0.tgz", + "integrity": "sha512-/zR9BmHF8h4OaVJ+fHHJBv/5FdPV9mjOAPIscQZbAijm7Aa15Ls/P8UBHD5OKU5jwu2niTxkkzzHKITE7oCMoQ==", "dev": true, "requires": { "commander": "2.9.0", - "shell-quote": "1.6.1", + "shell-quote": "1.7.3", "spawn-sync": "1.0.15", "when": "3.7.7", "which": "1.2.4", @@ -17451,13 +16473,10 @@ "dev": true }, "get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true }, "get-symbol-description": { "version": "1.0.0", @@ -17526,23 +16545,22 @@ } }, "globby": { - "version": "11.0.4", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz", - "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==", + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-13.1.1.tgz", + "integrity": "sha512-XMzoDZbGZ37tufiv7g0N4F/zp3zkwdFtVbV3EHsVl1KQr4RPLfNoT068/97RPshz2J5xYNEjLKKBKaGHifBd3Q==", "dev": true, "requires": { - "array-union": "^2.1.0", "dir-glob": "^3.0.1", - "fast-glob": "^3.1.1", - "ignore": "^5.1.4", - "merge2": "^1.3.0", - "slash": "^3.0.0" + "fast-glob": "^3.2.11", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^4.0.0" }, "dependencies": { - "ignore": { - "version": "5.1.8", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", - "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "slash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", "dev": true } } @@ -17590,9 +16608,9 @@ } }, "graceful-fs": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", - "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==", + "version": "4.2.9", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", + "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==", "dev": true }, "graceful-readlink": { @@ -17717,24 +16735,16 @@ "peer": true }, "http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", "dev": true, "requires": { "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - }, - "dependencies": { - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - } + "toidentifier": "1.0.1" } }, "http-proxy": { @@ -17802,9 +16812,9 @@ "dev": true }, "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", "dev": true }, "image-size": { @@ -17837,9 +16847,9 @@ "dev": true }, "import-local": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.0.3.tgz", - "integrity": "sha512-bE9iaUY3CXH8Cwfan/abDKAxe1KGT9kyGsBPqf6DMK/z0a2OzAsrukeYNgIH6cH5Xr452jb1TUL8rSfCLjZ9uA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", "dev": true, "requires": { "pkg-dir": "^4.2.0", @@ -18242,14 +17252,15 @@ "dev": true }, "istanbul-lib-instrument": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", - "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.1.0.tgz", + "integrity": "sha512-czwUz525rkOFDJxfKK6mYfIs9zBKILyrZQxjz3ABhjQXhbhFsSbo1HW/BFcsDnfJYJWA6thRR5/TUY2qs5W99Q==", "dev": true, "requires": { - "@babel/core": "^7.7.5", + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-coverage": "^3.2.0", "semver": "^6.3.0" }, "dependencies": { @@ -18273,9 +17284,9 @@ } }, "istanbul-lib-source-maps": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz", - "integrity": "sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", "dev": true, "requires": { "debug": "^4.1.1", @@ -18284,9 +17295,9 @@ } }, "istanbul-reports": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.0.2.tgz", - "integrity": "sha512-9tZvz7AiR3PEDNGiV9vIouQ/EAcqMXFmkcA1CDFTwOB98OZVDL0PH9glHotf5Ugp6GCOTypfzGWI/OqjWNCRUw==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.3.tgz", + "integrity": "sha512-x9LtDVtfm/t1GFiLl3NffC7hz+I1ragvgX1P/Lg1NlIagifZDKUkuuaAxH/qpwj2IuEfD8G2Bs/UKp+sZ/pKkg==", "dev": true, "requires": { "html-escaper": "^2.0.0", @@ -18305,9 +17316,9 @@ } }, "jasmine-core": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.10.1.tgz", - "integrity": "sha512-ooZWSDVAdh79Rrj4/nnfklL3NQVra0BcuhcuWoAwwi+znLDoUeH87AFfeX8s+YeYi6xlv5nveRyaA1v7CintfA==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-4.0.1.tgz", + "integrity": "sha512-w+JDABxQCkxbGGxg+a2hUVZyqUS2JKngvIyLGu/xiw2ZwgsoSB0iiecLQsQORSeaKQ6iGrCyWG86RfNDuoA7Lg==", "dev": true }, "jed": { @@ -18317,273 +17328,285 @@ "dev": true }, "jest": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/jest/-/jest-27.3.1.tgz", - "integrity": "sha512-U2AX0AgQGd5EzMsiZpYt8HyZ+nSVIh5ujQ9CPp9EQZJMjXIiSZpJNweZl0swatKRoqHWgGKM3zaSwm4Zaz87ng==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest/-/jest-27.5.1.tgz", + "integrity": "sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ==", "dev": true, "requires": { - "@jest/core": "^27.3.1", + "@jest/core": "^27.5.1", "import-local": "^3.0.2", - "jest-cli": "^27.3.1" + "jest-cli": "^27.5.1" } }, "jest-changed-files": { - "version": "27.3.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-27.3.0.tgz", - "integrity": "sha512-9DJs9garMHv4RhylUMZgbdCJ3+jHSkpL9aaVKp13xtXAD80qLTLrqcDZL1PHA9dYA0bCI86Nv2BhkLpLhrBcPg==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-27.5.1.tgz", + "integrity": "sha512-buBLMiByfWGCoMsLLzGUUSpAmIAGnbR2KJoMN10ziLhOLvP4e0SlypHnAel8iqQXTrcbmfEY9sSqae5sgUsTvw==", "dev": true, "requires": { - "@jest/types": "^27.2.5", + "@jest/types": "^27.5.1", "execa": "^5.0.0", "throat": "^6.0.1" } }, "jest-circus": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-27.3.1.tgz", - "integrity": "sha512-v1dsM9II6gvXokgqq6Yh2jHCpfg7ZqV4jWY66u7npz24JnhP3NHxI0sKT7+ZMQ7IrOWHYAaeEllOySbDbWsiXw==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-27.5.1.tgz", + "integrity": "sha512-D95R7x5UtlMA5iBYsOHFFbMD/GVA4R/Kdq15f7xYWUfWHBto9NYRsOvnSauTgdF+ogCpJ4tyKOXhUifxS65gdw==", "dev": true, "requires": { - "@jest/environment": "^27.3.1", - "@jest/test-result": "^27.3.1", - "@jest/types": "^27.2.5", + "@jest/environment": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", "@types/node": "*", "chalk": "^4.0.0", "co": "^4.6.0", "dedent": "^0.7.0", - "expect": "^27.3.1", + "expect": "^27.5.1", "is-generator-fn": "^2.0.0", - "jest-each": "^27.3.1", - "jest-matcher-utils": "^27.3.1", - "jest-message-util": "^27.3.1", - "jest-runtime": "^27.3.1", - "jest-snapshot": "^27.3.1", - "jest-util": "^27.3.1", - "pretty-format": "^27.3.1", + "jest-each": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1", "slash": "^3.0.0", "stack-utils": "^2.0.3", "throat": "^6.0.1" } }, "jest-cli": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-27.3.1.tgz", - "integrity": "sha512-WHnCqpfK+6EvT62me6WVs8NhtbjAS4/6vZJnk7/2+oOr50cwAzG4Wxt6RXX0hu6m1169ZGMlhYYUNeKBXCph/Q==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-27.5.1.tgz", + "integrity": "sha512-Hc6HOOwYq4/74/c62dEE3r5elx8wjYqxY0r0G/nFrLDPMFRu6RA/u8qINOIkvhxG7mMQ5EJsOGfRpI8L6eFUVw==", "dev": true, "requires": { - "@jest/core": "^27.3.1", - "@jest/test-result": "^27.3.1", - "@jest/types": "^27.2.5", + "@jest/core": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", "chalk": "^4.0.0", "exit": "^0.1.2", - "graceful-fs": "^4.2.4", + "graceful-fs": "^4.2.9", "import-local": "^3.0.2", - "jest-config": "^27.3.1", - "jest-util": "^27.3.1", - "jest-validate": "^27.3.1", + "jest-config": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", "prompts": "^2.0.1", "yargs": "^16.2.0" } }, "jest-config": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-27.3.1.tgz", - "integrity": "sha512-KY8xOIbIACZ/vdYCKSopL44I0xboxC751IX+DXL2+Wx6DKNycyEfV3rryC3BPm5Uq/BBqDoMrKuqLEUNJmMKKg==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-27.5.1.tgz", + "integrity": "sha512-5sAsjm6tGdsVbW9ahcChPAFCk4IlkQUknH5AvKjuLTSlcO/wCZKyFdn7Rg0EkC+OGgWODEy2hDpWB1PgzH0JNA==", "dev": true, "requires": { - "@babel/core": "^7.1.0", - "@jest/test-sequencer": "^27.3.1", - "@jest/types": "^27.2.5", - "babel-jest": "^27.3.1", + "@babel/core": "^7.8.0", + "@jest/test-sequencer": "^27.5.1", + "@jest/types": "^27.5.1", + "babel-jest": "^27.5.1", "chalk": "^4.0.0", "ci-info": "^3.2.0", "deepmerge": "^4.2.2", "glob": "^7.1.1", - "graceful-fs": "^4.2.4", - "jest-circus": "^27.3.1", - "jest-environment-jsdom": "^27.3.1", - "jest-environment-node": "^27.3.1", - "jest-get-type": "^27.3.1", - "jest-jasmine2": "^27.3.1", - "jest-regex-util": "^27.0.6", - "jest-resolve": "^27.3.1", - "jest-runner": "^27.3.1", - "jest-util": "^27.3.1", - "jest-validate": "^27.3.1", + "graceful-fs": "^4.2.9", + "jest-circus": "^27.5.1", + "jest-environment-jsdom": "^27.5.1", + "jest-environment-node": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-jasmine2": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-runner": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", "micromatch": "^4.0.4", - "pretty-format": "^27.3.1" + "parse-json": "^5.2.0", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" }, "dependencies": { "ci-info": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.2.0.tgz", - "integrity": "sha512-dVqRX7fLUm8J6FgHJ418XuIgDLZDkYcDFTeL6TA2gt5WlIZUQrrH6EZrNClwT/H0FateUsZkGIOPRrLbP+PR9A==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", + "integrity": "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==", "dev": true } } }, "jest-diff": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.3.1.tgz", - "integrity": "sha512-PCeuAH4AWUo2O5+ksW4pL9v5xJAcIKPUPfIhZBcG1RKv/0+dvaWTQK1Nrau8d67dp65fOqbeMdoil+6PedyEPQ==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", + "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", "dev": true, "requires": { "chalk": "^4.0.0", - "diff-sequences": "^27.0.6", - "jest-get-type": "^27.3.1", - "pretty-format": "^27.3.1" + "diff-sequences": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" } }, "jest-docblock": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-27.0.6.tgz", - "integrity": "sha512-Fid6dPcjwepTFraz0YxIMCi7dejjJ/KL9FBjPYhBp4Sv1Y9PdhImlKZqYU555BlN4TQKaTc+F2Av1z+anVyGkA==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-27.5.1.tgz", + "integrity": "sha512-rl7hlABeTsRYxKiUfpHrQrG4e2obOiTQWfMEH3PxPjOtdsfLQO4ReWSZaQ7DETm4xu07rl4q/h4zcKXyU0/OzQ==", "dev": true, "requires": { "detect-newline": "^3.0.0" } }, "jest-each": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-27.3.1.tgz", - "integrity": "sha512-E4SwfzKJWYcvOYCjOxhZcxwL+AY0uFMvdCOwvzgutJiaiodFjkxQQDxHm8FQBeTqDnSmKsQWn7ldMRzTn2zJaQ==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-27.5.1.tgz", + "integrity": "sha512-1Ff6p+FbhT/bXQnEouYy00bkNSY7OUpfIcmdl8vZ31A1UUaurOLPA8a8BbJOF2RDUElwJhmeaV7LnagI+5UwNQ==", "dev": true, "requires": { - "@jest/types": "^27.2.5", + "@jest/types": "^27.5.1", "chalk": "^4.0.0", - "jest-get-type": "^27.3.1", - "jest-util": "^27.3.1", - "pretty-format": "^27.3.1" + "jest-get-type": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1" } }, "jest-environment-jsdom": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-27.3.1.tgz", - "integrity": "sha512-3MOy8qMzIkQlfb3W1TfrD7uZHj+xx8Olix5vMENkj5djPmRqndMaXtpnaZkxmxM+Qc3lo+yVzJjzuXbCcZjAlg==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-27.5.1.tgz", + "integrity": "sha512-TFBvkTC1Hnnnrka/fUb56atfDtJ9VMZ94JkjTbggl1PEpwrYtUBKMezB3inLmWqQsXYLcMwNoDQwoBTAvFfsfw==", "dev": true, "requires": { - "@jest/environment": "^27.3.1", - "@jest/fake-timers": "^27.3.1", - "@jest/types": "^27.2.5", + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", "@types/node": "*", - "jest-mock": "^27.3.0", - "jest-util": "^27.3.1", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1", "jsdom": "^16.6.0" } }, "jest-environment-node": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.3.1.tgz", - "integrity": "sha512-T89F/FgkE8waqrTSA7/ydMkcc52uYPgZZ6q8OaZgyiZkJb5QNNCF6oPZjH9IfPFfcc9uBWh1574N0kY0pSvTXw==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.5.1.tgz", + "integrity": "sha512-Jt4ZUnxdOsTGwSRAfKEnE6BcwsSPNOijjwifq5sDFSA2kesnXTvNqKHYgM0hDq3549Uf/KzdXNYn4wMZJPlFLw==", "dev": true, "requires": { - "@jest/environment": "^27.3.1", - "@jest/fake-timers": "^27.3.1", - "@jest/types": "^27.2.5", + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", "@types/node": "*", - "jest-mock": "^27.3.0", - "jest-util": "^27.3.1" + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1" + } + }, + "jest-extended": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/jest-extended/-/jest-extended-2.0.0.tgz", + "integrity": "sha512-6AgjJQVaBEKGSK3FH90kOiRUWJsbzn9NWtW0pjGkAFIdH0oPilfkV/gHPJdVvJeBiqT3jMHw8TUg9pUGC1azDg==", + "dev": true, + "requires": { + "jest-diff": "^27.2.5", + "jest-get-type": "^27.0.6" } }, "jest-get-type": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.3.1.tgz", - "integrity": "sha512-+Ilqi8hgHSAdhlQ3s12CAVNd8H96ZkQBfYoXmArzZnOfAtVAJEiPDBirjByEblvG/4LPJmkL+nBqPO3A1YJAEg==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", + "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==", "dev": true }, "jest-haste-map": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.3.1.tgz", - "integrity": "sha512-lYfNZIzwPccDJZIyk9Iz5iQMM/MH56NIIcGj7AFU1YyA4ewWFBl8z+YPJuSCRML/ee2cCt2y3W4K3VXPT6Nhzg==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.5.1.tgz", + "integrity": "sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==", "dev": true, "requires": { - "@jest/types": "^27.2.5", + "@jest/types": "^27.5.1", "@types/graceful-fs": "^4.1.2", "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", "fsevents": "^2.3.2", - "graceful-fs": "^4.2.4", - "jest-regex-util": "^27.0.6", - "jest-serializer": "^27.0.6", - "jest-util": "^27.3.1", - "jest-worker": "^27.3.1", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^27.5.1", + "jest-serializer": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", "micromatch": "^4.0.4", "walker": "^1.0.7" } }, "jest-jasmine2": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-27.3.1.tgz", - "integrity": "sha512-WK11ZUetDQaC09w4/j7o4FZDUIp+4iYWH/Lik34Pv7ukL+DuXFGdnmmi7dT58J2ZYKFB5r13GyE0z3NPeyJmsg==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-27.5.1.tgz", + "integrity": "sha512-jtq7VVyG8SqAorDpApwiJJImd0V2wv1xzdheGHRGyuT7gZm6gG47QEskOlzsN1PG/6WNaCo5pmwMHDf3AkG2pQ==", "dev": true, "requires": { - "@babel/traverse": "^7.1.0", - "@jest/environment": "^27.3.1", - "@jest/source-map": "^27.0.6", - "@jest/test-result": "^27.3.1", - "@jest/types": "^27.2.5", + "@jest/environment": "^27.5.1", + "@jest/source-map": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", "@types/node": "*", "chalk": "^4.0.0", "co": "^4.6.0", - "expect": "^27.3.1", + "expect": "^27.5.1", "is-generator-fn": "^2.0.0", - "jest-each": "^27.3.1", - "jest-matcher-utils": "^27.3.1", - "jest-message-util": "^27.3.1", - "jest-runtime": "^27.3.1", - "jest-snapshot": "^27.3.1", - "jest-util": "^27.3.1", - "pretty-format": "^27.3.1", + "jest-each": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1", "throat": "^6.0.1" } }, "jest-leak-detector": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-27.3.1.tgz", - "integrity": "sha512-78QstU9tXbaHzwlRlKmTpjP9k4Pvre5l0r8Spo4SbFFVy/4Abg9I6ZjHwjg2QyKEAMg020XcjP+UgLZIY50yEg==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-27.5.1.tgz", + "integrity": "sha512-POXfWAMvfU6WMUXftV4HolnJfnPOGEu10fscNCA76KBpRRhcMN2c8d3iT2pxQS3HLbA+5X4sOUPzYO2NUyIlHQ==", "dev": true, "requires": { - "jest-get-type": "^27.3.1", - "pretty-format": "^27.3.1" + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" } }, "jest-matcher-utils": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.3.1.tgz", - "integrity": "sha512-hX8N7zXS4k+8bC1Aj0OWpGb7D3gIXxYvPNK1inP5xvE4ztbz3rc4AkI6jGVaerepBnfWB17FL5lWFJT3s7qo8w==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz", + "integrity": "sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==", "dev": true, "requires": { "chalk": "^4.0.0", - "jest-diff": "^27.3.1", - "jest-get-type": "^27.3.1", - "pretty-format": "^27.3.1" + "jest-diff": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" } }, "jest-message-util": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.3.1.tgz", - "integrity": "sha512-bh3JEmxsTZ/9rTm0jQrPElbY2+y48Rw2t47uMfByNyUVR+OfPh4anuyKsGqsNkXk/TI4JbLRZx+7p7Hdt6q1yg==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", + "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", "dev": true, "requires": { "@babel/code-frame": "^7.12.13", - "@jest/types": "^27.2.5", + "@jest/types": "^27.5.1", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", - "graceful-fs": "^4.2.4", + "graceful-fs": "^4.2.9", "micromatch": "^4.0.4", - "pretty-format": "^27.3.1", + "pretty-format": "^27.5.1", "slash": "^3.0.0", "stack-utils": "^2.0.3" } }, "jest-mock": { - "version": "27.3.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.3.0.tgz", - "integrity": "sha512-ziZiLk0elZOQjD08bLkegBzv5hCABu/c8Ytx45nJKkysQwGaonvmTxwjLqEA4qGdasq9o2I8/HtdGMNnVsMTGw==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz", + "integrity": "sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==", "dev": true, "requires": { - "@jest/types": "^27.2.5", + "@jest/types": "^27.5.1", "@types/node": "*" } }, @@ -18595,157 +17618,150 @@ "requires": {} }, "jest-regex-util": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.0.6.tgz", - "integrity": "sha512-SUhPzBsGa1IKm8hx2F4NfTGGp+r7BXJ4CulsZ1k2kI+mGLG+lxGrs76veN2LF/aUdGosJBzKgXmNCw+BzFqBDQ==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", + "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==", "dev": true }, "jest-resolve": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.3.1.tgz", - "integrity": "sha512-Dfzt25CFSPo3Y3GCbxynRBZzxq9AdyNN+x/v2IqYx6KVT5Z6me2Z/PsSGFSv3cOSUZqJ9pHxilao/I/m9FouLw==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.5.1.tgz", + "integrity": "sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw==", "dev": true, "requires": { - "@jest/types": "^27.2.5", + "@jest/types": "^27.5.1", "chalk": "^4.0.0", - "graceful-fs": "^4.2.4", - "jest-haste-map": "^27.3.1", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", "jest-pnp-resolver": "^1.2.2", - "jest-util": "^27.3.1", - "jest-validate": "^27.3.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", "resolve": "^1.20.0", "resolve.exports": "^1.1.0", "slash": "^3.0.0" } }, "jest-resolve-dependencies": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-27.3.1.tgz", - "integrity": "sha512-X7iLzY8pCiYOnvYo2YrK3P9oSE8/3N2f4pUZMJ8IUcZnT81vlSonya1KTO9ZfKGuC+svE6FHK/XOb8SsoRUV1A==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-27.5.1.tgz", + "integrity": "sha512-QQOOdY4PE39iawDn5rzbIePNigfe5B9Z91GDD1ae/xNDlu9kaat8QQ5EKnNmVWPV54hUdxCVwwj6YMgR2O7IOg==", "dev": true, "requires": { - "@jest/types": "^27.2.5", - "jest-regex-util": "^27.0.6", - "jest-snapshot": "^27.3.1" + "@jest/types": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-snapshot": "^27.5.1" } }, "jest-runner": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-27.3.1.tgz", - "integrity": "sha512-r4W6kBn6sPr3TBwQNmqE94mPlYVn7fLBseeJfo4E2uCTmAyDFm2O5DYAQAFP7Q3YfiA/bMwg8TVsciP7k0xOww==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-27.5.1.tgz", + "integrity": "sha512-g4NPsM4mFCOwFKXO4p/H/kWGdJp9V8kURY2lX8Me2drgXqG7rrZAx5kv+5H7wtt/cdFIjhqYx1HrlqWHaOvDaQ==", "dev": true, "requires": { - "@jest/console": "^27.3.1", - "@jest/environment": "^27.3.1", - "@jest/test-result": "^27.3.1", - "@jest/transform": "^27.3.1", - "@jest/types": "^27.2.5", + "@jest/console": "^27.5.1", + "@jest/environment": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", "@types/node": "*", "chalk": "^4.0.0", "emittery": "^0.8.1", - "exit": "^0.1.2", - "graceful-fs": "^4.2.4", - "jest-docblock": "^27.0.6", - "jest-environment-jsdom": "^27.3.1", - "jest-environment-node": "^27.3.1", - "jest-haste-map": "^27.3.1", - "jest-leak-detector": "^27.3.1", - "jest-message-util": "^27.3.1", - "jest-resolve": "^27.3.1", - "jest-runtime": "^27.3.1", - "jest-util": "^27.3.1", - "jest-worker": "^27.3.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^27.5.1", + "jest-environment-jsdom": "^27.5.1", + "jest-environment-node": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-leak-detector": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", "source-map-support": "^0.5.6", "throat": "^6.0.1" } }, "jest-runtime": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.3.1.tgz", - "integrity": "sha512-qtO6VxPbS8umqhEDpjA4pqTkKQ1Hy4ZSi9mDVeE9Za7LKBo2LdW2jmT+Iod3XFaJqINikZQsn2wEi0j9wPRbLg==", - "dev": true, - "requires": { - "@jest/console": "^27.3.1", - "@jest/environment": "^27.3.1", - "@jest/globals": "^27.3.1", - "@jest/source-map": "^27.0.6", - "@jest/test-result": "^27.3.1", - "@jest/transform": "^27.3.1", - "@jest/types": "^27.2.5", - "@types/yargs": "^16.0.0", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.5.1.tgz", + "integrity": "sha512-o7gxw3Gf+H2IGt8fv0RiyE1+r83FJBRruoA+FXrlHw6xEyBsU8ugA6IPfTdVyA0w8HClpbK+DGJxH59UrNMx8A==", + "dev": true, + "requires": { + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/globals": "^27.5.1", + "@jest/source-map": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", "chalk": "^4.0.0", "cjs-module-lexer": "^1.0.0", "collect-v8-coverage": "^1.0.0", "execa": "^5.0.0", - "exit": "^0.1.2", "glob": "^7.1.3", - "graceful-fs": "^4.2.4", - "jest-haste-map": "^27.3.1", - "jest-message-util": "^27.3.1", - "jest-mock": "^27.3.0", - "jest-regex-util": "^27.0.6", - "jest-resolve": "^27.3.1", - "jest-snapshot": "^27.3.1", - "jest-util": "^27.3.1", - "jest-validate": "^27.3.1", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-mock": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", "slash": "^3.0.0", - "strip-bom": "^4.0.0", - "yargs": "^16.2.0" + "strip-bom": "^4.0.0" } }, "jest-serializer": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.0.6.tgz", - "integrity": "sha512-PtGdVK9EGC7dsaziskfqaAPib6wTViY3G8E5wz9tLVPhHyiDNTZn/xjZ4khAw+09QkoOVpn7vF5nPSN6dtBexA==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.5.1.tgz", + "integrity": "sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==", "dev": true, "requires": { "@types/node": "*", - "graceful-fs": "^4.2.4" + "graceful-fs": "^4.2.9" } }, "jest-snapshot": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-27.3.1.tgz", - "integrity": "sha512-APZyBvSgQgOT0XumwfFu7X3G5elj6TGhCBLbBdn3R1IzYustPGPE38F51dBWMQ8hRXa9je0vAdeVDtqHLvB6lg==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-27.5.1.tgz", + "integrity": "sha512-yYykXI5a0I31xX67mgeLw1DZ0bJB+gpq5IpSuCAoyDi0+BhgU/RIrL+RTzDmkNTchvDFWKP8lp+w/42Z3us5sA==", "dev": true, "requires": { "@babel/core": "^7.7.2", "@babel/generator": "^7.7.2", - "@babel/parser": "^7.7.2", "@babel/plugin-syntax-typescript": "^7.7.2", "@babel/traverse": "^7.7.2", "@babel/types": "^7.0.0", - "@jest/transform": "^27.3.1", - "@jest/types": "^27.2.5", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", "@types/babel__traverse": "^7.0.4", "@types/prettier": "^2.1.5", "babel-preset-current-node-syntax": "^1.0.0", "chalk": "^4.0.0", - "expect": "^27.3.1", - "graceful-fs": "^4.2.4", - "jest-diff": "^27.3.1", - "jest-get-type": "^27.3.1", - "jest-haste-map": "^27.3.1", - "jest-matcher-utils": "^27.3.1", - "jest-message-util": "^27.3.1", - "jest-resolve": "^27.3.1", - "jest-util": "^27.3.1", + "expect": "^27.5.1", + "graceful-fs": "^4.2.9", + "jest-diff": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-util": "^27.5.1", "natural-compare": "^1.4.0", - "pretty-format": "^27.3.1", + "pretty-format": "^27.5.1", "semver": "^7.3.2" } }, "jest-util": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.3.1.tgz", - "integrity": "sha512-8fg+ifEH3GDryLQf/eKZck1DEs2YuVPBCMOaHQxVVLmQwl/CDhWzrvChTX4efLZxGrw+AA0mSXv78cyytBt/uw==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", "dev": true, "requires": { - "@jest/types": "^27.2.5", + "@jest/types": "^27.5.1", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", - "graceful-fs": "^4.2.4", + "graceful-fs": "^4.2.9", "picomatch": "^2.2.3" }, "dependencies": { @@ -18758,46 +17774,46 @@ } }, "jest-validate": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-27.3.1.tgz", - "integrity": "sha512-3H0XCHDFLA9uDII67Bwi1Vy7AqwA5HqEEjyy934lgVhtJ3eisw6ShOF1MDmRPspyikef5MyExvIm0/TuLzZ86Q==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-27.5.1.tgz", + "integrity": "sha512-thkNli0LYTmOI1tDB3FI1S1RTp/Bqyd9pTarJwL87OIBFuqEb5Apv5EaApEudYg4g86e3CT6kM0RowkhtEnCBQ==", "dev": true, "requires": { - "@jest/types": "^27.2.5", + "@jest/types": "^27.5.1", "camelcase": "^6.2.0", "chalk": "^4.0.0", - "jest-get-type": "^27.3.1", + "jest-get-type": "^27.5.1", "leven": "^3.1.0", - "pretty-format": "^27.3.1" + "pretty-format": "^27.5.1" }, "dependencies": { "camelcase": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", - "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true } } }, "jest-watcher": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-27.3.1.tgz", - "integrity": "sha512-9/xbV6chABsGHWh9yPaAGYVVKurWoP3ZMCv6h+O1v9/+pkOroigs6WzZ0e9gLP/njokUwM7yQhr01LKJVMkaZA==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-27.5.1.tgz", + "integrity": "sha512-z676SuD6Z8o8qbmEGhoEUFOM1+jfEiL3DXHK/xgEiG2EyNYfFG60jluWcupY6dATjfEsKQuibReS1djInQnoVw==", "dev": true, "requires": { - "@jest/test-result": "^27.3.1", - "@jest/types": "^27.2.5", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", - "jest-util": "^27.3.1", + "jest-util": "^27.5.1", "string-length": "^4.0.1" } }, "jest-worker": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.3.1.tgz", - "integrity": "sha512-ks3WCzsiZaOPJl/oMsDjaf0TRiSv7ctNgs0FqRr2nARsovz6AWWy4oLElwcquGSz692DzgZQrCLScPNs5YlC4g==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", "dev": true, "requires": { "@types/node": "*", @@ -18873,9 +17889,9 @@ }, "dependencies": { "ws": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.5.tgz", - "integrity": "sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w==", + "version": "7.5.7", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz", + "integrity": "sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==", "dev": true, "requires": {} } @@ -18909,9 +17925,9 @@ "dev": true }, "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", "dev": true }, "json-schema-traverse": { @@ -18951,12 +17967,6 @@ "universalify": "^2.0.0" } }, - "jsonify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", - "dev": true - }, "jsonwebtoken": { "version": "8.5.1", "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", @@ -18984,14 +17994,14 @@ } }, "jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", + "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", "dev": true, "requires": { "assert-plus": "1.0.0", "extsprintf": "1.3.0", - "json-schema": "0.2.3", + "json-schema": "0.4.0", "verror": "1.10.0" } }, @@ -19055,15 +18065,15 @@ } }, "karma": { - "version": "6.3.7", - "resolved": "https://registry.npmjs.org/karma/-/karma-6.3.7.tgz", - "integrity": "sha512-EEkswZhOx3EFt1ELlVECeOXHONbHSGw6fkbeMxvCSkLD77X38Kb1d/Oup2Re9ep/tSoa1He3YIBf3Hp+9EsKtg==", + "version": "6.3.17", + "resolved": "https://registry.npmjs.org/karma/-/karma-6.3.17.tgz", + "integrity": "sha512-2TfjHwrRExC8yHoWlPBULyaLwAFmXmxQrcuFImt/JsAsSZu1uOWTZ1ZsWjqQtWpHLiatJOHL5jFjXSJIgCd01g==", "dev": true, "requires": { + "@colors/colors": "1.5.0", "body-parser": "^1.19.0", "braces": "^3.0.2", "chokidar": "^3.5.1", - "colors": "^1.4.0", "connect": "^3.7.0", "di": "^0.0.1", "dom-serialize": "^2.2.1", @@ -19072,9 +18082,10 @@ "http-proxy": "^1.18.1", "isbinaryfile": "^4.0.8", "lodash": "^4.17.21", - "log4js": "^6.3.0", + "log4js": "^6.4.1", "mime": "^2.5.2", "minimatch": "^3.0.4", + "mkdirp": "^0.5.5", "qjobs": "^1.2.0", "range-parser": "^1.2.1", "rimraf": "^3.0.2", @@ -19083,12 +18094,23 @@ "tmp": "^0.2.1", "ua-parser-js": "^0.7.30", "yargs": "^16.1.1" + }, + "dependencies": { + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + } } }, "karma-chrome-launcher": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-3.1.0.tgz", - "integrity": "sha512-3dPs/n7vgz1rxxtynpzZTvb9y/GIaW8xjAwcIGttLbycqoFtI7yo1NGnQi6oFTherRE+GIhCAHZC4vEqWGhNvg==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-3.1.1.tgz", + "integrity": "sha512-hsIglcq1vtboGPAN+DGCISCFOxW+ZVnIqhDQcCMqqCp+4dmJ0Qpq5QAjkbA0X2L9Mi6OBkHi2Srrbmm7pUKkzQ==", "dev": true, "requires": { "which": "^1.2.1" @@ -19106,16 +18128,16 @@ } }, "karma-coverage": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/karma-coverage/-/karma-coverage-2.0.3.tgz", - "integrity": "sha512-atDvLQqvPcLxhED0cmXYdsPMCQuh6Asa9FMZW1bhNqlVEhJoB9qyZ2BY1gu7D/rr5GLGb5QzYO4siQskxaWP/g==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/karma-coverage/-/karma-coverage-2.2.0.tgz", + "integrity": "sha512-gPVdoZBNDZ08UCzdMHHhEImKrw1+PAOQOIiffv1YsvxFhBjqvo/SVXNk4tqn1SYqX0BJZT6S/59zgxiBe+9OuA==", "dev": true, "requires": { - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^4.0.1", + "istanbul-lib-coverage": "^3.2.0", + "istanbul-lib-instrument": "^5.1.0", "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.1", + "istanbul-reports": "^3.0.5", "minimatch": "^3.0.4" } }, @@ -19136,12 +18158,20 @@ "dev": true, "requires": { "jasmine-core": "^3.6.0" + }, + "dependencies": { + "jasmine-core": { + "version": "3.99.0", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.99.0.tgz", + "integrity": "sha512-+ZDaJlEfRopINQqgE+hvzRyDIQDeKfqqTvF8RzXsvU1yE3pBDRud2+Qfh9WvGgRpuzqxyQJVI6Amy5XQ11r/3w==", + "dev": true + } } }, "karma-rollup-preprocessor": { - "version": "7.0.7", - "resolved": "https://registry.npmjs.org/karma-rollup-preprocessor/-/karma-rollup-preprocessor-7.0.7.tgz", - "integrity": "sha512-Y1QwsTCiCBp8sSALZdqmqry/mWIWIy0V6zonUIpy+0/D/Kpb2XZvR+JZrWfacQvcvKQdZFJvg6EwlnKtjepu3Q==", + "version": "7.0.8", + "resolved": "https://registry.npmjs.org/karma-rollup-preprocessor/-/karma-rollup-preprocessor-7.0.8.tgz", + "integrity": "sha512-WiuBCS9qsatJuR17dghiTARBZ7LF+ml+eb7qJXhw7IbsdY0lTWELDRQC/93J9i6636CsAXVBL3VJF4WtaFLZzA==", "dev": true, "requires": { "chokidar": "^3.3.1", @@ -19155,6 +18185,15 @@ "dev": true, "requires": {} }, + "karma-spec-reporter": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/karma-spec-reporter/-/karma-spec-reporter-0.0.33.tgz", + "integrity": "sha512-xRVevDUkiIVhKbDQ3CmeGEpyzA4b3HeVl95Sx5yJAvurpdKUSYF6ZEbQOqKJ7vrtDniABV1hyFez9KX9+7ruBA==", + "dev": true, + "requires": { + "colors": "1.4.0" + } + }, "keyv": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.0.0.tgz", @@ -19259,13 +18298,13 @@ } }, "lighthouse-logger": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/lighthouse-logger/-/lighthouse-logger-1.2.0.tgz", - "integrity": "sha512-wzUvdIeJZhRsG6gpZfmSCfysaxNEr43i+QT+Hie94wvHDKFLi4n7C2GqZ4sTC+PH5b5iktmXJvU87rWvhP3lHw==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/lighthouse-logger/-/lighthouse-logger-1.3.0.tgz", + "integrity": "sha512-BbqAKApLb9ywUli+0a+PcV04SyJ/N1q/8qgCNe6U97KbPCS1BTksEuHFLYdvc8DltuhfxIUBqDZsC0bBGtl3lA==", "dev": true, "requires": { - "debug": "^2.6.8", - "marky": "^1.2.0" + "debug": "^2.6.9", + "marky": "^1.2.2" }, "dependencies": { "debug": { @@ -19306,12 +18345,6 @@ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, - "lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", - "dev": true - }, "lodash.includes": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", @@ -19366,31 +18399,17 @@ "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=", "dev": true }, - "lodash.truncate": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", - "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", - "dev": true - }, "log4js": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.3.0.tgz", - "integrity": "sha512-Mc8jNuSFImQUIateBFwdOQcmC6Q5maU0VVvdC2R6XMb66/VnT+7WS4D/0EeNMZu1YODmJe5NIn2XftCzEocUgw==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.4.1.tgz", + "integrity": "sha512-iUiYnXqAmNKiIZ1XSAitQ4TmNs8CdZYTAWINARF3LjnsLN8tY5m0vRwd6uuWj/yNY0YHxeZodnbmxKFUOM2rMg==", "dev": true, "requires": { - "date-format": "^3.0.0", - "debug": "^4.1.1", - "flatted": "^2.0.1", - "rfdc": "^1.1.4", - "streamroller": "^2.2.4" - }, - "dependencies": { - "flatted": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", - "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", - "dev": true - } + "date-format": "^4.0.3", + "debug": "^4.3.3", + "flatted": "^3.2.4", + "rfdc": "^1.3.0", + "streamroller": "^3.0.2" } }, "lowercase-keys": { @@ -19450,9 +18469,9 @@ } }, "malevic": { - "version": "0.18.6", - "resolved": "https://registry.npmjs.org/malevic/-/malevic-0.18.6.tgz", - "integrity": "sha512-Um4XRYJpVDhKjRRteiuHdDmcNbI5gX7URsXC6G+5Tk0Dai2W2RB39kg5C/M32IezNPudT+YsgApBh8JG6fIWrA==", + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/malevic/-/malevic-0.19.1.tgz", + "integrity": "sha512-Om8ryj2MufYydPSNM6DbBYQCCPlp5mgtOrrgQKw6tCZwUIXPFsyfM3d5S/2RIEAsQDYYZpIctM+SX55Fkv5r4w==", "dev": true }, "map-age-cleaner": { @@ -19574,9 +18593,9 @@ } }, "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", "dev": true }, "mkdirp": { @@ -19585,10 +18604,16 @@ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "dev": true }, + "mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "dev": true + }, "moment": { - "version": "2.29.1", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", - "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==", + "version": "2.29.2", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.2.tgz", + "integrity": "sha512-UgzG4rvxYpN15jgCmVJwac49h9ly9NurikMWGPdVxm8GZD6XjkKPxDTjQQ43gtGgnV3X0cAyWDdP2Wexoquifg==", "dev": true, "optional": true }, @@ -19678,9 +18703,9 @@ "optional": true }, "nanoid": { - "version": "3.1.30", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.30.tgz", - "integrity": "sha512-zJpuPDwOv8D2zq2WRoMe1HsfZthVewpel9CAvTfc/2mBD1uUT/agc5f7GHGWXlYkFvi1mVxe4IjvP2HNrop7nQ==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", + "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==", "dev": true }, "natural-compare": { @@ -19689,12 +18714,6 @@ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, - "natural-compare-lite": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", - "integrity": "sha1-F7CVgZiJef3a/gIB6TG6kzyWy7Q=", - "dev": true - }, "ncp": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz", @@ -19719,25 +18738,52 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, - "optional": true, + "optional": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "dev": true + }, + "node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dev": true, + "requires": { + "whatwg-url": "^5.0.0" + }, + "dependencies": { + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", + "dev": true + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=", + "dev": true + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "dev": true, "requires": { - "ms": "^2.1.1" + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" } } } }, - "negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", - "dev": true - }, - "node-fetch": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", - "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==", - "dev": true - }, "node-forge": { "version": "0.10.0", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz", @@ -19750,16 +18796,10 @@ "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=", "dev": true }, - "node-modules-regexp": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz", - "integrity": "sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=", - "dev": true - }, "node-releases": { - "version": "1.1.72", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.72.tgz", - "integrity": "sha512-LLUo+PpH3dU6XizX3iVoubUNheF/owjXCZZ5yACDxNnPtgFuludV1ZL3ayK1kVep42Rmm0+R9/Y60NQbZ2bifw==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.2.tgz", + "integrity": "sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg==", "dev": true }, "normalize-path": { @@ -19861,6 +18901,12 @@ "es-abstract": "^1.19.1" } }, + "on-exit-leak-free": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-0.2.0.tgz", + "integrity": "sha512-dqaz3u44QbRXQooZLTUKU41ZrzYrcvLISVgbrzbyCMxpmSLJvZ3ZamIJIZ29P6OhZIkNIQKosdeM6t1LYbA9hg==", + "dev": true + }, "on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", @@ -19940,6 +18986,15 @@ "strip-final-newline": "^2.0.0" } }, + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, "human-signals": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", @@ -20066,6 +19121,15 @@ } } }, + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, "got": { "version": "9.6.0", "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", @@ -20188,15 +19252,6 @@ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true }, - "path-is-network-drive": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/path-is-network-drive/-/path-is-network-drive-1.0.10.tgz", - "integrity": "sha512-D6kJYPUSKGZBpTM2nv10sOWNdC056p4JDx0y7ARe6gop0aXXm5G86Gn/SyKvaf0Ce8c9Guctf+J+qoFmzuhDQg==", - "dev": true, - "requires": { - "tslib": "^2.3.1" - } - }, "path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -20209,15 +19264,6 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, - "path-strip-sep": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-strip-sep/-/path-strip-sep-1.0.7.tgz", - "integrity": "sha512-9xDVZPblHde4lTuTDnwqBKr9LTbPZW+Iae63ho500+BpEiZe3X6wvLInHgbB6FSMtwCTvztljw3k2zcNDNESzg==", - "dev": true, - "requires": { - "tslib": "^2.3.1" - } - }, "path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", @@ -20244,9 +19290,9 @@ "dev": true }, "picocolors": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", - "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", "dev": true }, "picomatch": { @@ -20279,34 +19325,44 @@ } }, "pino": { - "version": "6.13.3", - "resolved": "https://registry.npmjs.org/pino/-/pino-6.13.3.tgz", - "integrity": "sha512-tJy6qVgkh9MwNgqX1/oYi3ehfl2Y9H0uHyEEMsBe74KinESIjdMrMQDWpcZPpPicg3VV35d/GLQZmo4QgU2Xkg==", + "version": "7.9.1", + "resolved": "https://registry.npmjs.org/pino/-/pino-7.9.1.tgz", + "integrity": "sha512-28+D7c5orCoScdcWtiPXrCA9tdVosBWrYQgVtPdYTyiuTt6u/+rbEtpJR+dtVG8k1flhv0H2f0XSkgGm+TdjqQ==", "dev": true, "requires": { "fast-redact": "^3.0.0", - "fast-safe-stringify": "^2.0.8", - "fastify-warning": "^0.2.0", - "flatstr": "^1.0.12", - "pino-std-serializers": "^3.1.0", + "on-exit-leak-free": "^0.2.0", + "pino-abstract-transport": "v0.5.0", + "pino-std-serializers": "^4.0.0", + "process-warning": "^1.0.0", "quick-format-unescaped": "^4.0.3", - "sonic-boom": "^1.0.2" + "real-require": "^0.1.0", + "safe-stable-stringify": "^2.1.0", + "sonic-boom": "^2.2.1", + "thread-stream": "^0.13.0" + } + }, + "pino-abstract-transport": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-0.5.0.tgz", + "integrity": "sha512-+KAgmVeqXYbTtU2FScx1XS3kNyfZ5TrXY07V96QnUSFqo2gAqlvmaxH67Lj7SWazqsMabf+58ctdTcBgnOLUOQ==", + "dev": true, + "requires": { + "duplexify": "^4.1.2", + "split2": "^4.0.0" } }, "pino-std-serializers": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-3.2.0.tgz", - "integrity": "sha512-EqX4pwDPrt3MuOAAUBMU0Tk5kR/YcCM5fNPEzgCO2zJ5HfX0vbiH9HbJglnyeQsN96Kznae6MWD47pZB5avTrg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-4.0.0.tgz", + "integrity": "sha512-cK0pekc1Kjy5w9V2/n+8MkZwusa6EyyxfeQCB799CQRhRt/CqYKiWs5adeu8Shve2ZNffvfC/7J64A2PJo1W/Q==", "dev": true }, "pirates": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.1.tgz", - "integrity": "sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA==", - "dev": true, - "requires": { - "node-modules-regexp": "^1.0.0" - } + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.4.tgz", + "integrity": "sha512-ZIrVPH+A52Dw84R0L3/VS9Op04PuQ2SEoJL6bkshmiTic/HldyW9Tf7oH5mhJZBK7NmDx27vSMrYEXPXclpDKw==", + "dev": true }, "pkg-dir": { "version": "4.2.0", @@ -20318,14 +19374,14 @@ } }, "postcss": { - "version": "8.3.9", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.3.9.tgz", - "integrity": "sha512-f/ZFyAKh9Dnqytx5X62jgjhhzttjZS7hMsohcI7HEI5tjELX/HxCy3EFhsRxyzGvrzFF+82XPvCS8T9TFleVJw==", + "version": "8.4.12", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.12.tgz", + "integrity": "sha512-lg6eITwYe9v6Hr5CncVbK70SoioNQIq81nsaG86ev5hAidQvmOeETBqs7jm43K2F5/Ley3ytDtriImV6TpNiSg==", "dev": true, "requires": { - "nanoid": "^3.1.28", - "picocolors": "^0.2.1", - "source-map-js": "^0.6.2" + "nanoid": "^3.3.1", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" } }, "prelude-ls": { @@ -20341,18 +19397,17 @@ "dev": true }, "prettier": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.4.1.tgz", - "integrity": "sha512-9fbDAXSBcc6Bs1mZrDYb3XKzDLm4EXXL9sC1LqKP5rZkT6KRr/rf9amVUcODVXgguK/isJz0d0hP72WeaKWsvA==", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.6.1.tgz", + "integrity": "sha512-8UVbTBYGwN37Bs9LERmxCPjdvPxlEowx2urIL6urHzdb3SDq4B/Z6xLFCblrSnE4iKWcS6ziJ3aOYrc1kz/E2A==", "dev": true }, "pretty-format": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.3.1.tgz", - "integrity": "sha512-DR/c+pvFc52nLimLROYjnXPtolawm+uWDxr4FjuLDLUn+ktWnSN851KoHwHzzqq6rfCOjkzN8FLgDrSub6UDuA==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", "dev": true, "requires": { - "@jest/types": "^27.2.5", "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", "react-is": "^17.0.1" @@ -20372,12 +19427,27 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, + "process-warning": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-1.0.0.tgz", + "integrity": "sha512-du4wfLyj4yCZq1VupnVSZmRsPJsNuxoDQFdCFHLaYiEbFBD7QE0a+I4D7hOxrVnh78QE/YipFAj9lXHiXocV+Q==", + "dev": true + }, "progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "dev": true }, + "promise-toolbox": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/promise-toolbox/-/promise-toolbox-0.20.0.tgz", + "integrity": "sha512-VXF6waqUheD19yOU7zxsXhw/HCKlXqXwUc4jM8mchtBqZFNA+GHA7dbJsQDLHP4IUpQuTLpCQRd0lCr5z4CqXQ==", + "dev": true, + "requires": { + "make-error": "^1.3.2" + } + }, "prompts": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", @@ -20444,48 +19514,23 @@ } }, "puppeteer-core": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-10.4.0.tgz", - "integrity": "sha512-KU8zyb7AIOqNjLCN3wkrFXxh+EVaG+zrs2P03ATNjc3iwSxHsu5/EvZiREpQ/IJiT9xfQbDVgKcsvRuzLCxglQ==", + "version": "13.5.1", + "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-13.5.1.tgz", + "integrity": "sha512-dobVqWjV34ilyfQHR3BBnCYaekBYTi5MgegEYBRYd3s3uFy8jUpZEEWbaFjG9ETm+LGzR5Lmr0aF6LLuHtiuCg==", "dev": true, "requires": { - "debug": "4.3.1", - "devtools-protocol": "0.0.901419", + "cross-fetch": "3.1.5", + "debug": "4.3.3", + "devtools-protocol": "0.0.969999", "extract-zip": "2.0.1", "https-proxy-agent": "5.0.0", - "node-fetch": "2.6.1", "pkg-dir": "4.2.0", - "progress": "2.0.1", + "progress": "2.0.3", "proxy-from-env": "1.1.0", "rimraf": "3.0.2", - "tar-fs": "2.0.0", - "unbzip2-stream": "1.3.3", - "ws": "7.4.6" - }, - "dependencies": { - "progress": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.1.tgz", - "integrity": "sha512-OE+a6vzqazc+K6LxJrX5UPyKFvGnL5CYmq2jFGNIBWHpc4QyE49/YOumcrpQFJpfejmvRtbJzgO1zPmMCqlbBg==", - "dev": true - }, - "unbzip2-stream": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.3.3.tgz", - "integrity": "sha512-fUlAF7U9Ah1Q6EieQ4x4zLNejrRvDWUYmxXUpN3uziFYCHapjWFaCAnreY9bGgxzaMCFAPPpYNng57CypwJVhg==", - "dev": true, - "requires": { - "buffer": "^5.2.1", - "through": "^2.3.8" - } - }, - "ws": { - "version": "7.4.6", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", - "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", - "dev": true, - "requires": {} - } + "tar-fs": "2.1.1", + "unbzip2-stream": "1.4.3", + "ws": "8.5.0" } }, "qjobs": { @@ -20495,9 +19540,9 @@ "dev": true }, "qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "version": "6.9.6", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.6.tgz", + "integrity": "sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ==", "dev": true }, "query-string": { @@ -20540,13 +19585,13 @@ "dev": true }, "raw-body": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", - "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.2.tgz", + "integrity": "sha512-RPMAFUJP19WIet/99ngh6Iv8fzAbqum4Li7AD6DtGaW2RpMB/11xDoalPiJMTbu6I3hkbMVkATvZrqb9EEqeeQ==", "dev": true, "requires": { - "bytes": "3.1.0", - "http-errors": "1.7.2", + "bytes": "3.1.1", + "http-errors": "1.8.1", "iconv-lite": "0.4.24", "unpipe": "1.0.0" } @@ -20603,6 +19648,12 @@ "picomatch": "^2.2.1" } }, + "real-require": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.1.0.tgz", + "integrity": "sha512-r/H9MzAWtrv8aSVjPCMFpDMl5q66GqtmmRkRjpHTsp4zBAa+snZyiQNlMONiUmEJcsnaw0wCauJ2GWODr/aFkg==", + "dev": true + }, "regenerator-runtime": { "version": "0.13.7", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", @@ -20610,9 +19661,9 @@ "dev": true }, "regexp.prototype.flags": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz", - "integrity": "sha512-JiBdRBq91WlY7uRJ0ds7R+dU02i6LKi8r3BuQhNXn+kmeLN+EfHhfjqMRis1zJxnlu88hq/4dx0P2OP3APRTOA==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.1.tgz", + "integrity": "sha512-pMR7hBVUUGI7PMA37m2ofIdQCsomVnas+Jn5UPGAHQ+/LlwKm/aTLJHdasmHRzlfeZwHiAOaRSo2rbBDm3nNUQ==", "dev": true, "requires": { "call-bind": "^1.0.2", @@ -20751,9 +19802,9 @@ } }, "qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", + "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", "dev": true }, "tough-cookie": { @@ -20780,12 +19831,6 @@ "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", "dev": true }, - "require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true - }, "requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", @@ -20862,9 +19907,9 @@ } }, "rollup": { - "version": "2.59.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.59.0.tgz", - "integrity": "sha512-l7s90JQhCQ6JyZjKgo7Lq1dKh2RxatOM+Jr6a9F7WbS9WgKbocyUSeLmZl8evAse7y96Ae98L2k1cBOwWD8nHw==", + "version": "2.70.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.70.1.tgz", + "integrity": "sha512-CRYsI5EuzLbXdxC6RnYhOuRdtz4bhejPMSWjsFLfVM/7w/85n2szZv6yExqUXsBdz5KT8eoubeyDUDjhLHEslA==", "dev": true, "requires": { "fsevents": "~2.3.2" @@ -20909,54 +19954,6 @@ } } }, - "rollup-plugin-typescript2": { - "version": "0.31.1", - "resolved": "https://registry.npmjs.org/rollup-plugin-typescript2/-/rollup-plugin-typescript2-0.31.1.tgz", - "integrity": "sha512-sklqXuQwQX+stKi4kDfEkneVESPi3YM/2S899vfRdF9Yi40vcC50Oq4A4cSZJNXsAQE/UsBZl5fAOsBLziKmjw==", - "dev": true, - "requires": { - "@rollup/pluginutils": "^4.1.0", - "@yarn-tool/resolve-package": "^1.0.36", - "find-cache-dir": "^3.3.1", - "fs-extra": "8.1.0", - "resolve": "1.20.0", - "tslib": "2.2.0" - }, - "dependencies": { - "fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "tslib": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz", - "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==", - "dev": true - }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true - } - } - }, "rollup-pluginutils": { "version": "2.8.2", "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", @@ -21006,6 +20003,12 @@ "dev": true, "optional": true }, + "safe-stable-stringify": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.3.1.tgz", + "integrity": "sha512-kYBSfT+troD9cDA85VDnHZ1rpHC50O0g1e6WlGHVCz/g+JS+9WKLj+XwFYyR8UbrZN8ll9HUpDAAddY58MGisg==", + "dev": true + }, "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -21064,9 +20067,9 @@ } }, "send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", - "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "version": "0.17.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz", + "integrity": "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==", "dev": true, "peer": true, "requires": { @@ -21077,9 +20080,9 @@ "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "0.5.2", - "http-errors": "~1.7.2", + "http-errors": "1.8.1", "mime": "1.6.0", - "ms": "2.1.1", + "ms": "2.1.3", "on-finished": "~2.3.0", "range-parser": "~1.2.1", "statuses": "~1.5.0" @@ -21112,25 +20115,25 @@ "peer": true }, "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true, "peer": true } } }, "serve-static": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", - "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.2.tgz", + "integrity": "sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==", "dev": true, "peer": true, "requires": { "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.17.1" + "send": "0.17.2" } }, "set-immediate-shim": { @@ -21140,9 +20143,9 @@ "dev": true }, "setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", "dev": true }, "sha.js": { @@ -21171,16 +20174,10 @@ "dev": true }, "shell-quote": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.6.1.tgz", - "integrity": "sha1-9HgZSczkAmlxJ0MOo7PFR29IF2c=", - "dev": true, - "requires": { - "array-filter": "~0.0.0", - "array-map": "~0.0.0", - "array-reduce": "~0.0.0", - "jsonify": "~0.0.0" - } + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz", + "integrity": "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==", + "dev": true }, "shellwords": { "version": "0.1.1", @@ -21200,20 +20197,20 @@ } }, "sign-addon": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/sign-addon/-/sign-addon-3.9.0.tgz", - "integrity": "sha512-a8IzM3jNPSHcf2wSkhLgME4QrIe+rKTb8y/qYwGGzby5ktODAH+WBsKIgGZ9p5d2mpppPwbNEsA+YzcL117bbA==", + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/sign-addon/-/sign-addon-3.11.0.tgz", + "integrity": "sha512-fcK2WzkMb8e8E9kvuccy+mrBTT81iR+1CowHLU594Elr4E9E9zZFr3itGlL0OoXcRouKmvt7rpXzoARu++tXRQ==", "dev": true, "requires": { - "common-tags": "1.8.0", - "core-js": "3.18.0", + "common-tags": "1.8.2", + "core-js": "3.21.0", "deepcopy": "2.1.0", "es6-error": "4.1.1", "es6-promisify": "7.0.0", "jsonwebtoken": "8.5.1", "mz": "2.7.0", "request": "2.88.2", - "source-map-support": "0.5.20", + "source-map-support": "0.5.21", "stream-to-promise": "3.0.0" } }, @@ -21235,46 +20232,24 @@ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true }, - "slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - } - }, "socket.io": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.3.1.tgz", - "integrity": "sha512-HC5w5Olv2XZ0XJ4gOLGzzHEuOCfj3G0SmoW3jLHYYh34EVsIr3EkW9h6kgfW+K3TFEcmYy8JcPWe//KUkBp5jA==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.4.1.tgz", + "integrity": "sha512-s04vrBswdQBUmuWJuuNTmXUVJhP0cVky8bBDhdkf8y0Ptsu7fKU2LuLbts9g+pdmAdyMMn8F/9Mf1/wbtUN0fg==", "dev": true, "requires": { "accepts": "~1.3.4", "base64id": "~2.0.0", "debug": "~4.3.2", - "engine.io": "~6.0.0", - "socket.io-adapter": "~2.3.2", + "engine.io": "~6.1.0", + "socket.io-adapter": "~2.3.3", "socket.io-parser": "~4.0.4" - }, - "dependencies": { - "debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - } } }, "socket.io-adapter": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.3.2.tgz", - "integrity": "sha512-PBZpxUPYjmoogY0aoaTmo1643JelsaS1CiAwNjRVdrI0X9Seuc19Y2Wife8k88avW6haG8cznvwbubAZwH4Mtg==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.3.3.tgz", + "integrity": "sha512-Qd/iwn3VskrpNO60BeRyCyr8ZWw9CPZyitW4AQwmRZ8zCiyDiL+znRnWX6tDHXnWn1sJrM1+b6Mn6wEDJJ4aYQ==", "dev": true }, "socket.io-parser": { @@ -21289,13 +20264,12 @@ } }, "sonic-boom": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-1.4.1.tgz", - "integrity": "sha512-LRHh/A8tpW7ru89lrlkU4AszXt1dbwSjVWguGrmlxE7tawVmDBlI1PILMkXAxJTwqhgsEeTHzj36D5CmHgQmNg==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-2.6.0.tgz", + "integrity": "sha512-6xYZFRmDEtxGqfOKcDQ4cPLrNa0SPEDI+wlzDAHowXE6YV42NeXqg9mP2KkiM8JVu3lHfZ2iQKYlGOz+kTpphg==", "dev": true, "requires": { - "atomic-sleep": "^1.0.0", - "flatstr": "^1.0.12" + "atomic-sleep": "^1.0.0" } }, "sort-keys": { @@ -21337,15 +20311,15 @@ "dev": true }, "source-map-js": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-0.6.2.tgz", - "integrity": "sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", "dev": true }, "source-map-support": { - "version": "0.5.20", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.20.tgz", - "integrity": "sha512-n1lZZ8Ve4ksRqizaBQgxXDgKwttHDhyfQjA6YZZn8+AroHbsIz+JjwxQDxbp+7y5OYCI8t1Yk7etjD9CRd2hIw==", + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, "requires": { "buffer-from": "^1.0.0", @@ -21377,6 +20351,12 @@ "through": "2" } }, + "split2": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.1.0.tgz", + "integrity": "sha512-VBiJxFkxiXRlUIeyMQi8s4hgvKCSjtknJv/LVYbrgALPwf5zSKmEwV9Lst25AkvMDnvxODugjdl6KZgwKM1WYQ==", + "dev": true + }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -21384,9 +20364,9 @@ "dev": true }, "sshpk": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", + "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", "dev": true, "requires": { "asn1": "~0.2.3", @@ -21415,6 +20395,12 @@ "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", "dev": true }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", + "dev": true + }, "stream-to-array": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/stream-to-array/-/stream-to-array-2.3.0.tgz", @@ -21436,48 +20422,14 @@ } }, "streamroller": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-2.2.4.tgz", - "integrity": "sha512-OG79qm3AujAM9ImoqgWEY1xG4HX+Lw+yY6qZj9R1K2mhF5bEmQ849wvrb+4vt4jLMLzwXttJlQbOdPOQVRv7DQ==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.0.2.tgz", + "integrity": "sha512-ur6y5S5dopOaRXBuRIZ1u6GC5bcEXHRZKgfBjfCglMhmIf+roVCECjvkEYzNQOXIN2/JPnkMPW/8B3CZoKaEPA==", "dev": true, "requires": { - "date-format": "^2.1.0", + "date-format": "^4.0.3", "debug": "^4.1.1", - "fs-extra": "^8.1.0" - }, - "dependencies": { - "date-format": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/date-format/-/date-format-2.1.0.tgz", - "integrity": "sha512-bYQuGLeFxhkxNOF3rcMtiZxvCBAquGzZm6oWA1oZ0g2THUzivaRhv8uOhdr19LmoobSOLoIAxeUK2RdbM8IFTA==", - "dev": true - }, - "fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true - } + "fs-extra": "^10.0.0" } }, "strict-uri-encode": { @@ -21645,61 +20597,16 @@ "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", "dev": true }, - "table": { - "version": "6.7.2", - "resolved": "https://registry.npmjs.org/table/-/table-6.7.2.tgz", - "integrity": "sha512-UFZK67uvyNivLeQbVtkiUs8Uuuxv24aSL4/Vil2PJVtMgU8Lx0CYkP12uCGa3kjyQzOSgV1+z9Wkb82fCGsO0g==", - "dev": true, - "requires": { - "ajv": "^8.0.1", - "lodash.clonedeep": "^4.5.0", - "lodash.truncate": "^4.4.2", - "slice-ansi": "^4.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1" - }, - "dependencies": { - "ajv": { - "version": "8.6.3", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.3.tgz", - "integrity": "sha512-SMJOdDP6LqTkD0Uq8qLi+gMwSt0imXLSV080qFVwJCpH9U6Mb+SUGHAXM0KNbcBPguytWyvFxcHgMLe2D2XSpw==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - } - } - }, "tar-fs": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.0.0.tgz", - "integrity": "sha512-vaY0obB6Om/fso8a8vakQBzwholQ7v5+uy+tF3Ozvxv1KNezmVQAiWtcNmMHFSFPqL3dJA8ha6gdtFbfX9mcxA==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", "dev": true, "requires": { "chownr": "^1.1.1", - "mkdirp": "^0.5.1", + "mkdirp-classic": "^0.5.2", "pump": "^3.0.0", - "tar-stream": "^2.0.0" - }, - "dependencies": { - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - } + "tar-stream": "^2.1.4" } }, "tar-stream": { @@ -21760,6 +20667,15 @@ "thenify": ">= 3.1.0 < 4" } }, + "thread-stream": { + "version": "0.13.2", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-0.13.2.tgz", + "integrity": "sha512-woZFt0cLFkPdhsa+IGpRo1jiSouaHxMIljzTgt30CMjBWoUYbbcHqnunW5Yv+BXko9H05MVIcxMipI3Jblallw==", + "dev": true, + "requires": { + "real-require": "^0.1.0" + } + }, "throat": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.1.tgz", @@ -21823,9 +20739,9 @@ } }, "toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", "dev": true }, "tosource": { @@ -21882,9 +20798,9 @@ } }, "ts-jest": { - "version": "27.0.7", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-27.0.7.tgz", - "integrity": "sha512-O41shibMqzdafpuP+CkrOL7ykbmLh+FqQrXEmV9CydQ5JBk0Sj0uAEF5TNNe94fZWKm3yYvWa/IbyV4Yg1zK2Q==", + "version": "27.1.4", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-27.1.4.tgz", + "integrity": "sha512-qjkZlVPWVctAezwsOD1OPzbZ+k7zA5z3oxII4dGdZo5ggX/PL7kvwTM0pXTr10fAtbiVpJaL3bWd502zAhpgSQ==", "dev": true, "requires": { "bs-logger": "0.x", @@ -21897,55 +20813,10 @@ "yargs-parser": "20.x" } }, - "ts-node": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.4.0.tgz", - "integrity": "sha512-g0FlPvvCXSIO1JDF6S232P5jPYqBkRL9qly81ZgAOSU7rwI0stphCgd2kLiCrU9DjQCrJMWEqcNSjQL02s6d8A==", - "dev": true, - "requires": { - "@cspotcode/source-map-support": "0.7.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "yn": "3.1.1" - }, - "dependencies": { - "acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", - "dev": true - } - } - }, - "ts-toolbelt": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/ts-toolbelt/-/ts-toolbelt-8.4.0.tgz", - "integrity": "sha512-hnGJXIgC49ZuF5g5oDthoge8t4cvT0dYg2pYO5C6yV/HmUUy1koooU2U/5K2N+Uw++hcXQpJAToLRa+GRp28Sg==", - "dev": true, - "peer": true - }, - "ts-type": { - "version": "1.2.40", - "resolved": "https://registry.npmjs.org/ts-type/-/ts-type-1.2.40.tgz", - "integrity": "sha512-Ux5e7Frys5pX7w8gYchEd0KfhG1H5puXOQC8yOBgMJ1aEwDSypeHLwxIUpKjecni1IGwtLI3JrxCVZaQO9JKmw==", - "dev": true, - "requires": { - "tslib": "^2.3.0", - "typedarray-dts": "^1.0.0" - } - }, "tsconfig-paths": { - "version": "3.11.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.11.0.tgz", - "integrity": "sha512-7ecdYDnIdmv639mmDwslG6KQg1Z9STTz1j7Gcz0xa+nshh/gKDAHcPxRbWOsA3SPp0tXP2leTcY9Kw+NAkfZzA==", + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.12.0.tgz", + "integrity": "sha512-e5adrnOYT6zqVnWqZu7i/BQ3BnhzvGbjEjejFXO20lKIKpwTaupkCPgEfv4GZK1IBciJUEhYs3J3p75FdaTFVg==", "dev": true, "requires": { "@types/json5": "^0.0.29", @@ -22046,12 +20917,6 @@ "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", "dev": true }, - "typedarray-dts": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typedarray-dts/-/typedarray-dts-1.0.0.tgz", - "integrity": "sha512-Ka0DBegjuV9IPYFT1h0Qqk5U4pccebNIJCGl8C5uU7xtOs+jpJvKGAY4fHGK25hTmXZOEUl9Cnsg5cS6K/b5DA==", - "dev": true - }, "typedarray-to-buffer": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", @@ -22062,9 +20927,9 @@ } }, "typescript": { - "version": "4.4.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.4.tgz", - "integrity": "sha512-DqGhF5IKoBl8WNf8C1gu8q0xZSInh9j1kJJMqT3a94w1JzVaBU4EXOSMrz9yDqMT0xt3selp83fuFMQ0uzv6qA==", + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz", + "integrity": "sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==", "dev": true }, "ua-parser-js": { @@ -22090,7 +20955,6 @@ "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", "dev": true, - "peer": true, "requires": { "buffer": "^5.2.1", "through": "^2.3.8" @@ -22123,18 +20987,6 @@ "integrity": "sha512-1uEe95xksV1O0CYKXo8vQvN1JEbtJp7lb7C5U9HMsIp6IVwntkH/oNUzyVNQSd4S1sYk2FpSSW44FqMc8qee5w==", "dev": true }, - "upath2": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/upath2/-/upath2-3.1.10.tgz", - "integrity": "sha512-7ph3GzTaVbQX+oIoMsGtM+9BAWQr+6Mn28TJKPu28+yGpZ+J4am590CPDBlDG0zyuo9T9T7o21ciqNzwIp/q0A==", - "dev": true, - "requires": { - "lodash": "^4.17.21", - "path-is-network-drive": "^1.0.10", - "path-strip-sep": "^1.0.7", - "tslib": "^2.3.1" - } - }, "update-notifier": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-5.1.0.tgz", @@ -22207,9 +21059,9 @@ "dev": true }, "v8-to-istanbul": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.0.tgz", - "integrity": "sha512-/PRhfd8aTNp9Ggr62HPzXg2XasNFGy5PBt0Rp04du7/8GNNSgxFL6WBTkgMKSL9bFjH+8kKEG3f37FmxiTqUUA==", + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz", + "integrity": "sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w==", "dev": true, "requires": { "@types/istanbul-lib-coverage": "^2.0.1", @@ -22295,24 +21147,23 @@ } }, "web-ext": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/web-ext/-/web-ext-6.5.0.tgz", - "integrity": "sha512-71DE73YkxKEyiy1O5Ei5Uy1ZCT0tOPriPWIkH3g+mpnd52Gr1u2buexpq2upATekhc1Mu87d9EmRqXg2Kqhszw==", + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/web-ext/-/web-ext-6.8.0.tgz", + "integrity": "sha512-qZ3a4YVs0Vdqet44QRZEcNUQznkrfhsAkSOnZp57O4T4A9Bo3pamePSBeRqdPdJv9GF8ntKG84o3eV0MrEvLbw==", "dev": true, "requires": { "@babel/runtime": "7.13.9", "@devicefarmer/adbkit": "2.11.3", - "addons-linter": "3.20.0", + "addons-linter": "4.14.0", "bunyan": "1.8.15", "camelcase": "6.2.0", - "chrome-launcher": "0.14.0", + "chrome-launcher": "0.15.0", "debounce": "1.2.0", "decamelize": "5.0.0", "es6-error": "4.1.1", - "event-to-promise": "0.8.0", - "firefox-profile": "4.2.1", + "firefox-profile": "4.2.2", "fs-extra": "9.1.0", - "fx-runner": "1.1.0", + "fx-runner": "1.2.0", "import-fresh": "3.3.0", "mkdirp": "1.0.4", "multimatch": "5.0.0", @@ -22320,7 +21171,8 @@ "node-notifier": "9.0.0", "open": "7.4.2", "parse-json": "5.2.0", - "sign-addon": "3.9.0", + "promise-toolbox": "0.20.0", + "sign-addon": "3.11.0", "source-map-support": "0.5.20", "strip-bom": "4.0.0", "strip-json-comments": "3.1.1", @@ -22370,6 +21222,16 @@ "which": "^2.0.2" } }, + "source-map-support": { + "version": "0.5.20", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.20.tgz", + "integrity": "sha512-n1lZZ8Ve4ksRqizaBQgxXDgKwttHDhyfQjA6YZZn8+AroHbsIz+JjwxQDxbp+7y5OYCI8t1Yk7etjD9CRd2hIw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, "ws": { "version": "7.4.6", "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", @@ -22490,9 +21352,9 @@ } }, "ws": { - "version": "8.2.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", - "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", + "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", "dev": true, "requires": {} }, @@ -22589,12 +21451,6 @@ "buffer-crc32": "~0.2.3" } }, - "yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true - }, "yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/package.json b/package.json index f834947298c8..f324f3cec28d 100644 --- a/package.json +++ b/package.json @@ -1,29 +1,33 @@ { "name": "darkreader", - "version": "4.9.42", + "version": "4.9.52", "description": "Dark mode for every website", "scripts": { "api": "node tasks/build.js --api", "benchmark-server": "node tests/benchmark-server/index.js", "build": "node tasks/build.js --release", - "code-style": "eslint --ignore-pattern \"!.eslintplugin.js\" --cache --fix \"src/**/*.ts\" \"src/**/*.tsx\" \"tasks/**/*.js\" \"tests/[!coverage]**/*.js\" \"tests/**/*.ts\" \".eslintrc.js\" \"index.d.ts\" \".eslintplugin.js\"", + "build:all": "node tasks/build.js --debug --release --api", + "code-style": "eslint --ignore-pattern '!.eslintplugin.js' --cache --fix -- 'src/**/*.ts' 'src/**/*.tsx' 'tasks/**/*.js' 'tests/[!coverage]**/*.js' 'tests/**/*.ts' '.eslintrc.js' 'index.d.ts' '.eslintplugin.js'", "debug": "node tasks/build.js --debug", "debug:watch": "node tasks/build.js --debug --watch", - "lint": "eslint --ignore-pattern \"!.eslintplugin.js\" \"src/**/*.ts\" \"src/**/*.tsx\" \"tasks/**/*.js\" \"tests/**/*.ts\" \"tests/[!coverage]**/*.js\" \"index.d.ts\" \".eslintplugin.js\"", + "lint": "eslint --ignore-pattern '!.eslintplugin.js' -- 'src/**/*.ts' 'src/**/*.tsx' 'tasks/**/*.js' 'tests/**/*.ts' 'tests/[!coverage]**/*.js' 'index.d.ts' '.eslintplugin.js'", + "lint:bundle": "(node ./tasks/check-exists.js ./build/debug/chrome || node tasks/build.js --debug --api) && eslint -- 'build/debug/chrome/**/*.js' 'darkreader.js'", "prepublishOnly": "npm test && npm run api", "release": "npm test && npm run lint && node tasks/build.js --release", - "test": "jest --config=tests/jest.config.js", - "test:browser": "npm run debug && jest --config=tests/browser/jest.config.js --runInBand", - "test:chrome": "npm run debug && jest --config=tests/browser/jest.config.chrome.js --runInBand", - "test:ci": "jest --config=tests/jest.config.js --runInBand", - "test:config": "jest --config=tests/config/jest.config.js", - "test:config:debug": "node --inspect-brk ./node_modules/jest/bin/jest --config=tests/config/jest.config.js --runInBand --no-cache --watch", - "test:coverage": "jest --config=tests/jest.config.js --coverage", - "test:firefox": "npm run debug && jest --config=tests/browser/jest.config.firefox.js --runInBand", - "test:inject": "node tests/inject/run.js", - "test:inject:debug": "node tests/inject/run.js --debug", - "test:utils": "jest --config=tests/utils/jest.config.js", - "test:utils:debug": "node --inspect-brk ./node_modules/jest/bin/jest --config=tests/utils/jest.config.js --runInBand --no-cache --watch" + "test": "npm run test:unit", + "test:all": "npm run test:unit; npm run test:browser; npm run test:inject; npm run test:project", + "test:browser": "npm run debug && npm run test:chrome && npm run test:firefox", + "test:chrome": "npm run debug && jest --config=tests/browser/jest.config.js --runInBand", + "test:ci": "npm run test:unit", + "test:coverage": "jest --config=tests/unit/jest.config.js --coverage", + "test:firefox": " npm run debug && jest --config=tests/browser/jest.config.firefox.js --runInBand", + "test:inject": "node --max-old-space-size=3072 node_modules/.bin/karma start ./tests/inject/karma.conf.js", + "test:inject:debug": "node --max-old-space-size=3072 node_modules/.bin/karma start ./tests/inject/karma.conf.js --debug", + "test:project": "jest --config=tests/project/jest.config.js", + "test:unit": "jest --config=tests/unit/jest.config.js", + "test:unit:debug": "node --inspect-brk ./node_modules/jest/bin/jest --config=tests/unit/jest.config.js --runInBand --no-cache --watch", + "test:update-snapshots": "npm run test -- --updateSnapshot && npm run test:project -- --updateSnapshot", + "translate-line": "node ./tasks/translate.js --line" }, "main": "darkreader.js", "repository": { @@ -44,66 +48,55 @@ "accessibility", "eye-care" ], - "browserslist": [ - "supports es5", - "not ie > 0", - "not ie_mob > 0", - "not op_mini all", - "not op_mob < 59", - "not android < 50", - "not ios_saf < 6", - "not safari < 9.3", - "not opera < 36", - "not chrome < 49", - "not firefox < 33", - "not edge <= 18" - ], "homepage": "https://darkreader.org/", "funding": { "type": "opencollective", - "url": "https://opencollective.com/darkreader" + "url": "https://opencollective.com/darkreader/donate" }, "devDependencies": { - "@rollup/plugin-node-resolve": "13.0.6", - "@rollup/plugin-replace": "3.0.0", - "@rollup/pluginutils": "4.1.1", - "@types/chrome": "0.0.162", - "@types/jasmine": "3.10.1", - "@types/jest": "27.0.2", - "@types/karma": "6.3.1", + "@rollup/plugin-node-resolve": "13.1.3", + "@rollup/plugin-replace": "4.0.0", + "@rollup/plugin-typescript": "8.3.1", + "@rollup/pluginutils": "4.2.0", + "@types/chrome": "0.0.180", + "@types/eslint": "8.4.1", + "@types/jasmine": "4.0.0", + "@types/jest": "27.4.1", + "@types/karma": "6.3.3", + "@types/karma-coverage": "2.0.1", + "@types/node": "17.0.23", "@types/offscreencanvas": "2019.6.4", - "@types/node": "16.11.6", - "@typescript-eslint/eslint-plugin": "5.3.0", - "@typescript-eslint/parser": "5.3.0", - "chokidar": "3.5.2", - "eslint": "8.1.0", - "eslint-plugin-import": "2.25.2", + "@typescript-eslint/eslint-plugin": "5.16.0", + "@typescript-eslint/parser": "5.16.0", + "chokidar": "3.5.3", + "eslint": "8.11.0", + "eslint-plugin-compat": "4.0.2", + "eslint-plugin-import": "2.25.4", "eslint-plugin-local": "1.0.0", - "fs-extra": "10.0.0", - "globby": "11.0.4", - "jasmine-core": "3.10.1", - "jest": "27.3.1", - "karma": "6.3.7", - "karma-chrome-launcher": "3.1.0", - "karma-coverage": "2.0.3", + "get-stream": "6.0.1", + "globby": "13.1.1", + "jasmine-core": "4.0.1", + "jest": "27.5.1", + "jest-extended": "2.0.0", + "karma": "6.3.17", + "karma-chrome-launcher": "3.1.1", + "karma-coverage": "2.2.0", "karma-firefox-launcher": "2.1.2", "karma-jasmine": "4.0.1", - "karma-rollup-preprocessor": "7.0.7", + "karma-rollup-preprocessor": "7.0.8", "karma-safari-launcher": "1.0.0", + "karma-spec-reporter": "0.0.33", "less": "4.1.2", - "malevic": "0.18.6", - "prettier": "2.4.1", - "puppeteer-core": "10.4.0", - "rollup": "2.59.0", + "malevic": "0.19.1", + "prettier": "2.6.1", + "puppeteer-core": "13.5.1", + "rollup": "2.70.1", "rollup-plugin-istanbul2": "2.0.2", - "rollup-plugin-typescript2": "0.31.1", - "ts-jest": "27.0.7", - "ts-node": "10.4.0", - "tsconfig-paths": "3.11.0", + "ts-jest": "27.1.4", "tslib": "2.3.1", - "typescript": "4.4.4", - "web-ext": "6.5.0", - "ws": "8.2.3", + "typescript": "4.6.3", + "web-ext": "6.8.0", + "ws": "8.5.0", "yazl": "2.5.1" } } diff --git a/src/_locales/ar.config b/src/_locales/ar.config index cd74f64bcac8..fa1ae1b96e6d 100644 --- a/src/_locales/ar.config +++ b/src/_locales/ar.config @@ -178,6 +178,8 @@ بإمكانك ضبط السطوع، التباين، الفلتر البني، الوضع المظلم، إعدادات الخط وقائمة التجاهل. +قد نطلب منك دعم تطوير التطبيق من خلال تبرع. قد ترى أخبارًا حول Dark Reader في قائمة الإعدادات المنبثقة. هناك أدوات المطور للمستخدمين ذوي الخبرة. + لا يقوم Dark Reader بعرض إعلانات ولا يقوم بإرسال بيانات المستخدم إلى أي مكان. الإضافة مفتوحة المصدر بالكامل https://github.com/darkreader/darkreader قبل التثبيت قم بتعطيل الإضافات المماثلة. استمتع بالمشاهدة! diff --git a/src/_locales/be.config b/src/_locales/be.config index 5f8ef149b3e9..f609031dd153 100644 --- a/src/_locales/be.config +++ b/src/_locales/be.config @@ -178,6 +178,8 @@ Маецца магчымасць наладжваць яркасць, кантраснасць, шрыфт, рэжым інверсіі, рэжым накладання жоўтага фільтра (сэпія). +Мы можам папрасіць вас падтрымаць распрацоўку прыкладання ахвяраваннем. Вы можаце ўбачыць навіны аб Dark Reader ва ўсплывальным акне налад. Ёсць інструменты распрацоўшчыка для вопытных карыстальнікаў. + Dark Reader ня ўбудоўвае рэкламу і не збірае дадзеныя карыстальніка, увесь зыходны код адкрыты https://github.com/darkreader/darkreader Перад усталёўкай адключыце падобныя пашырэнні. Прыемнага прагляду! diff --git a/src/_locales/bn.config b/src/_locales/bn.config index 4a25424fd07f..deaa766f5cd3 100644 --- a/src/_locales/bn.config +++ b/src/_locales/bn.config @@ -178,6 +178,8 @@ আপনি উজ্জ্বলতা, কনট্রাস্ট, সেপিয়া ফিল্টার, ডার্ক মোড, ফন্ট সেটিংস এবং ইগনোর-লিস্ট সমন্বয় করতে পারেন। +আমরা আপনাকে অনুদান দিয়ে অ্যাপটির বিকাশে সহায়তা করতে বলতে পারি। আপনি সেটিংস পপআপে ডার্ক রিডার সম্পর্কে খবর দেখতে পারেন। অভিজ্ঞ ব্যবহারকারীদের জন্য বিকাশকারী সরঞ্জাম রয়েছে। + Dark Reader বিজ্ঞাপন দেখায় না এবং ব্যবহারকারীর ডেটা কোথাও প্রেরণ করে না। এটি সম্পূর্ণ ওপেন সোর্স https://github.com/darkreader/darkreader ইনস্টল করার আগে অনুরূপ এক্সটেনশন ডিজ্যাবল করুন এবং এক্সটেনশনটি উপভোগ করুন! diff --git a/src/_locales/cs.config b/src/_locales/cs.config index f6f35010eba2..513fca37c1a3 100644 --- a/src/_locales/cs.config +++ b/src/_locales/cs.config @@ -178,6 +178,8 @@ Toto k očím šetrné rozšíření přepíná stránky do nočního režimu t Můžete upravit jas, kontrast, sépiový filtr, tmavý mód, nastavení písma a seznam ignorovaných stránek. +Můžeme vás požádat, abyste podpořili vývoj aplikace darem. Novinky o Dark Reader můžete vidět ve vyskakovacím okně nastavení. Pro zkušené uživatele existují nástroje pro vývojáře. + Dark Reader neobsahuje reklamy a nikam neodesílá data uživatele. Projekt je plně open-source a repositář je možné nalézt na https://github.com/darkreader/darkreader Před instalací vypněte všechna podobná rozšíření. Přejeme příjemné surfování! diff --git a/src/_locales/de.config b/src/_locales/de.config index 956534f61c92..774fd408cb9b 100644 --- a/src/_locales/de.config +++ b/src/_locales/de.config @@ -178,6 +178,8 @@ Zum Schutz der Augen ermöglicht diese Erweiterung das Erstellen dunkler Farblay Helligkeit, Kontrast, Sepia-Filter, Dark-Modus, Schrifteinstellungen und Ignorier-Liste können manuell verwaltet und individuell eingestellt werden. +Wir können Sie bitten, die Entwicklung der App mit einer Spende zu unterstützen. Möglicherweise sehen Sie im Einstellungs-Popup Neuigkeiten über Dark Reader. Es gibt Entwicklertools für erfahrene Benutzer. + Dark Reader zeigt dabei keine Werbung und sendet keine Benutzerdaten irgendwohin. Es ist komplett quelloffen: https://github.com/darkreader/darkreader Beachten Sie, dass Sie ähnliche Erweiterungen deaktivieren sollen, bevor Sie Dark Reader installieren. Viel Spaß beim angenehmeren Surfen! diff --git a/src/_locales/el.config b/src/_locales/el.config index ce2d1d2afdeb..970d3f242129 100644 --- a/src/_locales/el.config +++ b/src/_locales/el.config @@ -1,8 +1,8 @@ @extension_description -Σκούρα εμφάνιση για όλες τις ιστοσελίδες. Φροντήστε τα μάτια σας κάνοντας χρήση σκούρας εμφάνισης στο καθημερινό σας σερφάρισμα. +Σκούρα εμφάνιση για όλες τις ιστοσελίδες. Φροντίστε τα μάτια σας κάνοντας χρήση σκούρας εμφάνισης στο καθημερινό σας σερφάρισμα. @loading_please_wait -Γίνεται φόρτωση, παρακαλώ περιμένετε +Φόρτωση, παρακαλώ περιμένετε #==== Top section ==== @@ -14,14 +14,14 @@ On Off @toggle_current_site -αλλαγή τρέχουσας σελίδας +Αλλαγή τρέχουσας σελίδας @setup_hotkey_toggle_site Ρυθμίσεις τρέχουσας σελίδας αλλαγή hotkey @toggle_extension -αλλαγή πρόσθετου +Εναλλαγή πρόσθετου @setup_hotkey_toggle_extension Ρυθμίσεις πρόσθετου @@ -47,14 +47,14 @@ Off προστατεύεται @page_in_dark_list -Η σελίδα αυτή είναι -παγκόσμια Σκούρα Λίστα +Περιλαμβάνεται στην +καθολική Σκούρα Λίστα @system_dark_mode Χρησιμοποιήστε το συνδυασμό χρωμάτων του συστήματος @system_dark_mode_description -Ενεργοποιείται όταν το σύστημα σκοτεινή λειτουργία είναι ενεργοποιημένη +Ενεργοποιείται στη σκοτεινή λειτουργία συστήματος #==== Filter ==== @@ -87,7 +87,7 @@ Sepia Μόνο για @only_for_description -Ενεργοποίηση ρυθμίσεων μόνο για τη τρέχουσα σελίδα +Ενεργοποίηση μόνο στην τρέχουσα σελίδα #==== Site list ==== @@ -120,8 +120,8 @@ Sepia Σκιά γραμμάτων @try_experimental_theme_engines -Δοκιμάστε την **πειραματική** μηχανή θεμάτων: -**Φίλτρο+** διατήρηση αποχρώσεων κάνοντας χρήση της GPU +Δοκιμάστε τις **πειραματικές** μηχανές θεμάτων: +**Φίλτρο+** διατήρηση κορεσμού χρωμάτων **Στατικό θέμα** χρήση απλού, γρήγορου θέματος **Δυναμικό θέμα** ανάλυση χρωμάτων και εικόνων @@ -138,7 +138,7 @@ Sepia Δυναμικό @theme_generation_mode -Λειτουργία θέματος +Λειτουργία δημιουργίας θέματος @custom_browser_theme_on Προσαρμοσμένη @@ -147,7 +147,7 @@ Sepia Προεπιλογή @change_browser_theme -Αλλαγή θέματος προγραμματος περιήγησης +Αλλαγή θέματος προγράμματος περιήγησης #==== Footer ==== @@ -174,10 +174,12 @@ Sepia #==== Store listing ==== @store_listing -Αυτό το θεαματικό πρόσθετο, μετατρέπει ζωντανά τις ιστοσελίδες που επισκέπτεστε ως σκούρες. Ο Dark Reader αντιστρέφει τα χρώματα δημιουργώντας έντονη αντίθεση για ευκολότερη ανάγνωση κατά τις βραδυνές ώρες. +Αυτό το θεαματικό πρόσθετο, μετατρέπει ζωντανά τις ιστοσελίδες που επισκέπτεστε σε σκούρες. Το Dark Reader αντιστρέφει τα χρώματα δημιουργώντας έντονη αντίθεση για ευκολότερη ανάγνωση κατά τις βραδυνές ώρες. Μπορείτε να προσαρμόσετε φωτεινότητα, αντίθεση, φίλτρο sepia, σκούρα εμφάνιση και λίστα ιστσελίδων στις οποίες το πρόσθετο δεν θα παρεμβαίνει. +Μπορεί να σας ζητήσουμε να υποστηρίξετε την ανάπτυξη της εφαρμογής με μια δωρεά. Μπορεί να δείτε νέα σχετικά με το Dark Reader στο αναδυόμενο παράθυρο ρυθμίσεων. Υπάρχουν Εργαλεία προγραμματιστών για έμπειρους χρήστες. + Το Dark Reader δεν εμφανίζει διαφιμήσεις ούτε κάνει οποιαδήποτε αποστολή στατιστικών/πληροφορίών του χρήστη. Είναι 100% ανοικτού κώδικά https://github.com/darkreader/darkreader -Πριν εγκαταστήσετε το πρόσθετο αυτό θα πρέπει να αφαιρέσεται παρόμοια πρόσθετα. Καλό σερφάρισμα! +Πριν εγκαταστήσετε το πρόσθετο αυτό θα πρέπει να αφαιρέσετε παρόμοια πρόσθετα. Καλό σερφάρισμα! diff --git a/src/_locales/en-GB.config b/src/_locales/en-GB.config index 97b2a84c1eeb..12044c43d810 100644 --- a/src/_locales/en-GB.config +++ b/src/_locales/en-GB.config @@ -178,6 +178,8 @@ This eye-care extension enables night mode by creating dark themes for websites You can adjust the brightness, contrast, sepia filter, dark mode, font settings and the ignore-list. +We may ask you to support the development of the app with a donation. You may see news about Dark Reader in the settings popup. There are Developer Tools for experienced users. + Dark Reader doesn't show ads and doesn't send users' data anywhere. It's fully open-source: https://github.com/darkreader/darkreader Before you install it, disable similar extensions. Enjoy watching! diff --git a/src/_locales/en-US.config b/src/_locales/en-US.config index 8b84dba34a73..4e4f0d89621d 100644 --- a/src/_locales/en-US.config +++ b/src/_locales/en-US.config @@ -178,6 +178,8 @@ This eye-care extension enables night mode by creating dark themes for websites You can adjust the brightness, contrast, sepia filter, dark mode, font settings and the ignore-list. +We may ask you to support the development of the app with a donation. You may see news about Dark Reader in the settings popup. There are Developer Tools for experienced users. + Dark Reader doesn't show ads and doesn't send users' data anywhere. It's fully open-source: https://github.com/darkreader/darkreader Before you install it, disable similar extensions. Enjoy watching! diff --git a/src/_locales/en.config b/src/_locales/en.config index 8b84dba34a73..4e4f0d89621d 100644 --- a/src/_locales/en.config +++ b/src/_locales/en.config @@ -178,6 +178,8 @@ This eye-care extension enables night mode by creating dark themes for websites You can adjust the brightness, contrast, sepia filter, dark mode, font settings and the ignore-list. +We may ask you to support the development of the app with a donation. You may see news about Dark Reader in the settings popup. There are Developer Tools for experienced users. + Dark Reader doesn't show ads and doesn't send users' data anywhere. It's fully open-source: https://github.com/darkreader/darkreader Before you install it, disable similar extensions. Enjoy watching! diff --git a/src/_locales/es.config b/src/_locales/es.config index 4225ff00c345..17cd2385afc8 100644 --- a/src/_locales/es.config +++ b/src/_locales/es.config @@ -178,6 +178,8 @@ Esta extensión que cuida los ojos habilita el modo nocturno, creando temas oscu Puede ajustar brillo, contraste, filtro sepia, modo oscuro, configuración de fuentes y lista de ignorados +Es posible que le pidamos que apoye el desarrollo de la aplicación con una donación. Es posible que vea noticias sobre Dark Reader en la ventana emergente de configuración. Existen herramientas de desarrollo para usuarios experimentados. + Dark Reader no muestra publicidad y no envía la información del usuario a ningún lado. Es totalmente de código abierto https://github.com/darkreader/darkreader Antes de instalarlo, desactive extensiones similares. Disfrute mirando! diff --git a/src/_locales/fa-IR.config b/src/_locales/fa-IR.config index 33d74253c912..ffff0088eb8a 100644 --- a/src/_locales/fa-IR.config +++ b/src/_locales/fa-IR.config @@ -178,6 +178,8 @@ شما میتوانید میزان روشنایی، کنتراست، فیلتر قرمز قهوه ای، حالت تاریک، نوع قلم و لیست سایت های نادیده گرفته شده را تنظیم کنید. +ممکن است از شما بخواهیم با کمک مالی از توسعه برنامه حمایت کنید. ممکن است اخبار مربوط به Dark Reader را در پنجره بازشو ببینید. ابزارهای توسعه دهنده برای کاربران با تجربه وجود دارد. + دارک ریدر تبلیغات نشان نمیدهد و اطلاعات کاربران را برای جایی ارسال نمیکند. همچنین بصورت کامل متن باز است https://github.com/darkreader/darkreader قبل از نصب افزونه های مشابه را حذف کنید. از تماشا کردن لذت ببرید! diff --git a/src/_locales/fa.config b/src/_locales/fa.config index 33d74253c912..ffff0088eb8a 100644 --- a/src/_locales/fa.config +++ b/src/_locales/fa.config @@ -178,6 +178,8 @@ شما میتوانید میزان روشنایی، کنتراست، فیلتر قرمز قهوه ای، حالت تاریک، نوع قلم و لیست سایت های نادیده گرفته شده را تنظیم کنید. +ممکن است از شما بخواهیم با کمک مالی از توسعه برنامه حمایت کنید. ممکن است اخبار مربوط به Dark Reader را در پنجره بازشو ببینید. ابزارهای توسعه دهنده برای کاربران با تجربه وجود دارد. + دارک ریدر تبلیغات نشان نمیدهد و اطلاعات کاربران را برای جایی ارسال نمیکند. همچنین بصورت کامل متن باز است https://github.com/darkreader/darkreader قبل از نصب افزونه های مشابه را حذف کنید. از تماشا کردن لذت ببرید! diff --git a/src/_locales/fil.config b/src/_locales/fil.config index 0a09a6f8863b..a658c1c8f4bd 100644 --- a/src/_locales/fil.config +++ b/src/_locales/fil.config @@ -178,6 +178,8 @@ Mabilisang binubuksan ng ekstensyong ito ang night mode sa pamamagitan ng madili Puwede mong i-adjust ang liwanag, contrast, sepia filter, dark mode, mga setting ng font at ang ignore-list. +Maaari naming hilingin sa iyo na suportahan ang pagbuo ng app gamit ang isang donasyon. Maaari kang makakita ng mga balita tungkol sa Dark Reader sa popup ng mga setting. Mayroong Mga Tool ng Developer para sa mga may karanasang user. + Hindi nagpapakita ng mga ad ang Dark Reader o ipinapadala ang iyong data kung saan-saan. Open-source ito: https://github.com/darkreader/darkreader Bago mo ikabit (i-install) ito, tanggalin muna ang mga katulad na ekstensyon. Magsaya sa panonood! diff --git a/src/_locales/fr.config b/src/_locales/fr.config index 2a1338e0adc1..a625c06d41b5 100644 --- a/src/_locales/fr.config +++ b/src/_locales/fr.config @@ -1,40 +1,40 @@ @extension_description -Un thème sombre pour chaque site Web. Prenez soin de vos yeux, utilisez Dark Reader pour votre navigation nocturne et quotidienne. +Thème sombre partout sur le net. Détendez vous et vos yeux, profitez d'un thème sombre sur internet jour et nuit. @loading_please_wait -Chargement, veuillez patienter +Chargement en cours, veuillez patienter #==== Top section ==== @on -Marche +Actif @off -Arrêt +Inactif @toggle_current_site -Activer/Désactiver le site actuel +Activer/Désactiver sur le site actuel @setup_hotkey_toggle_site -Configurer la touche de raccourci -du basculement du site actuel +Configurer le raccourci clavier +pour activer/désactiver sur le site actuel @toggle_extension Activer/Désactiver l'extension @setup_hotkey_toggle_extension -Configuration de l'extension -Touche de raccourci bascule +Configurer l'extension +Raccourci clavier pour activer/désactiver @automation -Automatisation +Réglage automatique @set_active_hours -Définissez les heures d’activité +Définir les heures d’activité @set_location -Activer après le coucher du soleil à l'endroit +Activer après le coucher du soleil à cet emplacement @longitude Longitude @@ -48,13 +48,13 @@ par le navigateur @page_in_dark_list Ce site est dans la -liste noire mondiale +liste noire de l'extension @system_dark_mode -Utilisez des couleurs du système +Utiliser les couleurs du système @system_dark_mode_description -Activer lorsque le mode sombre du système est +Actif lorsque le mode sombre du système est actif #==== Filter ==== @@ -66,10 +66,10 @@ Filtrer Mode @dark -Obscur +Sombre @light -Lumineux +Clair @brightness Luminosité @@ -78,28 +78,28 @@ Luminosité Contraste @grayscale -Niveaux de gris +N/B @sepia Sépia @only_for -Uniquement pour +Uniquement @only_for_description -Appliquer les paramètres au site actuel seulement +Appliquer les paramètres au site actuel uniquement #==== Site list ==== @site_list -Liste de sites +Liste des sites @invert_listed_only -Uniquement inversé +Inversé seul @not_invert_listed -Non inversé +Non-inversé @add_site_to_list Ajouter un site à la liste @@ -114,7 +114,7 @@ Configurer un raccourci pour ajouter un site Plus @select_font -Sélectionnez une police +Choisir une police @text_stroke Trait du texte @@ -122,7 +122,7 @@ Trait du texte @try_experimental_theme_engines Essayez les moteurs de thème **expérimentaux**: **Filtre+** préserve la satur. des couleurs, utilise le GPU -**Thème statique** génère un thème rapide simple +**Thème statique** génère un thème simple et rapide **Dynamique** analyse les couleurs et les images @engine_filter @@ -132,7 +132,7 @@ Filtre Filtre+ @engine_static -Statique +Statiq. @engine_dynamic Dynamiq. @@ -141,7 +141,7 @@ Dynamiq. Mode de génération de thème @custom_browser_theme_on -Modifié +Custom. @custom_browser_theme_off Défaut @@ -159,10 +159,10 @@ Confid. Aide @donate -Donner +Dons @news -Nouvelles +Actus @read_more Lire la suite @@ -174,10 +174,12 @@ Dévelop. #==== Store listing ==== @store_listing -Cette extension de protection oculaire active le mode nuit en créant à la volée des thèmes sombres pour les sites Web. Dark Reader inverse les couleurs vives, ce qui les rend très contrastés et faciles à lire la nuit. +Cette extension de navigateur implémente un thème sombre global en créant à la volée des thèmes sombres pour chaque site Web que vous visitez. Dark Reader augmente le contraste des couleurs vives pour les rendre plus agréables à la vue la nuit. -Vous pouvez régler la luminosité, le contraste, le filtre sépia, le mode sombre, les paramètres de police et la liste des sites ignorés. +Vous pouvez également ajuster la luminosité, le contraste, le filtre sépia, le thème sombre, la police du texte ainsi que la liste des sites ignorés par l'extension. -Dark Reader n’affiche pas de publicités et n’envoie aucune donnée utilisateur. Il est entièrement open source https://github.com/darkreader/darkreader +Nous pouvons vous demander de soutenir le développement de l'application par un don. Vous pouvez voir des informations sur Dark Reader dans la fenêtre contextuelle des paramètres. Il existe des outils de développement pour les utilisateurs expérimentés. -Avant de l’installer, désactivez vos extensions similaires. Profitez et regardez! +Dark Reader n'intègre pas de publicités et ne partage vos données avec personne d'autre. Il est entièrement open-source. https://github.com/darkreader/darkreader + +Il est nécessaire de désactiver toute extension similaire à Dark Reader pour que celle-ci fonctionne correctement. Profitez-en et prenez soin de vos yeux! diff --git a/src/_locales/he.config b/src/_locales/he.config index 2611116859e4..ac37acfbc469 100644 --- a/src/_locales/he.config +++ b/src/_locales/he.config @@ -178,6 +178,8 @@ Dev tools ניתן להתאים את הבהירות, הניגודיות, מסנן חום-אדמדם, מצב כהה, הגדרות גופן ורשימת אתרים להתעלמות. +אנו עשויים לבקש ממך לתמוך בפיתוח האפליקציה בתרומה. ייתכן שתראה חדשות על Dark Reader בחלון הקופץ של ההגדרות. ישנם כלים למפתחים למשתמשים מנוסים. + Reader Dark אינו מציג מודעות ואינו שולח את נתוני המשתמש לשום מקום. זהו קוד פתוח לחלוטין https://github.com/darkreader/darkreader לצורך פעולה תקינה, השבת תוספים דומים. צפייה נעימה! diff --git a/src/_locales/hi.config b/src/_locales/hi.config index a69f911c7bea..426e2296d6da 100644 --- a/src/_locales/hi.config +++ b/src/_locales/hi.config @@ -178,6 +178,8 @@ आप चमक, कंट्रास्ट, सेपिया फ़िल्टर, डार्क मोड, फ़ॉन्ट सेटिंग्स और न चलन-सूची समायोजित कर सकते हैं। +हम आपसे दान के साथ ऐप के विकास का समर्थन करने के लिए कह सकते हैं। आप सेटिंग पॉपअप में डार्क रीडर के बारे में समाचार देख सकते हैं। अनुभवी उपयोगकर्ताओं के लिए डेवलपर टूल हैं। + डार्क रीडर विज्ञापन नहीं दिखाता है और कहीं भी उपयोगकर्ता का डेटा नहीं भेजता है। यह पूरी तरह से मुक्त-स्रोत है https://github.com/darkreader/darkreader डार्क रीडर का उपयोग करने से पहले इसी तरह की एक्सटेंशन अक्षम करें। देखने का मज़ा लें! diff --git a/src/_locales/id.config b/src/_locales/id.config index 20cb5534b299..19002bf21db1 100644 --- a/src/_locales/id.config +++ b/src/_locales/id.config @@ -178,6 +178,8 @@ Ekstensi ini mengaktifkan mode malam dengan membuat halaman situs web menjadi ge Anda bisa mengatur kecerahan, kontras, filter sepia, mode malam, setelan fon dan pengecualian situs web. +Kami mungkin meminta Anda untuk mendukung pengembangan aplikasi dengan donasi. Anda mungkin melihat berita tentang Pembaca Gelap di sembulan pengaturan. Ada Alat Pengembang untuk pengguna berpengalaman. + Dark Reader tidak menampilkan iklan dan tidak mengirimkan data penggunan ke manapun. Sepenuhnya bersumber terbuka: https://github.com/darkreader/darkreader Sebelum memasang, silakan nonaktifkan ekstensi serupa. Selamat berselancar! diff --git a/src/_locales/it.config b/src/_locales/it.config index bcf966410ce2..4c751542fb39 100644 --- a/src/_locales/it.config +++ b/src/_locales/it.config @@ -178,6 +178,8 @@ Questa estensione si prende cura dei tuoi occhi e ti consente di creare al volo Puoi modificare luminosità, contrasto, filtro seppia, modalità notturna, caratteri e lista di siti da ignorare. +Potremmo chiederti di sostenere lo sviluppo dell'app con una donazione. Potresti vedere notizie su Dark Reader nel popup delle impostazioni. Sono disponibili strumenti per sviluppatori per utenti esperti. + Dark Reader non mostra pubblicità e non invia i dati dell'utente da nessuna parte. È pienamente open-source https://github.com/darkreader/darkreader Prima di installare disabilita altre estensioni simili. Buona lettura! diff --git a/src/_locales/ja.config b/src/_locales/ja.config index 24f756476fc3..baa1ed6111cb 100644 --- a/src/_locales/ja.config +++ b/src/_locales/ja.config @@ -178,6 +178,8 @@ 明るさ、コントラスト、セピアフィルター、ダークモード、フォント設定、無視リストを調整することができます。 +寄付でアプリの開発をサポートするようお願いする場合があります。設定ポップアップにDarkReaderに関するニュースが表示される場合があります。経験豊富なユーザー向けの開発ツールがあります。 + Dark Readerは広告を表示せず、ユーザーのデータをどこにも送信しません。 また完全にオープンソースです https://github.com/darkreader/darkreader インストールする前に、同様の拡張機能を無効にしてください。 ブラウジングをお楽しみください! diff --git a/src/_locales/ko.config b/src/_locales/ko.config index 4175000a84bf..d3dc72039443 100644 --- a/src/_locales/ko.config +++ b/src/_locales/ko.config @@ -178,6 +178,8 @@ 밝기, 대비, 세피아 필터, 어두운 모드, 폰트와 예외 목록을 설정할 수 있습니다. +기부로 앱 개발 지원을 요청할 수 있습니다. 설정 팝업에서 Dark Reader에 대한 뉴스를 볼 수 있습니다. 숙련된 사용자를 위한 개발자 도구가 있습니다. + 다크 리더는 광고를 보여주지 않으며 사용자의 데이터를 어디에도 보내지 않습니다. 완전히 오픈 소스입니다. https://github.com/darkreader/darkreader 설치하기 전에 비슷한 기능을 가진 확장 기능을 사용 해제하시기 바랍니다. 편하게 읽으십시오! diff --git a/src/_locales/ms.config b/src/_locales/ms.config new file mode 100644 index 000000000000..a89e8ad996aa --- /dev/null +++ b/src/_locales/ms.config @@ -0,0 +1,185 @@ +@extension_description +Mod gelap untuk setiap laman web. Jaga mata anda, gunakan tema gelap untuk melayari laman web, malam dan siang. + +@loading_please_wait +Sedang dimuatkan, sila tunggu + + +#==== Top section ==== + +@on +Buka + +@off +Tutup + +@toggle_current_site +Toggel laman terkini + +@setup_hotkey_toggle_site +Menyiapkan laman terkini +toggel hotkey + +@toggle_extension +Toggel ekstensi + +@setup_hotkey_toggle_extension +Menyiapkan ekstensi +toggel hotkey + +@automation +Otomatisasi + +@set_active_hours +Sediakan waktu aktif + +@set_location +Aktifkan selepas asar di lokasi + +@longitude +Tegak + +@latitude +Lintang + +@page_protected +Halaman ini telah dilindungi +oleh pelayar + +@page_in_dark_list +Halamn in dalam senarai +gelap global + +@system_dark_mode +Gunakan skema warna sistem + +@system_dark_mode_description +Aktifkan semasa skema gelap sistem dibuka + + +#==== Filter ==== + +@filter +Penapis + +@mode +Mode + +@dark +Gelap + +@light +Terang + +@brightness +Kecerahan + +@contrast +Kontras + +@grayscale +Skala kelabu + +@sepia +Sepia + +@only_for +Hanya untuk + +@only_for_description +Gunakan tetapan pada laman web semasa sahaja + + +#==== Site list ==== + +@site_list +Senarai laman + +@invert_listed_only +Senarai songsang sahaja + +@not_invert_listed +Senarai tidak songsang + +@add_site_to_list +Tambahkan laman ke senarai + +@setup_add_site_hotkey +Sediakan hotkey untuk menambah laman + + +#==== More settings ==== + +@more +Lebih + +@select_font +Pilihkan fon + +@text_stroke +Lejang teks + +@try_experimental_theme_engines +Cubakan enjin tema **percubaan**: +**Penapis+** mengekalkan ketepuan warna, menggunakan GPU +**Tema statik** menjana tema pantas yang ringkas +**Tema dinamik** menganalisis warna dan imej + +@engine_filter +Penapis + +@engine_filter_plus +Penapis+ + +@engine_static +Statis + +@engine_dynamic +Dinamis + +@theme_generation_mode +Mod penjanaan tema + +@custom_browser_theme_on +Adat + +@custom_browser_theme_off +Lalai + +@change_browser_theme +Tukar tema pelayar + + +#==== Footer ==== + +@privacy +Privasi + +@help +Bantuan + +@donate +Derma + +@news +Berita + +@read_more +Baca lagi + +@open_dev_tools +Alat Developer + + +#==== Store listing ==== + +@store_listing +Ekstensi penjagaan mata ini mendayakan mod malam dengan mencipta tema gelap untuk laman web dengan cepat. Dark Reader menyongsangkan warna terang, menjadikannya kontras tinggi dan mudah dibaca pada waktu malam. + +Anda boleh melaraskan kecerahan, kontras, penapis sepia, mod gelap, tetapan fon dan senarai abaikan. + +Kami mungkin meminta anda menyokong pembangunan aplikasi dengan sumbangan. Anda mungkin melihat berita tentang Pembaca Gelap dalam pop timbul tetapan. Terdapat Alat Pembangun untuk pengguna berpengalaman. + +Dark Reader tidak memaparkan iklan dan tidak menghantar data pengguna ke mana-mana sahaja. Ia adalah sumber terbuka sepenuhnya: https://github.com/darkreader/darkreader + +Sebelum anda memasangnya, lumpuhkan sambungan yang serupa. Selamat menonton! diff --git a/src/_locales/nl.config b/src/_locales/nl.config index 4813308b609a..36439fe2a004 100644 --- a/src/_locales/nl.config +++ b/src/_locales/nl.config @@ -178,6 +178,8 @@ Deze oogzorgextensie heeft een nachtstand die automatisch donkere thema's maakt Je kunt de helderheid, het contrast, het kleurenfilter, de donkere modus, het lettertype en de lijst van te negeren websites geheel instellen naar wens. +We kunnen je vragen om de ontwikkeling van de app te ondersteunen met een donatie. Mogelijk ziet u nieuws over Dark Reader in de pop-up met instellingen. Er zijn Developer Tools voor ervaren gebruikers. + Dark Reader laat nooit advertenties zien en gebruikt nooit je gegevens. Deze extensie is volledig open-source op https://github.com/darkreader/darkreader Voor de installatie is het aangeraden soortgelijke extensies eerst uit te schakelen. Veel kijkplezier! diff --git a/src/_locales/no.config b/src/_locales/no.config index 89aaabd7073e..ff18d68c0990 100644 --- a/src/_locales/no.config +++ b/src/_locales/no.config @@ -178,6 +178,8 @@ Denne øye-beskyttelse utvidelsen aktiverer nattmodus og lager mørke temaer for Du kan regulere lysstyrken, kontrasten, bruntone, nattmodus, skrifttype-instillinger og ignorer-liste. +Vi kan be deg om å støtte utviklingen av appen med en donasjon. Du kan se nyheter om Dark Reader i popup-vinduet for innstillinger. Det finnes utviklerverktøy for erfarne brukere. + Dark Reader viser ikke reklame og sender ikke ut brukerens data. Utvidelsen er åpen-kilde tilgjengelig på https://github.com/darkreader/darkreader Deaktiver lignende utvidelser før du installerer. Nyt opplevelsen! diff --git a/src/_locales/pl.config b/src/_locales/pl.config index 8cc400d3c24e..11bf0b70c52f 100644 --- a/src/_locales/pl.config +++ b/src/_locales/pl.config @@ -178,6 +178,8 @@ To rozszerzenie dbające o zdrowie oczu aktywuje tryb nocny tworząc dynamiczne Możesz dopasować jasność, kontrast, filtr sepii, tryb ciemny, ustawienia czcionki i listę ignorowanych stron. +Możemy poprosić Cię o wsparcie rozwoju aplikacji darowizną. Możesz zobaczyć wiadomości o Dark Reader w wyskakującym okienku ustawień. Istnieją narzędzia programistyczne dla doświadczonych użytkowników. + Dark reader nie wyświetla reklam ani nie wysyła nigdzie danych użytkowników. Jest oprogramowaniem o w pełni otwartym kodzie źródłowym https://github.com/darkreader/darkreader Przed instalacją usuń podobne rozszerzenia. Miłego oglądania! diff --git a/src/_locales/pt-BR.config b/src/_locales/pt-BR.config index 4999bac31a82..3a17d9786300 100644 --- a/src/_locales/pt-BR.config +++ b/src/_locales/pt-BR.config @@ -1,8 +1,8 @@ @extension_description -Tema escuro para todos os sites. Mantenha seus olhos relaxados usando o tema escuro em sua navegação diária. +Tema escuro para todos os sites. Mantenha os seus olhos relaxados usando o tema escuro em sua navegação diária. @loading_please_wait -Carregando, por favor, aguarde +Carregando, aguarde #==== Top section ==== @@ -14,18 +14,18 @@ Ati. Des. @toggle_current_site -Ativar/Des. no site atual +Alternar (site atual) @setup_hotkey_toggle_site -Configurar o atalho de -alternância do site atual +Configurar atalho de +alternância (site atual) @toggle_extension -Ativar/Des. extensão +Ativar/des. extensão @setup_hotkey_toggle_extension -Atalho de alternância -da extensão +Configurar atalho de +alternância da extensão @automation Automatização @@ -48,13 +48,13 @@ pelo navegador @page_in_dark_list Este site está na -Lista Negra global +lista negra global @system_dark_mode Usar o esquema de cores do sistema @system_dark_mode_description -Ative quando o modo escuro do sistema estiver habilitado +Ativar quando o sistema estiver no modo escuro #==== Filter ==== @@ -78,10 +78,10 @@ Brilho Contraste @grayscale -Tons de Cinza +Tons de cinza @sepia -Tons de Sépia +Tons de sépia @only_for Somente para @@ -105,13 +105,13 @@ Não inverter listados Adicionar site à lista @setup_add_site_hotkey -Configurar uma tecla de atalho para adicionar um site +Configurar um atalho para adicionar um site #==== More settings ==== @more -Mais +Extras @select_font Selecione uma fonte @@ -121,7 +121,7 @@ Intensidade do texto @try_experimental_theme_engines Experimente os motores de temas **experimentais**: -**Filtro+** preserva a saturação de cores, usa a GPU +**Filtro+** preserva a saturação de cores (usa a GPU) **Tema estático** gera um tema simples rapidamente **Tema dinâmico** analisa cores e imagens @@ -174,10 +174,12 @@ Ferramentas #==== Store listing ==== @store_listing -Esta extensão ajuda seus olhos a relaxarem ao criar e aplicar o modo escuro aos sites que você visita. O Dark Reader inverte as cores brilhantes, tornando-as de alto contraste e deixando-as fáceis de serem lidas à noite. +Esta extensão ajuda os seus olhos a relaxarem ao criar e aplicar o modo escuro aos sites que você visita. O Dark Reader inverte as cores brilhantes, tornando-as de alto contraste e deixando-as fáceis de serem lidas à noite. Você pode ajustar o brilho, o contraste, os tons de sépia, o modo escuro, as configurações de fonte e a lista negra. -O Dark Reader não exibe anúncios e não compartilha os dados de seus usuários. O código-fonte é totalmente aberto (open-source) https://github.com/darkreader/darkreader +Podemos pedir que você apoie o desenvolvimento do aplicativo com uma doação. Você pode ver notícias sobre o Dark Reader no pop-up de configurações. Existem Ferramentas de Desenvolvedor para usuários experientes. + +O Dark Reader não exibe anúncios e não compartilha os dados de seus usuários. O código-fonte é totalmente aberto (open-source): https://github.com/darkreader/darkreader Antes de instalar esta extensão, desative extensões semelhantes. Divirta-se! diff --git a/src/_locales/pt-PT.config b/src/_locales/pt-PT.config index 22343dcee340..5fdc49f7cf22 100644 --- a/src/_locales/pt-PT.config +++ b/src/_locales/pt-PT.config @@ -1,8 +1,8 @@ @extension_description -Tema escuro para todos os sites. Cuide dos seus olhos, use o Dark Reader para navegação noturna e diária. +Tema escuro para todos os websites. Cuide dos seus olhos, use o Dark Reader para navegação noturna e diária. @loading_please_wait -Carregando, por favor espere +A carregar, por favor aguarde #==== Top section ==== @@ -28,13 +28,13 @@ Tecla de atalho de alternância da extensão de configuração @automation -Automação +Automatização @set_active_hours Defina as horas de atividade @set_location -Ative depois do sol no local +Ativar após o pôr-do-sol no local @longitude Longitude @@ -51,10 +51,10 @@ Este site está na lista negra global @system_dark_mode -Use esquema de cores do sistema +Usar esquema de cores do sistema @system_dark_mode_description -Ative quando o modo escuro sistema estiver ligado +Ativar quando o modo escuro sistema está ligado #==== Filter ==== @@ -66,10 +66,10 @@ Filtro Modo @dark -Sombrio +Escuro @light -Luz +Claro @brightness Brilho @@ -78,16 +78,16 @@ Brilho Contraste @grayscale -Em tons de cinza +Tons de cinza @sepia Sépia @only_for -Somente para +Apenas para @only_for_description -Aplicar configurações somente ao site atual +Aplicar definições apenas ao website atual #==== Site list ==== @@ -99,7 +99,7 @@ Lista de sites Inverter listado @not_invert_listed -Não invertido listado +Não inverter listado @add_site_to_list Adicionar site à lista @@ -114,13 +114,13 @@ Configurar uma tecla de atalho para adicionar site Mais @select_font -Selecione uma fonte +Selecionar um tipo de letra @text_stroke -Traço de texto +Traço do texto @try_experimental_theme_engines -Experimente os motores de temas **experimental**: +Experimentar os motores de temas **experimental**: **Filtro+** preserva a saturação de cores, usa GPU **Tema estático** gera um tema rápido simples **Tema dinâmico** analisa cores e imagens @@ -141,7 +141,7 @@ Dinâmico Modo de geração de tema @custom_browser_theme_on -Mudou +Personalizado @custom_browser_theme_off Predefinido @@ -162,10 +162,10 @@ Ajuda Doar @news -Notícia +Notícias @read_more -Ler mais +Saiba mais @open_dev_tools Ferramentas @@ -174,10 +174,12 @@ Ferramentas #==== Store listing ==== @store_listing -Esta extensão de cuidados com os olhos ativa o modo noturno criando temas escuros para sites. O Dark Reader inverte as cores brilhantes, tornando-as de alto contraste e fáceis de ler à noite. +Esta extensão de cuidados com os olhos ativa o modo noturno ao criar temas escuros para sites. O Dark Reader inverte as cores brilhantes, tornando-as de alto contraste e fáceis de ler à noite. -Você pode ajustar o brilho, o contraste, o filtro sépia, o modo escuro, as configurações de fonte e a lista de ignorados. +Pode ajustar o brilho, o contraste, o filtro sépia, o modo escuro, as definições do tipo de letra e a lista de ignorados. -O Dark Reader não exibe anúncios e não envia dados do usuário em nenhum lugar. É totalmente open-source https://github.com/darkreader/darkreader +Podemos pedir que você apoie o desenvolvimento do aplicativo com uma doação. Você pode ver notícias sobre o Dark Reader no pop-up de configurações. Existem Ferramentas de Desenvolvedor para usuários experientes. -Antes de instalar desativar extensões semelhantes. Visualização agradável! +O Dark Reader não mostra anúncios e não envia os dados dos utilizadores para lado nenhum. É totalmente de código aberto: https://github.com/darkreader/darkreader + +Antes de o instalar, desative extensões semelhantes. Desfrute da visualização! diff --git a/src/_locales/ro.config b/src/_locales/ro.config index 779fabab4903..18c8748f9926 100755 --- a/src/_locales/ro.config +++ b/src/_locales/ro.config @@ -178,6 +178,8 @@ Această extensie, care se îngrijește de ochii tăi, permite activarea modului Poți ajusta luminozitatea, contrastul, filtrul sepia, modul întunecat, setările fontului si lista siteurilor de ignorat. +Vă putem cere să susțineți dezvoltarea aplicației printr-o donație. Este posibil să vedeți știri despre Dark Reader în fereastra pop-up de setări. Există instrumente pentru dezvoltatori pentru utilizatorii experimentați. + Dark Reader nu afișează reclame și nu trimite datele utilizatorului nicăieri. Este în întregime open-source https://github.com/darkreader/darkreader Înainte de instalare dezactivează extensile similare. Vizionare plăcută! diff --git a/src/_locales/ru.config b/src/_locales/ru.config index 06b854bcf200..dc4aaa1c0f28 100644 --- a/src/_locales/ru.config +++ b/src/_locales/ru.config @@ -54,7 +54,7 @@ Использовать системную цветовую схему @system_dark_mode_description -Включить, когда системный ночной режим активен +Вкл., если системный ночной режим активен #==== Filter ==== @@ -178,6 +178,8 @@ Имеется возможность настраивать яркость, контрастность, шрифт, режим инверсии, режим наложения жёлтого фильтра (сепия). +Мы можем попросить вас поддержать разработку приложения пожертвованием. Вы можете увидеть новости о Dark Reader во всплывающем окне настроек. Есть инструменты разработчика для опытных пользователей. + Дарк Ридер не встраивает рекламу и не собирает пользовательские данные. Весь исходный код открыт https://github.com/darkreader/darkreader Перед установкой отключите подобные расширения. Приятного просмотра! diff --git a/src/_locales/si.config b/src/_locales/si.config index 3e75452d3929..6112c4952c54 100644 --- a/src/_locales/si.config +++ b/src/_locales/si.config @@ -178,6 +178,8 @@ Dev මෙවලම් ඔබට දීප්තිය (brightness), contrast, sepia ෆිල්ටරය, අඳුරු මාදිලිය, අකුරු (font) සැකසුම් සහ නොසලකා හැරීම් ලැයිස්තුව (ignore-list) සකස් කළ හැකිය. +පරිත්‍යාගයක් සමඟ යෙදුමේ සංවර්ධනයට සහාය දෙන ලෙස අපි ඔබෙන් ඉල්ලා සිටිය හැක. ඔබට සැකසීම් උත්පතන තුළ Dark Reader පිළිබඳ පුවත් දැකිය හැක. පළපුරුදු පරිශීලකයින් සඳහා සංවර්ධක මෙවලම් තිබේ. + Dark Reader දැන්වීම් නොපෙන්වන අතර පරිශීලකයාගේ දත්ත කොතැනකටවත් යවන්නේ නැත. එය සම්පූර්ණයෙන්ම විවෘත මූලාශ්‍රයකි (open-source) https://github.com/darkreader/darkreader ඔබ ස්ථාපනය කිරීමට පෙර සමාන දිගු (extensions) අක්‍රීය කරන්න. නැරඹීමෙන් විනෝද වන්න! diff --git a/src/_locales/sk.config b/src/_locales/sk.config index 3f6f18601c45..d39c00f25319 100644 --- a/src/_locales/sk.config +++ b/src/_locales/sk.config @@ -78,7 +78,7 @@ Jas Kontrast @grayscale -0dtiene sivej +Odtiene sivej @sepia Sépia @@ -178,6 +178,8 @@ Toto rozšírenie je šetrné k očiam, vytvára nočný režim pre stránky za Upravovať môžete jas, kontrast, sépiový filter, tmavý režim, nastavenia písma a zoznam ignorovaných stránok. +Môžeme vás požiadať, aby ste podporili vývoj aplikácie darom. Novinky o Dark Reader môžete vidieť vo vyskakovacom okne nastavení. Pre skúsených používateľov existujú nástroje pre vývojárov. + Dark Reader je bez reklám a nikam neodosiela žiadne dáta užívateľov. Má plne otvorený zdrojový kód https://github.com/darkreader/darkreader Pred inštaláciou zakážte podobné rozšírenia. Užite si sledovanie! diff --git a/src/_locales/sr.config b/src/_locales/sr.config index dff21c4af022..d7e03f6bd9f4 100644 --- a/src/_locales/sr.config +++ b/src/_locales/sr.config @@ -28,19 +28,19 @@ Podesite ekstenziju uklj. dugme @automation -Automacija +Automatizacija @set_active_hours Podesite aktivne sate @set_location -Aktivirajte po zalaski sunca +Aktivirajte po zalasku sunca @longitude -Longituda +Geogr. dužina @latitude -Latituda +Geogr. širina @page_protected Ovu stranicu štiti @@ -174,10 +174,12 @@ Alatke za razvoj #==== Store listing ==== @store_listing -Ova ekstenzija brine o vašim očima tako što omogućava tamnu temu za sajtove. Dark Reader invertuje svetle boje i pojačava kontrast što omogućava lakše čitanje noću. +Ova ekstenzija brine o vašim očima tako što omogućava tamnu temu za sajtove. Dark Reader invertuje svetle boje i pojačava kontrast, što omogućava lakše čitanje noću. Možete podesiti osvetljenje, kontrast, sepija filter, tamni mod, font i listu ignorisanih sajtova. -Dark Reader ne prikazuje reklame i nigde ne šalje podatke korisnika. Kod ekstenzije je upotpunosti otvoren: https://github.com/darkreader/darkreader +Možemo vas zamoliti da podržite razvoj aplikacije donacijom. Možda ćete videti vesti o Dark Reader-u u iskačućem prozoru za podešavanja. Postoje alatke za programere za iskusne korisnike. + +Dark Reader ne prikazuje reklame i nigde ne šalje podatke korisnika. Kod ekstenzije je u potpunosti otvoren: https://github.com/darkreader/darkreader Pre instalacije, isključite druge slične ekstenzije. Uživajte! diff --git a/src/_locales/sv.config b/src/_locales/sv.config index e33b87c6ebe2..05fa389ba73b 100644 --- a/src/_locales/sv.config +++ b/src/_locales/sv.config @@ -178,6 +178,8 @@ Detta ögonskonande tillägg aktiverar ett nattläge som skapar mörka teman på Du kan justera ljusstyrkan, kontrasten, sepiafiltret, mörkerläget, typsnittet och ignoreringslistan. +Vi kan be dig att stödja utvecklingen av appen med en donation. Du kan se nyheter om Dark Reader i popup-fönstret för inställningar. Det finns utvecklarverktyg för erfarna användare. + Dark Reader visar inte reklam och skickar inte användardata någonstans. Den har helt öppen källkod https://github.com/darkreader/darkreader Inaktivera liknande tillägg innan du installerar. Trevlig läsning! diff --git a/src/_locales/te.config b/src/_locales/te.config new file mode 100644 index 000000000000..1792ac0b0b36 --- /dev/null +++ b/src/_locales/te.config @@ -0,0 +1,185 @@ +@extension_description +ప్రతి వెబ్‌సైట్‌కి ముదురు థీమ్. మీ కళ్లను కాపాడుకోండి, రాత్రి మరియు పగలు బ్రౌజింగ్ట్‌కి ముదురు థీమ్ ఉపయోగించండి. + +@loading_please_wait +దయచేసి వేచి ఉండండి... + + +#====Top section ==== + +@on +ఆన్ + +@off +ఆపండి + +@toggle_current_site +సైట్ కోసం సక్రియం చేయండి + +@setup_hotkey_toggle_site +సైట్ మార్చడానికి పొడిగింపు సెటప్ +హాట్‌కీని ప్రారంభించండి + +@toggle_extension +పొడిగింపును ప్రారంభించండి + +@setup_hotkey_toggle_extension +పొడిగింపు సెట్టింగులు +హాట్‌కీని ప్రారంభించండి + +@automation +స్వయంచాలకంగా పూర్తయింది + +@set_active_hours +మేల్కొనే గంటలను మార్చండి + +@set_location +సూర్యాస్తమయం వద్ద ప్రారంభించండి + +@longitude +రేఖాంశం + +@latitude +అక్షాంశం + +@page_protected +ఈ పేజీ +బ్రౌజర్ ద్వారా రక్షించబడింది + +@page_in_dark_list +ఈ పేజీ +చీకటి థీమ్ జాబితాలో ఉంది + +@system_dark_mode +సిస్టమ్ కలర్ స్కీమ్‌ను ఉపయోగించండి + +@system_dark_mode_description +సిస్టమ్ కలర్ స్కీమ్ ఎనేబుల్ లో ఉంది + + +#==== Filter ==== + +@filter +ఫిల్టర్ + +@mode +మోడ్ + +@dark +నలుపు + +@light +కాంతి + +@brightness +ఎంత కాంతి + +@contrast +విరుద్ధంగా + +@grayscale +గ్రేస్కేల్ + +@sepia +సెపియా + +@only_for +దీని కోసం మాత్రమే + +@only_for_description +ప్రస్తుత సైట్ కోసం మాత్రమే ఎంపికలను వర్తించండి + + +#==== Site list ==== + +@site_list +సైట్ జాబితా + +@invert_listed_only +విలోమ జాబితా మాత్రమే + +@not_invert_listed +విలోమ జాబితా కాదు + +@add_site_to_list +జాబితాకు సైట్‌ను జోడించండి + +@setup_add_site_hotkey +సైట్‌ను జోడించడానికి హాట్‌కీని సెటప్ చేయండి + + +#==== More settings ==== + +@more +మరింత + +@select_font +ఫాంట్ ఎంచుకోండి + +@text_stroke +టెక్స్ట్ స్ట్రోక్ + +@try_experimental_theme_engines +ప్రయత్నించండి ** ప్రయోగాత్మక ** థీమ్ ఇంజన్లు: +** ఫిల్టర్+** రంగుల సంతృప్తతను సంరక్షిస్తుంది, GPU ని ఉపయోగిస్తుంది +** స్టాటిక్ థీమ్ ** సరళమైన వేగవంతమైన థీమ్‌ను ఉత్పత్తి చేస్తుంది +** డైనమిక్ థీమ్ ** రంగులు మరియు చిత్రాలను విశ్లేషిస్తుంది + +@engine_filter +ఫిల్టర్ + +@engine_filter_plus +ఫిల్టర్+ + +@engine_static +స్థిరమైన + +@engine_dynamic +చురుకుగా + +@theme_generation_mode +థీమ్ యొక్క మోడ్‌ను మార్చండి + +@custom_browser_theme_on +ఆచారం + +@custom_browser_theme_off +డిఫాల్ట్ + +@change_browser_theme +బ్రౌజర్ థీమ్‌ను మార్చండి + + +#==== Footer ==== + +@privacy +గోప్యత + +@help +సహాయం + +@donate +దయచేసి దానం చేయండి + +@news +వార్తలు + +@read_more +ఇంకా చదవండి + +@open_dev_tools +ఓపెన్ దేవ్ టూల్స్ + + +#==== Store listing ==== + +@store_listing +ఈ కంటి-సంరక్షణ పొడిగింపు ఫ్లైలో వెబ్‌సైట్ల కోసం చీకటి ఇతివృత్తాలను సృష్టించడం ద్వారా నైట్ మోడ్‌ను అనుమతిస్తుంది. డార్క్ రీడర్ ప్రకాశవంతమైన రంగులను విలోమం చేస్తుంది, అవి అధిక విరుద్ధంగా మరియు రాత్రి చదవడం సులభం చేస్తాడు. + +మీరు ప్రకాశం, కాంట్రాస్ట్, సెపియా ఫిల్టర్, డార్క్ మోడ్, ఫాంట్ సెట్టింగులు మరియు విస్మరించే-జాబితాను సర్దుబాటు చేయవచ్చు. + +మేము విరాళంతో యాప్ అభివృద్ధికి మద్దతు ఇవ్వమని మిమ్మల్ని అడగవచ్చు. మీరు సెట్టింగ్‌ల పాప్‌అప్‌లో డార్క్ రీడర్ గురించిన వార్తలను చూడవచ్చు. అనుభవజ్ఞులైన వినియోగదారుల కోసం డెవలపర్ సాధనాలు ఉన్నాయి. + +డార్క్ రీడర్ ప్రకటనలను చూపించదు మరియు వినియోగదారుల డేటాను ఎక్కడా పంపదు. ఇది పూర్తిగా ఓపెన్-సోర్స్: https://github.com/darkreader/darkreader + +మీరు దీన్ని ఇన్‌స్టాల్ చేయడానికి ముందు, ఇలాంటి పొడిగింపులను నిలిపివేయండి. చూడటం ఆనందించండి! diff --git a/src/_locales/th.config b/src/_locales/th.config index ddd54d2abf33..c6fce11dd037 100644 --- a/src/_locales/th.config +++ b/src/_locales/th.config @@ -178,6 +178,8 @@ คุณสามารถปรับแต่งความสว่าง, คอนทราสต์, สีซีเปีย, โหมดมืด, ตั้งค่าฟอนต์ และทำรายการยกเว้นได้ +เราอาจขอให้คุณสนับสนุนการพัฒนาแอพด้วยการบริจาค คุณอาจเห็นข่าวเกี่ยวกับ Dark Reader ในป๊อปอัปการตั้งค่า มีเครื่องมือสำหรับนักพัฒนาสำหรับผู้ใช้ที่มีประสบการณ์ + Dark Reader ไม่แสดงโฆษณา และไม่ส่งข้อมูลของผู้ใช้เด็ดขาด ตัวส่วนเสริมเป็นโอเพนซอร์สโดยสมบูรณ์ดูได้ที่ https://github.com/darkreader/darkreader ก่อนที่จะติดตั้ง ปิดส่วนเสริมที่ทำหน้าที่เหมือนๆกันก่อนนะ ขอให้สนุกกับธีมสีมืดนะ! diff --git a/src/_locales/tr.config b/src/_locales/tr.config index ba68d9069559..afb462c012bf 100644 --- a/src/_locales/tr.config +++ b/src/_locales/tr.config @@ -178,6 +178,8 @@ Bu göz bakım eklentisi web siteleri için anında koyu temalar oluşturarak ge Parlaklığı, kontrastı, sepya filtresini, koyu modu, yazı tipi ayarlarını ve yoksayma listesini ayarlayabilirsiniz. +Uygulamanın gelişimini bir bağışla desteklemenizi isteyebiliriz. Ayarlar açılır penceresinde Dark Reader ile ilgili haberleri görebilirsiniz. Deneyimli kullanıcılar için Geliştirici Araçları bulunmaktadır. + Dark Reader, reklam göstermez ve kullanıcının verilerini hiçbir yere göndermez. Tamamen açık kaynak kodludur. https://github.com/darkreader/darkreader Yüklemeden önce benzer uzantıları devre dışı bırakın. Gezintinin tadını çıkarın! diff --git a/src/_locales/uk.config b/src/_locales/uk.config index f57b5b953b6b..a9e81b6384cc 100644 --- a/src/_locales/uk.config +++ b/src/_locales/uk.config @@ -178,6 +178,8 @@ Ви можете налаштувати яскравість, контраст, сепію, темний вигляд, налаштування вигляду тексту та список нехтування. +Ми можемо попросити вас підтримати розробку програми пожертвуванням. Ви можете побачити новини про Dark Reader у спливаючому вікні налаштувань. Є інструменти розробника для досвідчених користувачів. + Dark Reader не містить рекламу і не надсилає дані користувача нікуди. Це розширення з відкритим кодом https://github.com/darkreader/darkreader Перед встановленням відімкніть подібні розширення. Насолоджуйтесь переглядом! diff --git a/src/_locales/vi.config b/src/_locales/vi.config index dbda1baf204f..52d125891e32 100644 --- a/src/_locales/vi.config +++ b/src/_locales/vi.config @@ -178,6 +178,8 @@ Tiện ích chăm sóc mắt này cho phép chế độ ban đêm tạo chủ đ Bạn có thể điều chỉnh độ sáng, độ tương phản, bộ lọc màu nâu đỏ, chế độ tối, cài đặt phông chữ và danh sách bỏ qua. +Chúng tôi có thể yêu cầu bạn hỗ trợ sự phát triển của ứng dụng bằng một khoản đóng góp. Bạn có thể thấy tin tức về Dark Reader trong cửa sổ bật lên cài đặt. Có Công cụ dành cho nhà phát triển cho người dùng có kinh nghiệm. + Dark Reader không hiển thị quảng cáo và không gửi dữ liệu của người dùng ở bất cứ đâu. Nó hoàn toàn là mã nguồn mở https://github.com/darkreader/darkreader Trước khi bạn cài đặt vô hiệu hóa các phần mở rộng tương tự. Thích xem! diff --git a/src/_locales/zh-CN.config b/src/_locales/zh-CN.config index f26bb5fc07d2..c38ad2e34b3a 100644 --- a/src/_locales/zh-CN.config +++ b/src/_locales/zh-CN.config @@ -178,6 +178,8 @@ 您可以调整亮度、对比度,应用棕褐色滤镜、黑暗模式,设置字体和忽略的网站列表。 +我们可能会要求您通过捐款来支持应用程序的开发。您可能会在设置弹出窗口中看到有关 Dark Reader 的新闻。有针对经验丰富的用户的开发人员工具。 + Dark Reader 无广告,也不会向任何地方发送用户的数据。它完全开源 https://github.com/darkreader/darkreader 安装前请禁用类似的扩展。冲浪愉快! diff --git a/src/_locales/zh-TW.config b/src/_locales/zh-TW.config index 580b16c62b59..240bc2b98ebb 100644 --- a/src/_locales/zh-TW.config +++ b/src/_locales/zh-TW.config @@ -178,6 +178,8 @@ 您可以調整亮度,對比度,套用棕褐色濾鏡,深色模式,設定字體和忽略的網站列表。 +我們可能會要求您通過捐款來支持應用程序的開發。您可能會在設置彈出窗口中看到有關 Dark Reader 的新聞。有針對經驗豐富的用戶的開發人員工具。 + Dark Reader 沒有廣告,也不會在任何地方發送用戶的資料。它完全開源於 https://github.com/darkreader/darkreader 安裝前請先停止使用類似的擴充套件,以避免衝突。瀏覽愉快! diff --git a/src/api/tsconfig.json b/src/api/tsconfig.json new file mode 100644 index 000000000000..d13f12403ba8 --- /dev/null +++ b/src/api/tsconfig.json @@ -0,0 +1,6 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "target": "ES5" + } +} diff --git a/src/background/devtools.ts b/src/background/devtools.ts index 65d9df190a0f..babeb2bb8870 100644 --- a/src/background/devtools.ts +++ b/src/background/devtools.ts @@ -3,6 +3,7 @@ import {parseInversionFixes, formatInversionFixes} from '../generators/css-filte import {parseDynamicThemeFixes, formatDynamicThemeFixes} from '../generators/dynamic-theme'; import {parseStaticThemes, formatStaticThemes} from '../generators/static-theme'; import type ConfigManager from './config-manager'; +import {isFirefox} from '../utils/platform'; // TODO(bershanskiy): Add support for reads/writes of multiple keys at once for performance. // TODO(bershanskiy): Popup UI heeds only hasCustom*Fixes() and nothing else. Consider storing that data separatelly. @@ -209,7 +210,9 @@ export default class DevTools { private store: DevToolsStorage; constructor(config: ConfigManager, onChange: () => void) { - if (typeof chrome.storage.local !== 'undefined' && chrome.storage.local !== null) { + // Firefox don't seem to like using storage.local to store big data on the background-extension. + // Disabling it for now and defaulting back to localStorage. + if (typeof chrome.storage.local !== 'undefined' && chrome.storage.local !== null && !isFirefox) { this.store = new PersistentStorageWrapper(); } else if (typeof localStorage !== 'undefined' && localStorage != null) { this.store = new LocalStorageWrapper(); diff --git a/src/background/extension.ts b/src/background/extension.ts index 174a5bc35c89..68431af56006 100644 --- a/src/background/extension.ts +++ b/src/background/extension.ts @@ -22,16 +22,23 @@ import {MessageType} from '../utils/message'; import {logInfo, logWarn} from '../utils/log'; import {PromiseBarrier} from '../utils/promise-barrier'; import {StateManager} from './utils/state-manager'; +import {debounce} from '../utils/debounce'; + +type AutomationState = 'turn-on' | 'turn-off' | 'scheme-dark' | 'scheme-light' | ''; interface ExtensionState { - isEnabled: boolean; + autoState: AutomationState; wasEnabledOnLastCheck: boolean; registeredContextMenus: boolean; } +interface SystemColorState { + isDark: boolean | null; +} + declare const __DEBUG__: boolean; -export class Extension { +export class Extension implements ExtensionState { config: ConfigManager; devtools: DevTools; icon: IconManager; @@ -40,9 +47,9 @@ export class Extension { tabs: TabManager; user: UserStorage; - private isEnabled: boolean = null; - private wasEnabledOnLastCheck: boolean = null; - private registeredContextMenus: boolean = null; + autoState: AutomationState = ''; + wasEnabledOnLastCheck: boolean = null; + registeredContextMenus: boolean = null; private popupOpeningListener: () => void = null; // Is used only with Firefox to bypass Firefox bug private wasLastColorSchemeDark: boolean = null; @@ -51,6 +58,12 @@ export class Extension { private static ALARM_NAME = 'auto-time-alarm'; private static LOCAL_STORAGE_KEY = 'Extension-state'; + + // Store system color theme + private static SYSTEM_COLOR_LOCAL_STORAGE_KEY = 'system-color-state'; + private systemColorStateManager: StateManager; + private isDark: boolean | null = null; + constructor() { this.config = new ConfigManager(); this.devtools = new DevTools(this.config, async () => this.onSettingsChanged()); @@ -61,10 +74,10 @@ export class Extension { getTabMessage: this.getTabMessage, onColorSchemeChange: this.onColorSchemeChange, }); - this.user = new UserStorage({onRemoteSettingsChange: () => this.onRemoteSettingsChange()}); + this.user = new UserStorage(); this.startBarrier = new PromiseBarrier(); this.stateManager = new StateManager(Extension.LOCAL_STORAGE_KEY, this, { - isEnabled: null, + autoState: '', wasEnabledOnLastCheck: null, registeredContextMenus: null, }); @@ -73,9 +86,9 @@ export class Extension { if (chrome.permissions.onRemoved) { chrome.permissions.onRemoved.addListener((permissions) => { - // As far as we know, this code is never actually run because there - // is no browser UI for removing 'contextMenus' permission. - // This code exists for future-proofing in case browsers ever add such UI. + // As far as we know, this code is never actually run because there + // is no browser UI for removing 'contextMenus' permission. + // This code exists for future-proofing in case browsers ever add such UI. if (!permissions.permissions.includes('contextMenus')) { this.registeredContextMenus = false; } @@ -83,61 +96,116 @@ export class Extension { } } + private async MV3initSystemColorStateManager(isDark: boolean | null): Promise { + if (!isMV3) { + return; + } + if (!this.systemColorStateManager) { + this.systemColorStateManager = new StateManager(Extension.SYSTEM_COLOR_LOCAL_STORAGE_KEY, this, { + isDark, + }); + } + if (isDark === null) { + // Attempt to restore data from storage + return this.systemColorStateManager.loadState(); + } else if (this.isDark !== isDark) { + this.isDark = isDark; + return this.systemColorStateManager.saveState(); + } + } + + private async MV3saveSystemColorStateManager(): Promise { + if (!isMV3) { + return; + } + if (!this.systemColorStateManager) { + logWarn('MV3saveSystemColorStateManager() called before MV3initSystemColorStateManager()'); + return; + } + return this.systemColorStateManager.saveState(); + } + private alarmListener = (alarm: chrome.alarms.Alarm): void => { if (alarm.name === Extension.ALARM_NAME) { - this.handleAutoCheck(); + this.callWhenSettingsLoaded(() => { + this.handleAutomationCheck(); + }); } }; - recalculateIsEnabled(): boolean { - if (!this.user.settings) { - logWarn('Extension.isEnabled() was called before Extension.user.settings is available.'); - return false; - } + private isExtensionSwitchedOn() { + return ( + this.autoState === 'turn-on' || + this.autoState === 'scheme-dark' || + this.autoState === 'scheme-light' || + (this.autoState === '' && this.user.settings.enabled) + ); + } + + private updateAutoState() { + const {automation, automationBehaviour: behavior} = this.user.settings; - const {automation} = this.user.settings; + let isAutoDark: boolean; let nextCheck: number; switch (automation) { - case 'time': - this.isEnabled = isInTimeIntervalLocal(this.user.settings.time.activation, this.user.settings.time.deactivation); - nextCheck = nextTimeInterval(this.user.settings.time.activation, this.user.settings.time.deactivation); + case 'time': { + const {time} = this.user.settings; + isAutoDark = isInTimeIntervalLocal(time.activation, time.deactivation); + nextCheck = nextTimeInterval(time.activation, time.deactivation); break; + } case 'system': if (isMV3) { - logWarn('system automation is not yet supported. Defaulting to ON.'); - this.isEnabled = true; + isAutoDark = this.isDark; + if (this.isDark === null) { + logWarn('System color scheme is unknown. Defaulting to Dark.'); + isAutoDark = true; + } break; } if (isFirefox) { // BUG: Firefox background page always matches initial color scheme. - this.isEnabled = this.wasLastColorSchemeDark == null + isAutoDark = this.wasLastColorSchemeDark == null ? isSystemDarkModeEnabled() : this.wasLastColorSchemeDark; } else { - this.isEnabled = isSystemDarkModeEnabled(); + isAutoDark = isSystemDarkModeEnabled(); } break; case 'location': { const {latitude, longitude} = this.user.settings.location; - if (latitude != null && longitude != null) { - this.isEnabled = isNightAtLocation(latitude, longitude); + isAutoDark = isNightAtLocation(latitude, longitude); nextCheck = nextTimeChangeAtLocation(latitude, longitude); } break; } - default: - this.isEnabled = this.user.settings.enabled; + case '': break; } + + let state: AutomationState = ''; + if (automation) { + if (behavior === 'OnOff') { + state = isAutoDark ? 'turn-on' : 'turn-off'; + } else if (behavior === 'Scheme') { + state = isAutoDark ? 'scheme-dark' : 'scheme-light'; + } + } + this.autoState = state; + if (nextCheck) { - chrome.alarms.create(Extension.ALARM_NAME, {when: nextCheck}); + if (nextCheck < Date.now()) { + logWarn(`Alarm is set in the past: ${nextCheck}. The time is: ${new Date()}. ISO: ${(new Date()).toISOString()}`); + } else { + chrome.alarms.create(Extension.ALARM_NAME, {when: nextCheck}); + } } - return this.isEnabled; } async start() { await this.config.load({local: true}); + await this.MV3initSystemColorStateManager(null); await this.user.loadSettings(); if (this.user.settings.enableContextMenus && !this.registeredContextMenus) { @@ -152,6 +220,7 @@ export class Extension { if (this.user.settings.syncSitesFixes) { await this.config.load({local: false}); } + this.updateAutoState(); this.onAppToggle(); logInfo('loaded', this.user.settings); @@ -219,21 +288,12 @@ export class Extension { collect: async () => { return await this.collectData(); }, - getActiveTabInfo: async () => { - if (!this.user.settings) { - await this.user.loadSettings(); - } - await this.stateManager.loadState(); - const url = await this.tabs.getActiveTabURL(); - const info = this.getURLInfo(url); - info.isInjected = await this.tabs.canAccessActiveTab(); - return info; - }, changeSettings: (settings) => this.changeSettings(settings), setTheme: (theme) => this.setTheme(theme), setShortcut: ({command, shortcut}) => this.setShortcut(command, shortcut), - toggleURL: (url) => this.toggleURL(url), + toggleActiveTab: async () => this.toggleActiveTab(), markNewsAsRead: async (ids) => await this.news.markAsRead(...ids), + markNewsAsDisplayed: async (ids) => await this.news.markAsDisplayed(...ids), onPopupOpen: () => this.popupOpeningListener && this.popupOpeningListener(), loadConfig: async (options) => await this.config.load(options), applyDevDynamicThemeFixes: (text) => this.devtools.applyDynamicThemeFixes(text), @@ -245,7 +305,7 @@ export class Extension { }; } - onCommand = async (command: string, frameURL?: string) => { + private onCommandInternal = async (command: string, frameURL?: string) => { if (this.startBarrier.isPending()) { await this.startBarrier.entry(); } @@ -254,19 +314,20 @@ export class Extension { case 'toggle': logInfo('Toggle command entered'); this.changeSettings({ - enabled: !this.isEnabled, + enabled: !this.isExtensionSwitchedOn(), automation: '', }); break; - case 'addSite': + case 'addSite': { logInfo('Add Site command entered'); const url = frameURL || await this.tabs.getActiveTabURL(); if (isPDF(url)) { this.changeSettings({enableForPDF: !this.user.settings.enableForPDF}); } else { - this.toggleURL(url); + this.toggleActiveTab(); } break; + } case 'switchEngine': { logInfo('Switch Engine command entered'); const engines = Object.values(ThemeEngines); @@ -278,6 +339,10 @@ export class Extension { } }; + // 75 is small enough to not notice it, and still catches when someone + // is holding down a certain shortcut. + onCommand = debounce(75, this.onCommandInternal); + private registerContextMenus() { const onCommandToggle = async () => this.onCommand('toggle'); const onCommandAddSite = async (data: chrome.contextMenus.OnClickData) => this.onCommand('addSite', data.frameUrl); @@ -333,12 +398,13 @@ export class Extension { } await this.stateManager.loadState(); return { - isEnabled: this.isEnabled, + isEnabled: this.isExtensionSwitchedOn(), isReady: true, settings: this.user.settings, news: await this.news.getLatest(), shortcuts: await this.getShortcuts(), colorScheme: this.config.COLOR_SCHEMES_RAW, + forcedScheme: this.autoState === 'scheme-dark' ? 'dark' : this.autoState === 'scheme-light' ? 'light' : null, devtools: { dynamicFixesText: await this.devtools.getDynamicThemeFixesText(), filterFixesText: await this.devtools.getInversionFixesText(), @@ -347,17 +413,32 @@ export class Extension { hasCustomFilterFixes: await this.devtools.hasCustomFilterFixes(), hasCustomStaticFixes: await this.devtools.hasCustomStaticFixes(), }, + activeTab: await this.getActiveTabInfo(), }; } + private async getActiveTabInfo() { + if (!this.user.settings) { + await this.user.loadSettings(); + } + await this.stateManager.loadState(); + const url = await this.tabs.getActiveTabURL(); + const info = this.getURLInfo(url); + info.isInjected = await this.tabs.canAccessActiveTab(); + if (this.user.settings.detectDarkTheme) { + info.isDarkThemeDetected = await this.tabs.isActiveTabDarkThemeDetected(); + } + return info; + } + private onNewsUpdate(news: News[]) { if (!this.icon) { this.icon = new IconManager(); } const latestNews = news.length > 0 && news[0]; - if (latestNews && latestNews.important && !latestNews.read) { - this.icon.showImportantBadge(); + if (latestNews && latestNews.badge && !latestNews.read && !latestNews.displayed) { + this.icon.showBadge(latestNews.badge); return; } @@ -373,31 +454,48 @@ export class Extension { }); } - private onColorSchemeChange = ({isDark}: {isDark: boolean}) => { + private callWhenSettingsLoaded(callback: () => void) { + if (this.user.settings) { + callback(); + return; + } + this.user.loadSettings() + .then(async () => { + await this.stateManager.loadState(); + callback(); + }); + } + + private onColorSchemeChange = (isDark: boolean) => { + this.MV3initSystemColorStateManager(isDark); if (isFirefox) { this.wasLastColorSchemeDark = isDark; } if (this.user.settings.automation !== 'system') { return; } - this.handleAutoCheck(); + this.callWhenSettingsLoaded(() => { + this.handleAutomationCheck(); + }); }; - private async handleAutoCheck() { - if (!this.user.settings) { - await this.user.loadSettings(); - } - await this.stateManager.loadState(); - this.recalculateIsEnabled(); - const isEnabled = this.isEnabled; - if (this.wasEnabledOnLastCheck === null || this.wasEnabledOnLastCheck !== isEnabled) { - this.wasEnabledOnLastCheck = isEnabled; + private handleAutomationCheck = () => { + this.updateAutoState(); + + const isSwitchedOn = this.isExtensionSwitchedOn(); + if ( + this.wasEnabledOnLastCheck === null || + this.wasEnabledOnLastCheck !== isSwitchedOn || + this.autoState === 'scheme-dark' || + this.autoState === 'scheme-light' + ) { + this.wasEnabledOnLastCheck = isSwitchedOn; this.onAppToggle(); this.tabs.sendMessage(); this.reportChanges(); this.stateManager.saveState(); } - } + }; changeSettings($settings: Partial) { const prev = {...this.user.settings}; @@ -407,17 +505,19 @@ export class Extension { if ( (prev.enabled !== this.user.settings.enabled) || (prev.automation !== this.user.settings.automation) || + (prev.automationBehaviour !== this.user.settings.automationBehaviour) || (prev.time.activation !== this.user.settings.time.activation) || (prev.time.deactivation !== this.user.settings.time.deactivation) || (prev.location.latitude !== this.user.settings.location.latitude) || (prev.location.longitude !== this.user.settings.location.longitude) ) { + this.updateAutoState(); this.onAppToggle(); } if (prev.syncSettings !== this.user.settings.syncSettings) { this.user.saveSyncSetting(this.user.settings.syncSettings); } - if (this.isEnabled && $settings.changeBrowserTheme != null && prev.changeBrowserTheme !== $settings.changeBrowserTheme) { + if (this.isExtensionSwitchedOn() && $settings.changeBrowserTheme != null && prev.changeBrowserTheme !== $settings.changeBrowserTheme) { if ($settings.changeBrowserTheme) { setWindowTheme(this.user.settings.theme); } else { @@ -441,7 +541,7 @@ export class Extension { setTheme($theme: Partial) { this.user.set({theme: {...this.user.settings.theme, ...$theme}}); - if (this.isEnabled && this.user.settings.changeBrowserTheme) { + if (this.isExtensionSwitchedOn() && this.user.settings.changeBrowserTheme) { setWindowTheme(this.user.settings.theme); } @@ -453,32 +553,33 @@ export class Extension { this.messenger.reportChanges(info); } - toggleURL(url: string) { + async toggleActiveTab() { + const settings = this.user.settings; + const tab = await this.getActiveTabInfo(); + const {url} = tab; const isInDarkList = isURLInList(url, this.config.DARK_SITES); - const siteList = isInDarkList ? - this.user.settings.siteListEnabled.slice() : - this.user.settings.siteList.slice(); - const pattern = getURLHostOrProtocol(url); - const index = siteList.indexOf(pattern); - if (index < 0) { - siteList.push(pattern); - } else { - siteList.splice(index, 1); + const host = getURLHostOrProtocol(url); + + function getToggledList(sourceList: string[]) { + const list = sourceList.slice(); + const index = list.indexOf(host); + if (index < 0) { + list.push(host); + } else { + list.splice(index, 1); + } + return list; } - if (isInDarkList) { - this.changeSettings({siteListEnabled: siteList}); - } else { - this.changeSettings({siteList}); + + const darkThemeDetected = !settings.applyToListedOnly && settings.detectDarkTheme && tab.isDarkThemeDetected; + if (isInDarkList || darkThemeDetected || settings.siteListEnabled.includes(host)) { + const toggledList = getToggledList(settings.siteListEnabled); + this.changeSettings({siteListEnabled: toggledList}); + return; } - } - /** - * Adds host name of last focused tab - * into Sites List (or removes). - */ - async toggleCurrentSite() { - const url = await this.tabs.getActiveTabURL(); - this.toggleURL(url); + const toggledList = getToggledList(settings.siteList); + this.changeSettings({siteList: toggledList}); } //------------------------------------ @@ -491,8 +592,7 @@ export class Extension { this.icon = new IconManager(); } - this.recalculateIsEnabled(); - if (this.isEnabled) { + if (this.isExtensionSwitchedOn()) { this.icon.setActive(); if (this.user.settings.changeBrowserTheme) { setWindowTheme(this.user.settings.theme); @@ -510,7 +610,7 @@ export class Extension { await this.user.loadSettings(); } await this.stateManager.loadState(); - this.wasEnabledOnLastCheck = this.isEnabled; + this.wasEnabledOnLastCheck = this.isExtensionSwitchedOn(); this.tabs.sendMessage(); this.saveUserSettings(); this.reportChanges(); @@ -536,16 +636,24 @@ export class Extension { url, isInDarkList, isProtected, - isInjected: null + isInjected: null, + isDarkThemeDetected: null, }; } private getTabMessage = (url: string, frameURL: string): TabData => { + const settings = this.user.settings; const urlInfo = this.getURLInfo(url); - if (this.isEnabled && isURLEnabled(url, this.user.settings, urlInfo)) { - const custom = this.user.settings.customThemes.find(({url: urlList}) => isURLInList(url, urlList)); - const preset = custom ? null : this.user.settings.presets.find(({urls}) => isURLInList(url, urls)); - const theme = custom ? custom.theme : preset ? preset.theme : this.user.settings.theme; + if (this.isExtensionSwitchedOn() && isURLEnabled(url, settings, urlInfo)) { + const custom = settings.customThemes.find(({url: urlList}) => isURLInList(url, urlList)); + const preset = custom ? null : settings.presets.find(({urls}) => isURLInList(url, urls)); + let theme = custom ? custom.theme : preset ? preset.theme : settings.theme; + if (this.autoState === 'scheme-dark' || this.autoState === 'scheme-light') { + const mode = this.autoState === 'scheme-dark' ? 1 : 0; + theme = {...theme, mode}; + } + const isIFrame = frameURL != null; + const detectDarkTheme = !isIFrame && settings.detectDarkTheme && !isURLInList(url, settings.siteListEnabled) && !isPDF(url); logInfo(`Creating CSS for url: ${url}`); logInfo(`Custom theme ${custom ? 'was found' : 'was not found'}, Preset theme ${preset ? 'was found' : 'was not found'} @@ -554,14 +662,20 @@ export class Extension { case ThemeEngines.cssFilter: { return { type: MessageType.BG_ADD_CSS_FILTER, - data: createCSSFilterStylesheet(theme, url, frameURL, this.config.INVERSION_FIXES_RAW, this.config.INVERSION_FIXES_INDEX), + data: { + css: createCSSFilterStylesheet(theme, url, frameURL, this.config.INVERSION_FIXES_RAW, this.config.INVERSION_FIXES_INDEX), + detectDarkTheme, + }, }; } case ThemeEngines.svgFilter: { if (isFirefox) { return { type: MessageType.BG_ADD_CSS_FILTER, - data: createSVGFilterStylesheet(theme, url, frameURL, this.config.INVERSION_FIXES_RAW, this.config.INVERSION_FIXES_INDEX), + data: { + css: createSVGFilterStylesheet(theme, url, frameURL, this.config.INVERSION_FIXES_RAW, this.config.INVERSION_FIXES_INDEX), + detectDarkTheme, + }, }; } return { @@ -570,30 +684,35 @@ export class Extension { css: createSVGFilterStylesheet(theme, url, frameURL, this.config.INVERSION_FIXES_RAW, this.config.INVERSION_FIXES_INDEX), svgMatrix: getSVGFilterMatrixValue(theme), svgReverseMatrix: getSVGReverseFilterMatrixValue(), + detectDarkTheme, }, }; } case ThemeEngines.staticTheme: { return { type: MessageType.BG_ADD_STATIC_THEME, - data: theme.stylesheet && theme.stylesheet.trim() ? - theme.stylesheet : - createStaticStylesheet(theme, url, frameURL, this.config.STATIC_THEMES_RAW, this.config.STATIC_THEMES_INDEX), + data: { + css: theme.stylesheet && theme.stylesheet.trim() ? + theme.stylesheet : + createStaticStylesheet(theme, url, frameURL, this.config.STATIC_THEMES_RAW, this.config.STATIC_THEMES_INDEX), + detectDarkTheme: settings.detectDarkTheme, + }, }; } case ThemeEngines.dynamicTheme: { - const filter = {...theme}; - delete filter.engine; const fixes = getDynamicThemeFixesFor(url, frameURL, this.config.DYNAMIC_THEME_FIXES_RAW, this.config.DYNAMIC_THEME_FIXES_INDEX, this.user.settings.enableForPDF); - const isIFrame = frameURL != null; return { type: MessageType.BG_ADD_DYNAMIC_THEME, - data: {filter, fixes, isIFrame}, + data: { + theme, + fixes, + isIFrame, + detectDarkTheme, + }, }; } - default: { + default: throw new Error(`Unknown engine ${theme.engine}`); - } } } diff --git a/src/background/icon-manager.ts b/src/background/icon-manager.ts index 0dea7517704d..01be0d35786f 100644 --- a/src/background/icon-manager.ts +++ b/src/background/icon-manager.ts @@ -34,9 +34,9 @@ export default class IconManager { }); } - showImportantBadge() { + showBadge(text: string) { chrome.browserAction.setBadgeBackgroundColor({color: '#e96c4c'}); - chrome.browserAction.setBadgeText({text: '!'}); + chrome.browserAction.setBadgeText({text}); } hideBadge() { diff --git a/src/background/index.ts b/src/background/index.ts index 2636914d5f2f..7cbccd09a62f 100644 --- a/src/background/index.ts +++ b/src/background/index.ts @@ -46,15 +46,13 @@ if (WATCH) { send({type: 'reloading'}); } switch (message.type) { - case 'reload:css': { + case 'reload:css': chrome.runtime.sendMessage({type: MessageType.BG_CSS_UPDATE}); break; - } - case 'reload:ui': { + case 'reload:ui': chrome.runtime.sendMessage({type: MessageType.BG_UI_UPDATE}); break; - } - case 'reload:full': { + case 'reload:full': chrome.tabs.query({}, (tabs) => { for (const tab of tabs) { if (canInjectScript(tab.url)) { @@ -64,7 +62,6 @@ if (WATCH) { chrome.runtime.reload(); }); break; - } } }; socket.onclose = () => { diff --git a/src/background/make-chromium-happy.ts b/src/background/make-chromium-happy.ts index 9753aab3a1b4..fe1c1115db1d 100644 --- a/src/background/make-chromium-happy.ts +++ b/src/background/make-chromium-happy.ts @@ -1,18 +1,18 @@ import {MessageType} from '../utils/message'; import type {Message} from '../definitions'; +import {isChromium, isMV3} from '../utils/platform'; // This function exists to prevent Chrome from logging an error about // closed conduit. It just sends a dummy message in response to incomming message // to utilise open conduit. This response message is not even used on the other side. export function makeChromiumHappy() { + if (isMV3 || !isChromium) { + return; + } chrome.runtime.onMessage.addListener((message: Message, _, sendResponse) => { if (![ - // TabManager - MessageType.CS_FRAME_CONNECT, - // Messenger MessageType.UI_GET_DATA, - MessageType.UI_GET_ACTIVE_TAB_INFO, MessageType.UI_APPLY_DEV_DYNAMIC_THEME_FIXES, MessageType.UI_APPLY_DEV_INVERSION_FIXES, MessageType.UI_APPLY_DEV_STATIC_THEMES, diff --git a/src/background/messenger.ts b/src/background/messenger.ts index 6d82a0e3241f..3441a31b0f0b 100644 --- a/src/background/messenger.ts +++ b/src/background/messenger.ts @@ -4,12 +4,12 @@ import {MessageType} from '../utils/message'; export interface ExtensionAdapter { collect: () => Promise; - getActiveTabInfo: () => Promise; changeSettings: (settings: Partial) => void; setTheme: (theme: Partial) => void; setShortcut: ({command, shortcut}: {command: string; shortcut: string}) => void; markNewsAsRead: (ids: string[]) => Promise; - toggleURL: (pattern: string) => void; + markNewsAsDisplayed: (ids: string[]) => Promise; + toggleActiveTab: () => void; onPopupOpen: () => void; loadConfig: (options: {local: boolean}) => Promise; applyDevDynamicThemeFixes: (json: string) => Error; @@ -34,7 +34,6 @@ export default class Messenger { this.adapter.onPopupOpen(); return ([ MessageType.UI_GET_DATA, - MessageType.UI_GET_ACTIVE_TAB_INFO ].includes(message.type)); } }); @@ -47,9 +46,6 @@ export default class Messenger { case MessageType.UI_GET_DATA: promise = this.adapter.collect(); break; - case MessageType.UI_GET_ACTIVE_TAB_INFO: - promise = this.adapter.getActiveTabInfo(); - break; // These types require data, so we need to add a listener to the port. case MessageType.UI_APPLY_DEV_DYNAMIC_THEME_FIXES: case MessageType.UI_APPLY_DEV_INVERSION_FIXES: @@ -90,73 +86,62 @@ export default class Messenger { private onUIMessage({type, data}: Message, sendResponse: (response: {data?: ExtensionData | TabInfo; error?: string}) => void) { switch (type) { - case MessageType.UI_GET_DATA: { + case MessageType.UI_GET_DATA: this.adapter.collect().then((data) => sendResponse({data})); break; - } - case MessageType.UI_GET_ACTIVE_TAB_INFO: { - this.adapter.getActiveTabInfo().then((data) => sendResponse({data})); - break; - } - case MessageType.UI_SUBSCRIBE_TO_CHANGES: { + case MessageType.UI_SUBSCRIBE_TO_CHANGES: this.changeListenerCount++; break; - } - case MessageType.UI_UNSUBSCRIBE_FROM_CHANGES: { + case MessageType.UI_UNSUBSCRIBE_FROM_CHANGES: this.changeListenerCount--; break; - } - case MessageType.UI_CHANGE_SETTINGS: { + case MessageType.UI_CHANGE_SETTINGS: this.adapter.changeSettings(data); break; - } - case MessageType.UI_SET_THEME: { + case MessageType.UI_SET_THEME: this.adapter.setTheme(data); break; - } - case MessageType.UI_SET_SHORTCUT: { + case MessageType.UI_SET_SHORTCUT: this.adapter.setShortcut(data); break; - } - case MessageType.UI_TOGGLE_URL: { - this.adapter.toggleURL(data); + case MessageType.UI_TOGGLE_ACTIVE_TAB: + this.adapter.toggleActiveTab(); break; - } - case MessageType.UI_MARK_NEWS_AS_READ: { + case MessageType.UI_MARK_NEWS_AS_READ: this.adapter.markNewsAsRead(data); break; - } - case MessageType.UI_LOAD_CONFIG: { + case MessageType.UI_MARK_NEWS_AS_DISPLAYED: + this.adapter.markNewsAsDisplayed(data); + break; + case MessageType.UI_LOAD_CONFIG: this.adapter.loadConfig(data); break; - } case MessageType.UI_APPLY_DEV_DYNAMIC_THEME_FIXES: { const error = this.adapter.applyDevDynamicThemeFixes(data); sendResponse({error: (error ? error.message : null)}); break; } - case MessageType.UI_RESET_DEV_DYNAMIC_THEME_FIXES: { + case MessageType.UI_RESET_DEV_DYNAMIC_THEME_FIXES: this.adapter.resetDevDynamicThemeFixes(); break; - } case MessageType.UI_APPLY_DEV_INVERSION_FIXES: { const error = this.adapter.applyDevInversionFixes(data); sendResponse({error: (error ? error.message : null)}); break; } - case MessageType.UI_RESET_DEV_INVERSION_FIXES: { + case MessageType.UI_RESET_DEV_INVERSION_FIXES: this.adapter.resetDevInversionFixes(); break; - } case MessageType.UI_APPLY_DEV_STATIC_THEMES: { const error = this.adapter.applyDevStaticThemes(data); sendResponse({error: error ? error.message : null}); break; } - case MessageType.UI_RESET_DEV_STATIC_THEMES: { + case MessageType.UI_RESET_DEV_STATIC_THEMES: this.adapter.resetDevStaticThemes(); break; - } + default: + break; } } diff --git a/src/background/newsmaker.ts b/src/background/newsmaker.ts index 851bc7285cb5..1f28d8d14fb3 100644 --- a/src/background/newsmaker.ts +++ b/src/background/newsmaker.ts @@ -69,15 +69,26 @@ export default class Newsmaker { ])); } + private async getDisplayedNews(): Promise { + const sync = await readSyncStorage({displayedNews: []}); + const local = await readLocalStorage({displayedNews: []}); + return Array.from(new Set([ + ...sync ? sync.displayedNews : [], + ...local ? local.displayedNews : [], + ])); + } + private async getNews() { try { const response = await fetch(`https://darkreader.github.io/blog/posts.json`, {cache: 'no-cache'}); - const $news: Array<{id: string; date: string; headline: string; important?: boolean}> = await response.json(); + const $news: Array & {date: string}> = await response.json(); const readNews = await this.getReadNews(); - const news: News[] = $news.map(({id, date, headline, important}) => { - const url = getBlogPostURL(id); - const read = this.isRead(id, readNews); - return {id, date, headline, url, important, read}; + const displayedNews = await this.getDisplayedNews(); + const news: News[] = $news.map((n) => { + const url = getBlogPostURL(n.id); + const read = this.wasRead(n.id, readNews); + const displayed = this.wasDisplayed(n.id, displayedNews); + return {...n, url, read, displayed}; }); for (let i = 0; i < news.length; i++) { const date = new Date(news[i].date); @@ -103,9 +114,9 @@ export default class Newsmaker { } }); if (changed) { - this.latest = this.latest.map(({id, date, url, headline, important}) => { - const read = this.isRead(id, results); - return {id, date, url, headline, important, read}; + this.latest = this.latest.map((n) => { + const read = this.wasRead(n.id, results); + return {...n, read}; }); this.onUpdate(this.latest); const obj = {readNews: results}; @@ -115,7 +126,34 @@ export default class Newsmaker { } } - isRead(id: string, readNews: string[]) { + async markAsDisplayed(...ids: string[]) { + const displayedNews = await this.getDisplayedNews(); + const results = displayedNews.slice(); + let changed = false; + ids.forEach((id) => { + if (displayedNews.indexOf(id) < 0) { + results.push(id); + changed = true; + } + }); + if (changed) { + this.latest = this.latest.map((n) => { + const displayed = this.wasDisplayed(n.id, results); + return {...n, displayed}; + }); + this.onUpdate(this.latest); + const obj = {displayedNews: results}; + await writeLocalStorage(obj); + await writeSyncStorage(obj); + await this.stateManager.saveState(); + } + } + + wasRead(id: string, readNews: string[]) { return readNews.includes(id); } + + wasDisplayed(id: string, displayedNews: string[]) { + return displayedNews.includes(id); + } } diff --git a/src/background/tab-manager.ts b/src/background/tab-manager.ts index c81be6c1e3b8..8b05a1643362 100644 --- a/src/background/tab-manager.ts +++ b/src/background/tab-manager.ts @@ -2,7 +2,7 @@ import {canInjectScript} from '../background/utils/extension-api'; import {createFileLoader} from './utils/network'; import type {FetchRequestParameters} from './utils/network'; import type {Message} from '../definitions'; -import {isFirefox, isMV3, isThunderbird} from '../utils/platform'; +import {isFirefox, isMV3, isOpera, isThunderbird} from '../utils/platform'; import {MessageType} from '../utils/message'; import {logWarn} from '../utils/log'; import {StateManager} from './utils/state-manager'; @@ -21,13 +21,14 @@ interface ConnectionMessageOptions { interface TabManagerOptions { getConnectionMessage: (options: ConnectionMessageOptions) => Message | Promise; getTabMessage: (url: string, frameUrl: string) => Message; - onColorSchemeChange: ({isDark}: {isDark: boolean}) => void; + onColorSchemeChange: (isDark: boolean) => void; } interface FrameInfo { url?: string; state: DocumentState; timestamp: number; + darkThemeDetected?: boolean; } interface TabManagerState { @@ -62,6 +63,22 @@ export default class TabManager { this.tabs = {}; this.getTabMessage = getTabMessage; + async function removeFrame(tabManager: TabManager, tabId: number, frameId: number){ + await tabManager.stateManager.loadState(); + + if (frameId === 0) { + delete tabManager.tabs[tabId]; + } + + if (tabManager.tabs[tabId] && tabManager.tabs[tabId][frameId]) { + // We need to use delete here because Object.entries() + // in sendMessage() would enumerate undefined as well. + delete tabManager.tabs[tabId][frameId]; + } + + tabManager.stateManager.saveState(); + } + chrome.runtime.onMessage.addListener(async (message: Message, sender, sendResponse) => { function addFrame(tabs: {[tabId: number]: {[frameId: number]: FrameInfo}}, tabId: number, frameId: number, senderURL: string, timestamp: number) { let frames: {[frameId: number]: FrameInfo}; @@ -80,6 +97,9 @@ export default class TabManager { switch (message.type) { case MessageType.CS_FRAME_CONNECT: { + if (isMV3) { + onColorSchemeChange(message.data.isDark); + } await this.stateManager.loadState(); const reply = (options: ConnectionMessageOptions) => { const message = getConnectionMessage(options); @@ -93,7 +113,8 @@ export default class TabManager { // Workaround for Thunderbird and Vivaldi. // On Thunderbird, sometimes sender.tab is undefined but accessing it will throw a very nice error. // On Vivaldi, sometimes sender.tab is undefined as well, but error is not very helpful. - const isPanel = typeof sender === 'undefined' || typeof sender.tab === 'undefined'; + // On Opera, sender.tab.index === -1. + const isPanel = typeof sender === 'undefined' || typeof sender.tab === 'undefined' || (isOpera && sender.tab.index === -1); if (isPanel) { // NOTE: Vivaldi and Opera can show a page in a side panel, // but it is not possible to handle messaging correctly (no tab ID, frame ID). @@ -125,38 +146,27 @@ export default class TabManager { frameURL: frameId === 0 ? null : senderURL, }); this.stateManager.saveState(); - sendResponse({type: '¯\\_(ツ)_/¯'}); break; } - case MessageType.CS_FRAME_FORGET: { - await this.stateManager.loadState(); + case MessageType.CS_FRAME_FORGET: if (!sender.tab) { logWarn('Unexpected message', message, sender); break; } - const tabId = sender.tab.id; - const frameId = sender.frameId; - - if (frameId === 0) { - delete this.tabs[tabId]; - } - - if (this.tabs[tabId] && this.tabs[tabId][frameId]) { - // We need to use delete here because Object.entries() - // in sendMessage() would enumerate undefined as well. - delete this.tabs[tabId][frameId]; - } - this.stateManager.saveState(); + removeFrame(this, sender.tab.id, sender.frameId); break; - } - case MessageType.CS_FRAME_FREEZE: + case MessageType.CS_FRAME_FREEZE: { await this.stateManager.loadState(); const info = this.tabs[sender.tab.id][sender.frameId]; info.state = DocumentState.FROZEN; info.url = null; this.stateManager.saveState(); break; + } case MessageType.CS_FRAME_RESUME: { + if (isMV3) { + onColorSchemeChange(message.data.isDark); + } await this.stateManager.loadState(); const tabId = sender.tab.id; const frameId = sender.frameId; @@ -173,12 +183,15 @@ export default class TabManager { this.stateManager.saveState(); break; } + case MessageType.CS_DARK_THEME_DETECTED: + this.tabs[sender.tab.id][sender.frameId].darkThemeDetected = true; + break; case MessageType.CS_FETCH: { // Using custom response due to Chrome and Firefox incompatibility // Sometimes fetch error behaves like synchronous and sends `undefined` const id = message.id; - const sendResponse = (response: Partial) => chrome.tabs.sendMessage(sender.tab.id, {type: MessageType.BG_FETCH_RESPONSE, id, ...response}); + const sendResponse = (response: Partial) => chrome.tabs.sendMessage(sender.tab.id, {type: MessageType.BG_FETCH_RESPONSE, id, ...response}, {frameId: sender.frameId}); if (isThunderbird) { // In thunderbird some CSS is loaded on a chrome:// URL. // Thunderbird restricted Add-ons to load those URL's. @@ -200,10 +213,9 @@ export default class TabManager { break; } - case MessageType.CS_COLOR_SCHEME_CHANGE: { + case MessageType.CS_COLOR_SCHEME_CHANGE: onColorSchemeChange(message.data); break; - } case MessageType.UI_SAVE_FILE: { const {content, name} = message.data; @@ -219,8 +231,13 @@ export default class TabManager { chrome.tabs.sendMessage(activeTab.id, {type: MessageType.BG_EXPORT_CSS}, {frameId: 0}); break; } + + default: + break; } }); + + chrome.tabs.onRemoved.addListener(async (tabId) => removeFrame(this, tabId, 0)); } getTabURL(tab: chrome.tabs.Tab): string { @@ -293,6 +310,11 @@ export default class TabManager { return Boolean(this.tabs[tab.id]); } + async isActiveTabDarkThemeDetected() { + const tab = await this.getActiveTab(); + return this.tabs[tab.id] && this.tabs[tab.id][0] && this.tabs[tab.id][0].darkThemeDetected; + } + async getActiveTabURL() { return this.getTabURL(await this.getActiveTab()); } diff --git a/src/background/user-storage.ts b/src/background/user-storage.ts index 240bc89431bf..faaff61544da 100644 --- a/src/background/user-storage.ts +++ b/src/background/user-storage.ts @@ -2,26 +2,19 @@ import {DEFAULT_SETTINGS, DEFAULT_THEME} from '../defaults'; import {debounce} from '../utils/debounce'; import {isURLMatched} from '../utils/url'; import type {UserSettings} from '../definitions'; -import {readSyncStorage, readLocalStorage, writeSyncStorage, writeLocalStorage, subscribeToOuterSettingsChange} from './utils/extension-api'; +import {readSyncStorage, readLocalStorage, writeSyncStorage, writeLocalStorage} from './utils/extension-api'; import {logWarn} from '../utils/log'; import {PromiseBarrier} from '../utils/promise-barrier'; +import {validateSettings} from '../utils/validation'; const SAVE_TIMEOUT = 1000; -interface UserStorageOptions { - onRemoteSettingsChange: () => void; -} - export default class UserStorage { private loadBarrier: PromiseBarrier; private saveStorageBarrier: PromiseBarrier; - constructor({onRemoteSettingsChange}: UserStorageOptions) { + constructor() { this.settings = null; - subscribeToOuterSettingsChange(async () => { - await this.loadSettings(); - onRemoteSettingsChange(); - }); } settings: Readonly; @@ -48,6 +41,8 @@ export default class UserStorage { this.loadBarrier = new PromiseBarrier(); const local = await readLocalStorage(DEFAULT_SETTINGS); + const {errors: localCfgErrors} = validateSettings(local); + localCfgErrors.forEach((err) => logWarn(err)); if (local.syncSettings == null) { local.syncSettings = DEFAULT_SETTINGS.syncSettings; } @@ -67,11 +62,13 @@ export default class UserStorage { return local; } - const sync = await readSyncStorage(DEFAULT_SETTINGS); - this.fillDefaults(sync); + const {errors: syncCfgErrors} = validateSettings($sync); + syncCfgErrors.forEach((err) => logWarn(err)); + + this.fillDefaults($sync); - this.loadBarrier.resolve(sync); - return sync; + this.loadBarrier.resolve($sync); + return $sync; } async saveSettings() { diff --git a/src/background/utils/extension-api.ts b/src/background/utils/extension-api.ts index b13a26f00197..5482b83ca2a3 100644 --- a/src/background/utils/extension-api.ts +++ b/src/background/utils/extension-api.ts @@ -1,6 +1,5 @@ import {isPDF} from '../../utils/url'; import {isFirefox, isEdge} from '../../utils/platform'; -import {Mutex} from '../../utils/mutex'; declare const browser: { commands: { @@ -38,14 +37,12 @@ export function canInjectScript(url: string) { ); } -const mutexStorageWriting = new Mutex(); - export async function readSyncStorage(defaults: T): Promise { return new Promise((resolve) => { chrome.storage.sync.get(null, (sync: any) => { if (chrome.runtime.lastError) { console.error(chrome.runtime.lastError.message); - resolve(defaults); + resolve(null); return; } @@ -68,7 +65,9 @@ export async function readSyncStorage(defaults: try { sync[key] = JSON.parse(string); } catch (error) { - console.error('Could not parse record from sync storage', string); + console.error(`sync[${key}]: Could not parse record from sync storage: ${string}`); + resolve(null); + return; } } @@ -121,37 +120,24 @@ function prepareSyncStorage(values: T): {[key: s export async function writeSyncStorage(values: T): Promise { return new Promise(async (resolve, reject) => { const packaged = prepareSyncStorage(values); - await mutexStorageWriting.lock(); chrome.storage.sync.set(packaged, () => { if (chrome.runtime.lastError) { reject(chrome.runtime.lastError); - mutexStorageWriting.unlock(); return; } resolve(); - setTimeout(() => mutexStorageWriting.unlock(), 500); }); }); } export async function writeLocalStorage(values: T): Promise { return new Promise(async (resolve) => { - await mutexStorageWriting.lock(); chrome.storage.local.set(values, () => { resolve(); - setTimeout(() => mutexStorageWriting.unlock(), 500); }); }); } -export const subscribeToOuterSettingsChange = (callback: () => void) => { - chrome.storage.onChanged.addListener((_, storageArea) => { - if (storageArea === 'sync' && !mutexStorageWriting.isLocked()) { - callback(); - } - }); -}; - export async function getCommands() { return new Promise((resolve) => { if (!chrome.commands) { diff --git a/src/background/utils/state-manager.ts b/src/background/utils/state-manager.ts index 70be6b9fbf1a..100c7ece1462 100644 --- a/src/background/utils/state-manager.ts +++ b/src/background/utils/state-manager.ts @@ -84,8 +84,8 @@ export class StateManager { private collectState() { const state = {} as T; - for (const key of Object.keys(this.defaults)) { - state[key as keyof T] = this.parent[key as keyof T] || this.defaults[key as keyof T]; + for (const key of Object.keys(this.defaults) as Array) { + state[key] = this.parent[key] || this.defaults[key]; } return state; } diff --git a/src/config/color-schemes.drconf b/src/config/color-schemes.drconf index 5e8feaeed3c4..db9d693a3b3a 100644 --- a/src/config/color-schemes.drconf +++ b/src/config/color-schemes.drconf @@ -10,6 +10,14 @@ text: #e8e6e3 ================================ +Catppuccin + +DARK +background: #161320 +text: #d9e0ee + +================================ + Dracula DARK @@ -18,6 +26,18 @@ text: #e8e6e3 ================================ +Gruvbox + +DARK +background: #282828 +text: #ebdbb2 + +LIGHT +background: #fbf1c7 +text: #3c3836 + +================================ + Nord DARK @@ -39,3 +59,16 @@ text: #93a1a1 LIGHT background: #fdf6e3 text: #586e75 + +================================ + +Tokyo Night + +DARK +background: #1a1b26 +text: #a9b1d6 + +LIGHT +background: #d5d6db +text: #343b58 + diff --git a/src/config/dark-sites.config b/src/config/dark-sites.config index ea3164334363..539cb4bf315c 100644 --- a/src/config/dark-sites.config +++ b/src/config/dark-sites.config @@ -9,10 +9,15 @@ 2bqueue.info 314n.org 5stardata.info +9anime.center +9anime.club +9anime.id 9anime.to +abletonbot.me absolucy.moe account.bhvr.com accounts.pubg.com +aceship.github.io acm.sdut.edu.cn/onlinejudge3/ addictinggames.com adridoesthings.com @@ -30,7 +35,10 @@ animencodes.com animepahe.com animixplay.to animk.info +anishde.dev +anitrack.co anon.sx +antalbiztonsag.com aonprd.com app.destinyitemmanager.com app.keeweb.info @@ -40,10 +48,12 @@ app.revolt.chat app.sqldbm.com applesilicongames.com application.security +aqtiongame.com ara-ara-ufufu.herokuapp.com arche-dev.codeberg.page archive.ragtag.moe argoto.snaz.in +ari-web.xyz arisuchan.jp arkadia.xyz arkenfox.github.io/TZP/ @@ -52,13 +62,14 @@ artixlinux.org artofkeys.com as2.aiae.ovh asciimation.co.nz +ashcam.xyz asherhe.com -ashishpanigrahi.me +ashishpanigrahi.xyz asoftmurmur.com aspenuwu.me -ass.rip -ass.software +assassins-creed.de ast4u.me +astronvim.github.io astrovpn.co atelier.net/virtual-economy atlassurvivalshelters.com @@ -69,11 +80,13 @@ audiomass.co audioz.download augmentedsteam.com avengedsevenfold.com +axyl-os.github.io azeria-labs.com azm.azerialabs.com badboybill.com batflix.org battle.net +battlelog.battlefield.com bbaovanc.com bbc.co.uk/iplayer bdeditor.dev @@ -87,17 +100,19 @@ benleggiero.blog benleggiero.me bequiet.com bestblackhatforum.com +beta.crunchyroll.com beta.destinyitemmanager.com +betteranime.net betterdiscord.app betterttv.com bherila.net bin.disroot.org binclub.dev -bing.com/$ bip.staszic.waw.pl birdie0.github.io bitcoinity.org/markets bitcoinwisdom.com +bithatch.co.uk bittube.video blackhat.com blackhatsem.com @@ -105,6 +120,7 @@ blackhatworld.com blackhole.run blackle.com blackmod.net +blakthumb.com blastpremier.com blgn.dev blink.sh @@ -124,6 +140,7 @@ brawldb.com breaksforeyes.app brew.sh bri.io +brianpmaher.com broadcasthe.net brodierobertson.xyz browserslist.vercel.app @@ -133,8 +150,10 @@ bugmenot.com buildbot.orphis.net bungie.net byte.co +bytebin.lucko.me c-saccoccio.fr cadence.moe +caesarshiba.com caniuse.com captaindisillusion.com caracal.club @@ -145,6 +164,7 @@ cascadr.co catvibers.me cdkeys.com cdnnow.pro +channel4.com chat.ryzom.com cheat.sh checkra.in @@ -152,19 +172,23 @@ chess.com chessbomb.com chitownhousemusic.com chromatic-tuner.com +cider.sh cinema-city.pl cl00e9ment.gitlab.io/kingdom-blazon-generator/ clash3d.com clashofstats.com clt.gg +cncnet.org codepen.io codesandbox.io codestackr.com codingame.com coinpot.co +colean.cc comicextra.com comicpunch.net conficturaindustries.com +connect-4.xyz coolmathgames.com copter.io corepacks.com @@ -189,7 +213,9 @@ cybercrime-tracker.net cyberdrop.me cyberpunk.net cybersole.io +cyberspatial.com cytu.be +daddyanity.com daily-fire.com daksh.eu.org danidev.net @@ -221,8 +247,9 @@ developerinsider.co developpement-systeme-exploitation.github.io/documentation di.fm diablo3.com +diablogame.de diep.io -dietpi.com +digi77.com digital.fashion disasm.pro disboard.org @@ -245,8 +272,10 @@ discourse.disneyheroesgame.com discuss.noisebridge.info disneyplus.com distrotube.com +djflame.tech dlive.tv dodi-repacks.site +doesitarm.com dood.la doodstream.com dota2.ru @@ -255,13 +284,16 @@ dotapicker.com dplay.com draculatheme.com draftkings.com +dragonage-game.de drakewars.com drunkenslug.com drvortex.dev +dsa-drakensang.de dsc.gg duckychannel.com.tw duelingnexus.com dumpert.nl +dungeon-lords.de dyno.gg easypastes.tk editor.freepik.com @@ -286,6 +318,7 @@ epack.js.org epicgames.com/id epicgames.com/store erai-raws.info +ericnl.com escapefromtarkov.com escapefromtarkov.fandom.com esportal.com @@ -293,6 +326,7 @@ etcroot.pw etke.cc etlegacy.com evewho.com +evokemusic.ai evowars.io extrememusic.com f.vision @@ -300,8 +334,11 @@ faceit-enhancer.com faceit.com factorio.com factoriobin.com +fallout-area.de femto.dev femto.pw +fictivekin.com +filmmakermode.com filterblade.xyz filterlists.com find.lolpros.gg @@ -313,6 +350,8 @@ flooxer.com florr.io fluxpoint.dev flyordie.io +fmovies.to +food-le.co fortnite-api.com forum.cswarzone.com forum.lastos.org @@ -323,15 +362,19 @@ forum.xda-developers.com forumplayer.dev forums.launchbox-app.com fox.com +fpn.firefox.com frankerfacez.com/$ freespeechextremist.com frozensand.com funnyjunk.com fusengine.github.io/apaxy-v2 +galacticabot.vercel.app gamebanana.com gamejolt.com gameloop.fun +gaming.amazon.com garamlee500.github.io +garudalinux.org gatsbyjs.org geekabit.nl geektyper.com @@ -339,6 +382,7 @@ gekri.com generated.photos genshin.gg geocities.restorativland.org +geometry.best getaether.net getdweb.net gethalfmoon.com @@ -352,6 +396,7 @@ ghidra-sre.org ghostpgp.com giantbomb.com gibber.cc +gibbu.github.io/ThemePreview/ gifrun.com gifyourgame.com giggl.app @@ -371,7 +416,9 @@ god.freevar.com gog.com/forum gogalaxy.com gogoanime.se +goodfirstissue.dev goosegame.io +grapheneos.org graydon2.dreamwidth.org grc.arikado.ru greatview.video @@ -393,11 +440,14 @@ hacktoberfest-projects.vercel.app halowaypoint.com hardcoregaming101.net hardforum.com +hardstuck.gg +hardwaretimes.com hastebin.com hbomax.com hdencode.com heapmedia.com heavybit.com +heliotrope.dk hellofromhe.re help.steampowered.com hermes.ksdfg.me @@ -405,11 +455,12 @@ herodamage.com hexiro.me hidive.com himovies.to +hiserod.github.io hiveos.farm hoarding.me -hoppscotch.io hostedtalk.net hotstar.com +hrmspms.sicorax.mu htmlpasta.com humblebundle.com/$ humblebundle.com/accessibility @@ -418,6 +469,7 @@ humblebundle.com/refer humblebundle.com/subscription humblegames.com hyper.is +hyperbeam.dev i3wm.org ibookpile.net identinator.com @@ -442,14 +494,17 @@ iq.com isitchristmas.com isthereanydeal.com isxander.dev +itv.com iwanttoeat.app ixirc.com jackdaniels.com jakobneumann.com jakubkaczor.com jakubkaczor.github.io +jbzd.com.pl jekyllrb.com jellymar.io +jeusto.com jhey.dev jigsawpuzzles.io jmoore.dev @@ -460,9 +515,14 @@ jqbx.fm jsben.ch jsfiddle.net jsitor.com +json-diff.com +justfive.news kadantiscam.netlify.app kaoskrew.org +kbh.games +kbhgames.com keezersquest.nl +kfocus.org killabee-gaming.com killtheradio.net kimbatt.github.io/js-Z @@ -472,13 +532,19 @@ kiwifarms.cc kiwifarms.net knockout.chat kodenames.io +kreatea.space kreato.cf +krisoneil.com/home +kristal.cc krunker.io ksp.mff.cuni.cz +kuik.li kulbachny.com +kwejk.pl kyleggiero.me lagom.nl/lcd-test lainchan.org +landchad.net larbs.xyz lbrynomics.com leakedsource.ru @@ -486,16 +552,18 @@ leakth.is lecantiche.com lemmi.no letterboxd.com +libreboot.org lightweightpdf.com limeshark.dev/editor link.brawlstars.com/invite linux.org.ru +linuxgamingcentral.com +lipu-linku.github.io liquidplus.com listen.moe livesplit.org +loadout.tf lolesports.com -lollilol.cf -lollilol.ml lollilol.xyz lookmovie.ag looskie.com @@ -504,6 +572,8 @@ lootgod.com lordofthemanor.io lospec.com lukesmith.xyz +lumina-desktop.org +lutris.net m2v.ru m4rtyr.github.io macbb.org @@ -513,9 +583,11 @@ magoware.tv manen.me mangaplus.shueisha.co.jp mango.pdf.zone -marekmaskarinec.github.io maroon.jonah.pw marte.dev +mastercomfig.com +mastodon.online +mastodon.social matteotiscia.com mcrpw.github.io mcskinhistory.com @@ -527,6 +599,8 @@ memory-alpha.fandom.com merklex.io metronom.us metropool.nl +mewho.com/starfield47 +migueldemoura.com mikemaximus.github.io/gbm-web minehut.com miniroyale2.io @@ -542,19 +616,32 @@ monkeytype.com monkrus.ws mope.io mouse-sensitivity.com +mrms.cz +music.com music.youtube.com mwittrien.github.io mwomercs.com +my00stv.com +my60stv.com +my70stv.com +my80stv.com +my90stv.com mynoise.net mypodficacademia.com +mystere.dev n-o-d-e.net namechk.com nanhu.ca +nationsglory.com +nationsglory.es +nationsglory.fr nchristopher.me neal.fun/size-of-space nee.lv neovim.io +netzhack.de neundex.com +neurocore.xyz newgrounds.com nexusmods.com nfs.fandom.com @@ -579,25 +666,30 @@ nitwhiz.xyz nodejs.dev noisebridge.net nomanssky.com +northward.info nostv.pt notebooks.quantumstat.com +notiger.xyz nowplayi.ng null.media nulledbb.com -obsidian.md obsproject.com +odysee.com offshorecorptalk.com ogusers.com ohmyz.sh oldergeeks.com oldfag.org +omcar.pl omgwtfnzbs.me onionplay.co online.lloydsbank.co.uk +onlyformats.netlify.app open.spotify.com openbase.io opendota.com openemu.org +openrazer.github.io orama-interactive.itch.io/pixelorama orteil.dashnet.org/cookieclicker osu.ppy.sh @@ -612,7 +704,9 @@ paimon.moe paper-io.com parahumans.wordpress.com paranoid.email +parrotsec.org passthepopcorn.me +pastes.dev pathof.info pathofexile.com pathofexile.fandom.com @@ -632,9 +726,18 @@ pic.cleoold.com pic8.co ping.pe piped.kavin.rocks +piped.mha.fi +piped.mint.lgbt +piped.moomoo.me +piped.privacy.com.de +piped.silkky.cloud +piped.tokhmi.xyz piracybank.org piskelapp.com pitokmm.it +planetneverwinter.de +plasticuproject.com +platinumgod.co.uk play.geforcenow.com play.hbogo.com play.mubert.com @@ -658,6 +761,7 @@ poelab.com poison.gg polsatboxgo.pl polsatgo.pl +polychromatic.app pony.tube pool.pm powercord.dev @@ -667,6 +771,7 @@ pre.fyp.nl premid.app primevideo.com progettosnaps.net +programsquared.com projectdiscovery.io protogen.dev protondb.com @@ -675,11 +780,16 @@ proxy.vulpes.one psi.cynicaloptimist.me psyoptions.io ptt.cc +pussthecat.org +pvplegacy.net pxseu.com pylon.bot qbraid.com +raidbots.com +raidcore.gg raider.io raidforums.com +raidplan.io raidtime.net rain-world-modding.github.io randacek.dev @@ -687,6 +797,9 @@ rapidheaven.com rate.house raunaksitoula.com rawg.io +rawgiving.com +ray.so +raycast.com razorsecure.com rbt.asia rdck.dev @@ -707,12 +820,16 @@ residentevil.net restream4me.com resurrectionremix.com retromusic.app +returnyoutubedislike.com reveddit.com revolt.chat +richup.io ripped.guide +rl6mans.com robofight.io rocketleagueesports.com roleypoly.com +roman.hn romefrontend.dev roosterteeth.fandom.com router.asus.com @@ -725,7 +842,9 @@ rust.nolt.io rythm.fm rythmbot.co sa-mp.com +sacred-legends.de sadh.life +sadistic.pl sammcheese.net samsai.eu sandervanderburg.blogspot.com @@ -747,7 +866,11 @@ securegroup.com seoringslerbhfa.club serebii.net settings.gg +seximal.net +sharkiller.ddns.net +shatteredpixel.com sheet.host +shellshock.io sherlock-project.github.io showtimeanytime.com shpposter.club @@ -771,14 +894,16 @@ slider.kz slippi.gg slither.io snazzah.com +somafm.com spacebattles.com spacestationgaming.com +spark.lucko.me +speedrun.com speedtest.net sportsurge.net spy-cards.lubar.me spyware.neocities.org srrdb.com -stadia.google.com star-made.org stargazing.net starlink.com @@ -787,6 +912,7 @@ staszic.waw.pl statbot.net stateofjs.com steam.tv +steamcharts.com steamchina.com steamcommunity.com steamdb.info @@ -807,13 +933,16 @@ sunxdcc.com supabase.io supinic.com support.steampowered.com +supremacy1914.com surviv.io svtplay.se -symfony.com +sync-tube.de szmarczak.com t.maisputain.ovh +tabstats.com tacoanon.github.io takethewalk.net +talentbrick.com tallguysfree.com tarkov-market.com tauri.studio @@ -822,11 +951,12 @@ teambeyond.net teamos-hkrg.com teaspeak.de techwithalext.com -teddit.namazso.eu teddit.zaggy.nl telecineplay.com.br +teleseer.com televizeseznam.cz telugucz.com +term.ooo terminal.sexy tetr.io textfiles.com @@ -835,6 +965,7 @@ tgw1916.net/bacteria_abis.html the-eye.eu thealiendrew.github.io thegraph.com +thelinuxcast.org themes.vscode.one thetatoken.org thinkwithportals.com @@ -844,13 +975,19 @@ throwbacks-music.com thunix.net tilde.club tilde.team +tilde.town +tildegit.org tildeverse.org tinyzonetv.to tio.run +title-case-converter.vercel.app tmtheme-editor.herokuapp.com +tommytran.io toneden.io +top.gg totalwarwarhammer.gamepedia.com tracker.fumik0.com +tracker.gg tracr.co training.azeria-labs.com trblwlf.tk @@ -869,10 +1006,12 @@ tuner.ninja tusharsadhwani.dev twelvesmith.com twist.moe +twnft.vercel.app tycrek.com tynker.com/ide typing.works ufplanets.com +ukui.org unc0ver.dev undergroundcellar.com underlords.com @@ -880,12 +1019,12 @@ undertale.com userdiag.com ussr.obys.agency uwatchfree.ax +v15.studio v3.wttr.in v3rmillion.net v7player.wostreaming.net v8.dev vakhtangov.ru -valh.io valvestore.forfansbyfans.com vancedapp.com vanillatweaks.net @@ -902,16 +1041,21 @@ virustotal.com/old-browsers visualboxsite.com vixlatio.com vizality.com +vogons.org vortetty.k3live.com vrv.co +vscode.dev +vscodethemes.com vtcdirectory.com vuecinemas.nl w0rp.com w41k3r.com +wago.io wallhaven.cc wallpaperplay.com wannabuy.biz warcraftdaily.com +warcraftlogs.com warezforums.com warsow.net wasm.continuation-labs.com/d3demo/ @@ -921,26 +1065,44 @@ weboas.is whirl.codes widgetbot.io wiki.step-project.com +windowsterminalthemes.dev +winget.run +wiocha.pl wolfy.fr +worldofamalur.de +worldofcyberpunk.de +worldofgothic.de +worldofrisen.de wormate.io wormhole.app wowaudit.com wowhead.com wowinterface.com +wtfast.com +wttr.in +www.ageofempires.com +www.canalplus.com +www.cc.com www.chiefdelphi.com +www.deviantart.com www.digikam.org www.directvnow.com www.gotimelinr.com +www.mtv.com www.netflix.com www.razer.com www.seebham.codes +www.siddharthray.com www.teamfortress.com www.tvnz.co.nz www.wickeditor.com/editor/ +www.worldofplayers.de x1337x.*/$ x64dbg.com xbins.org +xdox.me xela.dev +xerolinux.xyz xn--rpa.cc xonotic.org yande.re @@ -959,3 +1121,4 @@ zombsroyale.io zoomquilt.org zoomquilt2.com ztdp.ca +zunivers.zerator.com diff --git a/src/config/dynamic-theme-fixes.config b/src/config/dynamic-theme-fixes.config index 5c41c6d6ef8e..55a4f297fba2 100644 --- a/src/config/dynamic-theme-fixes.config +++ b/src/config/dynamic-theme-fixes.config @@ -17,9 +17,6 @@ CSS ::placeholder { opacity: 0.5 !important; } -a[href="https://coinmarketcap.com/"] > svg[width="94"][height="16"] > path { - fill: var(--darkreader-neutral-text) !important; -} #edge-translate-panel-body, .MuiTypography-body1 { color: var(--darkreader-neutral-text) !important; @@ -27,119 +24,35 @@ a[href="https://coinmarketcap.com/"] > svg[width="94"][height="16"] > path { gr-main-header { background-color: ${lightblue} !important; } - -IGNORE INLINE STYLE -.sr-wrapper * -.sr-reader * -.diigoHighlight - -================================ - -*.bbb.* - -CSS -div[class^='scrollableList'] { - background: none !important; - box-shadow: none !important; -} - -================================ - -*.screenconnect.com - -CSS -.OuterPanel .MainPanel .MasterPanel .MasterListContainer ul li.HasChildren > div > p { - filter: brightness(100%) !important; -} - -================================ - -*.stackexchange.com -askubuntu.com -mathoverflow.net -serverfault.com -stackapps.com -stackexchange.com -stackoverflow.com -superuser.com - -INVERT -._glyph -.favicon-mathoverflow -.favicon-mathoverflowmeta -.favicon-stackoverflowmeta -.h-auto[alt="Academia"] -.h-auto[alt="Anime & Manga"] -.h-auto[alt="Ask Different"] -.h-auto[alt="Aviation"] -.h-auto[alt="Code Review"] -.h-auto[alt="Electrical Engineering"] -.h-auto[alt="English Language Learners"] -.h-auto[alt="Japanese Language"] -.h-auto[alt="MathOverflow"] -.h-auto[alt="Mathematics"] -.h-auto[alt="Server Fault"] -.h-auto[alt="Skeptics"] -.h-auto[alt="Software Engineering"] -.h-auto[alt="Stack Apps"] -.h-auto[alt="Super User"] -.h-auto[alt="The Workplace"] -.h-auto[alt="Theoretical Computer Science"] -.h-auto[alt="Unix & Linux"] -.h-auto[alt="Web Applications"] -a.js-gps-track::before -img[alt="The Stack Exchange Network"] - -CSS -body { - background-image: none !important; -} -.profile-cards--graph { - background-image: repeating-linear-gradient(0deg, transparent, transparent 13px, ${#e4e6e8} -13px, ${#e4e6e8} 21px) !important; +.tou-z65h9k, +.tou-mignzq, +.tou-1b6i2ox, +.tou-lnqlqk { + background-color: var(--darkreader-neutral-background) !important; } -.c-pointer { - color: grey; +.tou-75mvi { + background-color: ${rgb(207, 236, 245)} !important; } -.js-accepted-answer-indicator.fc-green-500 { - color: var(--green) !important; +.tou-ta9e87, +.tou-1w3fhi0, +.tou-1b8t2us, +.tou-py7lfi, +.tou-1lpmd9d, +.tou-1frrtv8, +.tou-17ezmgn { + background-color: ${rgb(245, 245, 245)} !important; } -#newuser-box { - background-color: ${#FFF8DC} !important; +.tou-uknfeu { + background-color: ${rgb(250, 237, 218)} !important; } - -IGNORE INLINE STYLE -.chess-replayer-board td - -================================ - -*.ubereats.com - -INVERT -img[alt*='Home'] -div[class^='c5'] .gm-style -#main-content > h1 + div -#wrapper > div:nth-of-type(2) -#wrapper > div:nth-of-type(2) > header -#wrapper > div:nth-of-type(2) > footer -#wrapper > div:nth-of-type(2) > #main-content > div:first-child - -================================ - -*.vultr.com - -CSS -.svg-banner-shape { - fill: var(--darkreader-neutral-background) !important; +.tou-6i3zyv { + background-color: ${rgb(133, 195, 216)} !important; } IGNORE INLINE STYLE -.icon-ui * -.icon-user * -.icon-sm * -.svg-logo * -.svg-illustration * -.svg-product * -.svg-shape * +.sr-wrapper * +.sr-reader * +.diigoHighlight ================================ @@ -177,6 +90,15 @@ body, ================================ +10minutemail.com + +CSS +#main_content { + background-image: none !important; +} + +================================ + 123-3d.nl 123accu.nl 123inkt.nl @@ -202,7 +124,7 @@ ul.sub-menu { background-color: var(--darkreader-neutral-background) !important; } ul.sub-menu::after { - border-bottom-color: var(--darkreader-neutral-background) !important; + border-bottom-color: var(--darkreader-neutral-background) !important; } .progress-wrap { box-shadow: var(--darkreader-neutral-background) 0px 0px 0px 3px inset !important; @@ -312,6 +234,23 @@ body, .nav__main { ================================ +300gospodarka.pl +300polityka.pl + +INVERT +#logo +img[alt="300Gospodarka"] +img[alt="Zespół 300Gospodarki"] + +================================ + +40ton.net + +INVERT +.td-main-logo + +================================ + 4pda.ru CSS @@ -324,6 +263,32 @@ div.description > span { ================================ +4t-niagara.com + +CSS +.download_link > h3, +.buy_link > h3 { + color: ${#88c1ff} !important; +} +.download_link li, +.buy_link li { + color: ${white} !important; +} + +================================ + +a11ywithlindsey.com + +INVERT +.logo + +CSS +:root { + --off-white: var(--darkreader-neutral-background) !important; +} + +================================ + aad.org INVERT @@ -343,6 +308,16 @@ CSS ================================ +abcnews.go.com + +INVERT +.navLogo +#sections +#search +#notifications + +================================ + abiturma.de INVERT @@ -395,6 +370,22 @@ CSS ================================ +access.wgu.edu +my.wgu.edu + +INVERT +img[alt="WGU Logo"] +.nav-hamburger + +================================ + +accesswire.com + +INVERT +.v2-nav-logo + +================================ + account.live.com INVERT @@ -402,6 +393,11 @@ INVERT .ms-Grid-col.ms-sm4.ms-hiddenMdDown.pullout-textwrap .ms-Grid-col.ms-sm2 img +CSS +img[class="ShowMoreLoading"] { + filter: invert(93.7%) hue-rotate(180deg) contrast(90.6%) !important +} + ================================ account.orchid.com @@ -411,20 +407,22 @@ INVERT ================================ -account.protonmail.com +account.proton.me +account.protonvpn.com + +INVERT +.sign-layout-bg +.sign-layout-bg > * CSS -:root { - --field-background-color: var(--darkreader-bg--background-norm) !important; -} -.label-stack-item { - background-color: var(--color) !important; -} -.label-stack-item-button, -.label-stack-item-delete { - color: ${white} !important; +.qr-code { + border: 5px solid white !important; } +IGNORE INLINE STYLE +.logo * +.qr-code * + ================================ account.ui.com @@ -463,15 +461,20 @@ CSS ================================ -accounts.magister.net +accounts.zoho.com INVERT -.bottom > img +div#product_img.tfa_totp_mode +span.zoho_logo -CSS -.splash-container { - z-index: 0 !important; -} +================================ + +accuweather.com + +INVERT +.allergy-icon +.icon-search +img[src$="arrow-right-black.svg"] ================================ @@ -490,6 +493,21 @@ CSS ================================ +acorn.utoronto.ca + +CSS +.acorn-classic.page-container .academic-history .sessionHeader, +.acorn-classic.page-container .academic-history .credit-earned-section, +.acorn-classic.page-container .academic-history .average-section, +.acorn-classic.page-container .academic-history .courses, +.acorn-classic.page-container .academic-history .coursesHeader, +.acorn-classic.page-container .academic-history .academic-history-report .gpa-listing, +.acorn-classic.page-container .academic-history-recent table .emph { + color: var(--darkreader-neutral-text) !important; +} + +================================ + ad.nl CSS @@ -514,6 +532,18 @@ span.Permission-description:before ================================ +adguard-dns.io + +INVERT +.animation__video + +CSS +.animation__video { + z-index: 0 !important; +} + +================================ + adguard.com INVERT @@ -542,6 +572,13 @@ CSS ================================ +afterpay.com + +INVERT +div[class^="navigation_logo"] + +================================ + aftonbladet.se CSS @@ -609,6 +646,13 @@ CSS ================================ +aldi.us + +IGNORE INLINE STYLE +.company-logo-content * + +================================ + alertus.com INVERT @@ -667,7 +711,6 @@ svg[class^="ali-kit_Rating__star"] alipay.com INVERT -.alipay-logo #J_logoHomeUrl .global-logo @@ -679,7 +722,9 @@ CSS z-index: 0 !important; } .authcenter-head, -.authcenter-foot { +.authcenter-foot, +.authcenter-body-login, +.authcenter-body-logo > a { z-index: 1 !important; } @@ -698,13 +743,15 @@ allegro.pl INVERT i[title="Smart!"] +[alt*="smart" i] div[class="mpof_ki m389_6m"] img[alt="Zakup z pakietem Smart"] +div.sob6jg.so1d89.mpof_ki .so15i8 CSS #opbox-listing--base i, -[class*='2UYuR'] { +article i { background-size: 100% 100% !important; } .opbox-sheet-wrapper, @@ -718,6 +765,25 @@ IGNORE IMAGE ANALYSIS ================================ +allegrolokalnie.pl + +INVERT +.mlc-masthead__branding +.mlc-site-footer__branding + +================================ + +allestoringen.* +downdetector.* +downdetector.*.* +xn--allestrungen-9ib.* + +INVERT +#map_container +#map-card + +================================ + allmacworld.com INVERT @@ -731,6 +797,37 @@ INVERT ================================ +allrecipes.com + +INVERT +.checkbox-list-checkmark::before +.external-link-icon +.icon-ellipsis > svg +.icon-email-outline +.icon-search +.icon-share-favorite +.rating-bar-wrapper +img[src="/img/profile.png"] + +================================ + +allspice.io + +INVERT +[data-mesh-id="SITE_HEADERinlineContent"] img + +================================ + +alphacoders.com + +INVERT +.main +.main > * +#page_header +#page_header > * + +================================ + alphashooters.com CSS @@ -763,6 +860,13 @@ INVERT ================================ +amazingmarvin.com + +INVERT +.header-title + +================================ + amazon.* amazon.*.* @@ -778,6 +882,9 @@ img[src*="smile-logo"] .a-icon-popover .a-link-nav-icon .currencyINR +div.vse-video-title +div.vse-video-labels +i.a-icon-search CSS .banner-border { @@ -845,7 +952,7 @@ CSS androidpolice.com INVERT -.header-logo +.header-logo svg ================================ @@ -864,6 +971,14 @@ CSS ================================ +anibrain.ai + +IGNORE INLINE STYLE +div[class^="style__HexagonDiv"] * +svg[class^="styles__SvgWithShadow"] * + +================================ + anilibria.tv CSS @@ -965,25 +1080,49 @@ IGNORE IMAGE ANALYSIS ================================ -apclassroom.collegeboard.org - -INVERT -.overview-icon svg -.Zoom--expander svg -svg.icon--xmark -.RI_header__button svg.svg-icon +aosogrenci.anadolu.edu.tr CSS -.standalone_image img { - background-color: white; +.welcome { + background-image: none !important; } ================================ -api.kde.org +apartmentlist.com INVERT -.center +div[class*="LogoContainer"] +div[class*="MenuButton"] + +================================ + +apartments.com + +INVERT +.logo + +================================ + +apclassroom.collegeboard.org + +INVERT +.overview-icon svg +.Zoom--expander svg +svg.icon--xmark +.RI_header__button svg.svg-icon + +CSS +.standalone_image img { + background-color: white; +} + +================================ + +api.kde.org + +INVERT +.center .image CSS @@ -1002,6 +1141,35 @@ INVERT ================================ +app.betrybe.com + +INVERT +section.quiz-result__template summary +section.quiz-result__template summary .block-code + +CSS +.home-projects details, +.header button, +.header a, +.module-index-content { + background-color: transparent !important +} +.header button:hover, +.header a:hover, +.module-index-content summary:active, +.quiz-question label { + background-color: var(--darkreader-neutral-background) !important +} +.quiz-question label p { + color: rgb(180, 200, 255) !important +} +.quiz-question__alternatives label:hover, +.quiz-question__alternatives input[type=radio]:checked + label { + background: initial !important +} + +================================ + app.codesignal.com CSS @@ -1034,21 +1202,29 @@ svg text.time_cursor { ================================ -app.getpocket.com - -IGNORE IMAGE ANALYSIS -* - -================================ - app.grammarly.com CSS use.valueCircle_f6otssy { stroke: url(#pb-gradient-0); } +:root { + --highlight-bg: ${rgba(0, 0, 0, 0.2)} +} +.alerts-clarity { + --highlight-bg: ${rgba(57, 93, 207, 0.2)}; +} +.alerts-engagement { + --highlight-bg: ${rgba(29, 203, 162, 0.2)}; +} +.alerts-correctness { + --highlight-bg: ${rgba(255, 69, 103, 0.2)}; +} +.alerts-delivery { + --highlight-bg: ${rgba(124, 58, 172, 0.2)}; +} [class*="-alerts-markSelectedHigh"], span[class*="markSelectedFocused"] { - color: rgb(14, 16, 26) !important; + background-color: var(--highlight-bg) !important; } [class*="-navigation-counterWrapper"] [class*="-navigation-counterContent"], [class*="-paidview-counter"] [class*="-paidview-counterContent"] { @@ -1173,8 +1349,8 @@ INVERT aprs.fi INVERT -.gm-style > :first-child -.gm-style-iw-a +img[src*="maps.googleapis.com/maps/"] +img[src*="tile.openstreetmap.org/"] CSS #panel { @@ -1183,6 +1359,14 @@ CSS ================================ +apteka.ru + +INVERT +ymaps[class$="ground-pane"] +.icon--logo + +================================ + aras.com CSS @@ -1210,6 +1394,20 @@ CSS ================================ +ario-player.sourceforge.net + +INVERT +div.header + +CSS +div.main, +#menu li a, +#menu li { + background-image: none !important; +} + +================================ + ars.particify.de CSS @@ -1250,6 +1448,18 @@ INVERT ================================ +artsy.net + +CSS +[aria-checked="false"][role="checkbox"] svg path { + fill: transparent !important; +} + +IGNORE INLINE STYLE +[role="checkbox"] svg * + +================================ + arxiv.org CSS @@ -1334,6 +1544,23 @@ header, ================================ +askvg.com + +INVERT +.site-header img + +================================ + +askwoody.com + +CSS +.banner, +.content { + background-image: none !important; +} + +================================ + assetstore.unity.com CSS @@ -1391,22 +1618,22 @@ img[src*="https://github.githubassets.com/favicon.ico"].smart-link-icon img[src^="https://latexmath.bolo-app.com/render/"] CSS -span.code { +span.code, code.code { background-color: rgba(240,246,252,0.15) !important; } .ghx-parent-group, .ghx-issue { - background-color: rgba(119, 183, 255, 0.05) !important; + background-color: rgba(119, 183, 255, 0.05) !important; } span.loader-wrapper a, .css-s0tfqx, .css-1vn31bx, .css-1gx5gpx, .css-wvfva4 { - background-color: rgba(240,246,252,0.1) !important; + background-color: rgba(240,246,252,0.1) !important; } .css-1yfnrso, -.aui-flag, +.aui-flag, .aui-message { box-shadow: 0 0 20px rgba(240,246,252,0.15) !important; } @@ -1416,6 +1643,19 @@ span.loader-wrapper a, code:first-of-type { background-image: linear-gradient(to right, rgba(255,255,255,0.03),rgba(255,255,255,0.03)calc(1ch + 16px),transparent calc(1ch + 16px),transparent) !important; } +.sc-1jjaulc-0 { + box-shadow: 0 0 4px ${rgba(3,9,15,0.15)} !important; + background-color: ${rgba(3, 9, 15, 0.02)} !important; +} +.sc-186t4q4-1 { + background-color: ${rgba(3, 9, 15, 0.02)} !important; +} +#ak-main-content { + background-color: var(--darkreader-neutral-background) !important; +} +#jira-issue-header, #jira-issue-header-actions { + background-color: rgb(29, 32, 33) !important; +} .ak-editor-panel[data-panel-type="note"] { background-color: ${rgb(217, 200, 228)} !important; } @@ -1428,6 +1668,12 @@ code:first-of-type { .ak-editor-panel[data-panel-type="warning"] { background-color: ${rgb(238, 229, 187)} !important; } +.ak-renderer-document hr, .ProseMirror hr { + background-color: rgb(69, 70, 72) !important; +} +.ProseMirror hr.ak-editor-selected-node { + background-color: rgb(0, 101, 255) !important; +} IGNORE INLINE STYLE .ak-editor-content-area * @@ -1441,6 +1687,13 @@ INVERT ================================ +audio-technica.com + +INVERT +.o-header__logo + +================================ + audycje.tokfm.pl/widget CSS @@ -1450,6 +1703,27 @@ body { ================================ +auth0.com + +INVERT +button[data-handler="authorise-github"] > img.icon.icon-default + +================================ + +autoweek.com + +INVERT +.nav-logo + +================================ + +avanti24.pl + +INVERT +.box-logo + +================================ + avito.ru INVERT @@ -1471,6 +1745,14 @@ div[class^="item-preview-image"] { ================================ +avlab.pl + +INVERT +img[src*="avlab-logo"] +img[alt*="logo"] + +================================ + aws.amazon.com INVERT @@ -1488,6 +1770,13 @@ CSS ================================ +azuresynapse.net + +INVERT +.cursor + +================================ + azurlane.koumakan.jp IGNORE IMAGE ANALYSIS @@ -1563,11 +1852,25 @@ CSS ================================ +bandshed.net + +CSS +#content { + background-color: var(--darkreader-neutral-background) !important; +} + +================================ + banki.ru INVERT .header__logo +CSS +.comment:nth-child(even) { + background-color: ${#f5f5f5} !important; +} + ================================ bankier.pl @@ -1615,6 +1918,16 @@ INVERT ================================ +bbb.* + +CSS +div[class^='scrollableList'] { + background: none !important; + box-shadow: none !important; +} + +================================ + bbc.co.uk/weather bbc.com/weather @@ -1680,6 +1993,13 @@ body[style] { ================================ +behance.net + +INVERT +div[class^="PrimaryNav-logoWrap"] + +================================ + berlingske.dk INVERT @@ -1716,6 +2036,43 @@ input[type="radio" i] { ================================ +bestchange.ru + +INVERT +.tabs li a + +CSS +body, +.c-inner, +.c-block .c-wrap, +#content_table thead td, +.content .intro, +.c-block, +#content_table tbody td, +#content_reviews, +.review_header, +.review_middle, +.review_bottom { + background-image: none !important; +} + +================================ + +betanews.com + +CSS +.sectionTop, +.editorial .header, +.tabbed .tabs li:not(.active), +.tabbed .tabs li:not(.active) a { + background-image: none !important; +} +.tabbed .tabs li:not(.active) a { + background-color: ${#d9d9ff} !important; +} + +================================ + bettercap.org INVERT @@ -1755,6 +2112,26 @@ img[src^="/graphs/"] ================================ +bible.optina.ru + +CSS +body, +#left, +#right { + background-image: none !important; +} + +================================ + +bibliotecapleyades.net + +CSS +body { + background-image: none !important; +} + +================================ + bigocheatsheet.com INVERT @@ -1777,6 +2154,13 @@ INVERT ================================ +biliomask.com + +INVERT +div.header-title-logo + +================================ + binance.com CSS @@ -1798,7 +2182,7 @@ label > svg circle { bing.com INVERT -canvas +canvas[id^="Microsoft.Maps"] CSS .b_searchboxForm, @@ -1810,9 +2194,16 @@ CSS #b_results > li.b_ans.b_topborder, #b_results > li.b_ans.b_topborder.b_tophb.b_topshad { box-shadow: ${rgba(13, 13, 13, 0.05)} 0px 0px 0px 1px !important; } +.l_ecrd_imcolheader.gradient { + z-index: 2 !important; +} +#b_content { + background-image: none !important +} IGNORE INLINE STYLE .b_header_bg +.sp-tpwebicons.WIKI * ================================ @@ -1872,6 +2263,15 @@ IGNORE INLINE STYLE ================================ +bitcoinprice.com + +CSS +.highcharts-button-box { + fill: var(--darkreader-neutral-background) !important; +} + +================================ + bitly.com CSS @@ -1886,6 +2286,7 @@ bitwarden.com INVERT img[alt="Github Logo"] img[src$="forbes.png"] +app-login img.logo IGNORE IMAGE ANALYSIS blockquote .blockquote-header @@ -1940,6 +2341,16 @@ CSS ================================ +biznes.pap.pl + +CSS +body, +#copy { + background-image: none !important; +} + +================================ + blablacar.* blablacar.*.* @@ -2012,6 +2423,29 @@ CSS ================================ +blog.nightly.mozilla.org + +INVERT +.content > .logo > [href^="https://www.mozilla.org/"] +.nav-global-twitter a::before +.nav-global-join a::before + +CSS +.nav-util-search .fm-search input { + border-color: ${#999} !important; +} + +================================ + +blog.scssoft.com + +CSS +body { + background: none !important; +} + +================================ + blogger.com INVERT @@ -2029,6 +2463,20 @@ CSS ================================ +bloomberg.com + +INVERT +.navi-bar__button-icon +.navi-sections__item--LiveNow::before +.navi-sections__link--current::after + +CSS +.navi { + border-color: var(--darkreader-border--color-black) !important; +} + +================================ + blueberryroasters.pl INVERT @@ -2036,6 +2484,26 @@ div#logo ================================ +bluemic.com + +INVERT +.blue-logo + +================================ + +boardgamegeek.com + +CSS +.legacy button, +.legacy input, +.legacy optgroup, +.legacy select, +.legacy textarea{ + color: var(--darkreader-neutral-text) !important; +} + +================================ + bol.com CSS @@ -2045,6 +2513,13 @@ CSS ================================ +bonfire.com + +INVERT +.sw-Logo + +================================ + book.douban.com IGNORE IMAGE ANALYSIS @@ -2105,12 +2580,21 @@ INVERT ================================ -boxberry.ru +boringcompany.com -INVERT -.slider__image -img[src$="cancel.png"] -.box_img_block +CSS +.tweak-overlay-parallax-enabled .Parallax-item { + z-index: 1 !important; +} + +================================ + +boxberry.ru + +INVERT +.slider__image +img[src$="cancel.png"] +.box_img_block img[src$="Vector.png"] ymaps[class$="ground-pane"] ymaps[class$="svg-icon-content"] > ymaps @@ -2160,6 +2644,13 @@ section + img { ================================ +breitbart.com + +INVERT +#FootW #FWI p .parler + +================================ + brightspace.avans.nl CSS @@ -2169,6 +2660,15 @@ CSS ================================ +brilliant.org + +INVERT +[class*="b-sprite-landing"] +[class*="b-sprite-publishers"] +.logo + +================================ + bsi.bund.de INVERT @@ -2181,6 +2681,13 @@ CSS ================================ +buffer.com + +IGNORE INLINE STYLE +div[class^="style__LogoWrapper"] * + +================================ + bugreplay.com INVERT @@ -2191,39 +2698,86 @@ INVERT bugs.chromium.org INVERT -i.material-icons .project-logo +.anchor +.menu CSS :root { --darkreader-fix--border: 1px solid ${#ccc} !important; } -button[type="submit"], -input#searchq, -select#can, -mr-dropdown, -td, th.group-header { - border-bottom: var(--darkreader-fix--border) !important; - border-top: var(--darkreader-fix--border) !important; -} button[type="submit"] + mr-dropdown { border-right: var(--darkreader-fix--border) !important; } :host { - --mr-search-bar-background: var(--darkreader-neutral-background) !important; + --main-color: rgba(232, 230, 227, 0.87) !important; + --can-bg: #1c1c1c !important; + --mr-issue-bg: #121c14 !important; + --mr-search-bar-border: 1px solid var(--darkreader-bg--chops-gray-400) !important; --chops-choice-bg: ${#eceff1} !important; --chops-table-header-bg: ${#f1f3f4} !important; --chops-card-details-bg: var(--darkreader-neutral-background) !important; --chops-card-heading-bg: var(--darkreader-neutral-background) !important; + --chops-toggle-fix: rgba(255, 255, 255, 0.25) !important; } -#can { - border-left: var(--darkreader-fix--border) !important; - background-color: var(--darkreader-neutral-background) !important; +mr-header, mr-issue-header { + border-bottom: var(--darkreader-fix--border) !important; } -mr-header, -th { +.metadata-container { + border-right: var(--darkreader-fix--border) !important; +} +mr-issue-header, mr-issue-metadata { + background: var(--mr-issue-bg) !important; +} +mr-header, thead, .comment-header { + background: var(--chops-card-details-bg) !important; +} +mr-cue { + background: var(--darkreader-bg--chops-notice-bubble-bg) !important; + border: var(--darkreader-border--chops-notice-border) !important; +} +.byline { + color: var(--main-color) !important; +} +.select-container, .select-container optgroup { + color: var(--main-color) !important; + background: var(--can-bg) !important; +} +input#searchq, input#searchq + button, [label="Search options"] { + background: transparent !important; +} +.select-container, input#searchq, input#searchq + button, [label="Search options"] { + border-top: var(--darkreader-fix--border) !important; border-bottom: var(--darkreader-fix--border) !important; } +.select-container { + border-left: var(--darkreader-fix--border) !important; + border-right: var(--darkreader-fix--border) !important; +} +label[for="checkbox"] { + border: var(--darkreader-fix--border) !important; +} +input[type="checkbox"]:checked + label { + background: var(--chops-toggle-fix) !important; +} +.menu { + box-shadow: none !important; +} + +================================ + +bugs.mojang.com + +INVERT +#logo + +================================ + +bugs.python.org + +INVERT +img[title="has PR"] +img[title="GitHub"] ================================ @@ -2240,6 +2794,15 @@ CSS ================================ +bulbagarden.net + +CSS +body { + background-image: none !important; +} + +================================ + bulk.com INVERT @@ -2252,6 +2815,15 @@ CSS ================================ +bulldogjob.pl + +INVERT +img[alt~="Bulldogjob"] +img[src="/bulldog.guide.svg"] +img[src="/bulldog.tte.icon.svg"] + +================================ + bulldogjob.pl/proxied/job-offers IGNORE IMAGE ANALYSIS @@ -2278,12 +2850,16 @@ it.businessinsider.com INVERT .account-text-not-logged-in +.article-share_buttons .brand .brands-logo .drawer-heading.headline-bold .f-footer-logo .f-header-logo .f-header-editionLabel +.footer_logo-bi +.footer_social-links +.header-logo .ins-drawer-button-area .ins-drawer-vertical-link .logo @@ -2305,6 +2881,8 @@ INVERT .socialmedia-icon-list .verticals-listitem-label a[title="Business Insider España"] +a[id="menu-hamburger-button"] +a[href="/szukaj"] button[class*="drawer-dropdown-button"] button[class="unbutton"] > img div[class*="footer__LogoWrapper"] @@ -2314,6 +2892,18 @@ section[class*="brands-social"] ================================ +businesswire.com + +INVERT +body > header div:first-child + +CSS +#bw-home { + background-image: none !important; +} + +================================ + buzzsprout.com INVERT @@ -2330,6 +2920,30 @@ INVERT ================================ +caddyserver.com + +INVERT +#logo +#zerossl-logo +#footer-logo + +CSS +.hero { + background-image: none !important; +} + +================================ + +caf.fr + +CSS +#theme-contenu-cnaf .row[class*="conteneur-"][class*="-cnaf"] > [class*="col-"], +#theme-contenu-menu-background-cnaf { + background-image: none !important; +} + +================================ + caiyunapp.com INVERT @@ -2354,9 +2968,16 @@ CSS div[role="checkbox"] > div > div > div { border: 1px solid ${black} !important; } +div[role="dialog"] div[role="slider"][data-saturation] div:nth-child(2) { + background-image: linear-gradient(to right,#fff 0%,rgba(255,255,255,0) 100%) !important; +} IGNORE INLINE STYLE div[role="checkbox"] +div[role="gridcell"] div[role="button"] +div[role="dialog"] div[role="slider"] +div[role="dialog"] div[role="slider"] div[style] +div[role="dialog"] div[role="button"][data-contrast] ================================ @@ -2387,6 +3008,12 @@ canva.com INVERT #__next > div > section > div[style^="background-color"] +img[src*="category-public.canva.com/icons/"] + +CSS +._8aslVA svg path { + fill: ${black} !important; +} ================================ @@ -2440,6 +3067,36 @@ INVERT ================================ +castos.com/player/ + +INVERT +.playback__controls +button[class="player-btn__speed"][aria-label="Playback Speed"] +.play-pause-controls + +================================ + +catalog.update.microsoft.com + +CSS +#headerBox, +#searchButtonBox, +#searchGlowBottomBox, +#searchGlowPart4aBox, +#searchGlowPart4bBox, +#searchGlowPart8aBox, +#searchGlowPart8bBox, +#searchGlowTopBox, +.ResultsHeaderTD, +.dialogBody, +.mainBody, +.mainBodyHome, +.tabInactive { + background-image: none !important; +} + +================================ + cbpp.org INVERT @@ -2447,10 +3104,28 @@ INVERT ================================ +cbsnews.com + +CSS +.content__read-more { + color: var(--darkreader-neutral-color) !important; +} + +================================ + +cdaction.pl + +INVERT +a[href="/"] svg +footer > div > svg + +================================ + cdc.gov INVERT .cdc-logo path[fill="#000"] +img[src="/niosh/images/si-no-left-vp4.png"] ================================ @@ -2466,6 +3141,13 @@ CSS ================================ +cdn77.com + +INVERT +a[class^="Nav_logo"] + +================================ + cdp.contentdelivery.nu CSS @@ -2475,6 +3157,22 @@ body { ================================ +ceneo.pl + +INVERT +[data-new-icon]::before +.cat-prod-row__product-link::after +.add-to-favorite::after + +================================ + +central.proxyvote.com + +INVERT +.custom-control-label::after + +================================ + centrum24.pl INVERT @@ -2523,6 +3221,9 @@ CSS chase.com +INVERT +.single-logo-icon + CSS .menu-button-item { color: var(--darkreader-neutral-text) !important; @@ -2548,6 +3249,32 @@ header .logo ================================ +checkout.minecraft.net + +IGNORE INLINE STYLE +symbol#esrb [fill="#000"] +symbol#esrb [fill="#fff"] + +================================ + +chem.libretexts.org + +INVERT +.internal + +================================ + +chessprogramming.org + +INVERT +.mw-parser-output div[class^='float'] > a > img:not(.thumbimage):not(.thumbborder) +.mw-wiki-logo + +IGNORE IMAGE ANALYSIS +.mw-wiki-logo + +================================ + chilkatsoft.com CSS @@ -2613,6 +3340,19 @@ INVERT ================================ +churchofjesuschrist.org + +INVERT +svg + +CSS +.container, +#PFmainFooter { + background: var(--darkreader-neutral-background) !important +} + +================================ + cinedrome.ch CSS @@ -2622,6 +3362,25 @@ body { ================================ +circleci.com/docs + +CSS +body { + background-image: none !important; +} + +================================ + +circt.llvm.org +mlir.llvm.org + +CSS +header { + background: none !important; +} + +================================ + circuit-diagram.org INVERT @@ -2629,6 +3388,14 @@ INVERT ================================ +cisce.org + +INVERT +.nav-wrapper +hgroup + +================================ + citilink.ru INVERT @@ -2644,6 +3411,14 @@ IGNORE INLINE STYLE ================================ +cityam.com + +INVERT +.site-logo__image +.menu-item a:before + +================================ + citybuzz.pl INVERT @@ -2738,6 +3513,9 @@ span[role="presentation"] { .ansiout { color: ${rgb(85, 85, 85)} !important; } +.rm-modal { + background: var(--darkreader-neutral-background) !important; +} ================================ @@ -2758,6 +3536,13 @@ devsite-footer-utility { ================================ +cloudflare.com + +IGNORE INLINE STYLE +.footer-bottom-row-margin > div > a > svg > path + +================================ + cloudhostnews.com INVERT @@ -2765,10 +3550,31 @@ INVERT ================================ +cloudlinux.com + +INVERT +img.mega-menu-logo + +================================ + +cnbc.com + +INVERT +.RenderKeyPoints-list li::before +.WatchLiveRightRail-logo + +CSS +div[class^="FeaturedStories-styles-makeit-background"]::before { + opacity: 0.1 !important; +} + +================================ + cnki.net INVERT .hello-yx-box +.klogin_header_Logo .search-main > .input-box > .search-btn .Logo @@ -2785,13 +3591,19 @@ CSS cnn.com INVERT -[data-test="section-link"] > svg +[data-test="section-link"] > svg:not(.business-logo-icon) img.metadata-header__logo +CSS +#header-nav-container::before { + border-bottom-color: transparent !important; +} + IGNORE INLINE STYLE svg.cnn-badge-icon svg.cnn-badge-icon > rect svg.politics-logo-icon +svg.business-logo-icon ================================ @@ -2827,6 +3639,19 @@ CSS ================================ +codeberg.org +codeberg-test.org + +CSS +main header .header-background-image { + filter: brightness(50%) sepia(40%) !important; +} +main header .header-title { + z-index: 1 !important; +} + +================================ + codecademy.com INVERT @@ -2840,31 +3665,54 @@ codeforces.com INVERT #header > div:first-child img -.action-link > div > img:first-child -.roundbox-lt -.roundbox-rt -.roundbox-lb -.roundbox-rb +#userActivityGraph rect[data-items=""] .delete-resource-link -a.contestParticipantCountLinkMargin > img -.recent-actions > ul > li img[src*="hourglass"] +.action-link img +.non-decorated img[src$="tablesorter-bg.gif"] +.tex-formula CSS +.datatable, +.datatable > div, +.roundbox { + border-radius: 6px; +} .lt, .rt, .lb, .rb, .ilt, -.irt { +.irt, +.roundbox-lt, +.roundbox-rt, +.roundbox-lb, +.roundbox-rb { display: none; } -input[type="submit"], input[type="button"], select { - border-style: solid; +.backLava, +.leftLava { + border-radius: 4.5px; +} +.backLava, +.leftLava, +.bottomLava, +.cornerLava { + background: ${#BEBEBE} !important; +} +.sidebar-menu ul li { + border-color: transparent !important; +} +.highlighted-row td, +.highlighted-row th{ + background-color: ${rgb(195, 205, 215)} !important; } -input[type="submit"]:hover, input[type="button"]:hover, select:hover { - border-style: groove; +#footer img[alt="Telegram"] { + border-radius: 50%; } +IGNORE INLINE STYLE +#userActivityGraph rect + ================================ codewars.com @@ -2955,6 +3803,17 @@ IGNORE INLINE STYLE ================================ +comenius.susqu.edu + +CSS +body, +table, +td { + background-image: none !important; +} + +================================ + comicfury.com CSS @@ -2990,6 +3849,12 @@ INVERT commons.wikimedia.org +INVERT +.mw-mmv-filepage-buttons .mw-mmv-view-expanded .mw-ui-icon::before +.mw-mmv-filepage-buttons .mw-mmv-view-config .mw-ui-icon::before +.licensetpl td[style^="width"] +img[alt="audio speaker icon"] + IGNORE IMAGE ANALYSIS .mw-wiki-logo @@ -3036,7 +3901,17 @@ INVERT ================================ -compass.pressekompass.net +community.progress.com + +CSS +:root { + --lwc-colorContentAreaBackground: var(--darkreader-neutral-background) !important; + --lwc-pageHeaderColorBackground: ${rgb(243, 243, 243)} !important; +} + +================================ + +compass.pressekompass.net INVERT .logo-holder .brand-logo @@ -3076,6 +3951,15 @@ CSS ================================ +console-openshift-console.* + +CSS +.pf-c-dropdown__menu { + background-color: var(--darkreader-neutral-background) !important; +} + +================================ + console.cloud.google.com CSS @@ -3083,7 +3967,36 @@ CSS color: var(--darkreader-neutral-text) !important; } .cfc-color-text-secondary { - color: ${#333} !important; + color: ${#333} !important; +} + +================================ + +consumerlab.com + +INVERT +#overlay-toggle > .collapsed +.header-link-home + +CSS +span[style*="background-color: rgb(255, 255, 0)"] { + background-color: #550 !important; +} + +================================ + +contacts.google.com + +INVERT +img[src*="rotate"] + +================================ + +containertoolbx.org + +CSS +body, img, video, iframe { + filter: none !important; } ================================ @@ -3123,7 +4036,7 @@ CSS } IGNORE INLINE STYLE -#generator* +#generator * ================================ @@ -3163,6 +4076,13 @@ input#search-btn ================================ +costplusdrugs.com + +INVERT +img[src$="MCCP-wordmark-denim.png"] + +================================ + courses.fit.cvut.cz CSS @@ -3197,6 +4117,13 @@ a { ================================ +covims.org + +INVERT +img[alt="Covims Logo.png"] + +================================ + cowkrakowie.pl INVERT @@ -3266,6 +4193,10 @@ crowdin.com INVERT .crowdin-navbar__logo +svg.logo-icon-projects +.file_type.file_folder.file_branch +#master-loader > .master-loader-logo +#master-loader-progress.bar ================================ @@ -3282,6 +4213,13 @@ CSS ================================ +crutchfield.com + +INVERT +.logo-module svg + +================================ + cryptostorm.is INVERT @@ -3321,6 +4259,40 @@ INVERT ================================ +curseforge.com + +IGNORE IMAGE ANALYSIS +.e-generic-header + +================================ + +cxp.cengage.com + +INVERT +.owl_item_container img[src*=".gif"] +.ci-feedback img[src*=".gif"] +label img[src*=".gif"] +span.MathJax_SVG g[stroke="black"] + +CSS +.owl_item_container img[src*=".GIF"] { + background-color: ${black}; +} +font[color="white"] { + color: transparent !important; +} +div.tool-container.gradient > .controlButtons { + background-image: none; +} +div.tool-container.gradient { + box-shadow: none; +} + +IGNORE INLINE STYLE +span.MathJax_SVG g + +================================ + cynkra.com INVERT @@ -3343,6 +4315,13 @@ INVERT ================================ +czasnastopy.pl + +INVERT +.brandinglogo-wrap + +================================ + czypada.pl INVERT @@ -3380,6 +4359,20 @@ svg.main-logo.inline-flex g g[fill="#110133"] { ================================ +dailyexpose.uk + +INVERT +.header-image + +================================ + +dailymotion.com + +IGNORE INLINE STYLE +div[class*="logoContainer"] a svg path + +================================ + dailywritingtips.com CSS @@ -3469,6 +4462,18 @@ img[alt="Dawn Logo"] ================================ +deadpixeltest.org + +CSS +html { + background-color: transparent !important; +} + +IGNORE INLINE STYLE +body + +================================ + debian.org INVERT @@ -3516,11 +4521,31 @@ img[src$="logo.png"] ================================ +decisionproblem.com + +INVERT +.qChip + +CSS +#giftShopDiv { + color: ${white} !important; +} +.projectButton:disabled { + color: ${gray} !important; +} + +================================ + deepl.com INVERT .dl_ad_pro__features_item::before .dl_logo_text +img[class^="productNavigation-module--logoText"] +img#languageSelectorIcon +footer > div > div > div > div > a > img[alt="DeepL"] +div[class^="socialMediaLinks"] > a +div[class^="pageFooterV2-module--socialMediaLinks"] > a ================================ @@ -3548,6 +4573,16 @@ CSS ================================ +dell.com + +INVERT +.breadcrumbs +.cat-banner-text +.cfsf-ba-content-wrap +.hpg-cat-item-wrap svg + +================================ + delphipraxis.net CSS @@ -3640,6 +4675,7 @@ developer.android.com developer.android.google.cn tensorflow.org quantumai.google +cloud.google.com INVERT .devsite-site-logo @@ -3658,15 +4694,16 @@ CSS devsite-search .devsite-searchbox::before { background-color: unset; } -.devsite-wrapper { - background-color: inherit; -} +.devsite-wrapper, button { background-color: inherit; } code { background-color: rgba(255, 255, 255, 0.05); } +.devsite-breadcrumb-list { + background: none !important; +} ================================ @@ -3707,7 +4744,6 @@ CSS developer.mozilla.org INVERT -.logo .copy-icon .bc-browsers > th > span::before .bc-platforms > th::before @@ -3718,8 +4754,10 @@ a.external::after .breadcrumbs-container li .breadcrumb-penultimate::after .breadcrumbs-container li .breadcrumb::after ul.main-menu .top-level-entry::before +span.icon CSS +.logo-text, .search-results-list mark { color: var(--darkreader-neutral-text) !important; } @@ -3765,14 +4803,16 @@ CSS --devsite-searchbox-inactive: var(--darkreader-neutral-background) !important; --devsite-button-background: var(--darkreader-neutral-background) !important; --devsite-footer-background: var(--darkreader-neutral-background) !important; + --devsite-breadcrumb-list-background: var(--darkreader-neutral-background) !important; + --devsite-background-3: ${rgb(198, 198, 198)} !important; } button, a.button, .devsite-landing-row-item { border-color: var(--darkreader-border--devsite-select-border) !important; } -.pre-style, -code, +.pre-style, +code, pre { background: var(--darkreader-neutral-background) !important; } @@ -3783,6 +4823,15 @@ pre { ================================ +dhmo.org + +CSS +body { + background-image: none !important; +} + +================================ + di.com.pl INVERT @@ -3795,6 +4844,13 @@ div#naglowek { ================================ +diamondsdirect.com + +INVERT +[alt="Diamonds Direct Logo"] + +================================ + dianping.com INVERT @@ -3802,6 +4858,15 @@ INVERT ================================ +dicetower.com + +CSS +body { + background-image: none !important; +} + +================================ + dict.cc CSS @@ -3905,6 +4970,20 @@ INVERT ================================ +discover.com + +INVERT +img#flag +i.icon-help +i.icon-search +i.lock-icon +div.welcome-text-wrapper +div.slide--img.credit-card +div.slide--img.personal-loan +div.slide--img.home-loan + +================================ + discover.forem.com INVERT @@ -3912,20 +4991,10 @@ body > div:nth-child(1) > svg:nth-child(1) ================================ -discover.manjaro.org - -CSS -html, body { - background-image: url("/static/images/tux.svg") !important; - background-repeat: no-repeat !important; - background-position: bottom 0 left -12px !important; - background-size: 60px !important; - background-attachment: fixed !important; - background-color: var(--darkreader-neutral-background) !important; -} +discuss.pixls.us -IGNORE IMAGE ANALYSIS -body +INVERT +#site-logo.logo-big ================================ @@ -3937,6 +5006,21 @@ INVERT ================================ +distrowatch.com + +INVERT +img[src="images/cpxtu/dwbanner.png"] + +CSS +input, +.NavMenu, +select, +td:not(.NewsDate):not(.NewsHeadline) { + background-color: var(--darkreader-neutral-background) !important; +} + +================================ + ditu.baidu.com map.baidu.com maps.baidu.com @@ -3964,10 +5048,7 @@ INVERT .more-device #nearby-searchbox-hint #nearby-searchbox-hint-center -.pass-forceverify-wrapper -.pass-form-item .route-button -.tang-foreground .tang-pass-qrcode-title #userSignPanel @@ -3981,6 +5062,17 @@ CSS ================================ +djrankings.org + +CSS +body, +li a, +.moduleContentInner { + background-image: none !important; +} + +================================ + dlagentlemana.pl INVERT @@ -4008,7 +5100,9 @@ CSS img[src="/images/logos/ASALE2.png"], img[src="/images/logos/rae.png"], img[src="/images/LibroDeEstilo_300.jpg"], -img[src="/app/doc/es/img/dle.jpg"] { +img[src="/app/doc/es/img/dle.jpg"], +a[href="https://dej.rae.es"] > img.img-responsive.b-lazy.b-loaded, +img[src="/images/logos/BCRAEl.jpg"] { filter: invert(93.7%) hue-rotate(180deg) contrast(90.6%) !important } @@ -4021,6 +5115,32 @@ INVERT ================================ +dnd.su + +CSS +input, +select, +textarea, +.input-cast_time, +.input-style, +.input-select, +.button, +button:not(.lg-icon), +.workshop__checkbox .workshop__label::before, +.card-type, +.paper-1, +.desc .additionalInfo, +.subsection .additionalInfo, +.trumbowyg-editor .additionalInfo, +.social-menu ul, +#ya-site-form0 .ya-site-form__form .ya-site-form__input-text, +#ya-site-form0 .ya-site-form__submit { + background-image: none !important; + background-color: var(--darkreader-neutral-background) !important; +} + +================================ + dnd5e.wikidot.com CSS @@ -4057,6 +5177,13 @@ body { ================================ +dnscrypt.pl + +INVERT +.logo + +================================ + dnsleaktest.com INVERT @@ -4091,6 +5218,15 @@ header a[href="/"] svg { ================================ +doc.qt.io + +CSS +:root { + --content-bg-color: var(--darkreader-neutral-background) !important; +} + +================================ + docs.codacy.com INVERT @@ -4098,10 +5234,18 @@ div.footer-logo > img[alt="Codacy"] ================================ +docs.expo.dev + +IGNORE INLINE STYLE +tr svg * + +================================ + docs.google.com INVERT .docs-icon +.goog-flat-menu-button-caption .punch-filmstrip-controls-icon #docs-editor canvas .docs-homescreen-icon @@ -4208,6 +5352,15 @@ CSS ================================ +docs.soliditylang.org + +CSS +.wy-body-for-nav { + background-color: unset; +} + +================================ + dominos.* CSS @@ -4226,6 +5379,13 @@ svg.trackerbarimage:not(.complete svg.trackerbarimage) { ================================ +donald.pl + +INVERT +a[href="/"] + +================================ + doodle.com INVERT @@ -4276,6 +5436,13 @@ body { ================================ +dribbble.com + +INVERT +.site-nav-desktop-logo + +================================ + drive.google.com INVERT @@ -4286,9 +5453,10 @@ div[role="dialog"] ~ div[role="menu"] > div[role="menuitem"] > div > div:not([st img[src$="type/audio/mp3"] div[role="listitem"] > div > div > div > svg[fill="#000000"] > path div[role="menu"] > div > div[role="menuitem"] > div > div > div -div[role="menu"] > div > div[role="menuitem"][class*=" "] > div > :last-child div[data-label="nd"] > div > div > svg > path[fill="#000000"] div[role="document"] > div[role="button"] .a-b-c +div > svg > circle[fill="white"] +img[src*="empty_state_trash"] CSS span[data-type="spelling"] { @@ -4298,9 +5466,22 @@ div[role="menu"] div[role="menuitem"][class*=" "] > div > div > div, div[role="button"][aria-disabled="true"] > div { filter: invert(50%) !important; } +#request-access-icon { + filter: invert(93.7%) hue-rotate(180deg) contrast(90.6%) !important +} +:root { + --dt-secondary-container: ${#f1f3f4} !important; +} +button[guidedhelpid="new_menu_button"] { + background-color: ${#dbdde0} !important; +} +div[data-target="autopurgebanner"] > section { + background: ${#dbdde0} !important; +} IGNORE INLINE STYLE div[role="presentation"] svg +div[data-label="nd"] > div > div > svg > path[fill="#000000"] ================================ @@ -4310,6 +5491,11 @@ INVERT div[role="menu"] > div[role="menuitem"] > div > div > div div[role="menu"] > div[role="menuitem"] > div > div +CSS +#request-access-icon { + filter: invert(93.7%) hue-rotate(180deg) contrast(90.6%) !important +} + ================================ drive.google.com/picker @@ -4347,10 +5533,12 @@ INVERT .restorations-education__df-help__image .search__view--empty img .plan-status-section__icon img +.dropbox-logo__type IGNORE INLINE STYLE .home__suggest_image path .selection-preview-pane__icon path +.dig-WordmarkLogo path ================================ @@ -4370,6 +5558,15 @@ INVERT ================================ +dspguide.com + +CSS +#divPage { + background-image: none !important; +} + +================================ + dtf.ru INVERT @@ -4421,12 +5618,13 @@ INVERT [data-test="skill-icon"] + div img CSS -button[aria-disabled="true"] > span { +button[aria-disabled="true"] { opacity: 0.3 !important; } IGNORE INLINE STYLE div[data-test="challenge-translate-prompt"] svg * +div[data-test="challenge challenge-translate"] svg * ================================ @@ -4470,6 +5668,26 @@ INVERT ================================ +dziennikprawny.pl + +INVERT +a[href="/"] +.fullba + +CSS +.fullba { + background-image: none !important; +} + +================================ + +e.foundation + +INVERT +img.attachment-full.size-full + +================================ + ea.com INVERT @@ -4494,15 +5712,43 @@ body.origin-com, ================================ -easypost.com +eapteka.ru INVERT -.logo -.progress-bar +ymaps[class$="ground-pane"] +ymaps[class$="svg-icon-content"] > ymaps ================================ -ebok.pgnig.pl +easypost.com + +INVERT +.logo +.progress-bar + +================================ + +eatthis.com + +INVERT +svg.site-logo + +CSS +.header-leading-authority { + background-color: var(--darkreader-neutral-background); +} + +================================ + +eblocker.org + +INVERT +.site-logo-img +figure[class="aligncenter size-large is-resized"] + +================================ + +ebok.pgnig.pl INVERT img[src*="logo"] @@ -4585,6 +5831,26 @@ edziecko.pl INVERT .pageHeadBrand .col1 img +.main-navigation__logo + +================================ + +eevblog.com + +CSS +#main_content_section > div > span, +#quickModForm > div > span, +#main_content_section > span { + mix-blend-mode: color !important; +} +.frame, +.plainbox, +#header, +#content_section, +#footer_section { + background: var(--darkreader-neutral-background) !important; + color: var(--darkreader-neutral-text) !important; +} ================================ @@ -4658,6 +5924,20 @@ td { ================================ +elementary.io + +IGNORE INLINE STYLE +.logotype-svg + +================================ + +eletimes.com + +INVERT +.tdb-logo-img + +================================ + elp.northumbria.ac.uk INVERT @@ -4674,6 +5954,22 @@ body { ================================ +endeavouros.com + +INVERT +.navbar-brand + +================================ + +endoflife.date + +CSS +.bg-green-000, .bg-yellow-200, .bg-red-000 { + color: var(--darkreader-neutral-text) !important; +} + +================================ + endomondo.com INVERT @@ -4716,6 +6012,10 @@ CSS .col-lg-12.col-md-12 > div > div > p { color: var(--darkreader-neutral-background) !important; } +.bkg-icon, +.left-bkg-icon { + color: ${white} !important; +} ================================ @@ -4734,6 +6034,13 @@ select.input-small { ================================ +ernestjones.co.uk + +INVERT +.logo__img + +================================ + eshop-switch.com INVERT @@ -5041,7 +6348,7 @@ a[role="link"] > i.hu5pjgll, ._3w97 { ._2yu8 { background-color: rgba(255, 255, 255, .5) !important; } -img[src*="/map"], [style*="map"], +.leaflet-map-pane img[src*="theme=default"], [style*="map"][style*="theme=default"], ._8bb_ img[src*="/map"], ._8bb_ [style*="map"], img[src*="mapy.cz"], ._8bb_ img[src*="mapy.cz"], img[src*="%2Fmap"], ._8bb_ img[src*="%2Fmap"], @@ -5072,6 +6379,15 @@ IGNORE IMAGE ANALYSIS ================================ +fairtradeoriginal.* + +INVERT +.SiteLayout +.SiteLayout > * +.Inset-image + +================================ + fakespot.com INVERT @@ -5105,6 +6421,16 @@ INVERT .wds-global-navigation__logo-fandom CSS +body { + background-color: var(--theme-body-background-color) !important; +} +#mixed-content-footer, +.community-header-wrapper, +.top-ads-container, +.bottom-ads-container, +.global-footer { + z-index: 1 !important; +} .fandom-community-header__background.cover { z-index: 0 !important; } @@ -5113,6 +6439,7 @@ IGNORE INLINE STYLE .wds-global-navigation__logo-image g path .wds-global-footer__header-logo g path .wds-global-footer__link svg g path +symbol[id^="wds-brand-other"] * ================================ @@ -5176,6 +6503,16 @@ CSS ================================ +fcmed.pl + +INVERT +.mkd-logo-wrapper +a[href*="tel"] +.mkd-sidearea > .textwidget > a > img +.owl-wrapper + +================================ + fedex.com CSS @@ -5185,6 +6522,13 @@ CSS ================================ +fedoraforum.org + +INVERT +.logo-image + +================================ + feedly.com CSS @@ -5278,6 +6622,17 @@ header.ant-layout-header img ================================ +finn.no + +INVERT +finn-footer +article.ads__unit overflowmenu-active + +IGNORE INLINE STYLE +svg * + +================================ + fio.fnar.net INVERT @@ -5292,14 +6647,21 @@ INVERT ================================ +firefox.com + +INVERT +.fx-bento-app-link.fx-bento-link.fx-mobile > span::before + +================================ + firefox.net.cn CSS -.btn, -.core_follow, -.pop_deep .ct dt.reward, -.pages a, .pages strong, -.design_mode_edit, +.btn, +.core_follow, +.pop_deep .ct dt.reward, +.pages a, .pages strong, +.design_mode_edit, .pop_showmsg { background-image: none; } @@ -5333,6 +6695,13 @@ INVERT ================================ +flashscore.com.tr + +INVERT +.header__logo + +================================ + flightfinder.fi INVERT @@ -5356,15 +6725,19 @@ CSS background-color: rgba(255, 255, 255, 0.15) !important; background-blend-mode: color; } -.altitudetitle, .altdescmax, .altdescmin, -.zonedesctitle, .zonedescmax, .zonedesclight, +.altitudetitle, .altdescmax, .altdescmin, +.zonedesctitle, .zonedescmax, .zonedesclight, .maxhighlightval, .maxhighlightname { color: rgb(0, 0, 0) !important; } +.highcharts-background{ + fill: none !important; +} IGNORE INLINE STYLE .zonebox .zonestartbox +stop ================================ @@ -5398,6 +6771,20 @@ INVERT ================================ +fontawesome.com + +CSS +#icons-header, #docs-header, +#hero > div:not(.container), +.app-content.docs { + background-color: var(--darkreader-neutral-background) !important; +} +.doc-nav > div { + background-color: var(--darkreader-bg--background-norm) !important; +} + +================================ + fontsinuse.com INVERT @@ -5419,6 +6806,11 @@ fontsquirrel.com INVERT .fontlistitem +CSS +#main_content_container { + background-image: none !important; +} + ================================ foobar2000.org @@ -5428,6 +6820,13 @@ img[src="/foobarlogo.png"] ================================ +food4less.com + +INVERT +img[alt="Food4less logo"] + +================================ + foolcontrol.org CSS @@ -5445,6 +6844,18 @@ nav a > img[alt="Home"] ================================ +forms.reform.app + +INVERT +.logo + +CSS +svg.text-white { + color: var(--darkreader-neutral-background); +} + +================================ + forms.yandex.ru INVERT @@ -5466,6 +6877,13 @@ CSS ================================ +forum.dobreprogramy.pl + +INVERT +#site-logo + +================================ + forum.donanimhaber.com CSS @@ -5476,14 +6894,20 @@ body { ================================ forum.eset.com -forums.laptopvideo2go.com -nieidealny.pl forum.ithardware.pl +forums.getpaint.net +forums.laptopvideo2go.com +nieidealny.pl/forum INVERT +.ipsBadge_highlightedGroup +.ipsBadge_icon +.ipsBadge_popular +.ipsComment_authorBadge +.ipsItemStatus.ipsItemStatus_custom.ipsItemStatus_read .ipsReact_button img[alt="Forum komputerowe ITHardware"] -.ipsItemStatus.ipsItemStatus_custom.ipsItemStatus_read +img[alt="paint.net Forum"] CSS .ipsBadge { @@ -5528,7 +6952,7 @@ CSS } ul.dropmenu li { border: none !important; - background: var(--darkreader-neutral-background) !important; + background: var(--darkreader-neutral-background) !important; } ul.dropmenu ul { border: 1px solid var(--darkreader-neutral-text) !important; @@ -5540,6 +6964,32 @@ IGNORE INLINE STYLE ================================ +forum.kaosx.us + +INVERT +.Header-logo + +CSS +.Dropdown-toggle, +.item-refresh > Button, +.DiscussionList-loadMore > Button, +.LogInButton--github, +.Button--icon { + color: ${black} !important; + background: ${#6f7f92} !important; +} + +================================ + +forum.manjaro.org + +CSS +.custom-footer { + background-image: none !important; +} + +================================ + forum.miranda-ng.org CSS @@ -5571,6 +7021,31 @@ a[data-mentionid], ================================ +forums.comodo.com + +INVERT +.windowbg span.topslice +.windowbg span.botslice +.windowbg2 span.topslice +.windowbg2 span.botslice + +CSS +body { + background-image: none !important; +} +.buttonlist ul li a span:not(:hover) { + color: ${white} !important; +} + +================================ + +forums.gearsofwar.com + +IGNORE IMAGE ANALYSIS +body + +================================ + forums.mydigitallife.net IGNORE INLINE STYLE @@ -5600,10 +7075,36 @@ img[src$="layout/logo.svg"] ================================ +fosshost.org + +INVERT +img[alt="Fosshost Logo"] + +================================ + +fotw.info + +CSS +body { + background-image: none !important; +} + +================================ + frame.work INVERT a[title="Framework Home"] > img[alt="Framework"] +#site-logo + +================================ + +fredmeyerjewelers.com + +INVERT +#header1_mainlogo +.mobileNavIcons img +.mobileNavIcons input:not(.searchdesktop) ================================ @@ -5621,6 +7122,13 @@ CSS ================================ +freedom.press + +INVERT +.logo-heading-text + +================================ + freelancer.com INVERT @@ -5628,6 +7136,22 @@ INVERT ================================ +freetp.org + +CSS +html, +body, +.wmid, +.wfoot { + background-image: none !important; +} +html, +body { + background-color: var(--darkreader-neutral-background) !important; +} + +================================ + fritz.box INVERT @@ -5635,13 +7159,38 @@ div.formular input[type="radio"] div.formular input[type="checkbox"] CSS -div.formular input[type="radio"], +div.formular input[type="radio"], div.formular input[type="checkbox"] { background-color: transparent !important; } ================================ +fs.blog + +INVERT +.shared-counts-icon + +CSS +body, +.header-box { + background-color: var(--darkreader-neutral-background) !important; +} + +================================ + +fsfe.org + +INVERT +#logo + +CSS +body { + background-image: none !important; +} + +================================ + ftp.nluug.nl INVERT @@ -5649,6 +7198,15 @@ img[alt="[NLUUG]"] ================================ +fullstackopen.com + +CSS +.gatsby-highlight-code-line { + background-color: ${hsla(0,0%,48.2%,.3)} !important; +} + +================================ + funpay.ru INVERT @@ -5677,33 +7235,99 @@ td { ================================ -garmin.com +fz-juelich.de -INVERT -.gh__logo +CSS +body { + background-image: none !important; +} ================================ -gat.no - -INVERT -figure.logo > img +g1.com.br +g1.globo.com CSS -main.container .every_board > .row:not(.row--takeover) { - --front-background-color: var(--darkreader-neutral-background) !important; +.multicontent { + background-color: var(--darkreader-neutral-background) !important; + color: var(--darkreader-neutral-text) !important; +} +span.bstn-hl-summary { + color: var(--darkreader-neutral-text) !important; +} + +================================ + +gain.tv + +CSS +.body-new-index .hero-img-container { + z-index: 0 !important; +} + +================================ + +gamepress.gg + +CSS +.TLW-tier-charname { + color: ${black} !important; +} + +================================ + +gameranx.com + +CSS +body { + background-color: var(--darkreader-neutral-background) !important; +} +.mai-toc__listitem, +.mai-toc__details, +.mai-toc-default .mai-toc__summary { + background-color: ${#f7f7f7} !important; +} + +================================ + +garmin.com + +INVERT +.gh__logo + +================================ + +gasbuddy.com + +INVERT +.pin +.pin-small + +================================ + +gat.no + +INVERT +figure.logo > img + +CSS +main.container .every_board > .row:not(.row--takeover) { + --front-background-color: var(--darkreader-neutral-background) !important; } ================================ gazeta.pl plotek.pl +sport.pl INVERT .column .navigation__logo .main-navigation__logo +.serviceLogo__img .hp_redirector-circle-progress__svg +.vs__actions svg CSS .top_section_bg, .bottom_section_bg { @@ -5715,13 +7339,10 @@ CSS gazetaprawna.pl INVERT -.logoHeading +.bubbleMenuHamburger .homePageUrl - -CSS -#menuTrigger { - background-color: var(--darkreader-neutral-background) !important; -} +.serviceLogo +.servicesMenu #menuTrigger span ================================ @@ -5737,6 +7358,22 @@ CSS ================================ +ge.globo.com + +CSS +.glb-grid .tabela-body { + background-color: var(--darkreader-neutral-background) !important; +} + +================================ + +geekflare.com + +INVERT +.logo + +================================ + geeksforgeeks.org CSS @@ -5801,6 +7438,25 @@ span[aria-label="Manage in Google Photos"][role="menuitem"] path ================================ +getfedora.org + +INVERT +img[alt="globe"] + +================================ + +getlektor.com + +CSS +.body-wrapper .container { + background-color: var(--darkreader-neutral-background) !important; +} +pre { + background-image: none !important; +} + +================================ + getmimo.com INVERT @@ -5818,8 +7474,9 @@ login-container { getpocket.com CSS -a .title span { +p a[rel="noopener noreferrer"] { text-shadow: none !important; + background-image: linear-gradient(to top,transparent,transparent 1px,var(--darkreader-text--color-canvas) 1px,var(--darkreader-text--color-canvas) 2px,transparent 2px) !important; } ================================ @@ -6055,6 +7712,8 @@ IGNORE INLINE STYLE a[href^="https://apps.apple.com/app/"] g a[href^="https://apps.apple.com/app/"] path tracked-issues-progress svg * +div#user-repositories-list .tooltipped svg * +div#org-repositories .tooltipped svg * ================================ @@ -6109,6 +7768,15 @@ table.code .line_content *:not(pre), ================================ +gittigidiyor.com + +CSS +img[data-testid="productImage"] { + mix-blend-mode: normal !important; +} + +================================ + giveawayoftheday.com INVERT @@ -6130,16 +7798,16 @@ CSS border: none !important; } .overlay1::after { - background: unset !important; + background: unset !important; } -.overlay1::before { - opacity: 0.8 !important; - background-color: unset !impotant; - background-image: unset !impotant; +.overlay1::before { + opacity: 0.8 !important; + background-color: unset !impotant; + background-image: unset !impotant; } .overlay1::before { background-color: unset !important; - background-image: unset !important; + background-image: unset !important; } ================================ @@ -6175,7 +7843,7 @@ globo.com CSS .bar-scrubber .bar-scrubber-icon, -.bar-background .bar-fill-2 { +.bar-background .bar-fill-2 { background-color: var(--darkreader-neutral-text) !important; } .bar-background .bar-fill-1 { @@ -6218,6 +7886,13 @@ INVERT ================================ +godaddy.com + +INVERT +.logo-mark + +================================ + godoc.org CSS @@ -6318,7 +7993,7 @@ INVERT CSS #file-editor .CodeMirror, -#file-editor .CodeMirror-lines, +#file-editor .CodeMirror-lines, #file-editor .CodeMirror-gutters, #wrap { background-color: var(--darkreader-neutral-background) !important; @@ -6394,6 +8069,27 @@ a[href*="about/products"] img[src$="menu_black_24dp.png"] #assistive-chips .e2moi img button[guidedhelpid="searchbutton"] +a[href^="//myaccount.google.com/yourdata/maps"] > div +img[src^="//www.google.com/images/branding/lockups/"][alt="Google Maps"] +div[role="checkbox"] > div +div[aria-label="Toggle star"][role="checkbox"] +#legendPanel > div > div > div > div > div > div > div > div > div[jsaction^="keydown"][jsshadow=""][role="checkbox"][style=""] +#legendPanel > div > div > div > div > div > div > div > div > div > div > div > div[jsaction^="keydown"][jsshadow=""][role="checkbox"] +#map-canvas > div > #watermark +body.vsc-initialized > #app > #map-container > #map > .map-outer.map-extent +body.vsc-initialized > #app > #map-container > #map > div > div > div > button[jsaction="map.toggle-map-control"] > img +body.vsc-initialized > #app > #map-container > #map > div > div > div > div > div > button[jsaction="map.zoom-out"] > img +body.vsc-initialized > #app > #map-container > #map > div > div > div > div > div > button[jsaction="map.zoom-in"] > img +#app-container > #modal-dialog > div > div > div > div > button[jsaction="modal.close"] +#map-canvas div[data-tooltip] +div[style="top: 0px;"] > div > div > div > :first-child +div[style="top: 0px;"] > div > :last-child > div > :nth-child(2) +div[style="top: 0px;"] > div:first-child:not([style^="background"]) > :last-child + +CSS +#app-container > #modal-dialog > div > div > div > div > button[jsaction="modal.close"] { + background-color: $var(--darkreader-neutral-background) !important; +} IGNORE IMAGE ANALYSIS .widget-settings-map @@ -6414,6 +8110,15 @@ IGNORE IMAGE ANALYSIS ================================ +googleprojectzero.blogspot.com + +CSS +.c5 a img { + background-color: white !important; +} + +================================ + goplay.anontpp.com INVERT @@ -6458,6 +8163,28 @@ ymaps[class$="places-pane"] span ================================ +gov.pl/web/bip + +INVERT +.banner-promo +.banner-promo__text + +================================ + +gowork.pl + +INVERT +.city__img .city__text + +================================ + +grammarly.com + +INVERT +img[alt="Grammarly logo"] + +================================ + gramota.ru INVERT @@ -6467,6 +8194,30 @@ td > strong ================================ +gravatar.com + +INVERT +a.g-home +.g-user-menu > svg +body#page > div > div > nav > ul > li > a > svg.g-logo.g-logo--name-gravatar + +CSS +a[class="g-sign-in"] > svg > path { + fill: white !important; +} +body { + background-image: none !important; +} + +================================ + +grc.com + +INVERT +img[src*="gif"] + +================================ + greatergood.com INVERT @@ -6476,6 +8227,15 @@ INVERT ================================ +grocy.info + +INVERT +.navbar-brand +.carousel-control-prev-icon +.carousel-control-next-icon + +================================ + grubhub.com CSS @@ -6488,6 +8248,17 @@ label, h5, h6, header, .h5 { ================================ +gsmchoice.com +mgsm.pl + +INVERT +.promo-sticky__item--small +.promo-sticky__item--large +img[alt="mGSM.pl"] +img[alt="GSMchoice.com"] + +================================ + gsuite.google.com INVERT @@ -6525,6 +8296,13 @@ p.promo_price ================================ +guitarworld.com + +INVERT +.site-logo + +================================ + gurushots.com CSS @@ -6544,12 +8322,16 @@ habitica.com INVERT .logo path:nth-child(2) +IGNORE IMAGE ANALYSIS +* + ================================ habr.com INVERT img[src*="//tex.s2cms.ru/"] +img[data-tex] CSS html { @@ -6561,6 +8343,15 @@ html { ================================ +hacdias.com + +CSS +:root { + --background: var(--darkreader-neutral-background) !important; +} + +================================ + hackerone.com INVERT @@ -6594,6 +8385,15 @@ ul.notes li::before { ================================ +handwiki.org + +CSS +#mw-content { + background-color: var(--darkreader-neutral-background) !important; +} + +================================ + haokan.baidu.com INVERT @@ -6601,6 +8401,13 @@ INVERT ================================ +hbo.com + +INVERT +img[alt="HBO Logo"] + +================================ + hbr.org INVERT @@ -6621,6 +8428,16 @@ INVERT ================================ +hdlbits.01xz.net + +CSS +img.image, .image > img { + background-color: white !important; + filter: brightness(50%) sepia(40%) !important; +} + +================================ + heise.de INVERT @@ -6635,6 +8452,26 @@ INVERT ================================ +helzberg.com + +INVERT +.logo +.footer.content +.footer.content > div +.footer__column--logo + +IGNORE INLINE STYLE +a[id^="powered_by_pixleee"] + +================================ + +heraldscotland.com + +INVERT +.brand + +================================ + heritage.org/index INVERT @@ -6687,6 +8524,14 @@ body ================================ +hmong.* +wikihmong.com + +INVERT +span.mwe-math-element + +================================ + homebrewery.naturalcrit.com CSS @@ -6730,6 +8575,14 @@ img[src$="hootsuite_white_form3.png"] ================================ +hotel.meituan.com + +INVERT +.poi-hotellbs-map +.small-map + +================================ + howbuy.com INVERT @@ -6743,10 +8596,22 @@ INVERT ================================ +hp.com + +INVERT +#g-nav .c-logo + +CSS +.pdp-bg { + background-image: none !important; +} + +================================ + hs.fi CSS -article, +article, article > article { background-color: var(--darkreader-neutral-background) !important; } @@ -6762,6 +8627,13 @@ img[alt="INTERIA.PL"] ================================ +hubs.mozilla.com + +INVERT +svg.hmc-logo + +================================ + hvdic.thivien.net INVERT @@ -6812,6 +8684,23 @@ CSS ================================ +hypothes.is + +INVERT +a[href="https://hypothes.is"] > svg[aria-labelledby="logo-title"] > g > path[fill-rule="nonzero"] +img[class="fusion-standard-logo"] + +================================ + +i-item.jd.com + +CSS +.itemInfo-wrap .summary-price-wrap .summary-top .summary-promotion { + background-image: none !important; +} + +================================ + icloud.com INVERT @@ -6828,46 +8717,99 @@ INVERT ================================ +iconfinder.com + +INVERT +.logo + +================================ + iconify.design IGNORE INLINE STYLE svg.iconify * +svg#footer-icon-name * +svg#icon-nav-prev * +svg#icon-nav-next * .si-svg-wrapper svg * .block-container .icons svg * ================================ -iett.istanbul +icons8.com CSS -.LineTimeDuyuru > li:nth-child(1) { - display:none; -} -.LineTimeDuyuru::before { - content: "Kırmızı renkli seferler ÖHO ve OAŞ'a, beyaz renkli seferler İETT'ye aittir." +.main-page .gradient { + background-image: none !important; } -.DetailTable img { - filter: invert(100%) hue-rotate(180deg) !important; + +================================ + +icrc.org + +CSS +.logo, +.logo img { + background-color: #fff !important; } ================================ -iflscience.com +ieee.org INVERT -a.logo +.logo-left ================================ -ifood.com.br +iett.istanbul CSS -.responsive-header__logo svg { +#routedesc p:nth-child(2) { + font-size: 0; +} +#routedesc p:nth-child(2)::after { + font-size: 20px; + content: "Kırmızı renkli seferler ÖHO ve OAŞ; beyaz renkli seferler İETT’ye aittir." +} + +================================ + +ifixit.com + +INVERT +a[aria-label="home page"] + +================================ + +iflscience.com + +INVERT +a.logo + +================================ + +ifood.com.br + +CSS +.responsive-header__logo svg { --darkreader-inline-fill: rgb(212, 45, 58) !important; } ================================ +igurublog.wordpress.com + +CSS +body, +.entry, +#content, +#container { + background-image: none !important; +} + +================================ + ikea.* CSS @@ -6878,6 +8820,11 @@ CSS .hnf-svg-icon { fill: var(--darkreader-neutral-text) !important; } +.card, +.card-header, +.card-footer { + background-color: var(--darkreader-neutral-background) !important; +} IGNORE INLINE STYLE .gpr__color-dot @@ -6913,6 +8860,16 @@ body { ================================ +imap: +pop3: + +CSS +table[class|="moz-header"] { + background: none; +} + +================================ + imdb.com INVERT @@ -6981,6 +8938,9 @@ main { .ipc-switch__slider::after { background: #5799ef !important; } +.aux-content-widget-2 { + background: none !important; +} ================================ @@ -7002,6 +8962,34 @@ CSS ================================ +inc.com + +INVERT +svg[class*="logo"] + +================================ + +ind.ie + +INVERT +.three-rs .three-rs-list p + +================================ + +independent.co.uk + +INVERT +.logo-text +#MegaMenuButton +.search-toggle +.jw-slider-horizontal +.jw-slider-volume + +IGNORE INLINE STYLE +.logo-svg-cls-2 + +================================ + infinitysearch.co INVERT @@ -7012,6 +9000,13 @@ img[src$="boardreader.ico"] ================================ +info.wyborcza.biz + +INVERT +.imgw + +================================ + inforlex.pl INVERT @@ -7148,6 +9143,7 @@ instructure.com INVERT .equation_image +.Page-container ================================ @@ -7166,7 +9162,7 @@ INVERT .search-submit CSS -.calendar-date, +.calendar-date, .calendar-body { background-color: var(--darkreader-neutral-background) !important; background-image: none !important; @@ -7181,7 +9177,7 @@ img[src*="/img/"] CSS .star-on-png::before { - color: #FCAD03 !important; + color: #FCAD03 !important; } ================================ @@ -7193,6 +9189,14 @@ INVERT ================================ +investopedia.com + +INVERT +.widget-ticker-container +.mntl-dotdash-universal-nav__logo + +================================ + invisioncommunity.com INVERT @@ -7205,16 +9209,16 @@ CSS .ipsBadge { --darkreader-bg--badge--background: var(--darkreader-neutral-background) !important; } -.ipsReact_reactCount > a, -.ipsReact_reactCount > span, -.elFullInbox_menu, -.ipsMenu_auto, -.ipsMenu_footerBar, -.ipsMenu_headerBar, -.ipsMenu_innerContent, -.ipsMenu_item, -.ipsMenu_sep, -.ipsMenu_title, +.ipsReact_reactCount > a, +.ipsReact_reactCount > span, +.elFullInbox_menu, +.ipsMenu_auto, +.ipsMenu_footerBar, +.ipsMenu_headerBar, +.ipsMenu_innerContent, +.ipsMenu_item, +.ipsMenu_sep, +.ipsMenu_title, .ipsPadding { background-color: var(--darkreader-neutral-background) !important; } @@ -7247,7 +9251,7 @@ INVERT ipko.pl INVERT -._16muV +.NB3WM CSS ._1IGN3 { @@ -7259,6 +9263,13 @@ CSS ================================ +iplocation.net + +INVERT +img[src="/assets/images/logo.png"] + +================================ + iqiyi.com INVERT @@ -7266,6 +9277,13 @@ INVERT ================================ +irishtimes.com + +INVERT +.masthead-block-logo img + +================================ + is.muni.cz INVERT @@ -7293,17 +9311,26 @@ h4, h5, h6 { ising.pl CSS -body.grey-gui-bg #content, +body.grey-gui-bg #content, div.grey-gui-bg, -.small-navy-heading, -.small-blue-heading, -.small-purple-heading, +.small-navy-heading, +.small-blue-heading, +.small-purple-heading, .small-navy2-heading { background-image: none !important; } ================================ +istanbulfm.com.tr + +CSS +#jarallax-container-0 { + z-index: 0 !important; +} + +================================ + itbiznes.pl INVERT @@ -7316,6 +9343,11 @@ itch.io INVERT .header_widget .mobile_nav_btn +CSS +.youtube_game_promo_banner_widget .game_information .cta_button { + border-color: var(--darkreader-neutral-text) !important; +} + ================================ item.jd.com @@ -7379,6 +9411,13 @@ body { ================================ +jakdojade.pl + +INVERT +#main-map + +================================ + jamboard.google.com INVERT @@ -7397,6 +9436,17 @@ INVERT ================================ +jared.com +kay.com +banter.com +peoplesjewellers.com +zales.com + +INVERT +.company-logo + +================================ + java.com INVERT @@ -7419,13 +9469,20 @@ i[class^="icon"].hidden-xs { .product-tile .product-image { background-color: white !important; } -.product-tile .product-swatches .swatch-list li.selected img, +.product-tile .product-swatches .swatch-list li.selected img, .product-tile .product-swatches .swatch-list li.selected:hover img { border-color: white !important; } ================================ +jenkins.io + +IGNORE INLINE STYLE +.logo-jenkins * + +================================ + jewishcurrents.org INVERT @@ -7459,6 +9516,16 @@ CSS joemonster.org +INVERT +#commentHeader +.art-details span +.item-vote-down +.logo +.moderb +.mtv-item-not-working +.vote-down +.vote-up + CSS body { background-image: none !important; @@ -7487,6 +9554,7 @@ INVERT .PwECA .best-authors__arrow.best-authors__arrow--active .best-authors__arrow +label[class^="hamburgerMenu"] ================================ @@ -7559,6 +9627,14 @@ INVERT ================================ +juwai.com + +INVERT +.c-header__logo +.c-responsive-navigation__logo + +================================ + k-report.net CSS @@ -7587,8 +9663,14 @@ div.output_png img kahoot.it INVERT -path[d^="M39.99 12.621v14.736l14.736.001V39.99H39.99v14.736H27.359V39.99H12.62V27.359h14.736l.001-14.737H39.99z"] -path[d^="M46.244 15.355l8.127 7.393-25.623 28.184-15.526-14.483 7.743-7.747 7.333 6.396 17.946-19.743z"] +main[data-functional-selector="correct-answer"] > div > div > div > svg > g > path +main[data-functional-selector="incorrect-answer"] > div > div > div > svg > g > path +main[data-functional-selector="time-up-answer"] > div > div > div > svg > g > path +div[data-functional-selector="kahoot-settings__language-picker"] > div > div > div > div > img +.sc-iqxcLP.klWCeb +g#Background +g#Greyscale +span[data-functional-selector="kahoot-logo"] > svg > g > path IGNORE INLINE STYLE [data-functional-selector^="answer"] @@ -7601,11 +9683,23 @@ IGNORE IMAGE ANALYSIS kali.org +CSS +#kali-platforms .card > div { + background-image: none !important; +} + IGNORE IMAGE ANALYSIS #banner-logo ================================ +kaos-community-packages.github.io + +INVERT +.Header-brand + +================================ + kaosx.us INVERT @@ -7613,6 +9707,15 @@ INVERT ================================ +katahiromz.web.fc2.com + +CSS +body { + background-image: none !important; +} + +================================ + kaytrip.com INVERT @@ -7644,7 +9747,7 @@ CSS .status-20-fg { color: #FF2190 !important; } -.status-30-fg { +.status-30-fg { color: #FFF719 !important; } .status-40-fg { @@ -7653,10 +9756,10 @@ CSS .status-50-fg { color: #0062FF !important; } -.status-80-fg { +.status-80-fg { color: #47FF19 !important; } -.status-90-fg { +.status-90-fg { color: #727985 !important; } @@ -7707,6 +9810,30 @@ CSS ================================ +keyserver.pgp.com + +INVERT +a.button-text +#ImPGPComHelp +#ImPGPComHome +[src="images/crystal_button_left.gif"] +[src="images/crystal_button_left-dark.gif"] +[src="images/crystal_button_right.gif"] +[src="images/crystal_button_right-dark.gif"] +[src="images/global_dir_logo_web.gif"] +[background="images/crystal_button_fill.gif"] +[background="images/crystal_button_fill-dark.gif"] + +CSS +.card-top, .card-top-left-corner, .card-top-right-corner, +.divide-fill, +.header-bar-left, .header-bar-right, +.title-left, .title-right { + background-image: none !important; +} + +================================ + kfccoupons.co.nz CSS @@ -7784,6 +9911,14 @@ img[src$="close.svg"] ================================ +klubjagiellonski.pl + +INVERT +.logo +.site_hamb svg + +================================ + knife.media INVERT @@ -7792,6 +9927,14 @@ svg[class$="logo-image"] ================================ +knowyourmeme.com + +INVERT +.enlargeNavigation > #enlargeNav-prev +.enlargeNavigation > #enlargeNav-next + +================================ + ko-fi.com INVERT @@ -7818,6 +9961,34 @@ INVERT ================================ +konkret24.tvn24.pl + +INVERT +.header-left-corner__logo +.menu-button__bars +.report-toggle-button__icon +.search-panel-toggle-button__icon + +================================ + +kopalniawiedzy.pl + +INVERT +img[alt="Patronite"] + +================================ + +korso24.pl +korsosanockie.pl + +INVERT +img.weather-box__img +.nav-top__logo-wrapper +.nav-top__footer-burger > div > span +a.footer__logo + +================================ + kraken.com CSS @@ -7851,6 +10022,44 @@ img[src*="logo"] ================================ +ksiegowawsieci.pl + +INVERT +.logo + +================================ + +kubuntu.org + +INVERT +.logo + +================================ + +kulinarnyblog.pl + +INVERT +.logo-img + +================================ + +kyivindependent.com + +INVERT +.custom-logo-link +.donate__patreon::before + +================================ + +labfolder.com + +CSS +:root { + --secondary-color: ${#002b56} !important; +} + +================================ + lajtmobile.pl CSS @@ -7883,6 +10092,13 @@ a { ================================ +lambdalabs.com + +INVERT +.lambda-logo + +================================ + languagetool.org INVERT @@ -7969,6 +10185,21 @@ CSS ================================ +leagueoflegends.com + +INVERT +[data-testid="featurednews"] div[class^="style__ItemWrapper"] div[class^="style__Container"] canvas + +CSS +article > div > canvas[class^="style__Canvas"] { + display: none !important; +} +div[class^="style__NavContent"] { + background-color: var(--darkreader-neutral-background) !important; +} + +================================ + learnopengl.com CSS @@ -8048,6 +10279,14 @@ INVERT ================================ +lever.co + +INVERT +a.main-header-logo +div.site-branding + +================================ + lg.com INVERT @@ -8065,6 +10304,14 @@ img[src*="libertesklep.svg"] ================================ +libravatar.org + +INVERT +footer::before +.hero::before + +================================ + libretexts.org CSS @@ -8083,6 +10330,22 @@ INVERT ================================ +librewolf.com + +CSS +.docs-container .max-w-screen-md .screenshot + .inner { + background-image: linear-gradient( 180deg, rgba(255, 255, 255, 0) 0%, rgba(26, 24, 26, var(--darkreader-bg--tw-bg-opacity)) 50% ) !important; +} + +================================ + +licensing.biz + +INVERT +.logo + +================================ + lichess.org CSS @@ -8152,7 +10415,7 @@ body { div#header { color: black !important; } -div#header a:link, +div#header a:link, div#header a:visited { color: black !important; } @@ -8242,10 +10505,15 @@ INVERT linustechtips.com +INVERT +.ipsMenu + CSS -.ipsBadge, -a.ipsBadge { - --darkreader-bg--badge--background: ${white} linear-gradient(rgba(0,0,0,0.9), rgba(0,0,0,0.9)) +:root { + --darkreader-bg--badge--background: ${white} linear-gradient(rgba(0,0,0,0.9), rgba(0,0,0,0.9)) !important +} +.ipsHovercard { + background-color: ${#fff} !important; } ================================ @@ -8269,6 +10537,13 @@ body { ================================ +linuxuprising.com + +INVERT +.logo + +================================ + lirc.org CSS @@ -8324,6 +10599,21 @@ div.icoShare.iconSprite ================================ +liveuamap.com + +INVERT +.comment-link::after +.leaflet-pane > .leaflet-layer +.logo +.top-bright > label::after + +CSS +.head-news { + background-image: none !important; +} + +================================ + lkml.org INVERT @@ -8339,10 +10629,28 @@ td.c { ================================ +loepenshop.com +bonjourfoto.nl + +CSS +body { + background-image: none !important; +} + +IGNORE IMAGE ANALYSIS +div.art-Header-jpeg + +================================ + login.live.com INVERT div[id$="Proofs"] .tile-img +div.promoted-fed-cred-content > div > div > div > div > img +div#credentialList.form-group > div > div > div > div > div > img +div.pagination-view.has-identity-banner.animate.slide-in-next > div > div > div > img +span.help-button > img +button.backButton > img ================================ @@ -8357,6 +10665,20 @@ IGNORE IMAGE ANALYSIS ================================ +logowanie.edukacja.olsztyn.eu + +INVERT +img[alt="Nagłówek strony"] +img#logo +img[src="/Resources/wylogowano-plansza.jpg"] + +CSS +body { + background-image: none !important; +} + +================================ + lol.fandom.com CSS @@ -8404,6 +10726,14 @@ img { ================================ +lsa.umich.edu + +IGNORE IMAGE ANALYSIS +.header-wrap +.giving-wrap + +================================ + lunapic.com INVERT @@ -8462,6 +10792,13 @@ CSS ================================ +machinelearningmastery.com + +INVERT +img.size-full.wp-image-7676 + +================================ + madshi.net CSS @@ -8499,6 +10836,22 @@ body { ================================ +magister.net + +INVERT +.bottom > img + +CSS +.splash-container { + z-index: 0 !important; +} +.cijfers-k-grid.k-grid .grade.empty { + background-image: none !important; + background-color: ${#cfcfcf} !important; +} + +================================ + mail.google.com INVERT @@ -8574,28 +10927,6 @@ IGNORE INLINE STYLE ================================ -mail.protonmail.com - -CSS -.customCheckbox-input:not(:checked) + .customCheckbox-mask { - background: none !important; -} -select.field { - background: var(--darkreader-neutral-background) !important; - color: var(--darkreader-neutral-text) !important; -} -.label-stack-item { - background-color: var(--color,currentColor) !important; -} -.items-column-list-inner { - border: solid var(--bordercolor-input) !important; -} -.main { - border-color: ${darkgray} !important; -} - -================================ - mail.qq.com INVERT @@ -8661,6 +10992,18 @@ div.mb > div > svg > path { ================================ +mailbox.org + +CSS +body.bg-blog { + background-image: none !important; +} +.common .mod_article > .inside { + background-color: var(--darkreader-neutral-background) !important; +} + +================================ + makeuseof.com IGNORE IMAGE ANALYSIS @@ -8678,10 +11021,15 @@ INVERT manjaro.org CSS -.page-header-image { - z-index: 0 !important; +.bg-teal-accent-400, +.bg-teal-accent-400 path { + background-color: ${rgb(29,233,182)} !important; + fill: ${rgb(29,233,182)} !important; } +IGNORE INLINE STYLE +.bg-teal-accent-400 path + ================================ manualslib.com @@ -8805,6 +11153,13 @@ INVERT ================================ +math.tamu.edu + +INVERT +div[align="center"] > p + p > img + +================================ + mathsisfun.com CSS @@ -8814,7 +11169,7 @@ CSS } #searchBtn { border-color: black !important; - background-color: var(--darkreader-neutral-background) !important; + background-color: var(--darkreader-neutral-background) !important; } #content h1 { color: var(--darkreader-neutral-text) !important; @@ -8868,6 +11223,13 @@ a > svg ================================ +matrix.to + +INVERT +div.footer > p > img + +================================ + matsci.org INVERT @@ -8893,10 +11255,20 @@ section[class$="container"][style^="background-image"] { ================================ +mcbsys.com + +INVERT +.site-branding +.icon-image + +================================ + mediawiki.org INVERT #p-logo-text +.mw-logo-wordmark +img[alt="audio speaker icon"] IGNORE IMAGE ANALYSIS .mw.wiki-logo @@ -8908,6 +11280,7 @@ medium.com INVERT .svgIcon .svgIcon-use +div[role="separator"] ================================ @@ -8920,6 +11293,14 @@ span.markup--quote.markup--p-quote.is-other { ================================ +medrxiv.org + +INVERT +.blood_logo +.logo-img + +================================ + meet.google.com IGNORE INLINE STYLE @@ -8975,7 +11356,7 @@ mendeley.com CSS .highlightLayer * { - background-color: var(--darkreader-selection-text) !important; + background-color: var(--darkreader-selection-text) !important; } ================================ @@ -8998,6 +11379,18 @@ merriam-webster.com INVERT circle.outline.Oval +CSS +.logo-cnt path[fill="#004990"] { + fill: ${#0085e0} !important; +} + +================================ + +mesa3d.org + +INVERT +[data-bs-toggle="collapse"] > a > svg + ================================ messages.android.com @@ -9049,6 +11442,9 @@ CSS .j7vl6m33, .a8c37x1j, .bp9cbjyn, mask[id*="jsc_c"] > circle { fill: var(--always-white) !important; } +.a8c37x1j > rect { + fill: var(--darkreader-bg--fds-white) !important; +} :root, .__fb-light-mode { --filter-disabled-icon: invert(100%) opacity(30%) !important; --filter-placeholder-icon: invert(59%) sepia(11%) saturate(200%) saturate(135%) hue-rotate(176deg) brightness(96%) contrast(94%) !important; @@ -9090,6 +11486,13 @@ g > rect ================================ +metal.equinix.com + +INVERT +.tw-logo + +================================ + meteo.imgw.pl INVERT @@ -9105,6 +11508,35 @@ IGNORE IMAGE ANALYSIS ================================ +metrics.torproject.org + +INVERT +img[src^="/images/flags/"] +g > text +g > line + +CSS +.dot { + fill: var(--darkreader-neutral-background) !important; +} +div > img[src] { + filter: invert(90%) !important; +} + +================================ + +metrobyt-mobile.com + +INVERT +#digital-header-logo-img + +CSS +#Desktop-img { + z-index: 0 !important; +} + +================================ + mewe.com CSS @@ -9119,9 +11551,14 @@ body > .ember-view.dialog_wrapper { microsoft.com +INVERT +.m-updated-quicklinks .c-carousel.f-single-slide ul > li > a.c-hyperlink > img.large-icon + CSS #announce picture + div h3, -#announce picture + div p { +#announce picture + div p, +.edgeconsumer.features .m-hero h1, +.edgeconsumer.features .m-hero p { color: var(--darkreader-neutral-background) !important; } @@ -9157,12 +11594,10 @@ body, ================================ -minecraft.net +mikufan.com -CSS -div[style$="/bg-wool-white.png);"] { - background-image: none !important; -} +IGNORE IMAGE ANALYSIS +#header-container ================================ @@ -9182,6 +11617,20 @@ IGNORE IMAGE ANALYSIS ================================ +minesweeper.online + +IGNORE IMAGE ANALYSIS +* + +================================ + +minsu.dianping.com + +INVERT +.zg-map + +================================ + miro.com INVERT @@ -9190,6 +11639,15 @@ INVERT ================================ +mitx.* + +CSS +img { + background-color: white !important; +} + +================================ + mixcloud.com INVERT @@ -9208,6 +11666,16 @@ INVERT ================================ +mlb.com + +CSS +#percentile-rank text, +.legend { + fill: var(--darkreader-neutral-text) !important; +} + +================================ + mnt.ee CSS @@ -9296,7 +11764,7 @@ header.smaller #szukajka .inputsearch, background-image: none !important; background-color: var(--darkreader-neutral-background) !important; } -#searchbox, +#searchbox, select { color: var(--darkreader-neutral-background) !important; } @@ -9330,6 +11798,14 @@ a[href$="twitter.com/money_pl"] path:first-of-type { ================================ +monitor.firefox.com + +INVERT +svg[class="Mozilla-logo"] > path[fill="#ffffff"] +.fx-bento-app-link.fx-bento-link.fx-mobile > span::before + +================================ + monokai.pro INVERT @@ -9450,6 +11926,15 @@ CSS ================================ +motorsport.com + +CSS +.ms-schedule-table__cell { + background-color: var(--darkreader-neutral-dark) !important; +} + +================================ + mozilla.net INVERT @@ -9465,6 +11950,28 @@ INVERT ================================ +msi.com + +INVERT +a.logo +.site-logo +.site-header-menu-toggle--button span +.flickity-button-icon +.homeLink__logo + +CSS +#MSI_Support .top-headBg, +#MSI_Support .top-head, +#MSI_Support .main-contact-support { + background-image: none !important; +} +.related__link > .related__title, +.service__link > .service__head { + z-index: 1 !important; +} + +================================ + msmgtoolkit.in CSS @@ -9521,6 +12028,15 @@ CSS ================================ +multitran.com + +CSS +body { + background-image: none !important; +} + +================================ + mumble.info INVERT @@ -9529,6 +12045,13 @@ INVERT ================================ +murena.com + +INVERT +picture.wordmark--link + +================================ + musclewiki.com INVERT @@ -9549,6 +12072,11 @@ INVERT .m-table thead .u-btn2 .u-lv +.u-btn +.m-tabs +.n-srch .pgsrch +.n-srch .pgsrch .btn +.n-srch .pgsrch .srch CSS .n-myinfo { @@ -9575,10 +12103,10 @@ CSS music.apple.com INVERT -.web-navigation__logo-link.button-reset.ember-view -.native-upsell__logo -.native-upsell__action -.dt-search-box__icon +body:not(.dark-mode) .web-navigation__logo-link.button-reset.ember-view +body:not(.dark-mode) .native-upsell__logo +body:not(.dark-mode) .native-upsell__action +body:not(.dark-mode) .dt-search-box__icon .web-chrome-playback-controls .dt-media-contextual-menu .web-chrome-playback-lcd__contextual-badge--non-marquee.web-chrome-playback-lcd__contextual-badge @@ -9616,7 +12144,7 @@ CSS my.contabo.com CSS -#mainmenu > div, +#mainmenu > div, #submenu > div, .button, .ui-button { @@ -9692,6 +12220,10 @@ CSS body:not(.ownlist) { background-color: var(--darkreader-neutral-background) !important; } +body { + background-image: none !important; + background-color: var(--dakreader-neutral-background) !important; +} ================================ @@ -9702,6 +12234,13 @@ IGNORE INLINE STYLE ================================ +myfood4less.com + +INVERT +.elementor-widget-theme-site-logo + +================================ + mymenu.be INVERT @@ -9717,6 +12256,15 @@ IGNORE INLINE STYLE ================================ +mywikis.com + +INVERT +.heading-primary +.heading-subtext +.hero + +================================ + n.maps.yandex.ru mapeditor.yandex.com @@ -9733,6 +12281,16 @@ INVERT ================================ +narimiran.github.io/nim-basics + +CSS +body, +#toc.toc2 { + background-color: var(--darkreader-neutral-background) !important; +} + +================================ + nasa.gov IGNORE IMAGE ANALYSIS @@ -9740,6 +12298,15 @@ IGNORE IMAGE ANALYSIS ================================ +naszemiasto.pl +strefabiznesu.pl + +INVERT +.componentsNavigationNavbar__logo +.atomsNavigationFooterLinks__logo + +================================ + natemat.pl aszdziennik.pl innpoland.pl @@ -9750,14 +12317,22 @@ INVERT img[src*="/static/media/"] img[alt="close icon"] a[href="#comments"] +.st1 CSS img[class*="Footer--Logo"] { - background-color: #fff !important; + background-color: #fff !important; } ================================ +nationalgeographic.com + +INVERT +.NavBar__Logo__Container + +================================ + nature.com INVERT @@ -9775,6 +12350,13 @@ INVERT ================================ +navalnews.com + +INVERT +.logo + +================================ + nba.com INVERT @@ -9793,24 +12375,51 @@ IGNORE IMAGE ANALYSIS ================================ -neonet.pl +nbcphiladelphia.com INVERT -div[class^="newsSingleBar"] > div[class^="newsSingleBarHeaderWidescreen-category"] - -CSS -div[class^="newsSingleBar"] > div[class^="newsSingleBarHeaderWidescreen-category"] { - color: ${white} !important; -} +.site-footer__social-list-item .icon ================================ -neowin.net +nbi.ku.dk CSS -.select option { - background-color: #1c1e1f !important; - color: white !important; +.tile-link { + color: var(--darkreader-neutral-color) !important; +} + +================================ + +nejm.org + +INVERT +a[href="/"] svg + +================================ + +neonet.pl + +INVERT +div[class^="newsSingleBar"] > div[class^="newsSingleBarHeaderWidescreen-category"] + +CSS +div[class^="newsSingleBar"] > div[class^="newsSingleBarHeaderWidescreen-category"] { + color: ${white} !important; +} + +================================ + +neowin.net + +INVERT +.comment-link +.news-view-switcher span + +CSS +.select option { + background-color: #1c1e1f !important; + color: white !important; } ================================ @@ -9824,6 +12433,9 @@ INVERT netlify.com +INVERT +.masthead-home-logo + CSS [data-darkreader-inline-fill] { fill: var(--scrim-icon-color) !important; @@ -9927,6 +12539,13 @@ img[src*="hashpower@2x] ================================ +niestatystyczny.pl + +INVERT +div#logo > h1 > a > img + +================================ + nirsoft.net CSS @@ -9939,6 +12558,40 @@ CSS ================================ +niser.ac.in + +CSS +body, +#main-content, +#page { + background-image: none !important; +} + +================================ + +nixos.org + +INVERT +header a[href="/"]::after + +CSS +.demo-preview > .thumbnail svg .background { + fill: var(--darkreader-neutral-background) !important; +} +.packages-searchbox::before, +.packages-searchbox::after { + background-image: none !important; +} + +================================ + +nlnet.nl + +INVERT +.header_logo + +================================ + nnmclub.to nnm-club.me @@ -9970,6 +12623,17 @@ IGNORE IMAGE ANALYSIS ================================ +notebooks.githubusercontent.com/view/ipynb* + +CSS +.jp-CodeConsole .CodeMirror.cm-s-jupyter, +.jp-Notebook .CodeMirror.cm-s-jupyter, +.highlight { + background-color: var(--darkreader-neutral-background) !important; +} + +================================ + notion.so INVERT @@ -9979,19 +12643,16 @@ img[alt="People using Notion"] .desktop-illustration .illustration .next-image .api-section-image .next-image +.visual .next-image +.logo svg > :first-child CSS +body { + background-color: var(--darkreader-neutral-background) !important; +} .notion-divider-block div div { border-bottom: 1px solid ${rgba(55, 53, 47, 0.4)} !important; } -.header .logo svg > path:nth-child(1), -nav[aria-label="Main footer navigation"] .logo svg > path:nth-child(1) { - fill: var(--darkreader-neutral-background) !important; -} -.header .logo svg > path:nth-child(3), -nav[aria-label="Main footer navigation"] .logo svg > path:nth-child(3) { - fill: var(--darkreader-neutral-text) !important; -} ================================ @@ -10002,6 +12663,35 @@ INVERT ================================ +nowafarmacja.pl + +INVERT +.icon-chevron-down +.payment-banners +.hheader::after + +================================ + +nowemedium.pl + +INVERT +.logo-tagline-group +.menu_toggle + +================================ + +nperf.com + +INVERT +.SpeedTest > .resultPanel + +CSS +.SpeedTest > .resultPanel { + background-color: transparent !important; +} + +================================ + npmjs.com INVERT @@ -10027,7 +12717,7 @@ ns.nl CSS .section--nsYellow { - background-color: var(--darkreader-neutral-background) !important; + background-color: var(--darkreader-neutral-background) !important; } ================================ @@ -10063,6 +12753,22 @@ div.brand-container a svg { .taboff { background-image: none !important; } +.mid-gray { + fill: #999 !important; + background-color: #999 !important; +} +.dark .green40 { + fill: #3b5d00 !important; + background-color: #3b5d00 !important; +} +.green50 { + fill: #598b00 !important; + background-color: #598b00 !important; +} +.dark .green100 { + fill: #76b900 !important; + background-color: #76b900 !important; +} ================================ @@ -10082,25 +12788,48 @@ body, ================================ +nxos.org + +INVERT +#logo +a[href^="#sidewidgetarea"] + +================================ + nymag.com INVERT -.logo-svg +.article-feed-header svg .article-nav-top-center #latest-feed-title +.logo-svg #site-feed-curbed-title > .feed-title-wrapper .tab-trigger > svg .tab-trigger > svg > circle .tab-trigger > svg > g > circle +.title-logo #vulture-trigger > svg > g > path:nth-child(1) #wwwthecut-trigger > svg > .active > path +CSS +.collection-articles-lede_first-featured .lede-item[data-track-index="0"] .lede-image-wrap { + z-index: 0 !important; +} +.collection-articles-lede_first-featured .lede-item[data-track-index="0"] .lede-text-wrap { + z-index: 1 !important; + position: absolute !important; +} + ================================ nytimes.com INVERT +div#live-country-map.live-country-map-embed +div#live-us-map.live-us-map-embed +g > text .svelte-1v1dl99 +.vmap-zoom-buttons #xwd-board CSS @@ -10123,6 +12852,36 @@ a[data-testid] > svg { #xwd-board rect[class^="Cell-block--"] { fill: ${black} !important; } +#xwd-board text[class^="Cell-hidden--"] { + color: ${black} !important; +} +#xwd-board rect[class^="Cell-cell--"] { + fill: ${darkgrey} !important; +} +#xwd-board rect[class^="Cell-highlighted--"] { + fill: ${lightgrey} !important; +} +#xwd-board rect[class^="Cell-selected--"] { + fill: ${white} !important; +} +#xwd-board rect[class^="Cell-related--"] { + fill: ${goldenrod} !important; +} +#xwd-board rect[class^="xwd__cell--cell"] { + fill: ${darkgrey} !important; +} +#xwd-board rect[class^="xwd__cell--highlighted"] { + fill: ${lightgrey} !important; +} +#xwd-board rect[class^="xwd__cell--selected"] { + fill: ${white} !important; +} +#xwd-board rect[class^="xwd__cell--related"] { + fill: ${khaki} !important; +} +#xwd-board rect[class*="xwd__cell--penciled"] ~ text[text-anchor^="middle"] { + fill: ${blue} !important; +} ================================ @@ -10193,6 +12952,18 @@ span.icon-gray.quotation-mark ================================ +office.com + +INVERT +.ms-ohp-svg-Icon.ms-ohp-Icon--privacyLogo + +IGNORE IMAGE ANALYSIS +.ms-ohp-svg-Icon.ms-ohp-Icon--privacyLogo +.ms-ohp-svg-Icon.ms-ohp-Icon--calendarLogo::before +.ms-ohp-svg-Icon.ms-ohp-Icon--flowLogo::before + +================================ + oisd.nl INVERT @@ -10258,6 +13029,15 @@ IGNORE IMAGE ANALYSIS ================================ +omgubuntu.co.uk + +CSS +.header { + background: var(--header-background) !important; +} + +================================ + omni.se CSS @@ -10312,25 +13092,37 @@ table[style*="/cvir/UI"], ================================ +onelook.com + +INVERT +img[alt="OneLook"] + +================================ + onet.pl plejada.pl INVERT -.websiteLogo -.serviceIcon -a.serviceLogo > img -.sheet -.logoImage +[class*="WeatherDay_tempIcon"] +._3ZySwSLi_pur0unnAQO2No +.forecast img +.icon-shareIcon svg .locationName svg +.logo-cls-1 .logoImageRight +.serviceIcon +.sheet .weatherBox .iconNow -.forecast img -.weatherIcon -ul.contentList img.icon -._3ZySwSLi_pur0unnAQO2No -.WeatherDay_tempIcon__3Uzdm -img[alt="Plejada.pl"] +[class*="weatherIcon"] +.websiteLogo +a.serviceLogo img img[alt="O!Konto"] +img[alt="Plejada.pl"] +ul.contentList img.icon +svg[class*="MenuIcon"] +svg[class*="LoginIcon"] +.weatherExtrasWidget__category-image img +[class*="SponsorImage"] CSS .mainBoxBgHolder { @@ -10359,6 +13151,13 @@ INVERT ================================ +onlinelibrary.wiley.com + +INVERT +#mainLogo + +================================ + onlinetrade.ru INVERT @@ -10380,6 +13179,13 @@ body { ================================ +onlyoffice.com + +INVERT +.logo + +================================ + op.gg INVERT @@ -10442,10 +13248,21 @@ INVERT ================================ +openbenchmarking.org + +INVERT +g[font-size]:not(g[font-size][fill^="#fff" i]:not(.oborg_expandable_result g)) +g[font-size]:not(g[font-size][fill^="#fff" i]) > text[fill="#005a00"] + +IGNORE INLINE STYLE +g[font-size][fill^="#fff" i] + +================================ + opencollective.com INVERT -img[alt="Open collective"] +img[alt="Open Collective"] CSS #section-contributors > div { @@ -10489,6 +13306,9 @@ div[dir="ltr", id="map"] { .map-layout #map { background-color: ${#1b1b1b} !important; } +img.loader { + filter: invert(93.7%) hue-rotate(180deg) contrast(90.6%) !important +} IGNORE INLINE STYLE .ideditor .main-content * @@ -10536,6 +13356,21 @@ INVERT ================================ +osu.edu +ohio-state.edu + +CSS +#osu_navbar { + background-image: linear-gradient(rgb(40, 43, 45) 0%, rgb(63, 69, 71) 100%); + border-bottom: 5px solid rgb(187, 0, 0); +} +body.sidebar-layout #page #content, +#page #content { + background-image: none; +} + +================================ + otomoto.pl INVERT @@ -10543,10 +13378,24 @@ INVERT ================================ +outline.com + +INVERT +img[src="https://outline.com/images/wordmark.svg"] + +================================ + +outlook.live.com + +INVERT +div.o365cs-base > span.ms-Icon--WaffleOffice36 + +================================ + overleaf.com INVERT -.pdf-viewer +.canvasWrapper ================================ @@ -10618,6 +13467,22 @@ CSS ================================ +pan.baidu.com + +INVERT +.module-header-wrapper dt + +================================ + +panthema.net + +CSS +body { + background-image: none !important; +} + +================================ + papaya.rocks INVERT @@ -10633,6 +13498,15 @@ INVERT ================================ +paramountnetwork.com + +CSS +.module-container { + background-color: var(--darkreader-neutral-background) !important; +} + +================================ + park-in.gr CSS @@ -10654,6 +13528,48 @@ INVERT ================================ +paste.rs + +CSS +pre { + --darkreader-inline-bgcolor: var(--darkreader-neutral-background) !important; +} + +================================ + +patreon.com + +INVERT +a[href^="https://docs.google.com"] img +a[href^="https://forms.gle"] img + +IGNORE IMAGE ANALYSIS +* + +================================ + +patriotmemory.com + +INVERT +.w-nav a[href="/"] img +.w-nav-brand + +================================ + +patuscada.bar + +INVERT +.topo +.topo > * +.patuscada-logo +.botoes-topo a:last-child img +.logo + +IGNORE IMAGE ANALYSIS +.etiqueta-vermelha + +================================ + paulgraham.com CSS @@ -10666,7 +13582,7 @@ body { payu.com CSS -img[src$="PayU-Map_Homepage_World.svg"] { +img[src$="PayU-Map_Homepage_World.svg"] { filter: invert(90%) hue-rotate(180deg) contrast(90%) !important; } @@ -10679,6 +13595,9 @@ BODY.normal td.bodyarea { background-image: none !important; } +IGNORE INLINE STYLE +.page-header__brand > svg > path + ================================ pcdiga.com @@ -10692,10 +13611,22 @@ input, textarea { color: var(--darkreader-neutral-text) !important; } li.level0 > a { - color: var(--darkreader-neutral-text) !important; + color: var(--darkreader-neutral-text) !important; } li.level0 > a:hover { - color: #ff4d23 !important; + color: #ff4d23 !important; +} + +================================ + +pch24.pl + +INVERT +a[href="https://pch24.pl"] svg + +CSS +a[href="https://pch24.pl"] svg path[fill="#1d1e1d"] { + --darkreader-inline-fill: ${white} !important; } ================================ @@ -10711,6 +13642,8 @@ peardeck.com INVERT .boxy-svg +.mc-answer__check-inner +.check-svg ================================ @@ -10741,6 +13674,17 @@ img[src*="logo"] ================================ +petco.com/shop/en/petcostore + +INVERT +a[class^="LogoAnchor__Container"] +button[class^="HamburgerButton"] +img.center-block.margin-top-sm +h1.pals-header +img.center-block + +================================ + pgatour.com CSS @@ -10766,6 +13710,13 @@ div#outer { ================================ +photofeeler.com + +INVERT +.navbar-brand + +================================ + phys.nagoya-u.ac.jp INVERT @@ -10785,6 +13736,22 @@ img.math-display ================================ +piazza.com + +CSS +.dashboard_toolbar, .page_feed_bucket_header { + background: linear-gradient(to bottom, ${#c5c7cd} 0%, ${#dfe1e2} 100%) !important; +} + +================================ + +picknsave.com + +INVERT +.KrogerHeader-Logo--inner + +================================ + picrew.me IGNORE INLINE STYLE @@ -10812,6 +13779,33 @@ CSS ================================ +pipewire.org + +CSS +body, img, video, iframe { + filter: none !important; +} + +================================ + +pipiwiki.com + +INVERT +.mwe-math-fallback-image-display +.mwe-math-fallback-image-inline +#logo_img + +================================ + +pixaful.com + +CSS +body { + background-image: none !important; +} + +================================ + pixiv.net CSS @@ -10822,6 +13816,13 @@ CSS ================================ +pixlab.pl + +INVERT +img[src*="trust_us"] + +================================ + pl.glosbe.com INVERT @@ -10829,6 +13830,15 @@ footer > div > div > a > img ================================ +planet.gnome.org + +CSS +div.post { + background-image: none !important; +} + +================================ + planetagracza.pl INVERT @@ -10837,6 +13847,33 @@ p.site-title ================================ +planetminecraft.com + +CSS +#container, +.forum_replies_container, +.forum_reply, +.contents, +.spoiler_header, +#resource-log, +.tag, +.view_more:not(:hover), +#popup, +code { + background: var(--darkreader-neutral-background) !important; +} + +================================ + +plannedparenthood.org + +INVERT +a.top-level-nav-link::after +a.top-level-nav-link::before +a.top-level-nav-link > span::after + +================================ + plantuml.com INVERT @@ -10886,6 +13923,13 @@ a[title="Google apps"] ================================ +plotkibiznesowe.pl + +INVERT +#logo + +================================ + plumbingforums.com INVERT @@ -10918,6 +13962,13 @@ ymaps[class$="ground-pane"] ================================ +podium.com + +INVERT +.logoWrap + +================================ + poeditor.com INVERT @@ -10967,6 +14018,27 @@ INVERT ================================ +polskiemarki.info + +INVERT +a[id="powrot"] > img +img[src*="logo_fakro"] + +CSS +#katalog .container { + background-image: none !important; +} + +================================ + +polymc.org +polymc.github.io + +IGNORE INLINE STYLE +svg.home * + +================================ + poradnikzdrowie.pl INVERT @@ -10974,6 +14046,24 @@ INVERT ================================ +porkbun.com + +INVERT +img[src="/images/handshake-icon.svg"] + +================================ + +portal.edukacja.olsztyn.eu + +INVERT +div.main +div#welcome-img +#pageheader +div#ctl00_TheFooter img +a.link-gray > p + +================================ + portal.qiniu.com INVERT @@ -10981,6 +14071,13 @@ INVERT ================================ +portal.saltyfish.io + +INVERT +.logo-img + +================================ + portswigger.net INVERT @@ -10989,6 +14086,15 @@ img[alt="The Daily Swig"] ================================ +postani-student.hr + +CSS +body { + background-image: none !important; +} + +================================ + postnauka.ru INVERT @@ -10996,6 +14102,14 @@ INVERT ================================ +poszukiwania.pl + +INVERT +.header-logo +.footer-logo-address + +================================ + potplayer.daum.net INVERT @@ -11025,7 +14139,8 @@ CSS .company__img, .employer-profile-header .logo img, .company-job-list .logo img, -.epc-other-employers .logo img { +.epc-other-employers .logo img, +.home__partner-logo { filter: brightness(0.75) } @@ -11056,6 +14171,13 @@ INVERT ================================ +processon.com + +INVERT +#view_container canvas + +================================ + procyclingstats.com IGNORE IMAGE ANALYSIS @@ -11072,6 +14194,13 @@ INVERT ================================ +profiler.firefox.com + +INVERT +.chartCanvas + +================================ + projectstream.it CSS @@ -11081,6 +14210,22 @@ body { ================================ +pronote.toutatice.fr + +INVERT +.ObjetGrille +.Cours +.Insecable +.Calendrier_Jour_Selection + +CSS +body, +.ie-chips.tag-style { + background: linear-gradient(90deg, #282c2d 0, #282C2D calc(100% - 0.8rem), transparent calc(100% - 0.8rem), transparent 100%); +} + +================================ + pronto.io CSS @@ -11106,6 +14251,23 @@ body { ================================ +proton.me + +INVERT +img[src$="hero-2x.png"] + +================================ + +protonvpn.com + +INVERT +.navbar-brand +.protonmail-link +#page_home .parallax +#page_home .parallax > * + +================================ + proxmox.com INVERT @@ -11153,11 +14315,27 @@ CSS ================================ +publica.fraunhofer.de + +INVERT +img[src="/pub09img/logo-fraunhofer.gif"] + +================================ + publicwww.com CSS body { - background-image: none !important; + background-image: none !important; +} + +================================ + +pulumi.com + +CSS +:host { + --neutral-fill-stealth-rest: var(--darkreader-neutral-background) !important; } ================================ @@ -11215,11 +14393,20 @@ pz.gov.pl CSS .banner-text { - color: var(--darkreader-neutral-background) !important; + color: var(--darkreader-neutral-background) !important; } ================================ +qcc.com + +INVERT +.app-login-insert +.logo +.pay-insert + +================================ + quantrimang.com CSS @@ -11268,7 +14455,7 @@ CSS fill: rgb(219, 87, 83) !important; } body { - background-color: var(--darkreader-neutral-background) !important; + background-color: var(--darkreader-neutral-background) !important; } IGNORE INLINE STYLE @@ -11282,6 +14469,7 @@ qwant.com INVERT .background-home__logo .home__logo__container .home__logo +canvas.mapboxgl-canvas ================================ @@ -11304,32 +14492,75 @@ CSS ================================ -radar-opadow.pl +radar-opadow.pl + +INVERT +#chase-map +.ro_tooltip + +================================ + +radareu.cz + +INVERT +#radarMap .leaflet-map-pane + +================================ + +radeonramdisk.com + +INVERT +#logo + +================================ + +radio17.pl + +INVERT +.main-title + +================================ + +radiokolor.pl INVERT -#chase-map -.ro_tooltip +.nav-brand +.buttons-1 +a.logo-1 + +CSS +.content-box-1 { + background-image: none !important; +} ================================ -radareu.cz +railwaygazette.com INVERT -#radarMap .leaflet-map-pane +.mastheadLogo ================================ -radio17.pl +rain.thecomicseries.com -INVERT -.main-title +CSS +body { + background-color: var(--darkreader-neutral-background) !important; + background-image: none !important; + margin: 0px !important; + padding: 8px !important; +} +#comicimage { + background-color: #ffffff !important; +} ================================ -railwaygazette.com +rakuten.com INVERT -.mastheadLogo +.chakra-image ================================ @@ -11340,8 +14571,23 @@ td[style^="background:"] ================================ +raspberrypi.com + +INVERT +.__rptl-header-logo path[fill="#000"] + +CSS +body { + color: var(--darkreader-neutral-text) !important; +} + +================================ + raspberrypi.org +INVERT +.site-header__home-link + IGNORE IMAGE ANALYSIS .c-at-home__container @@ -11361,11 +14607,22 @@ INVERT ================================ -read.amazon.com +read.amazon.* INVERT .header_bar_icon:not(#kindleReader_button_close) .header_bar_button +#kindleReader_content + +================================ + +readme.io + +CSS +.rm-PlaygroundRequest, +.CodeTabs-toolbar { + background-color: var(--darkreader-neutral-background) !important; +} ================================ @@ -11388,6 +14645,26 @@ CSS ================================ +realmadridfin.net + +CSS +.button_submit, +#content_section, +#shoutbox_b, +#shoutbox_color, +#shoutbox_face, +#shoutbox_i, +#shoutbox_nosound, +#shoutbox_u, +#shoutbox_u + img { + background-image: none !important; +} +#shoutbox_message { + background-color: none !important; +} + +================================ + realmicentral.com INVERT @@ -11396,6 +14673,13 @@ div.fly-but-wrap.left.relative > span ================================ +redbubble.com + +INVERT +[data-testid="ds-wordmark"] + +================================ + reddit.com INVERT @@ -11445,6 +14729,14 @@ header > div > div + div button[aria-label] * { ================================ +reddit.zendesk.com + +INVERT +header > div.logo > a > img +img.hero-inner-image + +================================ + redditstatus.com INVERT @@ -11471,6 +14763,9 @@ p, li { background-color: ${white} !important; } +IGNORE INLINE STYLE +.redhat-logo * + ================================ redpenreviews.org @@ -11524,6 +14819,18 @@ CSS ================================ +relay.firefox.com + +INVERT +img.c-landing-hero-brands +img.c-brand-title +.fx-bento-app-link.fx-bento-link.fx-mobile > span::before +.fx-bento-app-link.fx-bento-link.fx-vpn > span::before +div.glocal-site-options > a > img +div.glocal-site-options > form > button::before + +================================ + relive.cc INVERT @@ -11543,9 +14850,6 @@ img.math replit.com -INVERT -.toggle-bars-wrapper - CSS .monaco-editor .cursor { background-color: ${#000}; @@ -11585,10 +14889,21 @@ body { ================================ +retracmirrors.com + +CSS +body, #app > div { + background-image: none !important; +} + +================================ + reuters.com INVERT path[d^="M121.865 50.29c0"] +svg[class^="nav-bar__arrow"] > path +svg[class^="nav-dropdown__icon"] > path ================================ @@ -11599,6 +14914,22 @@ INVERT ================================ +rg-adguard.net + +INVERT +img[src*="info"] +img[src*="like"] +img[src*="donate"] +img[src*="faq"] + +CSS +body, +.tftable th { + background: none !important; +} + +================================ + richie-bendall.ml CSS @@ -11669,6 +15000,20 @@ CSS ================================ +rocksbox.com + +INVERT +.nav_logo + +================================ + +rockylinux.org + +INVERT +img[alt="Rocky Linux"] + +================================ + rog.asus.com IGNORE IMAGE ANALYSIS @@ -11685,6 +15030,15 @@ CSS ================================ +roscidus.com + +CSS +span.caption-wrapper img { + background-color: white !important; +} + +================================ + roskomsvoboda.org INVERT @@ -11692,6 +15046,13 @@ img[src="/static/core/images/logo.svg"] ================================ +rostov.tele2.ru + +INVERT +.header-navbar-logo + +================================ + rottentomatoes.com IGNORE IMAGE ANALYSIS @@ -11701,13 +15062,23 @@ IGNORE IMAGE ANALYSIS ================================ +royalbank.com + +CSS +.rbc-select-input { + background-color: var(--darkreader-neutral-background) !important; +} + +================================ + rp.pl INVERT -img[alt="Logo RP"] -.slider-track -img[src$="stare-logo.png"] -img[src$="nowe-logo.png"] +a[href="/"] +.burger--menu span +.icon-logo::before +.footer--logo +.footer--copyright--content div ================================ @@ -11718,7 +15089,7 @@ p, .compat-types, .compat-hdr-left, .compat-status-container { - color: var(--darkreader-neutral-text) !important; + color: var(--darkreader-neutral-text) !important; } ================================ @@ -11741,6 +15112,28 @@ IGNORE IMAGE ANALYSIS ================================ +rt.ru + +INVERT +#logo_text + +================================ + +rte.ie + +INVERT +.masthead .nav-btn.menu + +CSS +.masthead .weather-widget .icon { + filter: none !important; +} +.theoplayer-skin .theo-control-bar-shadow { + background-image: linear-gradient(transparent var(--darkreader-neutral-background)) !important; +} + +================================ + rtlnieuws.nl CSS @@ -11786,6 +15179,14 @@ select { ================================ +rudeiczarne.pl + +INVERT +#logo +#footer-logo + +================================ + runkit.com INVERT @@ -11793,6 +15194,15 @@ INVERT ================================ +runtothefinish.com + +CSS +:root { + --body-background-color: var(--darkreader-neutral-background) !important; +} + +================================ + rynekzdrowia.pl INVERT @@ -11810,6 +15220,13 @@ INVERT ================================ +sadanduseless.com + +INVERT +.logo1 + +================================ + saladelcembalo.org INVERT @@ -11847,6 +15264,7 @@ samsung.* INVERT .icon +.gnb__logo CSS .feature-full-bleed-text img { @@ -11883,6 +15301,8 @@ div[role="banner"] > a > span a[aria-label="Homepage"] .gs_ico img[src*="scholar_logo"] +a#gs_hdr_lgo +a#gs_hdr_drw_lgo ================================ @@ -11894,6 +15314,13 @@ IGNORE IMAGE ANALYSIS ================================ +science.fandom.com + +INVERT +.mwe-math-fallback-image-inline + +================================ + science.org INVERT @@ -11907,6 +15334,13 @@ h1.news-article__hero__title { ================================ +sciencebasedmedicine.org + +INVERT +.site-logo + +================================ + scipy-lectures.org INVERT @@ -11934,6 +15368,8 @@ scp-wiki.net scp-wiki.wikidot.com scp-wiki-cn.wikidot.com scpwiki.com +scp-ru.wikidot.com +scpfoundation.net CSS div#container-wrap, .panel-body, .content-panel { @@ -11970,6 +15406,15 @@ path.blocklyFlyoutBackground { ================================ +screenconnect.com + +CSS +.OuterPanel .MainPanel .MasterPanel .MasterListContainer ul li.HasChildren > div > p { + filter: brightness(100%) !important; +} + +================================ + scribd.com INVERT @@ -11977,6 +15422,26 @@ INVERT ================================ +scribe.rip +scribe.nixnet.services +scribe.citizen4.eu +scribe.bus-hit.me +scribe.froth.zone + +CSS +body { + background-color: var(--darkreader-neutral-background) !important; +} + +================================ + +scribus.net + +INVERT +#site-header img + +================================ + script.google.com INVERT @@ -11984,6 +15449,9 @@ INVERT .icon .monaco-editor .cursors-layer > .cursor +IGNORE INLINE STYLE +mask > * + ================================ scroll.com @@ -12006,6 +15474,27 @@ INVERT ================================ +sea.playblackdesert.com + +INVERT +.original .characteristic .desc +.original .characteristic h3 +.original .characteristic .feature li span + +================================ + +seamonkey-project.org + +INVERT +img[src*="logo.png"] + +CSS +#breadcrumbs { + background-image: none !important; +} + +================================ + sec.sangfor.com sec.sangfor.com.cn @@ -12024,6 +15513,15 @@ INVERT ================================ +secure.fanboy.co.nz + +CSS +html { + background-image: none !important; +} + +================================ + secureage.com INVERT @@ -12050,6 +15548,14 @@ CSS ================================ +sematext.com + +INVERT +#logo +.sematext-clients-gamma figure + +================================ + sembr.org CSS @@ -12135,6 +15641,30 @@ INVERT ================================ +setupbits.com + +INVERT +.td-header-logo +.td-main-logo + +================================ + +sf-express.com + +INVERT +.home-icon +.map +.order-btn + +================================ + +shaneco.com + +INVERT +.logo-full + +================================ + share.dmhy.org CSS @@ -12171,6 +15701,21 @@ CSS ================================ +shells.com + +INVERT +img[alt="Shells Logo"] + +================================ + +shields.io + +INVERT +#app a +object + +================================ + shop.dr-rath.com CSS @@ -12180,6 +15725,21 @@ CSS ================================ +shop.surfboard.com + +INVERT +img.header-logo-image + +CSS +.homepage { + background-image: none !important; +} +.sb-searchpro .input-group .btn { + background-color: ${#fee9a4} !important; +} + +================================ + shopify.com shopify.dev @@ -12192,6 +15752,13 @@ INVERT ================================ +shoppy.gg + +INVERT +.footer-profile__logo + +================================ + shorthistory.org INVERT @@ -12214,6 +15781,27 @@ img[alt="Niantic"] ================================ +signulous.com + +INVERT +.checkbox input:checked + +CSS +.checkbox input:checked { + background-color: white; +} + +================================ + +simepar.br + +CSS +.highcharts-text-outline { + display: none !important; +} + +================================ + simplemachines.org CSS @@ -12240,6 +15828,15 @@ h3.catbg2, ================================ +simply-v.de + +CSS +body { + background-image: none !important; +} + +================================ + singularlabs.com INVERT @@ -12295,8 +15892,17 @@ body { slack.com -INVERT -.slack_logo > img +CSS +.c-slacklogo svg path:first-child { + fill: var(--darkreader-selection-text) !important; +} +.c-button:not(.v--primary, .v--secondary) { + background: inherit !important; + color: inherit !important; +} +.c-button:not(.v--primary, .v--secondary):hover { + text-decoration: underline !important; +} ================================ @@ -12364,6 +15970,17 @@ INVERT ================================ +smoglab.pl + +CSS +.main-nav, +.footer, +.module-title .main-title { + background-image: none !important; +} + +================================ + smzdm.com INVERT @@ -12381,6 +15998,15 @@ CSS ================================ +snapcraft.io + +CSS +.snapcraft-banner-background { + background-image: none !important; +} + +================================ + snapeda.com INVERT @@ -12428,6 +16054,12 @@ body, .searchTitle { background: none !important; } +.sc-classic .header__navMenu > li > a { + border-right-color: #454545 !important; +} +.headerSearch__input { + background: ${#f1f4f6} !important; +} ================================ @@ -12500,9 +16132,25 @@ INVERT ================================ +spaceweather.com + +INVERT +[src$="current_conditions.jpg"] +[src$="center_tablebg_top_r2_c1.jpg"] + +CSS +[background] { + background-image: none !important; +} + +================================ + spanish.kwiziq.com CSS +.bg-clouds { + background-image: none !important; +} .table-scroll-shadow-wrapper table td, .table-scroll-shadow-wrapper table th, .table-scroll-shadow-wrapper table tr { @@ -12511,6 +16159,47 @@ CSS ================================ +spc.noaa.gov + +CSS +body { + background-image: none !important; +} + +================================ + +spectrum.com + +INVERT +img[src$="spectrum-logo.svg"] + +CSS +.sp-background-image { + background-image: none !important; +} + +================================ + +spectrum.ieee.org + +INVERT +a[title="Spectrum Logo"] > svg + +================================ + +spectrum.net + +INVERT +.banner-wrapper > .image-container +img[src$="spectrum-logo.svg"] + +CSS +.unauthenticated-homepage { + background-image: none !important; +} + +================================ + speed.cloudflare.com INVERT @@ -12529,11 +16218,28 @@ img[src*="images/"] spidersweb.pl INVERT +.amp-site-title img[alt="logo bizBlog"] img[alt="bizblog to ludzie"] -a[href="/rozrywka"] -a[href="/plus"] -.amp-site-title + +================================ + +spidersweb.pl/plus + +INVERT +a[href="/plus"] svg + +================================ + +spidersweb.pl/rozrywka + +INVERT +a[href="/rozrywka"] svg + +CSS +a[href="/rozrywka"] svg path[fill="#211D26"] { + --darkreader-inline-fill: ${white} !important; +} ================================ @@ -12559,7 +16265,7 @@ INVERT sporza.be CSS -.sc-score, +.sc-score, .sc-score__away, .bouton:hover { color: ${#222} !important; @@ -12580,7 +16286,7 @@ CSS background-color: ${#AAA} !important; } .logo__letters { - fill: var(--darkreader-neutral-background) !important; + fill: var(--darkreader-neutral-background) !important; } .vrt-link { background-color: ${rgba(255, 165, 0, 0)} !important; @@ -12591,7 +16297,7 @@ CSS } .vrt-site-footer__navigation--green { background-color: ${#AAA} !important; - color: var(--darkreader-neutral-background) !important; + color: var(--darkreader-neutral-background) !important; } ================================ @@ -12616,6 +16322,13 @@ INVERT ================================ +sqlitebrowser.org/stats + +IGNORE INLINE STYLE +.plot-container.plotly * + +================================ + ssllabs.com INVERT @@ -12637,6 +16350,77 @@ INVERT ================================ +stackexchange.com +askubuntu.com +mathoverflow.net +serverfault.com +stackapps.com +stackexchange.com +stackoverflow.com +superuser.com + +INVERT +._glyph:not(.top-bar .-logo ._glyph) +.favicon-mathoverflow +.favicon-mathoverflowmeta +.favicon-stackoverflowmeta +.h-auto[alt="Academia"] +.h-auto[alt="Anime & Manga"] +.h-auto[alt="Ask Different"] +.h-auto[alt="Aviation"] +.h-auto[alt="Code Review"] +.h-auto[alt="Electrical Engineering"] +.h-auto[alt="English Language Learners"] +.h-auto[alt="Japanese Language"] +.h-auto[alt="MathOverflow"] +.h-auto[alt="Mathematics"] +.h-auto[alt="Server Fault"] +.h-auto[alt="Skeptics"] +.h-auto[alt="Software Engineering"] +.h-auto[alt="Stack Apps"] +.h-auto[alt="Super User"] +.h-auto[alt="The Workplace"] +.h-auto[alt="Theoretical Computer Science"] +.h-auto[alt="Unix & Linux"] +.h-auto[alt="Web Applications"] +.h-auto[alt="Role-playing Games"] +a.js-gps-track::before +img[alt="The Stack Exchange Network"] + +CSS +body, +#content { + background-image: none !important; + background-color: var(--darkreader-neutral-background) !important; +} +.profile-cards--graph { + background-image: repeating-linear-gradient(0deg, transparent, transparent 13px, ${#e4e6e8} -13px, ${#e4e6e8} 21px) !important; +} +.c-pointer { + color: grey; +} +.js-accepted-answer-indicator.fc-green-500 { + color: var(--green) !important; +} +#newuser-box { + background-color: ${#FFF8DC} !important; +} +.topbar .icon-site-switcher-bubble { + background-repeat: no-repeat !important; +} + +IGNORE INLINE STYLE +.chess-replayer-board td + +================================ + +standards.ieee.org + +INVERT +.logo-link + +================================ + stardewvalleywiki.com CSS @@ -12646,6 +16430,14 @@ html { ================================ +stardock.com + +INVERT +.mid +.careers + +================================ + start64.com INVERT @@ -12653,6 +16445,13 @@ img[alt="logo"] ================================ +startech.com.bd + +INVERT +#nav-toggler + +================================ + startpage.com INVERT @@ -12686,7 +16485,7 @@ stats.stackexchange.com CSS .site-header { - background-image: none !important; + background-image: none !important; } ================================ @@ -12722,6 +16521,13 @@ table > tbody > tr > td { ================================ +status.epicgames.com + +INVERT +div.eg-shield.white + +================================ + status.npmjs.org INVERT @@ -12738,6 +16544,13 @@ i.ml-1 ================================ +steamdeck.com + +IGNORE INLINE STYLE +#header-logo-arc ~ * + +================================ + stevendoesstuffs.dev INVERT @@ -12817,12 +16630,9 @@ CSS strava.com INVERT -.icon-dark .labelGroup #effort-box .gear::after -.icon-lg -.icon-edit .week.clearfix svg #compare-graph svg #compare-graph canvas @@ -12832,6 +16642,15 @@ nav svg .weekly-goal svg .sport-type footer img[alt="Strava"] .activity-indicator +.icon-other +#open-global-search-button +.icon-caret-down +.icon-share +.icon-kudo +.icon-comment +.icon-collapse +.icon-sm:not([class*="icon-at-pr"]):not(.icon-run) +.icon-star CSS .base-chart .grid-line, @@ -12867,10 +16686,10 @@ CSS } IGNORE IMAGE ANALYSIS -.app-icon.icon-nav-training .app-icon.icon-fb .app-icon.icon-rowing .app-icon.icon-nordicski +.app-icon.icon-walk ================================ @@ -12887,6 +16706,15 @@ INVERT ================================ +student.ladok.se + +CSS +#sidomeny .middle { + background: var(--darkreader-neutral-background) !important; +} + +================================ + studio.youtube.com INVERT @@ -12895,6 +16723,22 @@ paper-radio-button ================================ +studip.uni-passau.de + +CSS +#layout_container > div { + background-image: none; +} + +================================ + +studyflix.de + +INVERT +img[title='Rendered by QuickLaTeX.com'] + +================================ + subdivx.com INVERT @@ -12983,6 +16827,13 @@ mark { ================================ +subiektywnieofinansach.pl + +INVERT +.logo + +================================ + subscene.com CSS @@ -13007,6 +16858,15 @@ INVERT ================================ +sugaroutfitters.com + +CSS +.clearfix { + display: none !important; +} + +================================ + suite.smarttech-prod.com INVERT @@ -13021,6 +16881,14 @@ INVERT ================================ +superbuy.com + +INVERT +.header-logo +.logo img + +================================ + support.discord.com INVERT @@ -13052,7 +16920,7 @@ CSS .is-high-contrast .checkbox-button-display { opacity: 1 !important; } -.modern-browser .radio-button-display::after, +.modern-browser .radio-button-display::after, .modern-browser .checkbox-button-display::after { border-color: var(--darkreader-neutral-text) !important; } @@ -13100,7 +16968,7 @@ CSS .weather-icon { filter: invert(1) hue-rotate(180deg) !important; } -.live-marker .dot, +.live-marker .dot, .live-label::before, .active::before { background-color: var(--darkreader-neutral-text) !important; @@ -13182,18 +17050,47 @@ a[class^="PaginationButton"]:hover { ================================ -swiatrolnika.info +sw.kovidgoyal.net + +CSS +.sidebar-drawer, +.sidebar-search, +.toc-drawer { + background: var(--darkreader-neutral-background) !important; +} +.sidebar-tree a.current, +.sidebar-tree label:hover { + background: var(--darkreader-selection-background) !important; +} + +================================ + +swiatrolnika.info + +INVERT +img[alt*="logo"] +img[src*="/images/images2/icons/"] + +================================ + +system76.com + +INVERT +svg[class^="sys-logo"] + +================================ + +systemd.io INVERT -img[alt*="logo"] -img[src*="/images/images2/icons/"] +.page-logo img ================================ t.bilibili.com CSS -#app { +#app, .fixed-bg { background-image: none !important; } @@ -13216,7 +17113,7 @@ INVERT CSS section { - background-image: none !important; + background-image: none !important; } ================================ @@ -13237,12 +17134,31 @@ IGNORE INLINE STYLE ================================ +tabletochki.org + +INVERT +.perekaz__list img + +================================ + tails.boum.org +INVERT +.laptop + CSS body { - background-image: none !important; + background-image: none !important; +} +#donate-banner p { + color: var(--darkreader-neutral-background) !important; } +#donate-banner u { + border-bottom-color: var(--darkreader-neutral-background) !important; +} + +IGNORE IMAGE ANALYSIS +#donate-banner ================================ @@ -13308,6 +17224,22 @@ INVERT ================================ +tasks.google.com + +INVERT +div[role="listitem"] > div > div > div[role="presentation"] + +================================ + +tastoid.com/ + +CSS +.jumbotron.jumbotron-no-bg { + background: var(--darkreader-neutral-background) !important; +} + +================================ + tcrf.net CSS @@ -13355,6 +17287,13 @@ body, ================================ +technologyreview.com + +INVERT +a[class^="headerTemplate__logo"] + +================================ + teleman.pl INVERT @@ -13417,6 +17356,14 @@ INVERT ================================ +terazwy.pl + +INVERT +img[src*="img/loga"] +img[src*="img/logotr.png"] + +================================ + terraform.io IGNORE INLINE STYLE @@ -13461,7 +17408,7 @@ testudo.umd.edu CSS #secondary-side, #widgetbox_widget_parent_0 { - background-color: var(--darkreader-neutral-background) !important; + background-color: var(--darkreader-neutral-background) !important; } ================================ @@ -13476,8 +17423,9 @@ INVERT theatlantic.com INVERT -.c-nav__icon--lacroix -.hamburger-inner +[class^="NavHamburgerButton_root"] +[class^="NudgeShared_chevron"] +[class^="NonMeteredNudge_desktopTextContainer"]::after ================================ @@ -13540,11 +17488,27 @@ INVERT ================================ +thefreedictionary.com + +INVERT +strong.i.logo +a.i.keyboard-link.mobile-hidden +#regButton::before +ul.social-networks +a.i.icon-notif +div.box > a.i +div.cprh > span.i.A.cpr +a.i.popup-opener +ul.logos-list + +================================ + theguardian.com INVERT .inline-the-guardian-logo__svg a[data-link-name$="logo"] > svg +.crossword__grid .crossword__cell-text ================================ @@ -13580,6 +17544,16 @@ INVERT ================================ +themoscowtimes.com +moscowtimes.ru + +INVERT +.site-header__logo +.footer__logo +.contribute-teaser__button + +================================ + themoviedb.org INVERT @@ -13629,13 +17603,18 @@ theregister.*.* INVERT .row_label.title_rhs_line +.blocksandfiles_logo +.devclass_logo +#sitpub_logo ================================ thesaurus.com INVERT -#__next > div header svg +img[alt^="Grammar Coach"] +[data-grammar-coach-hero="true"] + [data-promotion-page="true"] +[data-grammar-coach-hero="true"] + [data-promotion-page="true"] > div ================================ @@ -13662,6 +17641,13 @@ a.logo ================================ +thriftbooks.com + +INVERT +.DesktopHeader-logo + +================================ + thronemaster.net INVERT @@ -13754,6 +17740,13 @@ svg > path[style*="--boost"] { ================================ +tizen.org + +INVERT +#header #logo + +================================ + tjournal.ru INVERT @@ -13778,6 +17771,18 @@ img[src="/img/logout-black.png"] ================================ +to-do.live.com + +INVERT +span[class^="ms-Toggle-thumb"] + +CSS +.backgroundLines { + background-image: linear-gradient(180deg, var(--darkreader-bg--bg-primary), var(--darkreader-bg--bg-primary) 52px, var(--darkreader-bg--bg-separator) 52px, var(--darkreader-bg--bg-separator) 52px) !important; +} + +================================ + todoist.com INVERT @@ -13806,7 +17811,7 @@ INVERT .play CSS -div.top_section_bg, +div.top_section_bg, div.bottom_section_bg { background-color: ${#e7e5e4} !important; } @@ -13826,6 +17831,14 @@ body { ================================ +torguard.net + +INVERT +img[src$="statusok.gif"] +img[src$="statusfailed.gif"] + +================================ + tosdr.org INVERT @@ -13835,6 +17848,34 @@ img[src*="guidelines.svg"] ================================ +totylkoteoria.pl + +INVERT +.site-branding +.header__socials + +CSS +.hero { + background-image: none !important; +} + +================================ + +toutatice.fr + +INVERT +.img-responsive +.banner + +================================ + +towhee.io + +INVERT +.logo-wrapper + +================================ + track.toggl.com CSS @@ -13855,7 +17896,7 @@ CSS background-color: var(--darkreader-neutral-background) !important; } .user-info__name { - color: inherit !important; + color: inherit !important; } .progress-ring__content { background-color: white !important; @@ -13867,6 +17908,13 @@ CSS ================================ +transifex.com + +INVERT +img.close_image + +================================ + translate.google.* translate.google.*.* @@ -13975,6 +18023,13 @@ INVERT ================================ +transport.orgp.spb.ru + +INVERT +#map + +================================ + trezor.io INVERT @@ -14007,6 +18062,13 @@ img[alt*="Trojmiasto.pl"] ================================ +truestory.pl + +INVERT +.tdb-logo-img + +================================ + truity.com INVERT @@ -14034,6 +18096,20 @@ button.slick-next.slick-arrow::before ================================ +tuxcare.com + +INVERT +.navbar__logo + +================================ + +tuxedocomputers.com + +INVERT +#logo + +================================ + tv.yandex.* INVERT @@ -14048,6 +18124,24 @@ IGNORE IMAGE ANALYSIS ================================ +tvland.com + +CSS +.module-container, +.header-container { + background-color: var(--darkreader-neutral-background) !important; +} + +================================ + +tvn24.pl + +INVERT +.header-menu__more-button +.hamburger-icon + +================================ + tvrain.ru INVERT @@ -14055,6 +18149,32 @@ INVERT ================================ +tvtropes.org + +INVERT +body.darthWiki > i +body.wmgWiki > i +.spi.darthwiki +.spi.sugarwiki +.spi.film +.spi.headscratchers +.spi.laconic-icon +.spi.lightnovel +.spi.manga +.spi.nightmarefuel +.spi.radar +.spi.recap +.spi.shoutout +.spi.wmg +.spi.ymmv +img[src="/img/loading-alt.gif"] + +IGNORE IMAGE ANALYSIS +body.sugarWiki #header-spacer-left::after +body.sugarWiki #header-spacer-right::after + +================================ + tweakers.net INVERT @@ -14066,7 +18186,7 @@ CSS background: url("https://tweakers.net/g/if/v3/framework/tweakers_logo_full.svg") no-repeat center !important;; } @media screen and (max-width: 1000px) { - #logo a { + #logo a { background: url("https://tweakers.net/g/if/v3/framework/menu_icons_responsive_v6.png") no-repeat -8px -220px !important; } } @@ -14115,7 +18235,7 @@ CSS border-color: ${#ccc} !important; } @media screen and (max-width: 767px) { - #userbar li.icon a { + #userbar li.icon a { background-image: url("https://tweakers.net/g/if/v3/framework/menu_icons_responsive_v6.png") !important; } #categoryBrowser li.more.active { @@ -14123,6 +18243,14 @@ CSS box-shadow: none !important; } } +#contentArea, +#categoryBrowser, +#categoryBrowser .sublist, +#categoryBrowser .mainlist, +#categoryBrowser ul, +#categoryBrowser li { + border-color: ${#b2b9bd} !important; +} IGNORE IMAGE ANALYSIS #categoryBrowser li a @@ -14130,6 +18258,13 @@ table.highlights .title a.showMoreItems ================================ +twit.tv + +INVERT +.logo-large + +================================ + twitch.tv INVERT @@ -14157,6 +18292,13 @@ header { ================================ +tygodnikkrag.pl + +INVERT +#header-logo-image + +================================ + typescriptlang.org CSS @@ -14169,21 +18311,45 @@ CSS ================================ +ubereats.com + +INVERT +img[alt*='Home'] +div[class^='c5'] .gm-style +#main-content > h1 + div +#wrapper > div:nth-of-type(2) +#wrapper > div:nth-of-type(2) > header +#wrapper > div:nth-of-type(2) > footer +#wrapper > div:nth-of-type(2) > #main-content > div:first-child + +================================ + ubuntu.com INVERT +.cls-2 .global-nav__header-logo-anchor CSS header[style$="image-background-paper.png);"] { background-image: none !important; } +.chart-key text { + fill: var(--darkreader-neutral-text) !important; +} IGNORE INLINE STYLE g#ubuntu-logo > path ================================ +ubuntubudgie.org + +INVERT +.custom-logo + +================================ + udemy.com CSS @@ -14207,6 +18373,15 @@ canvas[style^="height: 42px; width: 141px;"] ================================ +umweltinstitut.org + +CSS +.streifenBg { + background-image: none !important; +} + +================================ + un.org INVERT @@ -14214,6 +18389,60 @@ a.logo[title="United Nations"] ================================ +understandingwar.org + +CSS +#edit-search-block-form--2, +#nice-menu-1 > li > a { + color: var(--darkreader-neutral-background) !important; + text-shadow: none !important; +} +#mainwrap, +.secondarybox, +.content, +.view-filters { + background-image: none !important; +} +img[src*="ISW\%20LOGO"], +img[src*="ISW\%20Logo"] { + background-color: white !important; +} + +IGNORE IMAGE ANALYSIS +* + +================================ + +uokik.gov.pl + +INVERT +.a-press-office +.abgLong +h1[id="logo"] +p a +p.nav img +span[class="number"] +ul[class="tabs"] + +CSS +#subpage, +.sWrapper1, +.sWrapper2, +.tabs, +body#page, +div#right, +div#top, +div.fWrapper, +div[class="b1"], +h2#here { + background-image: none !important; +} +#footer .active { + color: #000000 !important; +} + +================================ + uol.com.br CSS @@ -14253,6 +18482,27 @@ CSS ================================ +upwork.com + +CSS +.profile-completeness-nudges-tiles-alternative .carousel-wrapper .up-icon svg { + filter: drop-shadow(0 0 0px var(--white)) drop-shadow(0 0 0px var(--white)); +} +.up-skill-container .up-btn.up-btn-next::before, +.up-skill-container .up-btn.up-btn-prev::before { + opacity: 0 !important; +} +.up-tab-scroll-hint:after { + background: none !important; +} +.up-d-skeleton { + color: transparent !important; + background-color: var(--darkreader-bg--skeleton-color) !important; + background-image: linear-gradient(90deg, var(--darkreader-bg--skeleton-color), #24242400, var(--darkreader-bg--skeleton-color)) !important; +} + +================================ + urbandecay.com IGNORE INLINE STYLE @@ -14264,11 +18514,16 @@ IGNORE INLINE STYLE urbandictionary.com INVERT -.top-bar-section .has-dropdown > a::after +nav a span > span +nav a[href="/"] svg > g > path:first-child + +================================ + +urpredditodicittadinanza.lavoro.gov.it CSS -.ribbon { - color: ${#333} !important; +:root { + --lwc-colorContentAreaBackground : transparent !important; } ================================ @@ -14296,13 +18551,14 @@ img[src$="hamburger.svg"] img[src$="search.svg"] ul.nav-list > li.menuheader::after ul.nav-list > li.qt-nav > div > ul > li > a > img +#usps-logo ================================ uteka.ru INVERT -img[src="/static/img/logo.svg"] +img[src^="/static/img/logo.svg"] ymaps[class$="ground-pane"] ================================ @@ -14352,6 +18608,14 @@ INVERT vanguard.com +INVERT +.vgn-accordionIcon +.vgn-arrow::after +#vgn-searchToggleButtonButton--long-form +#vgn-searchToggleButtonButton--small-form +input[id^="buysellForm:"] +input[id^="HoldingDetailForm:"] + CSS .hidePageIfJSdisabled { display: block !important; @@ -14444,6 +18708,15 @@ img[alt="VG24.PL logo"] ================================ +vh1.com + +CSS +.module-container { + background-color: var(--darkreader-neutral-background) !important; +} + +================================ + vice.com INVERT @@ -14473,6 +18746,15 @@ INVERT ================================ +vimeo.com + +INVERT +svg[alt="Vimeo"] +#header-vimeo-logo +footer > div > div > a > svg > path[d^="M89.05 23.658a12.087 12.087"] + +================================ + virtualbox.org CSS @@ -14548,6 +18830,15 @@ INVERT ================================ +vk.com + +CSS +body[scheme="vkcom_dark"] ._im_dialog_unread_ct { + background: var(--counter_primary_background) !important; +} + +================================ + vod.tvp.pl INVERT @@ -14592,10 +18883,28 @@ INVERT ================================ +vultr.com + +CSS +.svg-banner-shape { + fill: var(--darkreader-neutral-background) !important; +} + +IGNORE INLINE STYLE +.icon-ui * +.icon-user * +.icon-sm * +.svg-logo * +.svg-illustration * +.svg-product * +.svg-shape * + +================================ + w.atwiki.jp CSS -.atwiki-contents-shadow, +.atwiki-contents-shadow, .main_wrapper { background-color: var(--darkreader-neutral-background) !important; } @@ -14612,6 +18921,21 @@ img[alt*="equation" i] ================================ +wacom.com + +INVERT +img.full-size-logo +a.logo +div.minicart-wrapper +a.footer-brand + +CSS +img, div.bg-layer, div.flickity-viewport, canvas { + filter: brightness(50%) sepia(40%) !important; +} + +================================ + wakamaifondue.com CSS @@ -14621,6 +18945,15 @@ CSS ================================ +walbrzych24.com + +INVERT +a.social-icons__icon img +img.page-header__logo +img.page-footer__img + +================================ + wallet.myalgo.com IGNORE INLINE STYLE @@ -14628,6 +18961,16 @@ IGNORE INLINE STYLE ================================ +wanikani.com + +CSS +#question-type.meaning { + color: var(--darkreader-neutral-color) !important; + background-image: linear-gradient(rgb(98, 98, 98), rgb(41, 44, 46)) !important; +} + +================================ + warframe.com CSS @@ -14640,7 +18983,9 @@ CSS washingtonpost.com INVERT -.masthead_svg__wplogo +.hp-masthead +.switch +.switch::after CSS .flex * { @@ -14648,7 +18993,7 @@ CSS } IGNORE INLINE STYLE -a[data-sc-c="headerlogo"] path +.center > svg > path[fill="white"] ================================ @@ -14671,6 +19016,8 @@ text[class*="DonutChart"] IGNORE INLINE STYLE [id^="svg-symbol"] * +svg[class*="alerts--"] * +#svg-symbol-sun ================================ @@ -14758,6 +19105,25 @@ body { ================================ +webassign.net + +CSS +body { + color: var(--darkreader-neutral-text); +} +#webAssign { + background-color: var(--darkreader-neutral-background) !important; +} +#webAssignMain, +#webAssignContent { + background-color: var(--darkreader-neutral-background) !important; +} +img[alt~="key"] { + background-color: ${black} !important; +} + +================================ + webbrowsertools.com CSS @@ -14767,6 +19133,38 @@ CSS ================================ +webkitgtk.org + +CSS +#main_wrapper { + background-image: none !important; +} + +================================ + +weblate.org + +INVERT +h5.list-group-item-heading > svg + +================================ + +webmd.com + +INVERT +.global-nav-logo + +================================ + +webtoons.com + +CSS +.info { + color: rgb(0,0,0) !important; +} + +================================ + wego.here.com INVERT @@ -14841,6 +19239,14 @@ path[fill="currentColor"] ================================ +whitemad.pl + +INVERT +#logo +#cb-nav-logo + +================================ + who.int INVERT @@ -14855,6 +19261,15 @@ img[src^="logo.gif"] ================================ +wiadomoscihandlowe.pl + +INVERT +.dropdown-portal__link +.hamburger__button span +.search__icon + +================================ + wielkopolskiebilety.pl INVERT @@ -14887,7 +19302,7 @@ CSS body { background-color: transparent !important; } -.body { +.content { background-image: none !important; } @@ -14945,6 +19360,7 @@ INVERT .bookend .mwe-math-fallback-image-inline .mwe-math-fallback-image-display +img[alt="audio speaker icon"] IGNORE INLINE STYLE .infobox td @@ -14955,19 +19371,13 @@ wikidata.org INVERT .wd-mp-headerimage +img[alt="audio speaker icon"] IGNORE IMAGE ANALYSIS .mw-wiki-logo ================================ -wikiless.org - -INVERT -.mw-wiki-logo - -================================ - wikimapia.org INVERT @@ -14987,6 +19397,7 @@ wikimedia.org INVERT img.graphite-graph img[src="images/black.png"] +img[alt="audio speaker icon"] CSS div.mw-warning-with-logexcerpt, @@ -15001,22 +19412,38 @@ div.locked-warning { ================================ +wikimediafoundation.org + +INVERT +.nav-logo + +================================ + +wikimediastatus.net + +INVERT +.logo-container + +================================ + wikinews.org wikiquote.org INVERT .bookend +img[alt="audio speaker icon"] ================================ wikipedia.org +wikiless.org INVERT .mwe-math-fallback-image-inline .mwe-math-fallback-image-display -.MathJax:not(span#MathJax_Zoom > .MathJax) -span#MathJax_Zoom .mw-ext-score +.mw-logo-wordmark +.mw-logo-tagline .mw-wiki-logo .central-textlogo__image .svg-Wikimedia-logo_black @@ -15026,6 +19453,12 @@ div.post-content.footer-content > h2 > img .mw-hiero-outer.mw-hiero-table #p-logo-text body > .oo-ui-windowManager .vega .marks +.minerva-footer-logo img +.music-symbol img +.tool.tool-button[src$="background-image:"] +.mw-kartographer-map +.mw-kartographer-mapDialog-map +img[alt="audio speaker icon"] CSS .mwe-popups-discreet > svg, @@ -15078,10 +19511,12 @@ body.mediawiki, #dialogEngineContainer #dialogEngineDialog { background-color: var(--darkreader-neutral-background) !important; } +.template-facttext { + background-color: #eaecf0 !important; +} IGNORE INLINE STYLE -.legend-color -.infobox > tbody > tr > td[style*="background-color"] +.legend-color:not(table.wikitable .legend-color) #on_image_elements span IGNORE IMAGE ANALYSIS @@ -15091,15 +19526,20 @@ IGNORE IMAGE ANALYSIS wikisource.org wikiversity.org +wikivoyage.org INVERT .mwe-math-fallback-image-inline .mwe-math-fallback-image-display +img[alt="audio speaker icon"] ================================ wikitech.wikimedia.org +INVERT +img[alt="audio speaker icon"] + IGNORE IMAGE ANALYSIS .mw.wiki-logo @@ -15126,6 +19566,7 @@ wiktionary.org INVERT .bookend .central-featured-logo-text +img[alt="audio speaker icon"] CSS div.NavFrame div.NavHead { @@ -15142,6 +19583,14 @@ ymaps[class$="svg-icon-content"] > ymaps ================================ +willthompson.co.uk + +INVERT +body +body > * + +================================ + windows.php.net CSS @@ -15149,8 +19598,8 @@ CSS #page-area .content { background-image: none !important; } -#content-columns .block .corners-top, -#content-columns .block .corners-bottom, +#content-columns .block .corners-top, +#content-columns .block .corners-bottom, #page-area .content .corners-top, #page-area .content .corners-bottom { filter: invert(91%) !important; @@ -15190,6 +19639,7 @@ wired.com INVERT body a svg +a[data-testid="Logo"] .c-nav__open-icon .c-nav__close-icon .standard-navigation__logo-image > img @@ -15203,6 +19653,13 @@ INVERT ================================ +wirtualnemedia.pl + +INVERT +img[src$="logo-black.gif"] + +================================ + wmar2news.com INVERT @@ -15228,7 +19685,14 @@ img[alt="wordnik logo"] wordpress.com +INVERT +svg.masterbar__wpcom-wordmark +div.wp-login__footer.wp-login__footer--jetpack > img + CSS +svg.social-icons.social-icons__apple.social-icons--enabled { + fill: white !important; +} .p2020-sidebar { background-image: none !important; background: var(--darkreader-neutral-background); @@ -15245,9 +19709,9 @@ CSS worldcubeassociation.org CSS -.event-checkbox input[type="checkbox"] + i.cubing-icon, -.event-checkbox input[type="radio"] + i.cubing-icon, -.event-radio input[type="checkbox"] + i.cubing-icon, +.event-checkbox input[type="checkbox"] + i.cubing-icon, +.event-checkbox input[type="radio"] + i.cubing-icon, +.event-radio input[type="checkbox"] + i.cubing-icon, .event-radio input[type="radio"] + i.cubing-icon { color: rgba(0, 0, 0, 1) !important; } @@ -15339,6 +19803,15 @@ span ================================ +wszystkoconajwazniejsze.pl + +CSS +#papier img { + mix-blend-mode: normal !important; +} + +================================ + wuffs.org CSS @@ -15412,6 +19885,13 @@ footer { ================================ +www.baidu.com + +INVERT +#s_lg_img + +================================ + www.bromite.org CSS @@ -15521,6 +20001,13 @@ CSS .chr-full-bleed-hero { background-image: none !important; } +html, +body, +img, [role="img"], video, iframe, +#gb, +a[href^="https://shopping.google.com"][href*="/lists"] > span { + filter: none !important; +} IGNORE INLINE STYLE .kdPwrb @@ -15555,6 +20042,36 @@ www.mayoclinic.org INVERT .mc-logo .logo > a > img[alt="Mayo Clinic"] +img[src="/-/media/images/mayologo.png"] +img[src="/styles/img/gbs/logo-mayoclinic-mobile.png"] + +CSS +ul#nav.nav > li.no-image > a, +ul#nav.nav > li.current > a { + background-image: url("/UniversalNav/Styles/img/sprite-globalnavarrows.png") !important; +} + +================================ + +www.minecraft.net + +INVERT +.feature-details img +.ms-accordion .shade +.ms-accordion td.platform-data +.nav-links__tab-icon + +CSS +.ms-accordion td.platform-data { + background-color: white !important; +} +div[style*="background-image: url("][style*="/background-images/bg-wool-white.png"], +.promo-area .bg-wool-light { + background-image: none !important; +} + +IGNORE IMAGE ANALYSIS +.promo-area .trans-top-dark ================================ @@ -15600,6 +20117,15 @@ INVERT ================================ +www.physics.utoronto.ca/~aephraim/aephraim.html + +CSS +body { + --darkreader-inline-bgcolor: var(--darkreader-neutral-background) !important; +} + +================================ + www.pixivision.net INVERT @@ -15610,6 +20136,18 @@ INVERT ================================ +www.qt.io + +CSS +.b-background__wrapper .b-background__asset[style^="background-image"] { + filter: brightness(50%) sepia(40%) !important; +} +div[class*="frontpage"] .scheme--default p { + color: var(--darkreader-neutral-text) !important; +} + +================================ + www.realtek.com CSS @@ -15624,7 +20162,16 @@ body > div.t3-wrapper > div > div.section-wrap.bg-wrap1 > div > div > div.custom ================================ -www.soepub.com/discuzx33 +www.scien.cx + +CSS +body.custom-background { + background-image: none !important; +} + +================================ + +www.soepub.com/discuzx34 CSS .c_l, @@ -15640,6 +20187,10 @@ CSS www.songsterr.com +INVERT +use[href^="#rest"] +use[href^="#dot"] + CSS #tablature svg text { fill: var(--darkreader-neutral-text) !important; @@ -15672,6 +20223,18 @@ CSS ================================ +www.stern.de + +CSS +.page { + --page-background: var(--darkreader-neutral-background) !important; +} +.slide-navigation { + background: var(--darkreader-neutral-background) !important; +} + +================================ + www.storm.mg INVERT @@ -15717,6 +20280,15 @@ div[class*="DivVolumeControlContainer"] .volume-control-container-browser .seek-bar-container .volume-control-container +svg[class*="StyledLinkLogo"] +svg[class*="SvgPlayIcon"] + +CSS +[data-e2e="like-icon"] svg, +[data-e2e="comment-icon"] svg, +[data-e2e="share-icon"] svg { + fill: var(--darkreader-neutral-text) !important; +} ================================ @@ -15729,7 +20301,33 @@ a[title="Tinkoff"] www.tumblr.com +INVERT +.QnWzN > div +div[role="progressbar"] + CSS +a[data-testid="google-login-button"], +a[data-testid="apple-login-button"] { + background-color: var(--darkreader-neutral-background) !important; +} +a[href="/"] > div > svg { + fill: white !important; +} +a[href="/explore"] > svg { + fill: white !important; +} +a[aria-label="Tumblr"] > svg { + fill: white !important; +} +nav.FhRnI > ul > li { + filter: invert(100%) hue-rotate(180deg) contrast(200%) !important; +} +footer[role="contentinfo"] > ul > li > a { + filter: invert(0%) hue-rotate(180deg) contrast(200%) !important; +} +ul.AohpR > li > a { + filter: invert(0%) hue-rotate(180deg) contrast(200%) !important; +} :root { --darkreader-bg--white: 23, 23, 23 !important; --darkreader-text--black: 228, 224, 218 !important; @@ -15738,6 +20336,13 @@ CSS ================================ +www.w3schools.com + +IGNORE INLINE STYLE +.colorbox .innerbox + +================================ + www.windy.com INVERT @@ -15796,9 +20401,15 @@ INVERT a[href="/"] img a[href="https://x-kom.pl"] img a[href="https://www.x-kom.pl"] img +div[title*="panel"] svg img[alt="Menu"] img[alt*="Logo"] img[src*="Logo_strefy_marek"] +img[src*="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iM"] +img[src*="data:image/svg+xml;base64,PHN2ZyB4bWxucz0ia"] +.geex a img +a[href="https://geex.x-kom.pl/"] img +img[alt="Geex logotyp"] CSS .ePVVIv { @@ -15862,7 +20473,7 @@ span.logo.burger-sidebar__sidebar-logo yamicsoft.com CSS -.slider-wrapper .slide-secound-detail, +.slider-wrapper .slide-secound-detail, .slider-wrapper .slide-secound-title { color: var(--darkreader-neutral-background) !important; } @@ -15942,6 +20553,29 @@ img[src$="40x40_food_v2.svg"] ================================ +yeniakit.com.tr + +CSS +.photo-news-detail-cover .article-header > .image { + z-index: 0 !important; +} +.photo-news-detail-cover .article-header > .black-shadow { + z-index: 1 !important; +} +.photo-news-detail-cover .article-header > .social-box, +.photo-news-detail-cover .article-header > .category { + z-index: 2 !important; +} + +================================ + +yettel.rs + +INVERT +.header-container + +================================ + yle.fi INVERT @@ -15980,8 +20614,12 @@ youtube.com INVERT #tube-mount .b img +#ytd-player + .efyt-control-bar > button CSS +::-webkit-scrollbar { + background-color: var(--darkreader-bg--yt-spec-general-background-a); +} html[hide-scrollbar] ::-webkit-scrollbar { display: none !important; } @@ -16200,9 +20838,6 @@ button[aria-pressed="true"] > yt-icon:not(#guide-icon.ytd-app), .ytp-contextmenu .ytp-menuitem[aria-checked="true"] .ytp-menuitem-toggle-checkbox { background: url('data:image/svg+xml;utf8,') !important; } -#backgroundFrontLayer.tp-yt-app-header { - background-image: var(--app-header-background-front-layer_-_background-image) !important; -} #metadata-line.ytd-video-meta-block span.ytd-video-meta-block { color: var(--ytd-metadata-line-color, var(--yt-spec-text-secondary)) !important; } @@ -16228,7 +20863,7 @@ paper-item[aria-selected="true"] { background-color: rgba(255,255,255,0.2) !important; } iron-input.paper-input > input.paper-input, -.input-content.paper-input-container > label, +.input-content.paper-input-container > label, .input-content.paper-input-container > .paper-input-label { color: var(--paper-input-container-shared-input-style_-_color) !important; } @@ -16277,6 +20912,7 @@ a.yt-simple-endpoint.yt-formatted-string:hover { IGNORE INLINE STYLE yt-live-chat-ticker-paid-message-item-renderer * +#ytd-player + .efyt-control-bar > button path ================================ @@ -16304,6 +20940,14 @@ INVERT ================================ +zadania.info + +INVERT +img.math +img.math-display + +================================ + zdic.net INVERT @@ -16329,6 +20973,15 @@ CSS ================================ +zendesk.com + +CSS +.zendesk-editor--rich-text-container { + background-image: none !important; +} + +================================ + zenn.dev INVERT @@ -16350,6 +21003,15 @@ INVERT ================================ +zfsbootmenu.org + +CSS +body { + background-image: none !important; +} + +================================ + zhihu.com INVERT @@ -16357,6 +21019,18 @@ img[eeimg="1"] ================================ +zippyshare.com + +INVERT +img#browse + +CSS +.inner_main > table { + background-image: none !important; +} + +================================ + znanium.com INVERT @@ -16364,6 +21038,16 @@ INVERT ================================ +zorin.com + +INVERT +.logotype +.social +img[alt="GOG logo"] +img[alt="Windows to Zorin OS"] + +================================ + zybooks.com CSS diff --git a/src/config/inversion-fixes.config b/src/config/inversion-fixes.config index 852ec39f2843..242b77e408fa 100644 --- a/src/config/inversion-fixes.config +++ b/src/config/inversion-fixes.config @@ -114,6 +114,9 @@ CSS #nav-flyout-ewc { margin-right: -220px; } +.nav-flyout-body { + height: 100% !important; +} ================================ @@ -1963,6 +1966,24 @@ INVERT ================================ +sellercentral.amazon.com + +CSS +.sc-header { + background: #5c00ff !important; +} +.small,.account-switch-icon{ + fill: black !important; +} +.locale-icon-wrapper{ + color: black !important; +} +.logo-container { + filter: brightness(0%) !important; +} + +================================ + semlar.com INVERT @@ -2159,6 +2180,16 @@ img ================================ +thomann.de + +CSS +.fx-mix-blend-mode--multiply, +.product__image { + mix-blend-mode: unset !important; +} + +================================ + tianchi.aliyun.com NO INVERT @@ -2166,6 +2197,13 @@ img ================================ +tn.gov + +INVERT +img[src$="tn-seal.png"] + +================================ + toggl.com INVERT @@ -2444,8 +2482,13 @@ NO INVERT vk.com INVERT -#video_player +.videoplayer +.videoplayer_media +.videoplayer_timeline_preview +.mv_chat .mv_playlist +.mv_playlist_controls +#VideoLayerInfo__topControls .page_album_title .article_snippet__fade .article_snippet__info @@ -2483,9 +2526,10 @@ INVERT .audio_row__cover_back .poster__text .emoji_smiles_row +.Reaction NO INVERT -#video_player * +.mv_chat * .mv_playlist * #z_photoview img .box_grey .box_title diff --git a/src/config/static-themes.config b/src/config/static-themes.config index fe341c34f65b..c8f3c175e7fa 100644 --- a/src/config/static-themes.config +++ b/src/config/static-themes.config @@ -3,7 +3,7 @@ NEUTRAL BG html body -:not([style*="background-color:"]) +:not([style*="background-color:"]):not(iframe) NEUTRAL TEXT html diff --git a/src/defaults.ts b/src/defaults.ts index 33076cf24570..69ba9b9d0b9b 100644 --- a/src/defaults.ts +++ b/src/defaults.ts @@ -1,7 +1,7 @@ import type {ParsedColorSchemeConfig} from './utils/colorscheme-parser'; import type {Theme, UserSettings} from './definitions'; import ThemeEngines from './generators/theme-engines'; -import {isMacOS, isWindows} from './utils/platform'; +import {isMacOS, isWindows, isCSSColorSchemePropSupported} from './utils/platform'; export const DEFAULT_COLORS = { darkScheme: { @@ -31,9 +31,10 @@ export const DEFAULT_THEME: Theme = { lightSchemeTextColor: DEFAULT_COLORS.lightScheme.text, scrollbarColor: isMacOS ? '' : 'auto', selectionColor: 'auto', - styleSystemControls: true, + styleSystemControls: !isCSSColorSchemePropSupported, lightColorScheme: 'Default', darkColorScheme: 'Default', + immediateModify: false, }; export const DEFAULT_COLORSCHEME: ParsedColorSchemeConfig = { @@ -64,6 +65,7 @@ export const DEFAULT_SETTINGS: UserSettings = { syncSettings: true, syncSitesFixes: false, automation: '', + automationBehaviour: 'OnOff', time: { activation: '18:00', deactivation: '9:00', @@ -76,4 +78,5 @@ export const DEFAULT_SETTINGS: UserSettings = { enableForPDF: true, enableForProtectedPages: false, enableContextMenus: false, + detectDarkTheme: false, }; diff --git a/src/definitions.d.ts b/src/definitions.d.ts index 81e7d777a869..a6e62ee31c28 100644 --- a/src/definitions.d.ts +++ b/src/definitions.d.ts @@ -1,5 +1,6 @@ import type {ParsedColorSchemeConfig} from './utils/colorscheme-parser'; import type {FilterMode} from './generators/css-filter'; +import type {MessageType} from './utils/message'; export interface ExtensionData { isEnabled: boolean; @@ -8,6 +9,7 @@ export interface ExtensionData { news: News[]; shortcuts: Shortcuts; colorScheme: ParsedColorSchemeConfig; + forcedScheme: 'dark' | 'light'; devtools: { dynamicFixesText: string; filterFixesText: string; @@ -16,10 +18,11 @@ export interface ExtensionData { hasCustomFilterFixes: boolean; hasCustomStaticFixes: boolean; }; + activeTab: TabInfo; } export interface TabData { - type: string; + type: MessageType; data?: any; } @@ -27,8 +30,9 @@ export interface ExtensionActions { changeSettings(settings: Partial): void; setTheme(theme: Partial): void; setShortcut(command: string, shortcut: string): void; - toggleURL(url: string): void; + toggleActiveTab(): void; markNewsAsRead(ids: string[]): void; + markNewsAsDisplayed(ids: string[]): void; loadConfig(options: {local: boolean}): void; applyDevDynamicThemeFixes(text: string): Promise; resetDevDynamicThemeFixes(): void; @@ -63,6 +67,7 @@ export interface Theme { styleSystemControls: boolean; lightColorScheme: string; darkColorScheme: string; + immediateModify: boolean; } export type FilterConfig = Theme; @@ -92,12 +97,14 @@ export interface UserSettings { syncSettings: boolean; syncSitesFixes: boolean; automation: '' | 'time' | 'system' | 'location'; + automationBehaviour: 'OnOff' | 'Scheme'; time: TimeSettings; location: LocationSettings; previewNewDesign: boolean; enableForPDF: boolean; enableForProtectedPages: boolean; enableContextMenus: boolean; + detectDarkTheme: boolean; } export interface TimeSettings { @@ -115,10 +122,11 @@ export interface TabInfo { isProtected: boolean; isInjected: boolean; isInDarkList: boolean; + isDarkThemeDetected: boolean; } export interface Message { - type: string; + type: MessageType; data?: any; id?: number; error?: any; @@ -134,6 +142,7 @@ export interface DynamicThemeFix { css: string; ignoreInlineStyle: string[]; ignoreImageAnalysis: string[]; + disableStyleSheetsProxy: boolean; } export interface InversionFix { @@ -179,6 +188,8 @@ export interface News { date: string; url: string; headline: string; - important: boolean; read?: boolean; + displayed?: boolean; + badge?: string; + icon?: string; } diff --git a/src/generators/dynamic-theme.ts b/src/generators/dynamic-theme.ts index f188dfbbb7fd..6d259431a0d0 100644 --- a/src/generators/dynamic-theme.ts +++ b/src/generators/dynamic-theme.ts @@ -4,6 +4,7 @@ import type {SitePropsIndex} from './utils/parse'; import {parseArray, formatArray} from '../utils/text'; import {compareURLPatterns, isURLInList} from '../utils/url'; import type {DynamicThemeFix} from '../definitions'; +import {isChromium} from '../utils/platform'; const dynamicThemeFixesCommands: { [key: string]: keyof DynamicThemeFix } = { 'INVERT': 'invert', @@ -71,7 +72,11 @@ export function getDynamicThemeFixesFor(url: string, frameURL: string, text: str ignoreImageAnalysis: genericFix.ignoreImageAnalysis || [], }; if (enabledForPDF) { - common.css += '\nembed[type="application/pdf"] { filter: invert(100%) contrast(90%); }'; + if (isChromium) { + common.css += '\nembed[type="application/pdf"][src="about:blank"] { filter: invert(100%) contrast(90%); }'; + } else { + common.css += '\nembed[type="application/pdf"] { filter: invert(100%) contrast(90%); }'; + } } const sortedBySpecificity = fixes .slice(1) diff --git a/src/generators/modify-colors.ts b/src/generators/modify-colors.ts index f0916a133d2b..a3626afe137a 100644 --- a/src/generators/modify-colors.ts +++ b/src/generators/modify-colors.ts @@ -138,7 +138,7 @@ function modifyBgHSL({h, s, l, a}: HSLA, pole: HSLA) { return {h, s, l: lx, a}; } - const lx = scale(l, 0.5, 1, MAX_BG_LIGHTNESS, pole.l); + let lx = scale(l, 0.5, 1, MAX_BG_LIGHTNESS, pole.l); if (isNeutral) { const hx = pole.h; @@ -157,6 +157,12 @@ function modifyBgHSL({h, s, l, a}: HSLA, pole: HSLA) { } } + // Lower the lightness, if the resulting + // hue is in lower yellow spectrum. + if (hx > 40 && hx < 80) { + lx *= 0.75; + } + return {h: hx, s, l: lx, a}; } diff --git a/src/icons/dr_128.png b/src/icons/dr_128.png index 2dabac59684f..09b3a5276038 100644 Binary files a/src/icons/dr_128.png and b/src/icons/dr_128.png differ diff --git a/src/icons/dr_16.png b/src/icons/dr_16.png index 5bbda00fcfec..ee96c1ec6461 100644 Binary files a/src/icons/dr_16.png and b/src/icons/dr_16.png differ diff --git a/src/icons/dr_48.png b/src/icons/dr_48.png index ec3c88c8073e..74d2b6e57669 100644 Binary files a/src/icons/dr_48.png and b/src/icons/dr_48.png differ diff --git a/src/icons/dr_active_19.png b/src/icons/dr_active_19.png index 974ac716d592..a53fb24130b6 100644 Binary files a/src/icons/dr_active_19.png and b/src/icons/dr_active_19.png differ diff --git a/src/icons/dr_active_38.png b/src/icons/dr_active_38.png index a0f157de83a4..c3c5334281a0 100644 Binary files a/src/icons/dr_active_38.png and b/src/icons/dr_active_38.png differ diff --git a/src/icons/dr_inactive_19.png b/src/icons/dr_inactive_19.png index fa147f09e0aa..cc3062315a6c 100644 Binary files a/src/icons/dr_inactive_19.png and b/src/icons/dr_inactive_19.png differ diff --git a/src/icons/dr_inactive_38.png b/src/icons/dr_inactive_38.png index e29357a42511..985fbcaae27b 100644 Binary files a/src/icons/dr_inactive_38.png and b/src/icons/dr_inactive_38.png differ diff --git a/src/inject/detector.ts b/src/inject/detector.ts new file mode 100644 index 000000000000..e259e05f42e3 --- /dev/null +++ b/src/inject/detector.ts @@ -0,0 +1,72 @@ +import {parse, getSRGBLightness} from '../utils/color'; + +function hasBuiltInDarkTheme() { + const drStyles = document.querySelectorAll('.darkreader') as NodeListOf; + drStyles.forEach((style) => style.disabled = true); + + const rootColor = parse(getComputedStyle(document.documentElement).backgroundColor); + const bodyColor = document.body ? parse(getComputedStyle(document.body).backgroundColor) : {r: 0, g: 0, b: 0, a: 0}; + const rootLightness = (1 - rootColor.a) + rootColor.a * getSRGBLightness(rootColor.r, rootColor.g, rootColor.b); + const finalLightness = (1 - bodyColor.a) * rootLightness + bodyColor.a * getSRGBLightness(bodyColor.r, bodyColor.g, bodyColor.b); + const darkThemeDetected = finalLightness < 0.5; + + drStyles.forEach((style) => style.disabled = false); + return darkThemeDetected; +} + +function runCheck(callback: (hasDarkTheme: boolean) => void) { + const darkThemeDetected = hasBuiltInDarkTheme(); + callback(darkThemeDetected); +} + +function hasSomeStyle() { + if (document.documentElement.style.backgroundColor || (document.body && document.body.style.backgroundColor)) { + return true; + } + for (const style of document.styleSheets) { + if (style && style.ownerNode && !(style.ownerNode as HTMLElement).classList.contains('darkreader')) { + return true; + } + } + return false; +} + +let observer: MutationObserver; +let readyStateListener: () => void; + +export function runDarkThemeDetector(callback: (hasDarkTheme: boolean) => void) { + stopDarkThemeDetector(); + if (document.body && hasSomeStyle()) { + runCheck(callback); + return; + } + + observer = new MutationObserver(() => { + if (document.body && hasSomeStyle()) { + stopDarkThemeDetector(); + runCheck(callback); + } + }); + observer.observe(document.documentElement, {childList: true}); + + if (document.readyState !== 'complete') { + readyStateListener = () => { + if (document.readyState === 'complete') { + stopDarkThemeDetector(); + runCheck(callback); + } + }; + document.addEventListener('readystatechange', readyStateListener); + } +} + +export function stopDarkThemeDetector() { + if (observer) { + observer.disconnect(); + observer = null; + } + if (readyStateListener) { + document.removeEventListener('readystatechange', readyStateListener); + readyStateListener = null; + } +} diff --git a/src/inject/dynamic-theme/css-rules.ts b/src/inject/dynamic-theme/css-rules.ts index 53c127add57a..34e6614cc6ca 100644 --- a/src/inject/dynamic-theme/css-rules.ts +++ b/src/inject/dynamic-theme/css-rules.ts @@ -89,10 +89,12 @@ export function iterateCSSDeclarations(style: CSSStyleDeclaration, iterate: (pro } export const cssURLRegex = /url\((('.+?')|(".+?")|([^\)]*?))\)/g; -export const cssImportRegex = /@import\s*(url\()?(('.+?')|(".+?")|([^\)]*?))\)? ?(screen)?;?/g; +export const cssImportRegex = /@import\s*(url\()?(('.+?')|(".+?")|([^\)]*?))\)? ?(screen)?;?/gi; +// First try to extract the CSS URL value. +// Then do some post fixes, like unescaping backslashes in the URL. (Chromium don't handle this natively). export function getCSSURLValue(cssURL: string) { - return cssURL.replace(/^url\((.*)\)$/, '$1').trim().replace(/^"(.*)"$/, '$1').replace(/^'(.*)'$/, '$1'); + return cssURL.trim().replace(/^url\((.*)\)$/, '$1').trim().replace(/^"(.*)"$/, '$1').replace(/^'(.*)'$/, '$1').replace(/(?:\\(.))/g, '$1'); } export function getCSSBaseBath(url: string) { diff --git a/src/inject/dynamic-theme/image.ts b/src/inject/dynamic-theme/image.ts index 7b6a77dcaba4..032d03dd7d5d 100644 --- a/src/inject/dynamic-theme/image.ts +++ b/src/inject/dynamic-theme/image.ts @@ -1,5 +1,6 @@ import {getSVGFilterMatrixValue} from '../../generators/svg-filter'; import {bgFetch} from './network'; +import {getSRGBLightness} from '../../utils/color'; import {loadAsDataURL} from '../../utils/network'; import type {FilterConfig} from '../../definitions'; import {logInfo, logWarn} from '../../utils/log'; @@ -140,17 +141,15 @@ function analyzeImage(image: HTMLImageElement) { for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { i = 4 * (y * width + x); - r = d[i + 0] / 255; - g = d[i + 1] / 255; - b = d[i + 2] / 255; - a = d[i + 3] / 255; + r = d[i + 0]; + g = d[i + 1]; + b = d[i + 2]; + a = d[i + 3]; - if (a < TRANSPARENT_ALPHA_THRESHOLD) { + if (a / 255 < TRANSPARENT_ALPHA_THRESHOLD) { transparentPixelsCount++; } else { - // Use sRGB to determine the `pixel Lightness` - // https://en.wikipedia.org/wiki/Relative_luminance - l = 0.2126 * r + 0.7152 * g + 0.0722 * b; + l = getSRGBLightness(r, g, b); if (l < DARK_LIGHTNESS_THRESHOLD) { darkPixelsCount++; } diff --git a/src/inject/dynamic-theme/index.ts b/src/inject/dynamic-theme/index.ts index 3aa369dd9859..b79e91b28f5a 100644 --- a/src/inject/dynamic-theme/index.ts +++ b/src/inject/dynamic-theme/index.ts @@ -5,7 +5,7 @@ import type {StyleElement, StyleManager} from './style-manager'; import {manageStyle, getManageableStyles, cleanLoadingLinks} from './style-manager'; import {watchForStyleChanges, stopWatchingForStyleChanges} from './watch'; import {forEach, push, toArray} from '../../utils/array'; -import {removeNode, watchForNodePosition, iterateShadowHosts, isDOMReady, removeDOMReadyListener, cleanReadyStateCompleteListeners, addDOMReadyListener} from '../utils/dom'; +import {removeNode, watchForNodePosition, iterateShadowHosts, isDOMReady, removeDOMReadyListener, cleanReadyStateCompleteListeners, addDOMReadyListener, setIsDOMReady} from '../utils/dom'; import {logInfo, logWarn} from '../../utils/log'; import {throttle} from '../../utils/throttle'; import {clamp} from '../../utils/math'; @@ -16,12 +16,13 @@ import type {FilterConfig, DynamicThemeFix} from '../../definitions'; import {generateUID} from '../../utils/uid'; import type {AdoptedStyleSheetManager} from './adopted-style-manger'; import {createAdoptedStyleSheetOverride} from './adopted-style-manger'; -import {isFirefox} from '../../utils/platform'; +import {isFirefox, isMV3} from '../../utils/platform'; import {injectProxy} from './stylesheet-proxy'; import {parse} from '../../utils/color'; import {parsedURLCache} from '../../utils/url'; import {variablesStore} from './variables'; +declare const __TEST__: boolean; const INSTANCE_ID = generateUID(); const styleManagers = new Map(); const adoptedStyleManagers = [] as AdoptedStyleSheetManager[]; @@ -43,6 +44,9 @@ function createOrUpdateStyle(className: string, root: ParentNode = document.head return element; } +/** + * Note: This function is used only with MV2. + */ function createOrUpdateScript(className: string, root: ParentNode = document.head || document) { let element: HTMLScriptElement = root.querySelector(`.${className}`); if (!element) { @@ -53,6 +57,18 @@ function createOrUpdateScript(className: string, root: ParentNode = document.hea return element; } +/** + * Note: This function is used only with MV3. + * String passed as src parameter must be included in web_accessible_resources manifest key. + */ +function injectProxyScriptMV3(arg: boolean) { + logInfo('MV3 proxy injector: regular path attempts to inject...'); + const element = document.createElement('script'); + element.src = chrome.runtime.getURL('inject/proxy.js'); + element.dataset.arg = JSON.stringify(arg); + document.head.prepend(element); +} + const nodePositionWatchers = new Map>(); function setupNodePositionWatcher(node: Node, alias: string) { @@ -132,10 +148,17 @@ function createStaticStyleOverrides() { const rootVarsStyle = createOrUpdateStyle('darkreader--root-vars'); document.head.insertBefore(rootVarsStyle, variableStyle.nextSibling); - const proxyScript = createOrUpdateScript('darkreader--proxy'); - proxyScript.append(`(${injectProxy})()`); - document.head.insertBefore(proxyScript, rootVarsStyle.nextSibling); - proxyScript.remove(); + const injectProxyArg = !(fixes && fixes.disableStyleSheetsProxy); + if (isMV3) { + injectProxyScriptMV3(injectProxyArg); + // Notify dedicated injector of the data + document.dispatchEvent(new CustomEvent('__darkreader__stylesheetProxy__arg', {detail: injectProxyArg})); + } else { + const proxyScript = createOrUpdateScript('darkreader--proxy'); + proxyScript.append(`(${injectProxy})(${injectProxyArg})`); + document.head.insertBefore(proxyScript, rootVarsStyle.nextSibling); + proxyScript.remove(); + } } const shadowRootsWithOverrides = new Set(); @@ -257,6 +280,9 @@ function createManager(element: StyleElement) { variablesStore.addRulesForMatching(details.rules); variablesStore.matchVariablesAndDependants(); manager.render(filter, ignoredImageAnalysisSelectors); + if (__TEST__) { + document.dispatchEvent(new CustomEvent('__darkreader__test__dynamicUpdateComplete')); + } } const manager = manageStyle(element, {update, loadingStart, loadingEnd}); @@ -321,7 +347,7 @@ function createThemeAndWatchForUpdates() { watchForUpdates(); } - if (document.hidden) { + if (document.hidden && !filter.immediateModify) { watchForDocumentVisibility(runDynamicStyle); } else { runDynamicStyle(); @@ -331,13 +357,21 @@ function createThemeAndWatchForUpdates() { } function handleAdoptedStyleSheets(node: ShadowRoot | Document) { - if (Array.isArray(node.adoptedStyleSheets)) { - if (node.adoptedStyleSheets.length > 0) { - const newManger = createAdoptedStyleSheetOverride(node); + try { + if (Array.isArray(node.adoptedStyleSheets)) { + if (node.adoptedStyleSheets.length > 0) { + const newManger = createAdoptedStyleSheetOverride(node); - adoptedStyleManagers.push(newManger); - newManger.render(filter, ignoredImageAnalysisSelectors); + adoptedStyleManagers.push(newManger); + newManger.render(filter, ignoredImageAnalysisSelectors); + } } + } catch (err) { + // For future readers, Dark Reader typically does not use 'try/catch' in its code but, + // due to a problem in Firefox Nightly, this is an exception. Allowing this exception + // to occur causes no consequence. + // Ref: https://github.com/darkreader/darkreader/issues/8789#issuecomment-1114210080 + logWarn('Error occured in handleAdoptedStyleSheets: ', err); } } @@ -371,7 +405,7 @@ function watchForUpdates() { watchForInlineStyles((element) => { overrideInlineStyle(element, filter, ignoredInlineSelectors, ignoredImageAnalysisSelectors); if (element === document.documentElement) { - const styleAttr = element.getAttribute('style'); + const styleAttr = element.getAttribute('style') || ''; if (styleAttr.includes('--')) { variablesStore.matchVariablesAndDependants(); variablesStore.putRootVars(document.head.querySelector('.darkreader--root-vars'), filter); @@ -397,6 +431,18 @@ function stopWatchingForUpdates() { cleanReadyStateCompleteListeners(); } +let metaObserver: MutationObserver; + +function addMetaListener() { + metaObserver = new MutationObserver(() => { + if (document.querySelector('meta[name="darkreader-lock"]')) { + metaObserver.disconnect(); + removeDynamicTheme(); + } + }); + metaObserver.observe(document.head, {childList: true, subtree: true}); +} + function createDarkReaderInstanceMarker() { const metaElement: HTMLMetaElement = document.createElement('meta'); metaElement.name = 'darkreader'; @@ -405,6 +451,10 @@ function createDarkReaderInstanceMarker() { } function isAnotherDarkReaderInstanceActive() { + if (document.querySelector('meta[name="darkreader-lock"]')) { + return true; + } + const meta: HTMLMetaElement = document.querySelector('meta[name="darkreader"]'); if (meta) { if (meta.content !== INSTANCE_ID) { @@ -413,6 +463,7 @@ function isAnotherDarkReaderInstanceActive() { return false; } createDarkReaderInstanceMarker(); + addMetaListener(); return false; } @@ -426,6 +477,13 @@ export function createOrUpdateDynamicTheme(filterConfig: FilterConfig, dynamicTh ignoredImageAnalysisSelectors = []; ignoredInlineSelectors = []; } + + if (filter.immediateModify) { + setIsDOMReady(() => { + return true; + }); + } + isIFrame = iframe; if (document.head) { if (isAnotherDarkReaderInstanceActive()) { @@ -491,6 +549,8 @@ export function removeDynamicTheme() { manager.destroy(); }); adoptedStyleManagers.splice(0); + + metaObserver && metaObserver.disconnect(); } export function cleanDynamicThemeCache() { diff --git a/src/inject/dynamic-theme/inline-style.ts b/src/inject/dynamic-theme/inline-style.ts index 5a0cb14d086f..e17bbfc7c23f 100644 --- a/src/inject/dynamic-theme/inline-style.ts +++ b/src/inject/dynamic-theme/inline-style.ts @@ -2,6 +2,7 @@ import {forEach, push} from '../../utils/array'; import {iterateShadowHosts, createOptimizedTreeObserver, isReadyStateComplete, addReadyStateCompleteListener} from '../utils/dom'; import {iterateCSSDeclarations} from './css-rules'; import {getModifiableCSSDeclaration} from './modify-css'; +import type {CSSVariableModifier} from './variables'; import {variablesStore} from './variables'; import type {FilterConfig} from '../../definitions'; import {isShadowDomSupported} from '../../utils/platform'; @@ -171,7 +172,7 @@ function deepWatchForInlineStyles( const RETRY_TIMEOUT = getDuration({seconds: 2}); const MAX_ATTEMPTS_COUNT = 50; let cache: MutationRecord[] = []; - let timeoutId: number = null; + let timeoutId: ReturnType = null; const handleAttributeMutations = throttle((mutations: MutationRecord[]) => { mutations.forEach((m) => { @@ -251,7 +252,8 @@ export function overrideInlineStyle(element: HTMLElement, theme: FilterConfig, i const unsetProps = new Set(Object.keys(overrides)); function setCustomProp(targetCSSProp: string, modifierCSSProp: string, cssVal: string) { - const {customProp, dataAttr} = overrides[targetCSSProp]; + const isPropertyVariable = targetCSSProp.startsWith('--'); + const {customProp, dataAttr} = isPropertyVariable ? ({} as Overrides['']) : overrides[targetCSSProp]; const mod = getModifiableCSSDeclaration(modifierCSSProp, cssVal, {} as CSSStyleRule, variablesStore, ignoreImageSelectors, null); if (!mod) { @@ -261,11 +263,25 @@ export function overrideInlineStyle(element: HTMLElement, theme: FilterConfig, i if (typeof value === 'function') { value = value(theme) as string; } - element.style.setProperty(customProp, value); - if (!element.hasAttribute(dataAttr)) { - element.setAttribute(dataAttr, ''); + + // typeof value === 'object' always evaluate to true when + // `isPropertyVariable` is true, but it serves as a type hint for typescript. + // Such that `as ReturnType` won't error about the possible + // string type. + if (isPropertyVariable && typeof value === 'object') { + const typedValue = value as ReturnType; + typedValue.declarations.forEach(({property, value}) => { + !(value instanceof Promise) && element.style.setProperty(property, value); + }); + + // TODO: add listener for `onTypeChange`. + } else { + element.style.setProperty(customProp, value); + if (!element.hasAttribute(dataAttr)) { + element.setAttribute(dataAttr, ''); + } + unsetProps.delete(targetCSSProp); } - unsetProps.delete(targetCSSProp); } if (ignoreInlineSelectors.length > 0) { @@ -336,7 +352,7 @@ export function overrideInlineStyle(element: HTMLElement, theme: FilterConfig, i if (property === 'background-image' && value.includes('url')) { return; } - if (overrides.hasOwnProperty(property)) { + if (overrides.hasOwnProperty(property) || (property.startsWith('--') && !normalizedPropList[property])) { setCustomProp(property, property, value); } else { const overridenProp = normalizedPropList[property]; diff --git a/src/inject/dynamic-theme/modify-css.ts b/src/inject/dynamic-theme/modify-css.ts index b2052c3482e8..f6dba09c9535 100644 --- a/src/inject/dynamic-theme/modify-css.ts +++ b/src/inject/dynamic-theme/modify-css.ts @@ -10,7 +10,9 @@ import {getImageDetails, getFilteredImageDataURL, cleanImageProcessingCache} fro import type {CSSVariableModifier, VariablesStore} from './variables'; import {logWarn, logInfo} from '../../utils/log'; import type {FilterConfig, Theme} from '../../definitions'; -import {isFirefox} from '../../utils/platform'; +import {isFirefox, isCSSColorSchemePropSupported} from '../../utils/platform'; +import type {parsedGradient} from '../../utils/parsing'; +import {parseGradient} from '../../utils/parsing'; export type CSSValueModifier = (theme: Theme) => string | Promise; @@ -81,6 +83,10 @@ export function getModifiableCSSDeclaration( return null; } +function joinSelectors(...selectors: string[]) { + return selectors.filter(Boolean).join(', '); +} + export function getModifiedUserAgentStyle(theme: Theme, isIFrame: boolean, styleSystemControls: boolean) { const lines: string[] = []; if (!isIFrame) { @@ -88,10 +94,18 @@ export function getModifiedUserAgentStyle(theme: Theme, isIFrame: boolean, style lines.push(` background-color: ${modifyBackgroundColor({r: 255, g: 255, b: 255}, theme)} !important;`); lines.push('}'); } - lines.push(`${isIFrame ? '' : 'html, body, '}${styleSystemControls ? 'input, textarea, select, button' : ''} {`); - lines.push(` background-color: ${modifyBackgroundColor({r: 255, g: 255, b: 255}, theme)};`); - lines.push('}'); - lines.push(`html, body, ${styleSystemControls ? 'input, textarea, select, button' : ''} {`); + if (isCSSColorSchemePropSupported) { + lines.push('html {'); + lines.push(` color-scheme: ${theme.mode === 1 ? 'dark' : 'dark light'} !important;`); + lines.push('}'); + } + const bgSelectors = joinSelectors(isIFrame ? '' : 'html, body', styleSystemControls ? 'input, textarea, select, button' : ''); + if (bgSelectors) { + lines.push(`${bgSelectors} {`); + lines.push(` background-color: ${modifyBackgroundColor({r: 255, g: 255, b: 255}, theme)};`); + lines.push('}'); + } + lines.push(`${joinSelectors('html, body', styleSystemControls ? 'input, textarea, select, button' : '')} {`); lines.push(` border-color: ${modifyBorderColor({r: 76, g: 76, b: 76}, theme)};`); lines.push(` color: ${modifyForegroundColor({r: 0, g: 0, b: 0}, theme)};`); lines.push('}'); @@ -206,7 +220,7 @@ function getModifiedScrollbarStyle(theme: Theme) { export function getModifiedFallbackStyle(filter: FilterConfig, {strict}: {strict: boolean}) { const lines: string[] = []; // https://github.com/darkreader/darkreader/issues/3618#issuecomment-895477598 - const isMicrosoft = location.hostname.endsWith('microsoft.com'); + const isMicrosoft = ['microsoft.com', 'docs.microsoft.com'].includes(location.hostname); lines.push(`html, body, ${strict ? `body :not(iframe)${isMicrosoft ? ':not(div[style^="position:absolute;top:0;left:-"]' : ''}` : 'body > :not(iframe)'} {`); lines.push(` background-color: ${modifyBackgroundColor({r: 255, g: 255, b: 255}, filter)} !important;`); lines.push(` border-color: ${modifyBorderColor({r: 64, g: 64, b: 64}, filter)} !important;`); @@ -268,7 +282,6 @@ function getColorModifier(prop: string, value: string): string | CSSValueModifie } } -export const gradientRegex = /[\-a-z]+gradient\(([^\(\)]*(\(([^\(\)]*(\(.*?\)))*[^\(\)]*\))){0,15}[^\(\)]*\)/g; const imageDetailsCache = new Map(); const awaitingForImageLoading = new Map void>>(); @@ -289,6 +302,15 @@ function shouldIgnoreImage(selectorText: string, selectors: string[]) { return false; } +interface bgImageMatches { + type: 'url' | 'gradient'; + index: number; + match: string; + offset: number; + typeGradient?: string; + hasComma?: boolean; +} + export function getBgImageModifier( value: string, rule: CSSStyleRule, @@ -296,7 +318,7 @@ export function getBgImageModifier( isCancelled: () => boolean, ): string | CSSValueModifier { try { - const gradients = getMatches(gradientRegex, value); + const gradients = parseGradient(value); const urls = getMatches(cssURLRegex, value); if (urls.length === 0 && gradients.length === 0) { @@ -312,19 +334,18 @@ export function getBgImageModifier( }); }; - const matches = getIndices(urls).map((i) => ({type: 'url', ...i})) - .concat(getIndices(gradients).map((i) => ({type: 'gradient', ...i}))) - .sort((a, b) => a.index - b.index); + const matches: bgImageMatches[] = + (gradients.map((i) => ({type: 'gradient', ...i})) as bgImageMatches[]) + .concat(getIndices(urls).map((i) => ({type: 'url', offset: 0, ...i}))) + .sort((a, b) => a.index > b.index ? 1 : -1); - const getGradientModifier = (gradient: string) => { - const match = gradient.match(/^(.*-gradient)\((.*)\)$/); - const type = match[1]; - const content = match[2]; + const getGradientModifier = (gradient: parsedGradient) => { + const {typeGradient, match, hasComma} = gradient; const partsRegex = /([^\(\),]+(\([^\(\)]*(\([^\(\)]*\)*[^\(\)]*)?\))?[^\(\),]*),?/g; const colorStopRegex = /^(from|color-stop|to)\(([^\(\)]*?,\s*)?(.*?)\)$/; - const parts = getMatches(partsRegex, content, 1).map((part) => { + const parts = getMatches(partsRegex, match, 1).map((part) => { part = part.trim(); let rgb = tryParseColor(part); @@ -350,7 +371,7 @@ export function getBgImageModifier( }); return (filter: FilterConfig) => { - return `${type}(${parts.map((modify) => modify(filter)).join(', ')})`; + return `${typeGradient}(${parts.map((modify) => modify(filter)).join(', ')})${hasComma ? ', ' : ''}`; }; }; @@ -432,13 +453,22 @@ export function getBgImageModifier( const modifiers: CSSValueModifier[] = []; - let index = 0; - matches.forEach(({match, type, index: matchStart}, i) => { - const prefixStart = index; - const matchEnd = matchStart + match.length; - index = matchEnd; - modifiers.push(() => value.substring(prefixStart, matchStart)); - modifiers.push(type === 'url' ? getURLModifier(match) : getGradientModifier(match)); + let matchIndex = 0; + matches.forEach(({type, match, index, typeGradient, hasComma, offset}, i) => { + const matchStart = index; + const prefixStart = matchIndex; + const matchEnd = matchStart + match.length + offset; + matchIndex = matchEnd; + + // Make sure we still push all the unrelated content between gradients and URL's. + prefixStart !== matchStart && modifiers.push(() => value.substring(prefixStart, matchStart)); + + if (type === 'url') { + modifiers.push(getURLModifier(match)); + } else if (type === 'gradient') { + modifiers.push(getGradientModifier({match, index, typeGradient, hasComma, offset})); + } + if (i === matches.length - 1) { modifiers.push(() => value.substring(matchEnd)); } @@ -447,10 +477,9 @@ export function getBgImageModifier( return (filter: FilterConfig) => { const results = modifiers.filter(Boolean).map((modify) => modify(filter)); if (results.some((r) => r instanceof Promise)) { - return Promise.all(results) - .then((asyncResults) => { - return asyncResults.join(''); - }); + return Promise.all(results).then((asyncResults) => { + return asyncResults.filter(Boolean).join(''); + }); } return results.join(''); }; diff --git a/src/inject/dynamic-theme/mv3-injector.ts b/src/inject/dynamic-theme/mv3-injector.ts new file mode 100644 index 000000000000..b3cb133cab5c --- /dev/null +++ b/src/inject/dynamic-theme/mv3-injector.ts @@ -0,0 +1,26 @@ +/** + * Note: This content script is used only with MV3 to inject stylesheet proxy like so: + * 1. This file (injector) is run in isolated content script context and it injects proxy + * into the real page context. + * 2. The proxy prepares everything for stylesheet-proxy and executes it. + */ + +import {logInfo} from '../../utils/log'; + +logInfo('MV3 proxy injector: dedicated injector started...'); + +/** + * On the first run of event loop, document.head does not exist yet, so we have to wait for the second one. + */ +function injectScript() { + if (document.head) { + logInfo('MV3 proxy injector: dedicated injector attempts to inject...'); + const script = document.createElement('script'); + script.src = chrome.runtime.getURL('inject/proxy.js'); + document.head.prepend(script); + } else { + setTimeout(injectScript); + } +} + +injectScript(); diff --git a/src/inject/dynamic-theme/mv3-proxy.ts b/src/inject/dynamic-theme/mv3-proxy.ts new file mode 100644 index 000000000000..8b3a5c1de242 --- /dev/null +++ b/src/inject/dynamic-theme/mv3-proxy.ts @@ -0,0 +1,58 @@ +import {injectProxy} from './stylesheet-proxy'; +import {logInfo} from '../../utils/log'; + +document.currentScript.remove(); + +const key = 'darkreaderProxyInjected'; +const EVENT_DONE = '__darkreader__stylesheetProxy__done'; +const EVENT_ARG = '__darkreader__stylesheetProxy__arg'; + +function injectProxyAndCleanup(arg: boolean) { + injectProxy(arg); + doneReceiver(); + document.dispatchEvent(new CustomEvent(EVENT_DONE)); +} + +function regularPath() { + const argString = document.currentScript.dataset.arg; + if (argString !== undefined) { + document.documentElement.dataset[key] = 'true'; + const arg: boolean = JSON.parse(argString); + logInfo(`MV3 proxy injector: regular path runs injectProxy(${arg}).`); + injectProxyAndCleanup(arg); + } +} + +function dataReceiver(e: any) { + document.removeEventListener(EVENT_ARG, dataReceiver); + if (document.documentElement.dataset[key] !== undefined) { + logInfo(`MV3 proxy injector: dedicated path exits because everything is done.`); + return; + } + document.documentElement.dataset[key] = 'true'; + logInfo(`MV3 proxy injector: dedicated path runs injectProxy(${e.detail}).`); + injectProxyAndCleanup(e.detail); +} + +function doneReceiver() { + document.removeEventListener(EVENT_ARG, dataReceiver); + document.removeEventListener(EVENT_DONE, doneReceiver); +} + +function dedicatedPath() { + logInfo('MV3 proxy injector: dedicated path setup...'); + document.addEventListener(EVENT_ARG, dataReceiver); + document.addEventListener(EVENT_DONE, doneReceiver); +} + +function inject() { + if (document.documentElement.dataset[key] !== undefined) { + logInfo('MV3 proxy injector: proxy exits because everything is done.'); + return; + } + logInfo('MV3 proxy injector: proxy attempts to inject...'); + regularPath(); + dedicatedPath(); +} + +inject(); diff --git a/src/inject/dynamic-theme/style-manager.ts b/src/inject/dynamic-theme/style-manager.ts index 32c5f8129a0e..9e367fe6b6f4 100644 --- a/src/inject/dynamic-theme/style-manager.ts +++ b/src/inject/dynamic-theme/style-manager.ts @@ -7,7 +7,7 @@ import {logInfo, logWarn} from '../../utils/log'; import {replaceCSSRelativeURLsWithAbsolute, removeCSSComments, replaceCSSFontFace, getCSSURLValue, cssImportRegex, getCSSBaseBath} from './css-rules'; import {bgFetch} from './network'; import {createStyleSheetModifier} from './stylesheet-modifier'; -import {isShadowDomSupported, isSafari, isThunderbird, isChromium, isFirefox} from '../../utils/platform'; +import {isShadowDomSupported, isSafari, isThunderbird, isFirefox} from '../../utils/platform'; declare global { interface Document { @@ -35,6 +35,22 @@ export interface StyleManager { export const STYLE_SELECTOR = 'style, link[rel*="stylesheet" i]:not([disabled])'; +// isFontsGoogleApiStyle returns is the given link element is a style from +// google fonts. +function isFontsGoogleApiStyle(element: HTMLLinkElement): boolean { + if (!element.href) { + return false; + } + + try { + const elementURL = new URL(element.href); + return elementURL.hostname === 'fonts.googleapis.com'; + } catch (err) { + logInfo(`Couldn't construct ${element.href} as URL`); + return false; + } +} + export function shouldManageStyle(element: Node) { return ( ( @@ -44,8 +60,10 @@ export function shouldManageStyle(element: Node) { element instanceof HTMLLinkElement && element.rel && element.rel.toLowerCase().includes('stylesheet') && + element.href && !element.disabled && - (isFirefox ? !element.href.startsWith('moz-extension://') : true) + (isFirefox ? !element.href.startsWith('moz-extension://') : true) && + !isFontsGoogleApiStyle(element) ) ) && !element.classList.contains('darkreader') && @@ -187,7 +205,7 @@ export function manageStyle(element: StyleElement, {update, loadingStart, loadin syncStyle.classList.add('darkreader'); syncStyle.classList.add('darkreader--sync'); syncStyle.media = 'screen'; - if (!isChromium && element.title) { + if (element.title) { syncStyle.title = element.title; } syncStyleSet.add(syncStyle); @@ -314,18 +332,6 @@ export function manageStyle(element: StyleElement, {update, loadingStart, loadin cancelAsyncOperations = false; function removeCSSRulesFromSheet(sheet: CSSStyleSheet) { - // Check if we can use a fastpath by using sheet.replaceSync. - // Because replaceSync can throw DOMExceptions we have to use try-catch. - try { - if (sheet.replaceSync) { - sheet.replaceSync(''); - return; - } - } catch (err) { - logWarn('Could not use fastpath for removing rules from stylesheet', err); - } - // If we hit this point, the replaceSync didn't work - // and we have to iterate over the CSSRules. for (let i = sheet.cssRules.length - 1; i >= 0; i--) { sheet.deleteRule(i); } diff --git a/src/inject/dynamic-theme/stylesheet-modifier.ts b/src/inject/dynamic-theme/stylesheet-modifier.ts index 687d6ef39eed..e5cdf17948fc 100644 --- a/src/inject/dynamic-theme/stylesheet-modifier.ts +++ b/src/inject/dynamic-theme/stylesheet-modifier.ts @@ -19,26 +19,30 @@ const themeCacheKeys: Array = [ ]; function getThemeKey(theme: Theme) { - return themeCacheKeys.map((p) => `${p}:${theme[p]}`).join(';'); + let resultKey = ''; + themeCacheKeys.forEach((key) => { + resultKey += `${key}:${theme[key]};`; + }); + return resultKey; } const asyncQueue = createAsyncTasksQueue(); +interface ModifySheetOptions { + sourceCSSRules: CSSRuleList; + theme: Theme; + ignoreImageAnalysis: string[]; + force: boolean; + prepareSheet: () => CSSStyleSheet; + isAsyncCancelled: () => boolean; +} + export function createStyleSheetModifier() { let renderId = 0; const rulesTextCache = new Set(); const rulesModCache = new Map(); const varTypeChangeCleaners = new Set<() => void>(); let prevFilterKey: string = null; - interface ModifySheetOptions { - sourceCSSRules: CSSRuleList; - theme: Theme; - ignoreImageAnalysis: string[]; - force: boolean; - prepareSheet: () => CSSStyleSheet; - isAsyncCancelled: () => boolean; - } - let hasNonLoadedLink = false; let wasRebuilt = false; function shouldRebuildStyle() { @@ -65,7 +69,7 @@ export function createStyleSheetModifier() { notFoundCacheKeys.delete(cssText); if (rule.parentRule instanceof CSSMediaRule) { - cssText += `;${ (rule.parentRule as CSSMediaRule).media.mediaText}`; + cssText += `;${(rule.parentRule as CSSMediaRule).media.mediaText}`; } if (!rulesTextCache.has(cssText)) { rulesTextCache.add(cssText); diff --git a/src/inject/dynamic-theme/stylesheet-proxy.ts b/src/inject/dynamic-theme/stylesheet-proxy.ts index 922dee6def88..6cdccac59107 100644 --- a/src/inject/dynamic-theme/stylesheet-proxy.ts +++ b/src/inject/dynamic-theme/stylesheet-proxy.ts @@ -1,4 +1,4 @@ -export function injectProxy() { +export function injectProxy(enableStyleSheetsProxy: boolean) { document.dispatchEvent(new CustomEvent('__darkreader__inlineScriptsAllowed')); const addRuleDescriptor = Object.getOwnPropertyDescriptor(CSSStyleSheet.prototype, 'addRule'); @@ -6,11 +6,22 @@ export function injectProxy() { const deleteRuleDescriptor = Object.getOwnPropertyDescriptor(CSSStyleSheet.prototype, 'deleteRule'); const removeRuleDescriptor = Object.getOwnPropertyDescriptor(CSSStyleSheet.prototype, 'removeRule'); - const documentStyleSheetsDescriptor = Object.getOwnPropertyDescriptor(Document.prototype, 'styleSheets'); + const documentStyleSheetsDescriptor = enableStyleSheetsProxy ? + Object.getOwnPropertyDescriptor(Document.prototype, 'styleSheets') : null; // Reference: // https://github.com/darkreader/darkreader/issues/6480#issuecomment-897696175 - const shouldWrapHTMLElement = location.hostname.endsWith('baidu.com'); + const shouldWrapHTMLElement = [ + 'baidu.com', + 'baike.baidu.com', + 'ditu.baidu.com', + 'map.baidu.com', + 'maps.baidu.com', + 'haokan.baidu.com', + 'pan.baidu.com', + 'passport.baidu.com', + 'tieba.baidu.com', + 'www.baidu.com'].includes(location.hostname); const getElementsByTagNameDescriptor = shouldWrapHTMLElement ? Object.getOwnPropertyDescriptor(Element.prototype, 'getElementsByTagName') : null; @@ -22,7 +33,9 @@ export function injectProxy() { Object.defineProperty(CSSStyleSheet.prototype, 'removeRule', removeRuleDescriptor); document.removeEventListener('__darkreader__cleanUp', cleanUp); document.removeEventListener('__darkreader__addUndefinedResolver', addUndefinedResolver); - Object.defineProperty(Document.prototype, 'styleSheets', documentStyleSheetsDescriptor); + if (enableStyleSheetsProxy) { + Object.defineProperty(Document.prototype, 'styleSheets', documentStyleSheetsDescriptor); + } if (shouldWrapHTMLElement) { Object.defineProperty(Element.prototype, 'getElementsByTagName', getElementsByTagNameDescriptor); } @@ -71,11 +84,32 @@ export function injectProxy() { } function proxyDocumentStyleSheets() { - const docSheets = documentStyleSheetsDescriptor.get.call(this); - const filtered = [...docSheets].filter((styleSheet: CSSStyleSheet) => { - return !(styleSheet.ownerNode as HTMLElement).classList.contains('darkreader'); - }); - return Object.setPrototypeOf(filtered, StyleSheetList.prototype); + const getCurrentValue = () => { + const docSheets = documentStyleSheetsDescriptor.get.call(this); + + const filteredSheets = [...docSheets].filter((styleSheet: CSSStyleSheet) => { + return !(styleSheet.ownerNode as HTMLElement).classList.contains('darkreader'); + }); + + (filteredSheets as any).item = (item: number) => { + return filteredSheets[item]; + }; + + return Object.setPrototypeOf(filteredSheets, StyleSheetList.prototype); + }; + + let elements = getCurrentValue(); + + // Because StyleSheetList are so called "live objects". + // Every time you access them, it will return all stylesheets from + // current situation of the DOM. Instead of a static list. + const styleSheetListBehavior: ProxyHandler = { + get: function (_: StyleSheetList, property: string) { + return getCurrentValue()[property]; + } + }; + elements = new Proxy(elements, styleSheetListBehavior); + return elements; } function proxyGetElementsByTagName(tagName: string): NodeListOf { @@ -96,12 +130,12 @@ export function injectProxy() { // Because NodeListOf and HTMLCollection are so called "live objects". // Every time you access them, it will return all tagnames from // current situation of the DOM. Instead of a static list. - const NodeListBehavior: ProxyHandler> = { + const nodeListBehavior: ProxyHandler> = { get: function (_: NodeListOf, property: string) { - return getCurrentElementValue()[Number(property)]; + return getCurrentElementValue()[Number(property) || property]; } }; - elements = new Proxy(elements, NodeListBehavior); + elements = new Proxy(elements, nodeListBehavior); return elements; } @@ -109,7 +143,9 @@ export function injectProxy() { Object.defineProperty(CSSStyleSheet.prototype, 'insertRule', Object.assign({}, insertRuleDescriptor, {value: proxyInsertRule})); Object.defineProperty(CSSStyleSheet.prototype, 'deleteRule', Object.assign({}, deleteRuleDescriptor, {value: proxyDeleteRule})); Object.defineProperty(CSSStyleSheet.prototype, 'removeRule', Object.assign({}, removeRuleDescriptor, {value: proxyRemoveRule})); - Object.defineProperty(Document.prototype, 'styleSheets', Object.assign({}, documentStyleSheetsDescriptor, {get: proxyDocumentStyleSheets})); + if (enableStyleSheetsProxy) { + Object.defineProperty(Document.prototype, 'styleSheets', Object.assign({}, documentStyleSheetsDescriptor, {get: proxyDocumentStyleSheets})); + } if (shouldWrapHTMLElement) { Object.defineProperty(Element.prototype, 'getElementsByTagName', Object.assign({}, getElementsByTagNameDescriptor, {value: proxyGetElementsByTagName})); } diff --git a/src/inject/dynamic-theme/variables.ts b/src/inject/dynamic-theme/variables.ts index 3553f7ee4c8e..d16450e28311 100644 --- a/src/inject/dynamic-theme/variables.ts +++ b/src/inject/dynamic-theme/variables.ts @@ -644,7 +644,7 @@ function parseRawValue(color: string) { splitted.forEach((number) => { resultInRGB += `${number.trim()}, `; }); - resultInRGB = resultInRGB.substr(0, resultInRGB.length - 2); + resultInRGB = resultInRGB.substring(0, resultInRGB.length - 2); resultInRGB += ')'; return {isRaw: true, color: resultInRGB}; } diff --git a/src/inject/dynamic-theme/watch.ts b/src/inject/dynamic-theme/watch.ts index a577c68cf8ef..d038ceed2a8d 100644 --- a/src/inject/dynamic-theme/watch.ts +++ b/src/inject/dynamic-theme/watch.ts @@ -219,7 +219,7 @@ export function watchForStyleChanges(currentStyles: StyleElement[], update: (sty onHugeMutations: handleHugeTreeMutations, }); const attrObserver = new MutationObserver(handleAttributeMutations); - attrObserver.observe(root, {attributes: true, attributeFilter: ['rel', 'disabled', 'media'], subtree: true}); + attrObserver.observe(root, {attributes: true, attributeFilter: ['rel', 'disabled', 'media', 'href'], subtree: true}); observers.push(treeObserver, attrObserver); observedRoots.add(root); } diff --git a/src/inject/index.ts b/src/inject/index.ts index 69b0954d5fba..25afc7c21f97 100644 --- a/src/inject/index.ts +++ b/src/inject/index.ts @@ -1,17 +1,18 @@ import {createOrUpdateStyle, removeStyle} from './style'; import {createOrUpdateSVGFilter, removeSVGFilter} from './svg-filter'; +import {runDarkThemeDetector, stopDarkThemeDetector} from './detector'; import {createOrUpdateDynamicTheme, removeDynamicTheme, cleanDynamicThemeCache} from './dynamic-theme'; -import {logInfo, logWarn} from '../utils/log'; -import {watchForColorSchemeChange} from './utils/watch-color-scheme'; +import {logInfo, logWarn, logInfoCollapsed} from '../utils/log'; +import {isSystemDarkScheme, runColorSchemeChangeDetector, stopColorSchemeChangeDetector} from './utils/watch-color-scheme'; import {collectCSS} from './dynamic-theme/css-collection'; import type {Message} from '../definitions'; import {MessageType} from '../utils/message'; -import {isThunderbird} from '../utils/platform'; +import {isMV3, isThunderbird} from '../utils/platform'; let unloaded = false; // TODO: Use background page color scheme watcher when browser bugs fixed. -let colorSchemeWatcher = watchForColorSchemeChange(({isDark}) => { +runColorSchemeChangeDetector((isDark) => { logInfo('Media query was changed'); sendMessage({type: MessageType.CS_COLOR_SCHEME_CHANGE, data: {isDark}}); }); @@ -22,80 +23,107 @@ function cleanup() { removeEventListener('freeze', onFreeze); removeEventListener('resume', onResume); cleanDynamicThemeCache(); - if (colorSchemeWatcher) { - colorSchemeWatcher.disconnect(); - colorSchemeWatcher = null; - } + stopDarkThemeDetector(); + stopColorSchemeChangeDetector(); } function sendMessage(message: Message) { if (unloaded) { return; } - try { - chrome.runtime.sendMessage(message, (response) => { - // Vivaldi bug workaround. See TabManager for details. - if (response === 'unsupportedSender') { - removeStyle(); - removeSVGFilter(); - removeDynamicTheme(); - cleanup(); - } - }); - } catch (e) { + const responseHandler = (response: 'unsupportedSender' | undefined) => { + // Vivaldi bug workaround. See TabManager for details. + if (response === 'unsupportedSender') { + removeStyle(); + removeSVGFilter(); + removeDynamicTheme(); + cleanup(); + } + }; + + if (isMV3) { /* * Background can be unreachable if: * - extension was disabled * - extension was uninstalled * - extension was updated and this is the old instance of content script */ - cleanup(); + const promise: Promise = chrome.runtime.sendMessage(message) as any; + promise.then(responseHandler).catch(cleanup); + } else { + chrome.runtime.sendMessage(message, responseHandler); } } function onMessage({type, data}: Message) { - logInfo('onMessage', type, data); + logInfoCollapsed(`onMessage[${type}]`, data); switch (type) { case MessageType.BG_ADD_CSS_FILTER: case MessageType.BG_ADD_STATIC_THEME: { - const css = data; + const {css, detectDarkTheme} = data; removeDynamicTheme(); createOrUpdateStyle(css, type === MessageType.BG_ADD_STATIC_THEME ? 'static' : 'filter'); + if (detectDarkTheme) { + runDarkThemeDetector((hasDarkTheme) => { + if (hasDarkTheme) { + removeStyle(); + onDarkThemeDetected(); + } + }); + } break; } case MessageType.BG_ADD_SVG_FILTER: { - const {css, svgMatrix, svgReverseMatrix} = data; + const {css, svgMatrix, svgReverseMatrix, detectDarkTheme} = data; removeDynamicTheme(); createOrUpdateSVGFilter(svgMatrix, svgReverseMatrix); createOrUpdateStyle(css, 'filter'); + if (detectDarkTheme) { + runDarkThemeDetector((hasDarkTheme) => { + if (hasDarkTheme) { + removeStyle(); + removeSVGFilter(); + onDarkThemeDetected(); + } + }); + } break; } case MessageType.BG_ADD_DYNAMIC_THEME: { - const {filter, fixes, isIFrame} = data; + const {theme, fixes, isIFrame, detectDarkTheme} = data; removeStyle(); - createOrUpdateDynamicTheme(filter, fixes, isIFrame); + createOrUpdateDynamicTheme(theme, fixes, isIFrame); + if (detectDarkTheme) { + runDarkThemeDetector((hasDarkTheme) => { + if (hasDarkTheme) { + removeDynamicTheme(); + onDarkThemeDetected(); + } + }); + } break; } - case MessageType.BG_EXPORT_CSS: { + case MessageType.BG_EXPORT_CSS: collectCSS().then((collectedCSS) => sendMessage({type: MessageType.CS_EXPORT_CSS_RESPONSE, data: collectedCSS})); break; - } case MessageType.BG_UNSUPPORTED_SENDER: - case MessageType.BG_CLEAN_UP: { + case MessageType.BG_CLEAN_UP: removeStyle(); removeSVGFilter(); removeDynamicTheme(); + stopDarkThemeDetector(); break; - } case MessageType.BG_RELOAD: logWarn('Cleaning up before update'); cleanup(); break; + default: + break; } } chrome.runtime.onMessage.addListener(onMessage); -sendMessage({type: MessageType.CS_FRAME_CONNECT}); +sendMessage({type: MessageType.CS_FRAME_CONNECT, data: {isDark: isSystemDarkScheme()}}); function onPageHide(e: PageTransitionEvent) { if (e.persisted === false) { @@ -108,7 +136,11 @@ function onFreeze() { } function onResume() { - sendMessage({type: MessageType.CS_FRAME_RESUME}); + sendMessage({type: MessageType.CS_FRAME_RESUME, data: {isDark: isSystemDarkScheme()}}); +} + +function onDarkThemeDetected() { + sendMessage({type: MessageType.CS_DARK_THEME_DETECTED}); } // Thunderbird don't has "tabs", and emails aren't 'frozen' or 'cached'. diff --git a/src/inject/style.ts b/src/inject/style.ts index 63520a539fe0..4b783bc41364 100644 --- a/src/inject/style.ts +++ b/src/inject/style.ts @@ -7,6 +7,7 @@ export function createOrUpdateStyle(css: string, type: string) { document.documentElement.setAttribute('data-darkreader-mode', type); const style = document.createElement('style'); style.id = 'dark-reader-style'; + style.classList.add('darkreader'); style.type = 'text/css'; style.textContent = css; target.appendChild(style); diff --git a/src/inject/utils/dom.ts b/src/inject/utils/dom.ts index 7ab967b57255..b5177d31c9a4 100644 --- a/src/inject/utils/dom.ts +++ b/src/inject/utils/dom.ts @@ -84,7 +84,7 @@ export function watchForNodePosition( } let attempts = 0; let start: number = null; - let timeoutId: number = null; + let timeoutId: ReturnType = null; const restore = throttle(() => { if (timeoutId) { return; @@ -183,19 +183,27 @@ export function iterateShadowHosts(root: Node, iterator: (host: Element) => void node != null; node = walker.nextNode() as Element ) { + if (node.classList.contains('surfingkeys_hints_host')) { + continue; + } + iterator(node); iterateShadowHosts(node.shadowRoot, iterator); } } -export function isDOMReady() { +export let isDOMReady = () => { return document.readyState === 'complete' || document.readyState === 'interactive'; +}; + +export function setIsDOMReady(newFunc: () => boolean) { + isDOMReady = newFunc; } const readyStateListeners = new Set<() => void>(); export function addDOMReadyListener(listener: () => void) { - readyStateListeners.add(listener); + isDOMReady() ? listener() : readyStateListeners.add(listener); } export function removeDOMReadyListener(listener: () => void) { @@ -211,7 +219,7 @@ export function isReadyStateComplete() { const readyStateCompleteListeners = new Set<() => void>(); export function addReadyStateCompleteListener(listener: () => void) { - readyStateCompleteListeners.add(listener); + isReadyStateComplete() ? listener() : readyStateCompleteListeners.add(listener); } export function cleanReadyStateCompleteListeners() { diff --git a/src/inject/utils/watch-color-scheme.ts b/src/inject/utils/watch-color-scheme.ts index 030a8f13d9d5..9e3910d34e24 100644 --- a/src/inject/utils/watch-color-scheme.ts +++ b/src/inject/utils/watch-color-scheme.ts @@ -1,20 +1,29 @@ import {isMatchMediaChangeEventListenerSupported} from '../../utils/platform'; -export function watchForColorSchemeChange(callback: ({isDark}: {isDark: boolean}) => void) { - const query = matchMedia('(prefers-color-scheme: dark)'); - const onChange = () => callback({isDark: query.matches}); +let query: MediaQueryList = null; +let onChange: () => void = null; + +export function runColorSchemeChangeDetector(callback: (isDark: boolean) => void) { + query = matchMedia('(prefers-color-scheme: dark)'); + onChange = () => callback(query.matches); if (isMatchMediaChangeEventListenerSupported) { query.addEventListener('change', onChange); } else { query.addListener(onChange); } - return { - disconnect() { - if (isMatchMediaChangeEventListenerSupported) { - query.removeEventListener('change', onChange); - } else { - query.removeListener(onChange); - } - }, - }; } + +export function stopColorSchemeChangeDetector() { + if (!query || !onChange) { + return; + } + if (isMatchMediaChangeEventListenerSupported) { + query.removeEventListener('change', onChange); + } else { + query.removeListener(onChange); + } + query = null; + onChange = null; +} + +export const isSystemDarkScheme = () => (query || matchMedia('(prefers-color-scheme: dark)')).matches; diff --git a/src/manifest-mv3.json b/src/manifest-mv3.json index 4f812c3e0d81..c316ad762b6a 100644 --- a/src/manifest-mv3.json +++ b/src/manifest-mv3.json @@ -11,6 +11,21 @@ "background": { "service_worker": "background.js" }, + "content_scripts": [ + { + "matches": [ + "" + ], + "js": [ + "inject/injector.js", + "inject/fallback.js", + "inject/index.js" + ], + "run_at": "document_start", + "all_frames": true, + "match_about_blank": true + } + ], "permissions": [ "alarms", "fontSettings", @@ -21,5 +36,11 @@ ], "host_permissions": [ "*://*/*" + ], + "web_accessible_resources": [ + { + "matches": ["*://*/*"], + "resources": ["inject/proxy.js"] + } ] } diff --git a/src/manifest.json b/src/manifest.json index ac49cedabf56..134d5e361f5a 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 2, "name": "Dark Reader", - "version": "4.9.42", + "version": "4.9.52", "author": "Alexander Shutau", "description": "__MSG_extension_description__", "default_locale": "en", diff --git a/src/tsconfig.json b/src/tsconfig.json index 7056a9d6c9a9..4d3119ec2c16 100644 --- a/src/tsconfig.json +++ b/src/tsconfig.json @@ -1,15 +1,14 @@ { "compilerOptions": { - "noImplicitAny": true, - "target": "es2019", - "baseUrl": ".", - "module": "es2015", + "target": "ES2019", + "baseUrl": "./", + "module": "ES2015", "moduleResolution": "node", "lib": [ - "es2015", - "es2017", - "dom", - "dom.iterable" + "ES2015", + "ES2017", + "Dom", + "DOM.Iterable" ], "types": [ "chrome", @@ -17,11 +16,10 @@ ], "allowJs": true, "downlevelIteration": true, - "noEmit": true, + "noImplicitAny": true, + "resolveJsonModule": true, "jsx": "react", - "jsxFactory": "m" - }, - "exclude": [ - "node_modules" - ] + "jsxFactory": "m", + "noEmit": true + } } diff --git a/src/ui/assets/images/darkreader-icon-256x256.png b/src/ui/assets/images/darkreader-icon-256x256.png index 0863217d1377..e6c1d71a2ec4 100644 Binary files a/src/ui/assets/images/darkreader-icon-256x256.png and b/src/ui/assets/images/darkreader-icon-256x256.png differ diff --git a/src/ui/assets/images/mode-dark-32.svg b/src/ui/assets/images/mode-dark-32.svg index 1708e276bacc..29be670234ee 100644 --- a/src/ui/assets/images/mode-dark-32.svg +++ b/src/ui/assets/images/mode-dark-32.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/src/ui/assets/images/mode-light-32.svg b/src/ui/assets/images/mode-light-32.svg index 125a6405c935..6374304aa4e1 100644 --- a/src/ui/assets/images/mode-light-32.svg +++ b/src/ui/assets/images/mode-light-32.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/src/ui/connect/connector.ts b/src/ui/connect/connector.ts index 2c6237a38ff9..29a861be7ced 100644 --- a/src/ui/connect/connector.ts +++ b/src/ui/connect/connector.ts @@ -1,5 +1,5 @@ import {isFirefox} from '../../utils/platform'; -import type {ExtensionData, ExtensionActions, FilterConfig, TabInfo, Message, UserSettings} from '../../definitions'; +import type {ExtensionData, ExtensionActions, FilterConfig, Message, UserSettings} from '../../definitions'; import {MessageType} from '../../utils/message'; export default class Connector implements ExtensionActions { @@ -9,7 +9,7 @@ export default class Connector implements ExtensionActions { this.changeSubscribers = new Set(); } - private async sendRequest(type: string, data?: string) { + private async sendRequest(type: MessageType, data?: string) { return new Promise((resolve, reject) => { chrome.runtime.sendMessage({type, data}, ({data, error}: Message) => { if (error) { @@ -21,7 +21,7 @@ export default class Connector implements ExtensionActions { }); } - private async firefoxSendRequestWithResponse(type: string, data?: string) { + private async firefoxSendRequestWithResponse(type: MessageType, data?: string) { return new Promise((resolve, reject) => { const dataPort = chrome.runtime.connect({name: type}); dataPort.onDisconnect.addListener(() => reject()); @@ -44,13 +44,6 @@ export default class Connector implements ExtensionActions { return await this.sendRequest(MessageType.UI_GET_DATA); } - async getActiveTabInfo() { - if (isFirefox) { - return await this.firefoxSendRequestWithResponse(MessageType.UI_GET_ACTIVE_TAB_INFO); - } - return await this.sendRequest(MessageType.UI_GET_ACTIVE_TAB_INFO); - } - private onChangesReceived = ({type, data}: Message) => { if (type === MessageType.BG_CHANGES) { this.changeSubscribers.forEach((callback) => callback(data)); @@ -77,14 +70,18 @@ export default class Connector implements ExtensionActions { chrome.runtime.sendMessage({type: MessageType.UI_SET_THEME, data: theme}); } - toggleURL(url: string) { - chrome.runtime.sendMessage({type: MessageType.UI_TOGGLE_URL, data: url}); + toggleActiveTab() { + chrome.runtime.sendMessage({type: MessageType.UI_TOGGLE_ACTIVE_TAB, data: {}}); } markNewsAsRead(ids: string[]) { chrome.runtime.sendMessage({type: MessageType.UI_MARK_NEWS_AS_READ, data: ids}); } + markNewsAsDisplayed(ids: string[]) { + chrome.runtime.sendMessage({type: MessageType.UI_MARK_NEWS_AS_DISPLAYED, data: ids}); + } + loadConfig(options: {local: boolean}) { chrome.runtime.sendMessage({type: MessageType.UI_LOAD_CONFIG, data: options}); } diff --git a/src/ui/connect/mock.ts b/src/ui/connect/mock.ts index 362a80034ad6..8d6d4bef269e 100644 --- a/src/ui/connect/mock.ts +++ b/src/ui/connect/mock.ts @@ -1,4 +1,4 @@ -import type {ExtensionData, TabInfo, Theme, UserSettings} from '../../definitions'; +import type {ExtensionData, Theme, UserSettings} from '../../definitions'; export function getMockData(override = {} as Partial): ExtensionData { return Object.assign({ @@ -31,6 +31,8 @@ export function getMockData(override = {} as Partial): ExtensionD enableForProtectedPages: false, syncSettings: true, automation: '', + automationBehaviour: 'OnOff', + previewNewDesign: false, time: { activation: '18:00', deactivation: '9:00', @@ -39,6 +41,7 @@ export function getMockData(override = {} as Partial): ExtensionD latitude: 52.4237178, longitude: 31.021786, }, + detectDarkTheme: false, } as UserSettings, fonts: [ 'serif', @@ -74,15 +77,14 @@ export function getMockData(override = {} as Partial): ExtensionD textColor: '#000000', }, }, - } + }, + forcedScheme: null, + activeTab: { + url: 'https://darkreader.org/', + isProtected: false, + isInDarkList: false, + isInjected: true, + isDarkThemeDetected: false, + }, } as ExtensionData, override); } - -export function getMockActiveTabInfo(): TabInfo { - return { - url: 'https://darkreader.org/', - isProtected: false, - isInDarkList: false, - isInjected: true, - }; -} diff --git a/src/ui/devtools/components/body.tsx b/src/ui/devtools/components/body.tsx index e6c0664911d1..c36a4528fcbe 100644 --- a/src/ui/devtools/components/body.tsx +++ b/src/ui/devtools/components/body.tsx @@ -4,18 +4,18 @@ import {withState, useState} from 'malevic/state'; import {Button, MessageBox, Overlay} from '../../controls'; import ThemeEngines from '../../../generators/theme-engines'; import {DEVTOOLS_DOCS_URL} from '../../../utils/links'; -import type {ExtWrapper, TabInfo} from '../../../definitions'; +import type {ExtWrapper} from '../../../definitions'; import {getCurrentThemePreset} from '../../popup/theme/utils'; import {isFirefox} from '../../../utils/platform'; -type BodyProps = ExtWrapper & {tab: TabInfo}; +type BodyProps = ExtWrapper; -function Body({data, tab, actions}: BodyProps) { +function Body({data, actions}: BodyProps) { const context = getContext(); const {state, setState} = useState({errorText: null as string}); let textNode: HTMLTextAreaElement; const previewButtonText = data.settings.previewNewDesign ? 'Switch to old design' : 'Preview new design'; - const {theme} = getCurrentThemePreset({data, tab, actions}); + const {theme} = getCurrentThemePreset({data, actions}); const wrapper = (theme.engine === ThemeEngines.staticTheme ? { diff --git a/src/ui/devtools/index.html b/src/ui/devtools/index.html index 372750087bb4..b825c5655e16 100644 --- a/src/ui/devtools/index.html +++ b/src/ui/devtools/index.html @@ -11,6 +11,6 @@ -$BODY + diff --git a/src/ui/devtools/index.tsx b/src/ui/devtools/index.tsx index 5c548d840088..43dd62ac257e 100644 --- a/src/ui/devtools/index.tsx +++ b/src/ui/devtools/index.tsx @@ -2,10 +2,10 @@ import {m} from 'malevic'; import {sync} from 'malevic/dom'; import Body from './components/body'; import Connector from '../connect/connector'; -import type {ExtensionData, TabInfo} from '../../definitions'; +import type {ExtensionData} from '../../definitions'; -function renderBody(data: ExtensionData, tab: TabInfo, actions: Connector) { - sync(document.body, ); +function renderBody(data: ExtensionData, actions: Connector) { + sync(document.body, ); } async function start() { @@ -13,9 +13,8 @@ async function start() { window.addEventListener('unload', () => connector.disconnect()); const data = await connector.getData(); - const tabInfo = await connector.getActiveTabInfo(); - renderBody(data, tabInfo, connector); - connector.subscribeToChanges((data) => renderBody(data, tabInfo, connector)); + renderBody(data, connector); + connector.subscribeToChanges((data) => renderBody(data, connector)); } start(); diff --git a/src/ui/popup/automation-page/index.tsx b/src/ui/popup/automation-page/index.tsx index 3ea37a03546e..ab192ef61f13 100644 --- a/src/ui/popup/automation-page/index.tsx +++ b/src/ui/popup/automation-page/index.tsx @@ -2,6 +2,7 @@ import {m} from 'malevic'; import {getLocalMessage} from '../../../utils/locales'; import {CheckBox, TimeRangePicker, TextBox, Button} from '../../controls'; import type {ViewProps} from '../types'; +import DropDown from '../../controls/dropdown/index'; export default function AutomationPage(props: ViewProps) { const isSystemAutomation = props.data.settings.automation === 'system'; @@ -70,7 +71,7 @@ export default function AutomationPage(props: ViewProps) {
props.actions.changeSettings({automation: e.target.checked ? 'time' : ''})} + onchange={(e: {target: {checked: boolean}}) => props.actions.changeSettings({automation: e.target.checked ? 'time' : ''})} /> props.actions.changeSettings({automation: e.target.checked ? 'location' : ''})} + onchange={(e: {target: {checked: boolean}}) => props.actions.changeSettings({automation: e.target.checked ? 'location' : ''})} /> locationChanged(e.target, e.target.value, 'latitude')} + onchange={(e: {target: HTMLInputElement}) => locationChanged(e.target, e.target.value, 'latitude')} oncreate={(node: HTMLInputElement) => node.value = getLocationString(locationSettings.latitude)} onkeypress={(e) => { if (e.key === 'Enter') { @@ -100,7 +101,7 @@ export default function AutomationPage(props: ViewProps) { locationChanged(e.target, e.target.value, 'longitude')} + onchange={(e: {target: HTMLInputElement}) => locationChanged(e.target, e.target.value, 'longitude')} oncreate={(node: HTMLInputElement) => node.value = getLocationString(locationSettings.longitude)} onkeypress={(e) => { if (e.key === 'Enter') { @@ -120,7 +121,7 @@ export default function AutomationPage(props: ViewProps) { props.actions.changeSettings({automation: e.target.checked ? 'system' : ''})} + onchange={(e: {target: {checked: boolean}}) => props.actions.changeSettings({automation: e.target.checked ? 'system' : ''})} />
); } diff --git a/src/ui/popup/automation-page/style.less b/src/ui/popup/automation-page/style.less index a9c5c9e46afd..723e705fc867 100644 --- a/src/ui/popup/automation-page/style.less +++ b/src/ui/popup/automation-page/style.less @@ -1,6 +1,9 @@ @import "../../theme"; .automation-page { + display: flex; + flex-direction: column; + &__button--active { background: @color-control-active; @@ -125,4 +128,28 @@ .toggle { width: 100%; } + + .dropdown { + background-color: transparent; + box-shadow: inset 0 0 0 @size-border @color-border; + height: @size-control-inner + 2 * @size-border; + margin-top: @indent-small; + } + + .dropdown__selected { + background-color: transparent; + background-position: center right 0.25rem + @size-border; + height: @size-control-inner; + margin-top: @size-border; + } + + .dropdown--open .dropdown__list { + border: @size-border solid @color-border; + margin-top: 0; + padding-top: @size-border; + } + + .dropdown__list__item { + height: @size-control-inner; + } } diff --git a/src/ui/popup/body/style.less b/src/ui/popup/body/style.less index deabf2150bc3..7034c2c3f709 100644 --- a/src/ui/popup/body/style.less +++ b/src/ui/popup/body/style.less @@ -237,3 +237,15 @@ font-size: 32px; } } + +.firefox { + .darkreader-version { + display: none; + } +} + +.preview:not(.mobile) { + body { + border-color: mix(@color-back, @color-control-fore); + } +} diff --git a/src/ui/popup/components/body.tsx b/src/ui/popup/components/body.tsx index 04ebb6cd4392..2c08546d7786 100644 --- a/src/ui/popup/components/body.tsx +++ b/src/ui/popup/components/body.tsx @@ -15,12 +15,11 @@ import {getDuration} from '../../../utils/time'; import {DONATE_URL, GITHUB_URL, PRIVACY_URL, TWITTER_URL, getHelpURL} from '../../../utils/links'; import {getLocalMessage} from '../../../utils/locales'; import {compose} from '../../utils'; -import type {ExtensionData, ExtensionActions, TabInfo, News as NewsObject} from '../../../definitions'; +import type {ExtensionData, ExtensionActions, News as NewsObject} from '../../../definitions'; import {isMobile, isFirefox, isThunderbird} from '../../../utils/platform'; interface BodyProps { data: ExtensionData; - tab: TabInfo; actions: ExtensionActions; } @@ -113,7 +112,6 @@ function Body(props: BodyProps & {fonts: string[]}) {
@@ -123,20 +121,20 @@ function Body(props: BodyProps & {fonts: string[]}) { onSwitchTab={(tab) => setState({activeTab: tab})} tabs={isThunderbird ? { 'Filter': ( - + ), 'More': ( - + ), } : { 'Filter': ( - + ), 'Site list': ( ), 'More': ( - + ), }} tabLabels={{ diff --git a/src/ui/popup/components/custom-settings-toggle/index.tsx b/src/ui/popup/components/custom-settings-toggle/index.tsx index 6675e40e4329..89abda60d4c9 100644 --- a/src/ui/popup/components/custom-settings-toggle/index.tsx +++ b/src/ui/popup/components/custom-settings-toggle/index.tsx @@ -2,10 +2,11 @@ import {m} from 'malevic'; import {Button} from '../../../controls'; import {getURLHostOrProtocol, isURLInList} from '../../../../utils/url'; import {getLocalMessage} from '../../../../utils/locales'; -import type {ExtWrapper, TabInfo} from '../../../../definitions'; +import type {ExtWrapper} from '../../../../definitions'; import {isThunderbird} from '../../../../utils/platform'; -export default function CustomSettingsToggle({data, tab, actions}: ExtWrapper & {tab: TabInfo}) { +export default function CustomSettingsToggle({data, actions}: ExtWrapper) { + const tab = data.activeTab; const host = getURLHostOrProtocol(tab.url); const isCustom = data.settings.customThemes.some(({url}) => isURLInList(tab.url, url)); diff --git a/src/ui/popup/components/filter-settings/index.tsx b/src/ui/popup/components/filter-settings/index.tsx index f7cc06a6aa43..4d70b1986138 100644 --- a/src/ui/popup/components/filter-settings/index.tsx +++ b/src/ui/popup/components/filter-settings/index.tsx @@ -4,10 +4,10 @@ import CustomSettingsToggle from '../custom-settings-toggle'; import ModeToggle from './mode-toggle'; import {getLocalMessage} from '../../../../utils/locales'; import {isURLInList} from '../../../../utils/url'; -import type {ExtWrapper, TabInfo, FilterConfig} from '../../../../definitions'; +import type {ExtWrapper, FilterConfig} from '../../../../definitions'; -export default function FilterSettings({data, actions, tab}: ExtWrapper & {tab: TabInfo}) { - const custom = data.settings.customThemes.find(({url}) => isURLInList(tab.url, url)); +export default function FilterSettings({data, actions}: ExtWrapper) { + const custom = data.settings.customThemes.find(({url}) => isURLInList(data.activeTab.url, url)); const filterConfig = custom ? custom.theme : data.settings.theme; function setConfig(config: Partial) { @@ -74,7 +74,7 @@ export default function FilterSettings({data, actions, tab}: ExtWrapper & {tab: {contrast} {sepia} {grayscale} - + ); } diff --git a/src/ui/popup/components/header/index.tsx b/src/ui/popup/components/header/index.tsx index ef0961c09a4a..dea64474c5ad 100644 --- a/src/ui/popup/components/header/index.tsx +++ b/src/ui/popup/components/header/index.tsx @@ -1,7 +1,7 @@ import {m} from 'malevic'; import {Shortcut, Toggle} from '../../../controls'; import {getLocalMessage} from '../../../../utils/locales'; -import type {ExtWrapper, TabInfo, UserSettings} from '../../../../definitions'; +import type {ExtWrapper, UserSettings} from '../../../../definitions'; import SunMoonIcon from '../../main-page/sun-moon-icon'; import SystemIcon from '../../main-page/system-icon'; import WatchIcon from '../../main-page/watch-icon'; @@ -13,11 +13,10 @@ function multiline(...lines: string[]) { } type HeaderProps = ExtWrapper & { - tab: TabInfo; onMoreToggleSettingsClick: () => void; }; -function Header({data, actions, tab, onMoreToggleSettingsClick}: HeaderProps) { +function Header({data, actions, onMoreToggleSettingsClick}: HeaderProps) { function toggleExtension(enabled: UserSettings['enabled']) { actions.changeSettings({ enabled, @@ -25,6 +24,7 @@ function Header({data, actions, tab, onMoreToggleSettingsClick}: HeaderProps) { }); } + const tab = data.activeTab; const isAutomation = Boolean(data.settings.automation); const isTimeAutomation = data.settings.automation === 'time'; const isLocationAutomation = data.settings.automation === 'location'; @@ -38,7 +38,6 @@ function Header({data, actions, tab, onMoreToggleSettingsClick}: HeaderProps) {
{tab.isProtected || !tab.isInjected ? ( diff --git a/src/ui/popup/components/loader/index.tsx b/src/ui/popup/components/loader/index.tsx index 66ecc083d678..1e56bb991770 100644 --- a/src/ui/popup/components/loader/index.tsx +++ b/src/ui/popup/components/loader/index.tsx @@ -1,6 +1,7 @@ import {m} from 'malevic'; import {getLocalMessage} from '../../../../utils/locales'; import {withState, useState} from 'malevic/state'; +import {getContext} from 'malevic/dom'; interface LoaderProps { complete: boolean; @@ -8,10 +9,27 @@ interface LoaderProps { interface LoaderState { finished: boolean; + errorOccured: boolean; } function Loader({complete = false}: LoaderProps) { - const {state, setState} = useState({finished: false}); + const context = getContext(); + const {state, setState} = useState({finished: false, errorOccured: false}); + + // Add a setTimeout for 3 seconds(in which the UI should be loaded already) + // after the 3 seconds show a generic error message that the UI couldn't be loaded. + if (!state.errorOccured && !complete) { + context.store.loaderTimeoutID = setTimeout(() => { + setState({errorOccured: true}); + context.refresh(); + }, 3000); + } + if (complete) { + clearTimeout(context.store.loaderTimeoutID); + } + + const labelMessage = state.errorOccured ? "A unknown error has occured, the UI couldn't be loaded" : getLocalMessage('loading_please_wait'); + return (
setState({finished: true})} > - +
); } diff --git a/src/ui/popup/components/loader/style.less b/src/ui/popup/components/loader/style.less index f762bc7e24aa..d0b9b8ce985a 100644 --- a/src/ui/popup/components/loader/style.less +++ b/src/ui/popup/components/loader/style.less @@ -51,6 +51,10 @@ bottom: @popup-content-height + @popup-content-padding - @size-control-inner - @indent-small; } + &__error { + font-size: @size-text-normal; + } + &--complete &__message { color: fade(@color-heading, 0%); transition: color @loading-fade-duration ease-out; diff --git a/src/ui/popup/components/more-settings/index.tsx b/src/ui/popup/components/more-settings/index.tsx index f545c729a6ea..9277e20b6abb 100644 --- a/src/ui/popup/components/more-settings/index.tsx +++ b/src/ui/popup/components/more-settings/index.tsx @@ -6,10 +6,11 @@ import {Toggle} from '../../../controls'; import {isURLInList} from '../../../../utils/url'; import {compileMarkdown} from '../../utils/markdown'; import {getLocalMessage} from '../../../../utils/locales'; -import type {ExtWrapper, FilterConfig, TabInfo} from '../../../../definitions'; +import type {ExtWrapper, FilterConfig} from '../../../../definitions'; import {isFirefox} from '../../../../utils/platform'; -export default function MoreSettings({data, actions, tab, fonts}: ExtWrapper & {tab: TabInfo} & {fonts: string[]}) { +export default function MoreSettings({data, actions, fonts}: ExtWrapper & {fonts: string[]}) { + const tab = data.activeTab; const custom = data.settings.customThemes.find(({url}) => isURLInList(tab.url, url)); const filterConfig = custom ? custom.theme : data.settings.theme; @@ -34,7 +35,7 @@ export default function MoreSettings({data, actions, tab, fonts}: ExtWrapper & { setConfig({engine})} />
- + {tab.isProtected ? (

{getLocalMessage('page_protected').replace(/\n/g, ' ')} diff --git a/src/ui/popup/components/news/index.tsx b/src/ui/popup/components/news/index.tsx index 18ff6dce8511..7eac609e9720 100644 --- a/src/ui/popup/components/news/index.tsx +++ b/src/ui/popup/components/news/index.tsx @@ -36,10 +36,13 @@ export function NewsGroup({news, expanded, onNewsOpen, onClose}: NewsProps) { class={{ 'news__event': true, 'news__event--unread': !event.read, - 'news__event--important': event.important, + 'news__event--has-icon': event.icon, }} > onNewsOpen(event)} href={event.url} target="_blank" rel="noopener noreferrer"> + {event.icon ? + + : null} {formattedDate} diff --git a/src/ui/popup/components/news/style.less b/src/ui/popup/components/news/style.less index 776404605c62..a55c41f899bf 100644 --- a/src/ui/popup/components/news/style.less +++ b/src/ui/popup/components/news/style.less @@ -1,5 +1,7 @@ @import "../../../theme"; +@size-news-icon: 2.5rem; + .news { bottom: @size-control-inner + @size-border + @popup-content-padding; box-sizing: border-box; @@ -97,6 +99,22 @@ } } + &__icon { + background-position: center; + background-repeat: no-repeat; + background-size: contain; + display: inline-block; + height: @size-news-icon; + left: 0; + position: absolute; + top: calc(50% - @size-news-icon / 2); + width: @size-news-icon; + } + + &--has-icon { + padding-left: @size-news-icon + @indent-small; + } + &--unread { font-weight: bold; diff --git a/src/ui/popup/components/site-toggle/index.tsx b/src/ui/popup/components/site-toggle/index.tsx index 2347f7e156c9..a4ec4e382b01 100644 --- a/src/ui/popup/components/site-toggle/index.tsx +++ b/src/ui/popup/components/site-toggle/index.tsx @@ -2,15 +2,17 @@ import {m} from 'malevic'; import CheckmarkIcon from './checkmark-icon'; import {Button} from '../../../controls'; import {getURLHostOrProtocol, isURLEnabled, isPDF} from '../../../../utils/url'; -import type {ExtWrapper, TabInfo} from '../../../../definitions'; +import type {ExtWrapper} from '../../../../definitions'; import {isThunderbird} from '../../../../utils/platform'; -export default function SiteToggleButton({data, tab, actions}: ExtWrapper & {tab: TabInfo}) { +export default function SiteToggleButton({data, actions}: ExtWrapper) { + const tab = data.activeTab; + function onSiteToggleClick() { if (pdf) { actions.changeSettings({enableForPDF: !data.settings.enableForPDF}); } else { - actions.toggleURL(tab.url); + actions.toggleActiveTab(); } } diff --git a/src/ui/popup/index.html b/src/ui/popup/index.html index 511c16962823..f22c43c88623 100644 --- a/src/ui/popup/index.html +++ b/src/ui/popup/index.html @@ -12,6 +12,10 @@ -$BODY + +

+ diff --git a/src/ui/popup/index.tsx b/src/ui/popup/index.tsx index 7e9db7e4dadd..d8ee727ecf6a 100644 --- a/src/ui/popup/index.tsx +++ b/src/ui/popup/index.tsx @@ -3,12 +3,12 @@ import {sync} from 'malevic/dom'; import Connector from '../connect/connector'; import Body from './components/body'; import {popupHasBuiltInHorizontalBorders, popupHasBuiltInBorders, fixNotClosingPopupOnNavigation} from './utils/issues'; -import type {ExtensionData, ExtensionActions, TabInfo} from '../../definitions'; +import type {ExtensionData, ExtensionActions} from '../../definitions'; import {isMobile, isFirefox} from '../../utils/platform'; import {MessageType} from '../../utils/message'; import {getFontList} from '../utils'; -function renderBody(data: ExtensionData, tab: TabInfo, fonts: string[], actions: ExtensionActions) { +function renderBody(data: ExtensionData, fonts: string[], actions: ExtensionActions) { if (data.settings.previewNewDesign) { if (!document.documentElement.classList.contains('preview')) { document.documentElement.classList.add('preview'); @@ -17,8 +17,15 @@ function renderBody(data: ExtensionData, tab: TabInfo, fonts: string[], actions: document.documentElement.classList.remove('preview'); } + if (data.news && data.news.length > 0) { + const latest = data.news[0]; + if (latest && !latest.displayed) { + actions.markNewsAsDisplayed([latest.id]); + } + } + sync(document.body, ( - + )); } @@ -26,13 +33,12 @@ async function start() { const connector = new Connector(); window.addEventListener('unload', () => connector.disconnect()); - const [data, tab, fonts] = await Promise.all([ + const [data, fonts] = await Promise.all([ connector.getData(), - connector.getActiveTabInfo(), getFontList() ]); - renderBody(data, tab, fonts, connector); - connector.subscribeToChanges((data) => renderBody(data, tab, fonts, connector)); + renderBody(data, fonts, connector); + connector.subscribeToChanges((data) => renderBody(data, fonts, connector)); } addEventListener('load', start); diff --git a/src/ui/popup/main-page/site-toggle.tsx b/src/ui/popup/main-page/site-toggle.tsx index 365223aaaad3..5a143454f5d1 100644 --- a/src/ui/popup/main-page/site-toggle.tsx +++ b/src/ui/popup/main-page/site-toggle.tsx @@ -5,14 +5,14 @@ import ControlGroup from '../control-group'; import type {ViewProps} from '../types'; export default function SiteToggleGroup(props: ViewProps) { - const isPageEnabled = isURLEnabled(props.tab.url, props.data.settings, props.tab); - const descriptionText = isPDF(props.tab.url) ? - isPageEnabled ? - 'Enabled for PDF files' : - 'Disabled for PDF files' : - isPageEnabled ? - 'Enabled for current website' : - 'Disabled for current website'; + const tab = props.data.activeTab; + const isPageEnabled = isURLEnabled(tab.url, props.data.settings, tab); + const {isDarkThemeDetected} = tab; + const descriptionText = isPDF(tab.url) ? ( + isPageEnabled ? 'Enabled for PDF files' : 'Disabled for PDF files' + ) : isDarkThemeDetected ? 'Dark theme detected on page' : ( + isPageEnabled ? 'Enabled for current website' : 'Disabled for current website' + ); const description = ( isURLInList(props.tab.url, url) + ({url}) => isURLInList(props.data.activeTab.url, url) ); const engine = custom ? custom.theme.engine : diff --git a/src/ui/popup/news-section/index.tsx b/src/ui/popup/news-section/index.tsx index 39e328ec6ade..ec47c80f8907 100644 --- a/src/ui/popup/news-section/index.tsx +++ b/src/ui/popup/news-section/index.tsx @@ -1,4 +1,5 @@ import {m} from 'malevic'; +import {getContext} from 'malevic/dom'; import {getDuration} from '../../../utils/time'; import type {News} from '../../../definitions'; import type {ViewProps} from '../types'; @@ -13,20 +14,76 @@ function isFresh(n: News) { } } +function NewsLink(props: {news: News; isSmall?: boolean; onClick: () => void}) { + const {news} = props; + return ( + + {news.icon ? + + : null} + {news.headline} + + ); +} + export default function NewsSection(props: ViewProps) { + const context = getContext(); + const store = context.getStore({ + expanded: false, + didNewsSlideIn: false, + }); + const {expanded, didNewsSlideIn} = store; + const news = props.data.news; const latest = news && news.length > 0 ? news[0] : null; + + function markLatestAsRead() { + if (latest) { + props.actions.markNewsAsRead([latest.id]); + } + } + + function toggleNews() { + if (expanded) { + markLatestAsRead(); + } + store.expanded = !expanded; + store.didNewsSlideIn = didNewsSlideIn || !store.expanded; + context.refresh(); + } + + context.onRender(() => { + if (latest && !latest.read && !store.expanded && !store.didNewsSlideIn) { + setTimeout(toggleNews, 750); + } + }); + return ( -
- {latest ? - {latest.headline} - : null} +
+ {latest ? : null} +
+
+
+ What's New +
+ +
+ {latest ? : null} +
); } diff --git a/src/ui/popup/news-section/style.less b/src/ui/popup/news-section/style.less index 301a1a006726..1fd8ad021227 100644 --- a/src/ui/popup/news-section/style.less +++ b/src/ui/popup/news-section/style.less @@ -1,33 +1,92 @@ @import "../../theme.less"; +@news-section-expanded-height: 6rem; +@news-section-collapsed-height: 1.875rem; + .news-section { background-color: @color-back; + border-bottom-left-radius: @news-section-collapsed-height / 2; + border-bottom-right-radius: @news-section-collapsed-height / 2; bottom: 0; box-sizing: border-box; - height: 1.875rem; + display: flex; + flex-direction: column; + height: @news-section-collapsed-height; left: 0; overflow: hidden; - padding: 0.375rem 1rem 0.5rem 1rem; + padding: 0; position: absolute; text-align: center; + transition: height @time-slow; user-select: none; white-space: nowrap; width: 100%; - &__main-link { + &__popover { + align-items: stretch; + background-color: @color-back; + display: flex; + flex-direction: column; + left: 0; + height: @news-section-expanded-height; + opacity: 0; + pointer-events: none; + position: absolute; + top: 0; + transition: opacity @time-slow; + width: 100%; + + &__top { + border-top: @size-border solid @color-border; + display: flex; + flex-direction: row; + justify-content: space-between; + margin-bottom: @indent-small; + } + } + + &__title { + color: @color-heading; + font-size: @size-text-large; + line-height: @size-control-inner; + margin-left: @popup-content-padding; + } + + &__news { + align-items: center; box-sizing: border-box; color: @color-fore; - display: inline-block; - font-weight: bold; - line-height: 1rem; - height: 1rem; - overflow: hidden; - position: relative; - text-overflow: ellipsis; + display: flex; + flex-direction: row; + font-weight: normal; + justify-content: flex-start; + height: 2.5rem; + padding: 0 @popup-content-padding; width: 100%; - &--fresh:not(:visited) { + &__icon { + background-position: center; + background-repeat: no-repeat; + background-size: contain; + display: inline-block; + flex: none; + height: 3rem; + margin-right: @indent-small; + width: 3rem; + } + + &__text { + flex: auto; + font-size: @size-text-large; + display: inline-block; + line-height: @size-text-large; + text-align: left; + white-space: normal; + } + + &--highlight { color: @color-heading; + font-weight: bold; } &:hover { @@ -35,7 +94,49 @@ } } - &:empty { - display: none; + &__close { + color: @color-heading; + cursor: pointer; + display: inline-block; + font-size: @size-control-inner * 3 / 4; + height: @size-control-inner; + line-height: @size-control-inner; + text-align: center; + user-select: none; + width: @size-control-inner; + + &:hover { + background-color: fade(@color-control-active, 25%); + } + } + + &--expanded { + height: @news-section-expanded-height; } } + +.news-section--expanded .news-section__popover { + opacity: 1; + pointer-events: all; +} + +.news-section__news--small { + bottom: 0; + font-weight: bold; + height: @news-section-collapsed-height; + padding: 0 @popup-content-padding; +} + +.news-section__news--small .news-section__news__icon { + height: 1.5rem; + margin-right: @indent-small / 2; + width: 1.5rem; +} + +.news-section__news--small .news-section__news__text { + font-size: @size-text-normal; + line-height: @size-text-normal-height; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} diff --git a/src/ui/popup/settings-page/detect-dark-theme.tsx b/src/ui/popup/settings-page/detect-dark-theme.tsx new file mode 100644 index 000000000000..612672d7bac9 --- /dev/null +++ b/src/ui/popup/settings-page/detect-dark-theme.tsx @@ -0,0 +1,20 @@ +import {m} from 'malevic'; +import CheckButton from '../check-button'; +import type {ViewProps} from '../types'; + +export default function DetectDarkTheme(props: ViewProps) { + function onDetectDarkThemeChange(checked: boolean) { + props.actions.changeSettings({detectDarkTheme: checked}); + } + + return ( + + ); +} diff --git a/src/ui/popup/settings-page/index.tsx b/src/ui/popup/settings-page/index.tsx index 1fafae0cd73d..b502a2f6932f 100644 --- a/src/ui/popup/settings-page/index.tsx +++ b/src/ui/popup/settings-page/index.tsx @@ -5,6 +5,7 @@ import DevToolsGroup from './devtools'; import ManageSettingsButton from './mange-settings-button'; import SiteListButton from './site-list-button'; import EnabledByDefaultGroup from './enabled-by-default'; +import DetectDarkThemeGroup from './detect-dark-theme'; import ChangeBrowserTheme from './change-browser-theme'; import ContextMenusGroup from './context-menus'; import Version from './version'; @@ -26,6 +27,7 @@ export default function SettingsPage(props: SettingsPageProps) { + ); diff --git a/src/ui/popup/theme/controls/immediate-modify.tsx b/src/ui/popup/theme/controls/immediate-modify.tsx new file mode 100644 index 000000000000..829958aac280 --- /dev/null +++ b/src/ui/popup/theme/controls/immediate-modify.tsx @@ -0,0 +1,16 @@ +import {m} from 'malevic'; +import {DropDown} from '../../../controls'; +import ThemeControl from './theme-control'; + +export default function ImmediateModify(props: {value: boolean; onChange: (value: boolean) => void}) { + const options = [{id: true, content: 'Yes'}, {id: false, content: 'No'}]; + return ( + + + + ); +} diff --git a/src/ui/popup/theme/controls/index.tsx b/src/ui/popup/theme/controls/index.tsx index b555d2b9839a..c06e3bca8737 100644 --- a/src/ui/popup/theme/controls/index.tsx +++ b/src/ui/popup/theme/controls/index.tsx @@ -4,6 +4,7 @@ import Contrast from './contrast'; import ColorSchemeDropDown from './color-scheme'; import FontPicker from './font-picker'; import Grayscale from './grayscale'; +import ImmediateModify from './immediate-modify'; import Mode from './mode'; import ResetButton from './reset-button'; import Scheme from './scheme'; @@ -22,6 +23,7 @@ export { ColorSchemeDropDown, FontPicker, Grayscale, + ImmediateModify, Mode, ResetButton, Scheme, diff --git a/src/ui/popup/theme/page/index.tsx b/src/ui/popup/theme/page/index.tsx index 13286ecc43b0..1232d2459627 100644 --- a/src/ui/popup/theme/page/index.tsx +++ b/src/ui/popup/theme/page/index.tsx @@ -3,7 +3,7 @@ import {DEFAULT_SETTINGS, DEFAULT_THEME, DEFAULT_COLORS} from '../../../../defau import type {Theme} from '../../../../definitions'; import type {ParsedColorSchemeConfig} from '../../../../utils/colorscheme-parser'; import type {ViewProps} from '../../types'; -import {BackgroundColor, Brightness, Contrast, FontPicker, Grayscale, Mode, ResetButton, Scheme, Scrollbar, SelectionColorEditor, Sepia, TextColor, TextStroke, UseFont, StyleSystemControls, ColorSchemeDropDown} from '../controls'; +import {BackgroundColor, Brightness, Contrast, FontPicker, Grayscale, Mode, ResetButton, Scheme, Scrollbar, SelectionColorEditor, Sepia, TextColor, TextStroke, UseFont, StyleSystemControls, ColorSchemeDropDown, ImmediateModify} from '../controls'; import ThemePresetPicker from '../preset-picker'; import {getCurrentThemePreset} from '../utils'; import Collapsible from './collapsible-panel'; @@ -126,6 +126,10 @@ function FontGroup({theme, fonts, change}: FontGroupsProps) { value={theme.styleSystemControls} onChange={(styleSystemControls) => change({styleSystemControls})} /> + change({immediateModify})} + /> ); } diff --git a/src/ui/popup/theme/preset-picker/index.tsx b/src/ui/popup/theme/preset-picker/index.tsx index e93274bd986b..64e4e733af93 100644 --- a/src/ui/popup/theme/preset-picker/index.tsx +++ b/src/ui/popup/theme/preset-picker/index.tsx @@ -46,12 +46,13 @@ function PresetItem(props: ViewProps & {preset: ThemePreset}) { const MAX_ALLOWED_PRESETS = 3; export default function PresetPicker(props: ViewProps) { - const host = getURLHostOrProtocol(props.tab.url); + const tab = props.data.activeTab; + const host = getURLHostOrProtocol(tab.url); const preset = props.data.settings.presets.find( - ({urls}) => isURLInList(props.tab.url, urls) + ({urls}) => isURLInList(tab.url, urls) ); const custom = props.data.settings.customThemes.find( - ({url}) => isURLInList(props.tab.url, url) + ({url}) => isURLInList(tab.url, url) ); const selectedPresetId = custom ? 'custom' : preset ? preset.id : 'default'; @@ -82,11 +83,11 @@ export default function PresetPicker(props: ViewProps) { ].filter(Boolean); function onPresetChange(id: string) { - const filteredCustomThemes = props.data.settings.customThemes.filter(({url}) => !isURLInList(props.tab.url, url)); + const filteredCustomThemes = props.data.settings.customThemes.filter(({url}) => !isURLInList(tab.url, url)); const filteredPresets = props.data.settings.presets.map((preset) => { return { ...preset, - urls: preset.urls.filter((template) => !isURLMatched(props.tab.url, template)), + urls: preset.urls.filter((template) => !isURLMatched(tab.url, template)), }; }); if (id === 'default') { diff --git a/src/ui/popup/theme/utils.ts b/src/ui/popup/theme/utils.ts index 57d8b1bd2700..1dc29b0862b2 100644 --- a/src/ui/popup/theme/utils.ts +++ b/src/ui/popup/theme/utils.ts @@ -4,16 +4,20 @@ import type {ViewProps} from '../types'; export function getCurrentThemePreset(props: ViewProps) { const custom = props.data.settings.customThemes.find( - ({url}) => isURLInList(props.tab.url, url) + ({url}) => isURLInList(props.data.activeTab.url, url) ); const preset = custom ? null : props.data.settings.presets.find( - ({urls}) => isURLInList(props.tab.url, urls) + ({urls}) => isURLInList(props.data.activeTab.url, urls) ); - const theme = custom ? + let theme = custom ? custom.theme : preset ? preset.theme : props.data.settings.theme; + if (props.data.forcedScheme) { + const mode = props.data.forcedScheme === 'dark' ? 1 : 0; + theme = {...theme, mode}; + } function setTheme(config: Partial) { if (custom) { @@ -29,6 +33,15 @@ export function getCurrentThemePreset(props: ViewProps) { } else { props.actions.setTheme(config); } + if ( + config.mode != null && + props.data.settings.automation && + props.data.settings.automationBehaviour === 'Scheme' + ) { + props.actions.changeSettings({ + automation: '', + }); + } } return { diff --git a/src/ui/popup/types.d.ts b/src/ui/popup/types.d.ts index 109716b66c14..1f474470fe6c 100644 --- a/src/ui/popup/types.d.ts +++ b/src/ui/popup/types.d.ts @@ -1,8 +1,7 @@ -import type {ExtensionData, ExtensionActions, TabInfo} from '../../definitions'; +import type {ExtensionData, ExtensionActions} from '../../definitions'; export interface ViewProps { actions: ExtensionActions; data: ExtensionData; - tab: TabInfo; fonts?: string[]; } diff --git a/src/ui/stylesheet-editor/components/body.tsx b/src/ui/stylesheet-editor/components/body.tsx index 085573ef9edf..ca0107ba5c14 100644 --- a/src/ui/stylesheet-editor/components/body.tsx +++ b/src/ui/stylesheet-editor/components/body.tsx @@ -2,16 +2,12 @@ import {m} from 'malevic'; import {getContext} from 'malevic/dom'; import {Button, MessageBox, Overlay} from '../../controls'; import {getURLHostOrProtocol, isURLInList} from '../../../utils/url'; -import type {ExtWrapper, TabInfo} from '../../../definitions'; +import type {ExtWrapper} from '../../../definitions'; -interface BodyProps extends ExtWrapper { - tab: TabInfo; -} - -export default function Body({data, tab, actions}: BodyProps) { +export default function Body({data, actions}: ExtWrapper) { const context = getContext(); - const host = getURLHostOrProtocol(tab.url); - const custom = data.settings.customThemes.find(({url}) => isURLInList(tab.url, url)); + const host = getURLHostOrProtocol(data.activeTab.url); + const custom = data.settings.customThemes.find(({url}) => isURLInList(data.activeTab.url, url)); let textNode: HTMLTextAreaElement; diff --git a/src/ui/stylesheet-editor/index.html b/src/ui/stylesheet-editor/index.html index eadceace5aaf..728037da7a36 100644 --- a/src/ui/stylesheet-editor/index.html +++ b/src/ui/stylesheet-editor/index.html @@ -10,6 +10,6 @@ -$BODY + diff --git a/src/ui/stylesheet-editor/index.tsx b/src/ui/stylesheet-editor/index.tsx index f5557eaadae6..e25da82b81d3 100644 --- a/src/ui/stylesheet-editor/index.tsx +++ b/src/ui/stylesheet-editor/index.tsx @@ -2,10 +2,10 @@ import {m} from 'malevic'; import {sync} from 'malevic/dom'; import Body from './components/body'; import Connector from '../connect/connector'; -import type {ExtensionActions, ExtensionData, TabInfo} from '../../definitions'; +import type {ExtensionActions, ExtensionData} from '../../definitions'; -function renderBody(data: ExtensionData, tab: TabInfo, actions: ExtensionActions) { - sync(document.body, ); +function renderBody(data: ExtensionData, actions: ExtensionActions) { + sync(document.body, ); } async function start() { @@ -13,9 +13,8 @@ async function start() { window.addEventListener('unload', () => connector.disconnect()); const data = await connector.getData(); - const tab = await connector.getActiveTabInfo(); - renderBody(data, tab, connector); - connector.subscribeToChanges((data) => renderBody(data, tab, connector)); + renderBody(data, connector); + connector.subscribeToChanges((data) => renderBody(data, connector)); } start(); diff --git a/src/utils/color.ts b/src/utils/color.ts index dc5e756bdc22..bf869cc80b46 100644 --- a/src/utils/color.ts +++ b/src/utils/color.ts @@ -1,3 +1,6 @@ +import {evalMath} from './math-eval'; +import {getParenthesesRange} from './text'; + export interface RGBA { r: number; g: number; @@ -246,15 +249,6 @@ function getSystemColor($color: string) { }; } -// Check if the char is a digit. -const isCharDigit = (char: string) => char >= '0' && char <= '9'; - -// Get the amount of digits their are in a number. -// f(5) => 1 -// f(123) => 3 -// f(912412) => 6 -const getAmountOfDigits = (number: number) => Math.floor(Math.log10(number)) + 1; - // lowerCalcExpression is a helper function that tries to remove `calc(...)` // expressions from the given string. It can only lower expressions to a certain // degree so we can keep this function easy and simple to understand. @@ -263,90 +257,31 @@ export function lowerCalcExpression(color: string): string { // the calc(...) expression. let searchIndex = 0; - const replaceBetweenIndices = (start: number, end:number, replacement: string) => { + // Replace the content between two indices. + const replaceBetweenIndices = (start: number, end: number, replacement: string) => { color = color.substring(0, start) + replacement + color.substring(end); }; - // Because we're talking about numbers within variables - // We assume that the max length of such number is 3. - const getNumber = () => { - let resultNumber = 0; - for (let i = 1; i < 4; i++) { - const char = color[searchIndex + i]; - // If we hit a whitespace that means we hit the end of the number. - if (char === ' ') { - break; - } - // Check if the current char is numeric. - if (isCharDigit(char)) { - // Ensure that the current number is multipled by 10 - // So that the "first" digit on that number is a 0 - // Which is going to be filled by the `char`. - resultNumber *= 10; - resultNumber += Number(char); - } else { - break; - } - } - const lenDigits = getAmountOfDigits(resultNumber); - searchIndex += lenDigits; - - // We've now got the first number, let's try to see if this number - // a percentage, which is the currently only supported element type. - const possibleType = color[searchIndex + 1]; - if (possibleType !== '%') { - return; - } - searchIndex++; - return resultNumber; - }; - - while ((searchIndex = color.indexOf('calc(')) !== 0) { - const startIndex = searchIndex; - searchIndex += 4; - // Get the first number - const firstNumber = getNumber(); - - // No first number? Let's not break this while loop. - // And return the current state of color variable. - if (!firstNumber) { - break; - } - - // The char after the xxx% should be a whitespace. - if (color[searchIndex + 1] !== ' ') { - break; - } - searchIndex++; - - const operation = color[searchIndex + 1]; - // Only allow - and + - if (operation !== '+' && operation !== '-') { + // Run this code until it doesn't find any `calc(...)`. + while ((searchIndex = color.indexOf('calc(')) !== -1) { + // Get the parantheses ranges of `calc(...)` + const range = getParenthesesRange(color, searchIndex); + if (!range) { break; } - searchIndex++; - // The char after the xxx% -/+ should be a whitespace. - if (color[searchIndex + 1] !== ' ') { - break; - } - searchIndex++; + // Get the content between the parentheses. + let slice = color.slice(range.start + 1, range.end - 1); + // Does the content include a percentage? + const includesPercentage = slice.includes('%'); + // Remove all percentages. + slice = slice.split('%').join(''); - // Get the second number - const secondNumber = getNumber(); - if (!secondNumber) { - break; - } - // Create the replacement string. - let replacement: string; - if (operation === '+') { - replacement = `${firstNumber + secondNumber}%`; - } else { - replacement = `${firstNumber - secondNumber}%`; - } + // Pass the content to the evalMath library and round it's output. + const output = Math.round(evalMath(slice)); - // Replace the string between the indices. - replaceBetweenIndices(startIndex, searchIndex + 2, replacement); + // Replace `calc(...)` with the result. + replaceBetweenIndices(range.start - 4, range.end, output + (includesPercentage ? '%' : '')); } return color; } @@ -533,3 +468,8 @@ const systemColors: Map = new Map(Object.entries({ WindowText: 0x000000, '-webkit-focus-ring-color': 0xe59700 }).map(([key, value]) => [key.toLowerCase(), value] as [string, number])); + +// https://en.wikipedia.org/wiki/Relative_luminance +export function getSRGBLightness(r: number, g: number, b: number) { + return (0.2126 * r + 0.7152 * g + 0.0722 * b) / 255; +} diff --git a/src/utils/debounce.ts b/src/utils/debounce.ts index 12cec1e7adf9..27283c4b8f31 100644 --- a/src/utils/debounce.ts +++ b/src/utils/debounce.ts @@ -1,7 +1,7 @@ type AnyFn = (...args: any[]) => any; export function debounce(delay: number, fn: F): F { - let timeoutId: number = null; + let timeoutId: ReturnType = null; return ((...args: any[]) => { if (timeoutId) { clearTimeout(timeoutId); diff --git a/src/utils/links.ts b/src/utils/links.ts index dbe55f865e35..303d30bc8dfd 100644 --- a/src/utils/links.ts +++ b/src/utils/links.ts @@ -2,7 +2,7 @@ import {getUILanguage} from './locales'; export const BLOG_URL = 'https://darkreader.org/blog/'; export const DEVTOOLS_DOCS_URL = 'https://github.com/darkreader/darkreader/blob/master/CONTRIBUTING.md'; -export const DONATE_URL = 'https://opencollective.com/darkreader'; +export const DONATE_URL = 'https://opencollective.com/darkreader/donate'; export const GITHUB_URL = 'https://github.com/darkreader/darkreader'; export const PRIVACY_URL = 'https://darkreader.org/privacy/'; export const TWITTER_URL = 'https://twitter.com/darkreaderapp'; diff --git a/src/utils/log.ts b/src/utils/log.ts index 1881dd7c470a..e5b6642fe9ca 100644 --- a/src/utils/log.ts +++ b/src/utils/log.ts @@ -8,3 +8,11 @@ export function logInfo(...args: any[]) { export function logWarn(...args: any[]) { DEBUG && console.warn(...args); } + +export function logInfoCollapsed(title: any, ...args: any[]) { + if (DEBUG) { + console.groupCollapsed(title); + console.log(...args); + console.groupEnd(); + } +} diff --git a/src/utils/math-eval.ts b/src/utils/math-eval.ts new file mode 100644 index 000000000000..66e6b63932c4 --- /dev/null +++ b/src/utils/math-eval.ts @@ -0,0 +1,100 @@ +// evalMath is a function that's able to evaluates a mathematical expression and return it's ouput. +// +// Internally it uses the Shunting Yard algoritm. First it produces a reverse polish notation(RPN) stack. +// Example: 1 + 2 * 3 -> [1, 2, 3, *, +] which with parentheses means 1 (2 3 *) + +// +// Then it evaluates the RPN stack and returns the output. +export function evalMath(expression: string): number { + // Stack where operators & numbers are stored in RPN. + const rpnStack: string[] = []; + // The working stack where new tokens are pushed. + const workingStack: string[] = []; + + let lastToken: string; + // Iterate over the expression. + for (let i = 0, len = expression.length; i < len; i++) { + const token = expression[i]; + + // Skip if the token is empty or a whitespace. + if (!token || token === ' ') { + continue; + } + + // Is the token a operator? + if (operators.has(token)) { + const op = operators.get(token); + + // Go trough the workingstack and determine it's place in the workingStack + while (workingStack.length) { + const currentOp = operators.get(workingStack[0]); + if (!currentOp) { + break; + } + + // Is the current operation equal or less than the current operation? + // Then move that operation to the rpnStack. + if (op.lessOrEqualThan(currentOp)) { + rpnStack.push(workingStack.shift()); + } else { + break; + } + } + // Add the operation to the workingStack. + workingStack.unshift(token); + // Otherwise was the last token a operator? + } else if (!lastToken || operators.has(lastToken)) { + rpnStack.push(token); + // Otherwise just append the result to the last token(e.g. multiple digits numbers). + } else { + rpnStack[rpnStack.length - 1] += token; + } + // Set the last token. + lastToken = token; + } + + // Push the working stack on top of the rpnStack. + rpnStack.push(...workingStack); + + // Now evaluate the rpnStack. + const stack: number[] = []; + for (let i = 0, len = rpnStack.length; i < len; i++) { + const op = operators.get(rpnStack[i]); + if (op) { + // Get the arguments of for the operation(first two in the stack). + const args = stack.splice(0, 2); + // Excute it, because of reverse notation we first pass second item then the first item. + stack.push(op.exec(args[1], args[0])); + } else { + // Add the number to the stack. + stack.unshift(parseFloat(rpnStack[i])); + } + } + + return stack[0]; +} + +// Operator class defines a operator that can be parsed & evaluated by evalMath. +class Operator { + private precendce: number; + private execMethod: (left: number, right: number) => number; + + constructor(precedence: number, method: (left: number, right: number) => number) { + this.precendce = precedence; + this.execMethod = method; + } + + public exec(left: number, right: number): number { + return this.execMethod(left, right); + } + + public lessOrEqualThan(op: Operator) { + return this.precendce <= op.precendce; + } +} + +const operators: Map = new Map([ + ['+', new Operator(1, (left: number, right: number): number => left + right)], + ['-', new Operator(1, (left: number, right: number): number => left - right)], + ['*', new Operator(2, (left: number, right: number): number => left * right)], + ['/', new Operator(2, (left: number, right: number): number => left / right)], +]); diff --git a/src/utils/message.ts b/src/utils/message.ts index dc00bea73966..20502b9052b5 100644 --- a/src/utils/message.ts +++ b/src/utils/message.ts @@ -1,41 +1,43 @@ -export const MessageType = { - UI_GET_DATA: 'ui-get-data', - UI_GET_ACTIVE_TAB_INFO: 'ui-get-active-tab-info', - UI_SUBSCRIBE_TO_CHANGES: 'ui-subscribe-to-changes', - UI_UNSUBSCRIBE_FROM_CHANGES: 'ui-unsubscribe-from-changes', - UI_CHANGE_SETTINGS: 'ui-change-settings', - UI_SET_THEME: 'ui-set-theme', - UI_SET_SHORTCUT: 'ui-set-shortcut', - UI_TOGGLE_URL: 'ui-toggle-url', - UI_MARK_NEWS_AS_READ: 'ui-mark-news-as-read', - UI_LOAD_CONFIG: 'ui-load-config', - UI_APPLY_DEV_DYNAMIC_THEME_FIXES: 'ui-apply-dev-dynamic-theme-fixes', - UI_RESET_DEV_DYNAMIC_THEME_FIXES: 'ui-reset-dev-dynamic-theme-fixes', - UI_APPLY_DEV_INVERSION_FIXES: 'ui-apply-dev-inversion-fixes', - UI_RESET_DEV_INVERSION_FIXES: 'ui-reset-dev-inversion-fixes', - UI_APPLY_DEV_STATIC_THEMES: 'ui-apply-dev-static-themes', - UI_RESET_DEV_STATIC_THEMES: 'ui-reset-dev-static-themes', - UI_SAVE_FILE: 'ui-save-file', - UI_REQUEST_EXPORT_CSS: 'ui-request-export-css', +export enum MessageType { + UI_GET_DATA = 'ui-get-data', + UI_SUBSCRIBE_TO_CHANGES = 'ui-subscribe-to-changes', + UI_UNSUBSCRIBE_FROM_CHANGES = 'ui-unsubscribe-from-changes', + UI_CHANGE_SETTINGS = 'ui-change-settings', + UI_SET_THEME = 'ui-set-theme', + UI_SET_SHORTCUT = 'ui-set-shortcut', + UI_TOGGLE_ACTIVE_TAB = 'ui-toggle-active-tab', + UI_MARK_NEWS_AS_READ = 'ui-mark-news-as-read', + UI_MARK_NEWS_AS_DISPLAYED = 'ui-mark-news-as-displayed', + UI_LOAD_CONFIG = 'ui-load-config', + UI_APPLY_DEV_DYNAMIC_THEME_FIXES = 'ui-apply-dev-dynamic-theme-fixes', + UI_RESET_DEV_DYNAMIC_THEME_FIXES = 'ui-reset-dev-dynamic-theme-fixes', + UI_APPLY_DEV_INVERSION_FIXES = 'ui-apply-dev-inversion-fixes', + UI_RESET_DEV_INVERSION_FIXES = 'ui-reset-dev-inversion-fixes', + UI_APPLY_DEV_STATIC_THEMES = 'ui-apply-dev-static-themes', + UI_RESET_DEV_STATIC_THEMES = 'ui-reset-dev-static-themes', + UI_SAVE_FILE = 'ui-save-file', + UI_REQUEST_EXPORT_CSS = 'ui-request-export-css', - BG_CHANGES: 'bg-changes', - BG_ADD_CSS_FILTER: 'bg-add-css-filter', - BG_ADD_STATIC_THEME: 'bg-add-static-theme', - BG_ADD_SVG_FILTER: 'bg-add-svg-filter', - BG_ADD_DYNAMIC_THEME: 'bg-add-dynamic-theme', - BG_EXPORT_CSS: 'bg-export-css', - BG_UNSUPPORTED_SENDER: 'bg-unsupported-sender', - BG_CLEAN_UP: 'bg-clean-up', - BG_RELOAD: 'bg-reload', - BG_FETCH_RESPONSE: 'bg-fetch-response', - BG_UI_UPDATE: 'bg-ui-update', - BG_CSS_UPDATE: 'bg-css-update', + BG_CHANGES = 'bg-changes', + BG_ADD_CSS_FILTER = 'bg-add-css-filter', + BG_ADD_STATIC_THEME = 'bg-add-static-theme', + BG_ADD_SVG_FILTER = 'bg-add-svg-filter', + BG_ADD_DYNAMIC_THEME = 'bg-add-dynamic-theme', + BG_EXPORT_CSS = 'bg-export-css', + BG_UNSUPPORTED_SENDER = 'bg-unsupported-sender', + BG_CLEAN_UP = 'bg-clean-up', + BG_RELOAD = 'bg-reload', + BG_FETCH_RESPONSE = 'bg-fetch-response', + BG_UI_UPDATE = 'bg-ui-update', + BG_CSS_UPDATE = 'bg-css-update', - CS_COLOR_SCHEME_CHANGE: 'cs-color-scheme-change', - CS_FRAME_CONNECT: 'cs-frame-connect', - CS_FRAME_FORGET: 'cs-frame-forget', - CS_FRAME_FREEZE: 'cs-frame-freeze', - CS_FRAME_RESUME: 'cs-frame-resume', - CS_EXPORT_CSS_RESPONSE: 'cs-export-css-response', - CS_FETCH: 'cs-fetch', -}; + CS_COLOR_SCHEME_CHANGE = 'cs-color-scheme-change', + CS_FRAME_CONNECT = 'cs-frame-connect', + CS_FRAME_FORGET = 'cs-frame-forget', + CS_FRAME_FREEZE = 'cs-frame-freeze', + CS_FRAME_RESUME = 'cs-frame-resume', + CS_EXPORT_CSS_RESPONSE = 'cs-export-css-response', + CS_FETCH = 'cs-fetch', + CS_DARK_THEME_DETECTED = 'cs-dark-theme-detected', + CS_DARK_THEME_NOT_DETECTED = 'cs-dark-theme-not-detected', +} diff --git a/src/utils/mutex.ts b/src/utils/mutex.ts deleted file mode 100644 index aa9d83395c0b..000000000000 --- a/src/utils/mutex.ts +++ /dev/null @@ -1,54 +0,0 @@ -import {logWarn} from './log'; - -/** - * This is the Mutex(Not to confuse with RW-Mutex). - * This is to ensure that certain access are only done by 1 callback(a current fallpit of PromiseBarrier). - * This ensures that their is a global mutex which can be called by a finite amount of callbacks. - * We should ensure that the mutex can only be locked by the first callback which has requrested it - * and only give the next callback the mutex lock once it's been released. - */ -export class Mutex { - private awaitingResolves = [] as Array<() => void>; - private locked = false; - - public isLocked() { - return this.locked; - } - - // Request a lock from the mutex. - // It should only return/resolve once the lock is granted. - public async lock() { - // Easiest path, the mutex is not locked. - // We lock the mutex and check if the mutex is locked. - // If it is locked, we wait for the mutex to be unlocked. - if (!this.locked) { - this.locked = true; - return; - } - return new Promise((resolve) => { - // Harder path, we will push the resolve - // into the array and let it be for now. - this.awaitingResolves.push(resolve); - }); - } - - // Unlock the mutex. - public unlock() { - if (!this.locked) { - logWarn('An unlocked mutex was tried to be unlocked.'); - return; - } - this.locked = false; - setTimeout(() => this.executeNextOperation()); - } - - // Execute the next lock actions. - private executeNextOperation() { - if (this.awaitingResolves.length > 0) { - // Get the first entry. - const resolve = this.awaitingResolves.shift(); - // Simply execute the resolve. - resolve(); - } - } -} diff --git a/src/utils/parsing.ts b/src/utils/parsing.ts new file mode 100644 index 000000000000..be444f2545ba --- /dev/null +++ b/src/utils/parsing.ts @@ -0,0 +1,85 @@ +import {getParenthesesRange} from './text'; + +const gradientLength = 'gradient'.length; +const conicGradient = 'conic-'; +const conicGradientLength = conicGradient.length; +const radialGradient = 'radial-'; +const linearGradient = 'linear-'; + +export interface parsedGradient { + typeGradient: string; + match: string; + hasComma: boolean; + index: number; + offset: number; +} + +// Parse the value according to the specifiction. +// +// Specification: https://drafts.csswg.org/css-images-4/#gradients +export function parseGradient(value: string): parsedGradient[] { + const result: parsedGradient[] = []; + + // Loop trough the value until we find the first `gradient` keyword. + // We will be using the indexOf to find the keyword. From their on + // we will check which specific graidient we are dealing with. + // Then we will try to parse the rest of the value as a gradient. + let index = 0; + let startIndex = conicGradient.length; + while ((index = value.indexOf('gradient', startIndex)) !== -1) { + let typeGradient: string; + // Now we check the type of gradient. + // the current index starts at `g` of gradient. + // So we have to do a reverse lookup to find the type of gradient. + // Because each type of gradient has a different length + // will we get the substring of the possible gradient types. + [linearGradient, radialGradient, conicGradient].find((possibleType) => { + if (index - possibleType.length >= 0) { + const possibleGradient = value.substring(index - possibleType.length, index); + if (possibleGradient === possibleType) { + // Check if the type has a `-` before the `type-gradient` keyword. + // If it does, it's a repeating gradient. + if (value.slice(index - possibleType.length - 10, index - possibleType.length - 1) === 'repeating') { + typeGradient = `repeating-${possibleType}gradient`; + return true; + } + if (value.slice(index - possibleType.length - 8, index - possibleType.length - 1) === '-webkit') { + typeGradient = `-webkit-${possibleType}gradient`; + return true; + } + typeGradient = `${possibleType}gradient`; + return true; + } + } + }); + + if (!typeGradient) { + break; + } + + // Now we know the type of gradient. + // We can go parse the rest of the value as a gradient. + const {start, end} = getParenthesesRange(value, index + gradientLength); + + const match = value.substring(start + 1, end - 1); + startIndex = end + 1 + conicGradientLength; + + result.push({ + typeGradient, + match, + // -gradient() is not within match, so in order to still "skip" that section + // we add that length as offset. + offset: typeGradient.length + 2, + index: index - typeGradient.length + gradientLength, + hasComma: true, + }); + } + + // Set the last result to not have a comma. + if (result.length) { + result[result.length - 1].hasComma = false; + } + + + return result; +} diff --git a/src/utils/platform.ts b/src/utils/platform.ts index ae66747a043d..180eaa269ad8 100644 --- a/src/utils/platform.ts +++ b/src/utils/platform.ts @@ -1,9 +1,30 @@ -const userAgent = typeof navigator === 'undefined' ? 'some useragent' : navigator.userAgent.toLowerCase(); -const platform = typeof navigator === 'undefined' ? 'some platform' : navigator.platform.toLowerCase(); +interface UserAgentData { + brands: Array<{ + brand: string; + version: string; + }>; + mobile: boolean; + platform: string; +} + +declare global { + interface NavigatorID { + userAgentData: UserAgentData; + } +} + +const isNavigatorDefined = typeof navigator !== 'undefined'; +const userAgent = isNavigatorDefined ? navigator.userAgentData ? + navigator.userAgentData.brands.map((brand) => `${brand.brand.toLowerCase()} ${brand.version}`).join(' ') : navigator.userAgent.toLowerCase() + : 'some useragent'; + +const platform = isNavigatorDefined ? navigator.userAgentData ? + navigator.userAgentData.platform.toLowerCase() : navigator.platform.toLowerCase() + : 'some platform'; export const isChromium = userAgent.includes('chrome') || userAgent.includes('chromium'); export const isThunderbird = userAgent.includes('thunderbird'); -export const isFirefox = userAgent.includes('firefox') || isThunderbird; +export const isFirefox = userAgent.includes('firefox') || userAgent.includes('librewolf') || isThunderbird; export const isVivaldi = userAgent.includes('vivaldi'); export const isYaBrowser = userAgent.includes('yabrowser'); export const isOpera = userAgent.includes('opr') || userAgent.includes('opera'); @@ -11,7 +32,7 @@ export const isEdge = userAgent.includes('edg'); export const isSafari = userAgent.includes('safari') && !isChromium; export const isWindows = platform.startsWith('win'); export const isMacOS = platform.startsWith('mac'); -export const isMobile = userAgent.includes('mobile'); +export const isMobile = (isNavigatorDefined && navigator.userAgentData) ? navigator.userAgentData.mobile : userAgent.includes('mobile'); export const isShadowDomSupported = typeof ShadowRoot === 'function'; export const isMatchMediaChangeEventListenerSupported = ( typeof MediaQueryList === 'function' && @@ -19,7 +40,7 @@ export const isMatchMediaChangeEventListenerSupported = ( ); export const chromiumVersion = (() => { - const m = userAgent.match(/chrom[e|ium]\/([^ ]+)/); + const m = userAgent.match(/chrom(?:e|ium)(?:\/| )([^ ]+)/); if (m && m[1]) { return m[1]; } @@ -51,3 +72,12 @@ export const isXMLHttpRequestSupported = typeof XMLHttpRequest === 'function'; export const isFetchSupported = typeof fetch === 'function'; export const isMV3 = (globalThis as any).chrome && (globalThis as any).chrome.runtime && (globalThis as any).chrome.runtime.getManifest && (globalThis as any).chrome.runtime.getManifest().manifest_version === 3; + +export const isCSSColorSchemePropSupported = (() => { + if (typeof document === 'undefined') { + return false; + } + const el = document.createElement('div'); + el.setAttribute('style', 'color-scheme: dark'); + return el.style && el.style.colorScheme === 'dark'; +})(); diff --git a/src/utils/throttle.ts b/src/utils/throttle.ts index d6ccc170edb7..f5734b4a3a9c 100644 --- a/src/utils/throttle.ts +++ b/src/utils/throttle.ts @@ -30,6 +30,8 @@ export function throttle any>(callback: T) { type Task = () => void; +declare const __TEST__: boolean; + export function createAsyncTasksQueue() { const tasks: Task[] = []; let frameId: number = null; @@ -40,6 +42,9 @@ export function createAsyncTasksQueue() { task(); } frameId = null; + if (__TEST__) { + document.dispatchEvent(new CustomEvent('__darkreader__test__asyncQueueComplete')); + } } function add(task: Task) { diff --git a/src/utils/time.ts b/src/utils/time.ts index ea042a20a195..933dec03885a 100644 --- a/src/utils/time.ts +++ b/src/utils/time.ts @@ -56,6 +56,8 @@ export function nextTimeInterval(time0: string, time1: string, date: Date = new // Schedule for todate at time a date.setHours(a[0]); date.setMinutes(a[1]); + date.setSeconds(0); + date.setMilliseconds(0); return date.getTime(); } @@ -64,6 +66,8 @@ export function nextTimeInterval(time0: string, time1: string, date: Date = new // Schedule for today at time b date.setHours(b[0]); date.setMinutes(b[1]); + date.setSeconds(0); + date.setMilliseconds(0); return date.getTime(); } diff --git a/src/utils/uid.ts b/src/utils/uid.ts index 639b5f4d3a43..fd8f4e1d6b1d 100644 --- a/src/utils/uid.ts +++ b/src/utils/uid.ts @@ -4,8 +4,7 @@ function hexify(number: number) { export function generateUID() { if ('randomUUID' in crypto) { - // TODO: remove any cast once type declarations are updated - const uuid = (crypto as any).randomUUID(); + const uuid = crypto.randomUUID(); return uuid.substring(0, 8) + uuid.substring(9, 13) + uuid.substring(14, 18) + uuid.substring(19, 23) + uuid.substring(24); } diff --git a/src/utils/url.ts b/src/utils/url.ts index 032dbfebad4f..6006eea93fcd 100644 --- a/src/utils/url.ts +++ b/src/utils/url.ts @@ -1,4 +1,4 @@ -import type {UserSettings} from '../definitions'; +import type {UserSettings, TabInfo} from '../definitions'; import {isIPV6, compareIPV6} from './ipv6'; import {isThunderbird} from './platform'; @@ -15,7 +15,7 @@ function fixBaseURL($url: string) { } export function parseURL($url: string, $base: string = null) { - const key = `${$url}${$base ? `;${ $base}` : ''}`; + const key = `${$url}${$base ? `;${$base}` : ''}`; if (parsedURLCache.has(key)) { return parsedURLCache.get(key); } @@ -72,6 +72,8 @@ export function getURLHostOrProtocol($url: string) { const url = new URL($url); if (url.host) { return url.host; + } else if (url.protocol === 'file:') { + return url.pathname; } return url.protocol; } @@ -204,7 +206,7 @@ export function isPDF(url: string) { return false; } -export function isURLEnabled(url: string, userSettings: UserSettings, {isProtected, isInDarkList}: {isProtected: boolean; isInDarkList: boolean}) { +export function isURLEnabled(url: string, userSettings: UserSettings, {isProtected, isInDarkList, isDarkThemeDetected}: Partial) { if (isProtected && !userSettings.enableForProtectedPages) { return false; } @@ -219,14 +221,16 @@ export function isURLEnabled(url: string, userSettings: UserSettings, {isProtect const isURLInUserList = isURLInList(url, userSettings.siteList); const isURLInEnabledList = isURLInList(url, userSettings.siteListEnabled); - if (userSettings.applyToListedOnly && !isURLInEnabledList) { - return isURLInUserList; + if (userSettings.applyToListedOnly) { + return isURLInEnabledList || isURLInUserList; } - - if (isURLInEnabledList && isInDarkList) { + if (isURLInEnabledList) { return true; } - return (!isInDarkList && !isURLInUserList); + if (isInDarkList || (userSettings.detectDarkTheme && isDarkThemeDetected)) { + return false; + } + return !isURLInUserList; } export function isFullyQualifiedDomain(candidate: string) { diff --git a/src/utils/validation.ts b/src/utils/validation.ts new file mode 100644 index 000000000000..9419f0de53b3 --- /dev/null +++ b/src/utils/validation.ts @@ -0,0 +1,200 @@ +import {DEFAULT_SETTINGS, DEFAULT_THEME} from '../defaults'; +import type {UserSettings, Theme, ThemePreset, CustomSiteConfig, TimeSettings, LocationSettings} from '../definitions'; + +function isBoolean(x: any): x is boolean { + return typeof x === 'boolean'; +} + +function isPlainObject(x: any): x is Record { + return typeof x === 'object' && x != null && !Array.isArray(x); +} + +function isArray(x: any) { + return Array.isArray(x); +} + +function isString(x: any): x is string { + return typeof x === 'string'; +} + +function isNonEmptyString(x: any): x is string { + return x && isString(x); +} + +function isNonEmptyArrayOfNonEmptyStrings(x: any): x is any[] { + return Array.isArray(x) && x.length > 0 && x.every((s) => isNonEmptyString(s)); +} + +function isRegExpMatch(regexp: RegExp) { + return (x: any): x is string => { + return isString(x) && x.match(regexp) != null; + }; +} + +const isTime = isRegExpMatch(/^((0?[0-9])|(1[0-9])|(2[0-3])):([0-5][0-9])$/); +function isNumber(x: any): x is number { + return typeof x === 'number' && !isNaN(x); +} + +function isNumberBetween(min: number, max: number) { + return (x: any): x is number => { + return isNumber(x) && x >= min && x <= max; + }; +} + +function isOneOf(...values: any[]) { + return (x: any) => values.includes(x); +} + +function hasRequiredProperties(obj: T, keys: Array) { + return keys.every((key) => obj.hasOwnProperty(key)); +} + +function createValidator() { + const errors: string[] = []; + + function validateProperty(obj: T, key: keyof T, validator: (x: any) => boolean, fallback: T) { + if (!obj.hasOwnProperty(key) || validator(obj[key])) { + return; + } + errors.push(`Unexpected value for "${key}": ${JSON.stringify(obj[key])}`); + obj[key] = fallback[key]; + } + + function validateArray(obj: T, key: keyof T, validator: (x: any) => boolean) { + if (!obj.hasOwnProperty(key)) { + return; + } + const wrongValues = new Set(); + const arr: any[] = obj[key] as any; + for (let i = 0; i < arr.length; i++) { + if (!validator(arr[i])) { + wrongValues.add(arr[i]); + arr.splice(i, 1); + i--; + } + } + if (wrongValues.size > 0) { + errors.push(`Array "${key}" has wrong values: ${Array.from(wrongValues).map((v) => JSON.stringify(v)).join('; ')}`); + } + } + + return {validateProperty, validateArray, errors}; +} + +export function validateSettings(settings: Partial) { + if (!isPlainObject(settings)) { + return {errors: ['Settings are not a plain object'], settings: DEFAULT_SETTINGS}; + } + + const {validateProperty, validateArray, errors} = createValidator(); + const isValidPresetTheme = (theme: Theme) => { + if (!isPlainObject(theme)) { + return false; + } + const {errors: themeErrors} = validateTheme(theme); + return themeErrors.length === 0; + }; + + validateProperty(settings, 'enabled', isBoolean, DEFAULT_SETTINGS); + validateProperty(settings, 'fetchNews', isBoolean, DEFAULT_SETTINGS); + + validateProperty(settings, 'theme', isPlainObject, DEFAULT_SETTINGS); + const {errors: themeErrors} = validateTheme(settings.theme); + errors.push(...themeErrors); + + validateProperty(settings, 'presets', isArray, DEFAULT_SETTINGS); + validateArray(settings, 'presets', (preset: ThemePreset) => { + const presetValidator = createValidator(); + if (!(isPlainObject(preset) && hasRequiredProperties(preset, ['id', 'name', 'urls', 'theme']))) { + return false; + } + presetValidator.validateProperty(preset, 'id', isNonEmptyString, preset); + presetValidator.validateProperty(preset, 'name', isNonEmptyString, preset); + presetValidator.validateProperty(preset, 'urls', isNonEmptyArrayOfNonEmptyStrings, preset); + presetValidator.validateProperty(preset, 'theme', isValidPresetTheme, preset); + return presetValidator.errors.length === 0; + }); + + validateProperty(settings, 'customThemes', isArray, DEFAULT_SETTINGS); + validateArray(settings, 'customThemes', (custom: CustomSiteConfig) => { + if (!(isPlainObject(custom) && hasRequiredProperties(custom, ['url', 'theme']))) { + return false; + } + const presetValidator = createValidator(); + presetValidator.validateProperty(custom, 'url', isNonEmptyArrayOfNonEmptyStrings, custom); + presetValidator.validateProperty(custom, 'theme', isValidPresetTheme, custom); + return presetValidator.errors.length === 0; + }); + + validateProperty(settings, 'siteList', isArray, DEFAULT_SETTINGS); + validateArray(settings, 'siteList', isNonEmptyString); + validateProperty(settings, 'siteListEnabled', isArray, DEFAULT_SETTINGS); + validateArray(settings, 'siteListEnabled', isNonEmptyString); + + validateProperty(settings, 'applyToListedOnly', isBoolean, DEFAULT_SETTINGS); + validateProperty(settings, 'changeBrowserTheme', isBoolean, DEFAULT_SETTINGS); + validateProperty(settings, 'syncSettings', isBoolean, DEFAULT_SETTINGS); + validateProperty(settings, 'syncSitesFixes', isBoolean, DEFAULT_SETTINGS); + validateProperty(settings, 'automation', isOneOf('', 'time', 'system', 'location'), DEFAULT_SETTINGS); + validateProperty(settings, 'automationBehaviour', isOneOf('OnOff', 'Scheme'), DEFAULT_SETTINGS); + + validateProperty(settings, 'time', (time: TimeSettings) => { + if (!isPlainObject(time)) { + return false; + } + const timeValidator = createValidator(); + timeValidator.validateProperty(time, 'activation', isTime, time); + timeValidator.validateProperty(time, 'deactivation', isTime, time); + return timeValidator.errors.length === 0; + }, DEFAULT_SETTINGS); + + validateProperty(settings, 'location', (location: LocationSettings) => { + if (!isPlainObject(location)) { + return false; + } + const locValidator = createValidator(); + const isValidLoc = (x: any) => x === null || isNumber(x); + locValidator.validateProperty(location, 'latitude', isValidLoc, location); + locValidator.validateProperty(location, 'longitude', isValidLoc, location); + return locValidator.errors.length === 0; + }, DEFAULT_SETTINGS); + + validateProperty(settings, 'previewNewDesign', isBoolean, DEFAULT_SETTINGS); + validateProperty(settings, 'enableForPDF', isBoolean, DEFAULT_SETTINGS); + validateProperty(settings, 'enableForProtectedPages', isBoolean, DEFAULT_SETTINGS); + validateProperty(settings, 'enableContextMenus', isBoolean, DEFAULT_SETTINGS); + validateProperty(settings, 'detectDarkTheme', isBoolean, DEFAULT_SETTINGS); + + return {errors, settings}; +} + +export function validateTheme(theme: Partial) { + if (!isPlainObject(theme)) { + return {errors: ['Theme is not a plain object'], theme: DEFAULT_THEME}; + } + + const {validateProperty, errors} = createValidator(); + validateProperty(theme, 'mode', isOneOf(0, 1), DEFAULT_THEME); + validateProperty(theme, 'brightness', isNumberBetween(0, 200), DEFAULT_THEME); + validateProperty(theme, 'contrast', isNumberBetween(0, 200), DEFAULT_THEME); + validateProperty(theme, 'grayscale', isNumberBetween(0, 100), DEFAULT_THEME); + validateProperty(theme, 'sepia', isNumberBetween(0, 100), DEFAULT_THEME); + validateProperty(theme, 'useFont', isBoolean, DEFAULT_THEME); + validateProperty(theme, 'fontFamily', isNonEmptyString, DEFAULT_THEME); + validateProperty(theme, 'textStroke', isNumberBetween(0, 1), DEFAULT_THEME); + validateProperty(theme, 'engine', isOneOf('dynamicTheme', 'staticTheme', 'cssFilter', 'svgFilter'), DEFAULT_THEME); + validateProperty(theme, 'stylesheet', isString, DEFAULT_THEME); + validateProperty(theme, 'darkSchemeBackgroundColor', isRegExpMatch(/^#[0-9a-f]{6}$/i), DEFAULT_THEME); + validateProperty(theme, 'darkSchemeTextColor', isRegExpMatch(/^#[0-9a-f]{6}$/i), DEFAULT_THEME); + validateProperty(theme, 'lightSchemeBackgroundColor', isRegExpMatch(/^#[0-9a-f]{6}$/i), DEFAULT_THEME); + validateProperty(theme, 'lightSchemeTextColor', isRegExpMatch(/^#[0-9a-f]{6}$/i), DEFAULT_THEME); + validateProperty(theme, 'scrollbarColor', (x: any) => x === '' || isRegExpMatch(/^(auto)|(#[0-9a-f]{6})$/i)(x), DEFAULT_THEME); + validateProperty(theme, 'selectionColor', isRegExpMatch(/^(auto)|(#[0-9a-f]{6})$/i), DEFAULT_THEME); + validateProperty(theme, 'styleSystemControls', isBoolean, DEFAULT_THEME); + validateProperty(theme, 'lightColorScheme', isNonEmptyString, DEFAULT_THEME); + validateProperty(theme, 'darkColorScheme', isNonEmptyString, DEFAULT_THEME); + validateProperty(theme, 'immediateModify', isBoolean, DEFAULT_THEME); + + return {errors, theme}; +} diff --git a/tasks/build.js b/tasks/build.js index 189f0da4c48d..ccb71fc8d0aa 100644 --- a/tasks/build.js +++ b/tasks/build.js @@ -11,6 +11,7 @@ const codeStyle = require('./code-style'); const zip = require('./zip'); const {runTasks} = require('./task'); const {log} = require('./utils'); +const {fork} = require('child_process'); const standardTask = [ clean, @@ -55,9 +56,28 @@ async function api() { } } +async function executeChildProcess(args) { + if (process.env.BUILD_CHILD) { + throw new Error('Infinite loop'); + } + const env = {...process.env, BUILD_CHILD: '1'}; + const child = fork(__filename, args, {env}); + // Send SIGINTs as SIGKILLs, which are not ignored + process.on('SIGINT', () => { + child.kill('SIGKILL'); + process.exit(130); + }); + return new Promise((resolve, reject) => child.on('error', reject).on('close', resolve)); +} + async function run() { const args = process.argv.slice(2); + // Enable Ctrl+C to cancel the build immediately + if (!process.env.BUILD_CHILD) { + return executeChildProcess(args); + } + if (args.includes('--release')) { await build({debug: false, watch: false}); } diff --git a/tasks/bundle-api.js b/tasks/bundle-api.js index 23b8e3b2f971..f49649a50726 100644 --- a/tasks/bundle-api.js +++ b/tasks/bundle-api.js @@ -1,36 +1,36 @@ +// @ts-check const rollup = require('rollup'); const rollupPluginNodeResolve = require('@rollup/plugin-node-resolve').default; +/** @type {any} */ const rollupPluginReplace = require('@rollup/plugin-replace'); -const rollupPluginTypescript = require('rollup-plugin-typescript2'); +/** @type {any} */ +const rollupPluginTypescript = require('@rollup/plugin-typescript'); const typescript = require('typescript'); const packageJSON = require('../package.json'); -const fs = require('fs-extra'); +const fs = require('fs'); const os = require('os'); const {createTask} = require('./task'); +const {rootDir, rootPath} = require('./paths'); async function bundleAPI({debug}) { - const src = 'src/api/index.ts'; + const src = rootPath('src/api/index.ts'); const dest = 'darkreader.js'; - const bundle = await rollup.rollup({ input: src, plugins: [ rollupPluginNodeResolve(), rollupPluginTypescript({ + rootDir, typescript, - tsconfig: 'src/tsconfig.json', - tsconfigOverride: { - compilerOptions: { - removeComments: true, - target: 'es5', - }, - }, - clean: true, - cacheRoot: debug ? `${fs.realpathSync(os.tmpdir())}/darkreader_api_typescript_cache` : null, + tsconfig: rootPath('src/api/tsconfig.json'), + removeComments: true, + noEmitOnError: true, + cacheDir: debug ? `${fs.realpathSync(os.tmpdir())}/darkreader_api_typescript_cache` : null, }), rollupPluginReplace({ preventAssignment: true, '__DEBUG__': 'false', + '__TEST__': 'false', }), ].filter((x) => x) }); diff --git a/tasks/bundle-css.js b/tasks/bundle-css.js index 45a378a6cf3b..437063050777 100644 --- a/tasks/bundle-css.js +++ b/tasks/bundle-css.js @@ -1,25 +1,26 @@ -const fs = require('fs-extra'); +// @ts-check const less = require('less'); const path = require('path'); -const {getDestDir, PLATFORM} = require('./paths'); +const {getDestDir, PLATFORM, rootPath} = require('./paths'); const reload = require('./reload'); const {createTask} = require('./task'); +const {copyFile, readFile, writeFile} = require('./utils'); function getLessFiles({debug}) { const dir = getDestDir({debug, platform: PLATFORM.CHROME}); return { - 'src/ui/devtools/style.less': `${dir}/ui/devtools/style.css`, - 'src/ui/popup/style.less': `${dir}/ui/popup/style.css`, - 'src/ui/stylesheet-editor/style.less': `${dir}/ui/stylesheet-editor/style.css`, + [rootPath('src/ui/devtools/style.less')]: `${dir}/ui/devtools/style.css`, + [rootPath('src/ui/popup/style.less')]: `${dir}/ui/popup/style.css`, + [rootPath('src/ui/stylesheet-editor/style.less')]: `${dir}/ui/stylesheet-editor/style.css`, }; } async function bundleCSSEntry({src, dest}) { - const srcDir = path.join(process.cwd(), path.dirname(src)); - const input = await fs.readFile(src, {encoding: 'utf8'}); + const srcDir = path.dirname(src); + const input = await readFile(src); const output = await less.render(input, {paths: [srcDir], math: 'always'}); const {css} = output; - await fs.outputFile(dest, css, {encoding: 'utf8'}); + await writeFile(dest, css); } async function bundleCSS({debug}) { @@ -28,16 +29,14 @@ async function bundleCSS({debug}) { await bundleCSSEntry({src, dest}); } const dir = getDestDir({debug, platform: PLATFORM.CHROME}); - const firefoxDir = getDestDir({debug, platform: PLATFORM.FIREFOX}); - const mv3Dir = getDestDir({debug, platform: PLATFORM.CHROME_MV3}); - const thunderBirdDir = getDestDir({debug, platform: PLATFORM.THUNDERBIRD}); - for (const dest of Object.values(files)) { - const ffDest = `${firefoxDir}/${dest.substring(dir.length + 1)}`; - const tbDest = `${thunderBirdDir}/${dest.substring(dir.length + 1)}`; - const mv3Dest = `${mv3Dir}/${dest.substring(dir.length + 1)}`; - await fs.copy(dest, ffDest); - await fs.copy(dest, mv3Dest); - await fs.copy(dest, tbDest); + const copyDirs = [PLATFORM.FIREFOX, PLATFORM.CHROME_MV3, PLATFORM.THUNDERBIRD].map((platform) => { + return getDestDir({debug, platform}); + }); + for (const file of Object.values(files)) { + for (const copyDir of copyDirs) { + const copyTo = `${copyDir}/${file.substring(dir.length + 1)}`; + await copyFile(file, copyTo); + } } } diff --git a/tasks/bundle-html.js b/tasks/bundle-html.js index 1fcf9af09193..86aa8f697f4b 100644 --- a/tasks/bundle-html.js +++ b/tasks/bundle-html.js @@ -1,97 +1,32 @@ -const fs = require('fs-extra'); -const {getDestDir, PLATFORM} = require('./paths'); +// @ts-check +const {getDestDir, PLATFORM, rootPath} = require('./paths'); const reload = require('./reload'); const {createTask} = require('./task'); - -const enLocale = fs.readFileSync('src/_locales/en.config', {encoding: 'utf8'}).replace(/^#.*?$/gm, ''); -global.chrome = global.chrome || {}; -global.chrome.i18n = global.chrome.i18n || {}; -global.chrome.i18n.getMessage = global.chrome.i18n.getMessage || ((name) => { - const index = enLocale.indexOf(`@${name}`); - if (index < 0) { - throw new Error(`Message @${name} not found`); - } - const start = index + name.length + 1; - let end = enLocale.indexOf('@', start); - if (end < 0) { - end = enLocale.length; - } - const message = enLocale.substring(start, end).trim(); - return message; -}); -global.chrome.i18n.getUILanguage = global.chrome.i18n.getUILanguage || (() => 'en-US'); - -const tsConfig = require('../src/tsconfig.json'); -require('ts-node').register({ - transpileOnly: true, - compilerOptions: { - ...tsConfig.compilerOptions, - module: 'commonjs', - }, -}); -require('tsconfig-paths').register({ - baseUrl: './', - paths: { - 'malevic/*': ['node_modules/malevic/umd/*'], - 'malevic': ['node_modules/malevic/umd/index'], - } -}); -const Malevic = require('malevic/umd/index'); -const MalevicString = require('malevic/umd/string'); -const DevToolsBody = require('../src/ui/devtools/components/body').default; -const PopupBody = require('../src/ui/popup/components/body').default; -const CSSEditorBody = require('../src/ui/stylesheet-editor/components/body').default; -const {getMockData, getMockActiveTabInfo} = require('../src/ui/connect/mock'); +const {copyFile, readFile, writeFile} = require('./utils'); const pages = [ - { - cwdPath: 'ui/popup/index.html', - rootComponent: PopupBody, - props: { - data: getMockData({isReady: false}), - tab: getMockActiveTabInfo(), - actions: null, - }, - }, - { - cwdPath: 'ui/devtools/index.html', - rootComponent: DevToolsBody, - props: { - data: getMockData({isReady: false}), - tab: getMockActiveTabInfo(), - actions: null, - }, - }, - { - cwdPath: 'ui/stylesheet-editor/index.html', - rootComponent: CSSEditorBody, - props: { - data: getMockData({isReady: false}), - tab: getMockActiveTabInfo(), - actions: null, - }, - }, + 'ui/popup/index.html', + 'ui/devtools/index.html', + 'ui/stylesheet-editor/index.html', ]; -async function bundleHTMLPage({cwdPath, rootComponent, props}, {debug}) { - let html = await fs.readFile(`src/${cwdPath}`, 'utf8'); - const bodyText = MalevicString.stringify(Malevic.m(rootComponent, props)); - html = html.replace('$BODY', bodyText); +async function bundleHTMLPage({cwdPath}, {debug}) { + let html = await readFile(rootPath(`src/${cwdPath}`)); const getPath = (dir) => `${dir}/${cwdPath}`; const outPath = getPath(getDestDir({debug, platform: PLATFORM.CHROME})); - const firefoxPath = getPath(getDestDir({debug, platform: PLATFORM.FIREFOX})); - const mv3Path = getPath(getDestDir({debug, platform: PLATFORM.CHROME_MV3})); - const thunderBirdPath = getPath(getDestDir({debug, platform: PLATFORM.THUNDERBIRD})); - await fs.outputFile(outPath, html); - await fs.copy(outPath, firefoxPath); - await fs.copy(outPath, mv3Path); - await fs.copy(outPath, thunderBirdPath); + const copyToPaths = [PLATFORM.FIREFOX, PLATFORM.CHROME_MV3, PLATFORM.THUNDERBIRD].map((platform) => { + return getPath(getDestDir({debug, platform})); + }); + await writeFile(outPath, html); + for (const copyTo of copyToPaths) { + await copyFile(outPath, copyTo); + } } async function bundleHTML({debug}) { for (const page of pages) { - await bundleHTMLPage(page, {debug}); + await bundleHTMLPage({cwdPath: page}, {debug}); } } @@ -102,8 +37,8 @@ function getSrcPath(cwdPath) { async function rebuildHTML(changedFiles) { await Promise.all( pages - .filter((page) => changedFiles.some((changed) => changed === getSrcPath(page.cwdPath))) - .map((page) => bundleHTMLPage(page, {debug: true})) + .filter((page) => changedFiles.some((changed) => changed === getSrcPath(page))) + .map((page) => bundleHTMLPage({cwdPath: page}, {debug: true})) ); } @@ -111,7 +46,7 @@ module.exports = createTask( 'bundle-html', bundleHTML, ).addWatcher( - pages.map((page) => getSrcPath(page.cwdPath)), + pages.map((page) => getSrcPath(page)), async (changedFiles) => { await rebuildHTML(changedFiles); reload({type: reload.UI}); diff --git a/tasks/bundle-js.js b/tasks/bundle-js.js index c8a1fdc1743b..2c03b5b30004 100644 --- a/tasks/bundle-js.js +++ b/tasks/bundle-js.js @@ -1,23 +1,25 @@ -const fs = require('fs-extra'); +// @ts-check +const fs = require('fs'); const os = require('os'); const rollup = require('rollup'); const rollupPluginNodeResolve = require('@rollup/plugin-node-resolve').default; +/** @type {any} */ const rollupPluginReplace = require('@rollup/plugin-replace'); -const rollupPluginTypescript = require('rollup-plugin-typescript2'); +/** @type {any} */ +const rollupPluginTypescript = require('@rollup/plugin-typescript'); const typescript = require('typescript'); -const {getDestDir, PLATFORM} = require('./paths'); +const {getDestDir, PLATFORM, rootDir, rootPath} = require('./paths'); const reload = require('./reload'); const {PORT} = reload; const {createTask} = require('./task'); +const {copyFile, readFile, writeFile} = require('./utils'); async function copyToBrowsers({cwdPath, debug}) { const destPath = `${getDestDir({debug, platform: PLATFORM.CHROME})}/${cwdPath}`; - const ffDestPath = `${getDestDir({debug, platform: PLATFORM.FIREFOX})}/${cwdPath}`; - const mv3DestPath = `${getDestDir({debug, platform: PLATFORM.CHROME_MV3})}/${cwdPath}`; - const tbDestPath = `${getDestDir({debug, platform: PLATFORM.THUNDERBIRD})}/${cwdPath}`; - await fs.copy(destPath, ffDestPath); - await fs.copy(destPath, mv3DestPath); - await fs.copy(destPath, tbDestPath); + for (const platform of [PLATFORM.FIREFOX, PLATFORM.CHROME_MV3, PLATFORM.THUNDERBIRD]) { + const path = `${getDestDir({debug, platform})}/${cwdPath}`; + await copyFile(destPath, path); + } } function replace(str, find, replace) { @@ -44,8 +46,9 @@ function patchMV3JS(/** @type {string} */code) { * @property {string} src * @property {string} dest * @property {string} reloadType - * @property {({debug}) => Promise} postBuild + * @property {(({debug}) => Promise) | undefined} postBuild * @property {string[]} watchFiles + * @property {(typeof PLATFORM.CHROME) | undefined} platform */ /** @type {JSEntry[]} */ @@ -60,12 +63,12 @@ const jsEntries = [ // Prior to Chrome 93, background service worker had to be in top-level directory const mv3DestPath = `${getDestDir({debug, platform: PLATFORM.CHROME_MV3})}/background.js`; const tbDestPath = `${getDestDir({debug, platform: PLATFORM.THUNDERBIRD})}/${this.dest}`; - const code = await fs.readFile(destPath, 'utf8'); + const code = await readFile(destPath); const patchedCodeFirefox = patchFirefoxJS(code); const patchedCodeMV3 = patchMV3JS(code); - await fs.outputFile(ffDestPath, patchedCodeFirefox); - await fs.outputFile(mv3DestPath, patchedCodeMV3); - await fs.copy(ffDestPath, tbDestPath); + await writeFile(ffDestPath, patchedCodeFirefox); + await writeFile(mv3DestPath, patchedCodeMV3); + await copyFile(ffDestPath, tbDestPath); }, watchFiles: null, }, @@ -78,6 +81,20 @@ const jsEntries = [ }, watchFiles: null, }, + { + src: 'src/inject/dynamic-theme/mv3-injector.ts', + dest: 'inject/injector.js', + reloadType: reload.FULL, + platform: PLATFORM.CHROME_MV3, + watchFiles: null, + }, + { + src: 'src/inject/dynamic-theme/mv3-proxy.ts', + dest: 'inject/proxy.js', + reloadType: reload.FULL, + platform: PLATFORM.CHROME_MV3, + watchFiles: null, + }, { src: 'src/inject/fallback.ts', dest: 'inject/fallback.js', @@ -119,38 +136,37 @@ const jsEntries = [ async function bundleJS(/** @type {JSEntry} */entry, {debug, watch}) { const {src, dest} = entry; const bundle = await rollup.rollup({ - input: src, + input: rootPath(src), plugins: [ rollupPluginNodeResolve(), rollupPluginTypescript({ + rootDir, typescript, - tsconfig: 'src/tsconfig.json', - tsconfigOverride: { - compilerOptions: { - noImplicitAny: debug ? false : true, - removeComments: debug ? false : true, - sourceMap: debug ? true : false, - }, - }, - clean: debug ? false : true, - cacheRoot: debug ? `${fs.realpathSync(os.tmpdir())}/darkreader_typescript_cache` : null, + tsconfig: rootPath('src/tsconfig.json'), + noImplicitAny: debug ? false : true, + removeComments: debug ? false : true, + sourceMap: debug ? true : false, + inlineSources: debug ? true : false, + noEmitOnError: true, + cacheDir: debug ? `${fs.realpathSync(os.tmpdir())}/darkreader_typescript_cache` : null, }), rollupPluginReplace({ preventAssignment: true, '__DEBUG__': debug ? 'true' : 'false', '__PORT__': watch ? String(PORT) : '-1', + '__TEST__': 'false', '__WATCH__': watch ? 'true' : 'false', }), ].filter((x) => x) }); entry.watchFiles = bundle.watchFiles; await bundle.write({ - file: `${getDestDir({debug, platform: PLATFORM.CHROME})}/${dest}`, + file: `${getDestDir({debug, platform: entry.platform || PLATFORM.CHROME})}/${dest}`, strict: true, format: 'iife', sourcemap: debug ? 'inline' : false, }); - await entry.postBuild({debug}); + entry.postBuild && await entry.postBuild({debug}); } function getWatchFiles() { diff --git a/tasks/bundle-locales.js b/tasks/bundle-locales.js index c9376df6efe1..78831e39b907 100644 --- a/tasks/bundle-locales.js +++ b/tasks/bundle-locales.js @@ -1,10 +1,12 @@ -const fs = require('fs-extra'); -const {getDestDir, PLATFORM} = require('./paths'); +// @ts-check +const fs = require('fs').promises; +const {getDestDir, PLATFORM, rootPath} = require('./paths'); const reload = require('./reload'); const {createTask} = require('./task'); +const {readFile, writeFile} = require('./utils'); async function bundleLocale(/** @type {string} */filePath, {debug}) { - let file = await fs.readFile(filePath, 'utf8'); + let file = await readFile(filePath); file = file.replace(/^#.*?$/gm, ''); const messages = {}; @@ -27,18 +29,14 @@ async function bundleLocale(/** @type {string} */filePath, {debug}) { const locale = fileName.substring(0, fileName.lastIndexOf('.')).replace('-', '_'); const json = `${JSON.stringify(messages, null, 4)}\n`; const getOutputPath = (dir) => `${dir}/_locales/${locale}/messages.json`; - const chromeDir = getDestDir({debug, platform: PLATFORM.CHROME}); - const firefoxDir = getDestDir({debug, platform: PLATFORM.FIREFOX}); - const mv3Dir = getDestDir({debug, platform: PLATFORM.CHROME_MV3}); - const thunderBirdDir = getDestDir({debug, platform: PLATFORM.THUNDERBIRD}); - await fs.outputFile(getOutputPath(chromeDir), json); - await fs.outputFile(getOutputPath(mv3Dir), json); - await fs.outputFile(getOutputPath(firefoxDir), json); - await fs.outputFile(getOutputPath(thunderBirdDir), json); + for (const platform of Object.values(PLATFORM)) { + const dir = getDestDir({debug, platform}); + await writeFile(getOutputPath(dir), json); + } } async function bundleLocales({debug}) { - const localesSrcDir = 'src/_locales'; + const localesSrcDir = rootPath('src/_locales'); const list = await fs.readdir(localesSrcDir); for (const name of list) { if (!name.endsWith('.config')) { diff --git a/tasks/check-exists.js b/tasks/check-exists.js new file mode 100644 index 000000000000..fae04fbeaa2c --- /dev/null +++ b/tasks/check-exists.js @@ -0,0 +1,9 @@ +// @ts-check +const {existsSync} = require('fs'); + +const lastArg = process.argv.pop(); +if (lastArg === __filename) { + throw new Error('Error: File or directory expected as a single argument'); +} + +process.exit(existsSync(lastArg) ? 0 : 1); diff --git a/tasks/clean.js b/tasks/clean.js index ba7cde183982..eac0bad62d4a 100644 --- a/tasks/clean.js +++ b/tasks/clean.js @@ -1,12 +1,12 @@ -const fs = require('fs-extra'); +// @ts-check const {getDestDir, PLATFORM} = require('./paths'); const {createTask} = require('./task'); +const {removeFolder} = require('./utils'); async function clean({debug}) { - await fs.remove(getDestDir({debug, platform: PLATFORM.CHROME})); - await fs.remove(getDestDir({debug, platform: PLATFORM.FIREFOX})); - await fs.remove(getDestDir({debug, platform: PLATFORM.CHROME_MV3})); - await fs.remove(getDestDir({debug, platform: PLATFORM.THUNDERBIRD})); + for (const platform of Object.values(PLATFORM)) { + await removeFolder(getDestDir({debug, platform})); + } } module.exports = createTask( diff --git a/tasks/code-style.js b/tasks/code-style.js index fe7a7d59b7cb..3879bed0f4d3 100644 --- a/tasks/code-style.js +++ b/tasks/code-style.js @@ -1,10 +1,10 @@ -const fs = require('fs-extra'); -const globby = require('globby'); +// @ts-check const prettier = require('prettier'); const {getDestDir, PLATFORM} = require('./paths'); const {createTask} = require('./task'); -const {log} = require('./utils'); +const {log, readFile, writeFile, getPaths} = require('./utils'); +/** @type {import('prettier').Options} */ const options = { arrowParens: 'always', bracketSpacing: false, @@ -20,15 +20,15 @@ const extensions = ['html', 'css', 'js']; async function codeStyle({debug}) { const dir = getDestDir({debug, platform: PLATFORM.CHROME}); - const files = await globby(extensions.map((ext) => `${dir}/**/*.${ext}`)); + const files = await getPaths(extensions.map((ext) => `${dir}/**/*.${ext}`)); for (const file of files) { - const code = await fs.readFile(file, 'utf8'); + const code = await readFile(file); const formatted = prettier.format(code, { ...options, filepath: file, }); if (code !== formatted) { - await fs.outputFile(file, formatted); + await writeFile(file, formatted); debug && log.ok(file); } } diff --git a/tasks/copy.js b/tasks/copy.js index 2b2320d6383d..f04f63057172 100644 --- a/tasks/copy.js +++ b/tasks/copy.js @@ -1,8 +1,8 @@ -const fs = require('fs-extra'); -const globby = require('globby'); +// @ts-check const {getDestDir, PLATFORM} = require('./paths'); const reload = require('./reload'); const {createTask} = require('./task'); +const {pathExists, copyFile, readFile, writeFile, getPaths} = require('./utils'); const srcDir = 'src'; const cwdPaths = [ @@ -19,25 +19,35 @@ function getCwdPath(/** @type {string} */srcPath) { return srcPath.substring(srcDir.length + 1); } +async function readJSON(path) { + const file = await readFile(path); + return JSON.parse(file); +} + +async function writeJSON(path, json) { + const content = JSON.stringify(json, null, 4); + return await writeFile(path, content); +} + async function patchManifestFirefox({debug, platform}) { - const manifest = await fs.readJson(`${srcDir}/manifest.json`); - const fireFoxPatch = await fs.readJson(`${srcDir}/manifest-firefox.json`); - const thunderBirdPatch = await fs.readJson(`${srcDir}/manifest-thunderbird.json`); + const manifest = await readJSON(`${srcDir}/manifest.json`); + const fireFoxPatch = await readJSON(`${srcDir}/manifest-firefox.json`); + const thunderBirdPatch = await readJSON(`${srcDir}/manifest-thunderbird.json`); const patched = platform === PLATFORM.FIREFOX ? {...manifest, ...fireFoxPatch} : {...manifest, ...thunderBirdPatch}; const destDir = getDestDir({debug, platform}); - await fs.writeJson(`${destDir}/manifest.json`, patched, {spaces: 4}); + await writeJSON(`${destDir}/manifest.json`, patched); } async function patchManifestMV3({debug}) { - const manifest = await fs.readJson(`${srcDir}/manifest.json`); - const mv3Patch = await fs.readJson(`${srcDir}/manifest-mv3.json`); + const manifest = await readJSON(`${srcDir}/manifest.json`); + const mv3Patch = await readJSON(`${srcDir}/manifest-mv3.json`); const patched = {...manifest, ...mv3Patch}; patched.browser_action = undefined; const destDir = getDestDir({debug, platform: PLATFORM.CHROME_MV3}); - await fs.writeJson(`${destDir}/manifest.json`, patched, {spaces: 4}); + await writeJSON(`${destDir}/manifest.json`, patched); } -async function copyFile(path, {debug, platform}) { +async function copyManifest(path, {debug, platform}) { const cwdPath = getCwdPath(path); const destDir = getDestDir({debug, platform}); if ((platform === PLATFORM.FIREFOX || platform === PLATFORM.THUNDERBIRD) && cwdPath === 'manifest.json') { @@ -49,17 +59,16 @@ async function copyFile(path, {debug, platform}) { } else { const src = `${srcDir}/${cwdPath}`; const dest = `${destDir}/${cwdPath}`; - await fs.copy(src, dest); + await copyFile(src, dest); } } async function copy({debug}) { - const files = await globby(paths); + const files = await getPaths(paths); for (const file of files) { - await copyFile(file, {debug, platform: PLATFORM.CHROME}); - await copyFile(file, {debug, platform: PLATFORM.FIREFOX}); - await copyFile(file, {debug, platform: PLATFORM.CHROME_MV3}); - await copyFile(file, {debug, platform: PLATFORM.THUNDERBIRD}); + for (const platform of Object.values(PLATFORM)) { + await copyManifest(file, {debug, platform}); + } } } @@ -70,11 +79,10 @@ module.exports = createTask( paths, async (changedFiles) => { for (const file of changedFiles) { - if (await fs.exists(file)) { - await copyFile(file, {debug: true, platform: PLATFORM.CHROME}); - await copyFile(file, {debug: true, platform: PLATFORM.FIREFOX}); - await copyFile(file, {debug: true, platform: PLATFORM.CHROME_MV3}); - await copyFile(file, {debug: true, platform: PLATFORM.THUNDERBIRD}); + if (await pathExists(file)) { + for (const platform of Object.values(PLATFORM)) { + await copyManifest(file, {debug: true, platform}); + } } } reload({type: reload.FULL}); diff --git a/tasks/paths.js b/tasks/paths.js index ec39fd70e6ed..3de77f13abd3 100644 --- a/tasks/paths.js +++ b/tasks/paths.js @@ -1,3 +1,8 @@ +const {dirname, join} = require('path'); +const packageJson = require.resolve('../package.json'); +const rootDir = dirname(packageJson); +const rootPath = (...paths) => join(rootDir, ...paths); + module.exports = { PLATFORM: { CHROME: 'chrome', @@ -8,5 +13,11 @@ module.exports = { getDestDir: function ({debug, platform}) { const buildTypeDir = `build/${debug ? 'debug' : 'release'}`; return `${buildTypeDir}/${platform}`; - } + }, + getTestDestDir: function () { + return `build/tests`; + }, + + rootDir, + rootPath, }; diff --git a/tasks/task.js b/tasks/task.js index 163f7aeb98be..e325b06a760a 100644 --- a/tasks/task.js +++ b/tasks/task.js @@ -66,7 +66,7 @@ class Task { /** * @param {string} name - * @param {(options: TaskOptions) => void | Promise} run + * @param {(options: TaskOptions) => void | Promise} run */ function createTask(name, run) { return new Task(name, run); diff --git a/tasks/translate.js b/tasks/translate.js new file mode 100644 index 000000000000..54d723992aa0 --- /dev/null +++ b/tasks/translate.js @@ -0,0 +1,93 @@ +// @ts-check +const fs = require('fs').promises; +const {readFile, writeFile, httpsRequest, timeout, log} = require('./utils'); + +// To use this tool: +// 1. Edit a line in en.config. +// 2. Run `npm run translate-line 123` where 123 is a line number starting from 1. +// 3. The line will be translated and written into other locales. +// TODO: If neccessary, new @id and empty lines should be copied as well. +// TODO: Serbian translates into Cyrillic, but it is somehow possible to do Latin. + +/** @typedef {{locale: string; file: string; content: string}} LocaleFile */ + +const dir = 'src/_locales'; + +/** + * Translates `en` locale line for all locales + * @param {number} lineNumber Line number starting from 1 + */ +async function translateEnLine(lineNumber) { + log(`Translating line ${lineNumber}`); + + const locales = await getAllLocales(); + const enLocale = locales.find((l) => l.locale === 'en'); + const otherLocales = locales.filter((l) => l.locale !== 'en'); + + const enLines = enLocale.content.split('\n'); + const index = lineNumber - 1; + const line = enLines[index]; + + for (const l of otherLocales) { + await timeout(1000); + const translated = await translate(line, l.locale); + const lines = l.content.split('\n'); + lines.splice( + index, + // Replace the line if already exists + lines.length === enLines.length ? 1 : 0, + translated, + ); + await writeFile(`${dir}/${l.file}`, lines.join('\n')); + log(`${l.locale}: ${translated}`); + } + + log.ok('Translation done'); +} + +/** + * @returns {Promise} + */ +async function getAllLocales() { + const fileList = await fs.readdir(dir); + + /** @type {LocaleFile[]} */ + const locales = []; + + for (const file of fileList) { + if (!file.endsWith('.config')) { + continue; + } + const locale = file.substring(0, file.lastIndexOf('.config')); + const content = await readFile(`${dir}/${file}`); + locales.push({locale, file, content}); + } + + return locales; +} + +/** + * @param {string} text + * @param {string} lang + * @return {Promise} + */ +async function translate(text, lang) { + const url = new URL('https://translate.googleapis.com/translate_a/single'); + url.search = (new URLSearchParams({ + client: 'gtx', + sl: 'en-US', + tl: lang, + dt: 't', + dj: '1', + q: text, + })).toString(); + const response = await httpsRequest(url.toString()); + const translation = JSON.parse(response.text()); + return translation.sentences.map((s) => s.trans).join(''); +} + +const args = process.argv.slice(2); +if (args[0] === '--line') { + const lineNumber = Number(args[1]); + translateEnLine(lineNumber); +} diff --git a/tasks/utils.js b/tasks/utils.js index 0921d59d9a79..04c30be56f01 100644 --- a/tasks/utils.js +++ b/tasks/utils.js @@ -1,25 +1,145 @@ +// @ts-check +const fs = require('fs').promises; +const https = require('https'); +const path = require('path'); + +/** @type {{[color: string]: (text: string) => string}} */ const colors = Object.entries({ gray: '\x1b[90m', green: '\x1b[32m', red: '\x1b[31m', yellow: '\x1b[33m', -}).reduce((map, [key, value]) => Object.assign(map, {[key]: (text) => `${value}${text}\x1b[0m`}), {}); +}).reduce((map, [key, value]) => Object.assign(map, {[key]: (/** @type {string} */text) => `${value}${text}\x1b[0m`}), {}); +/** + * @param {string} text + * @returns + */ function logWithTime(text) { const now = new Date(); const hours = now.getHours(); const minutes = now.getMinutes(); const seconds = now.getSeconds(); - const leftpad = (n) => String(n).padStart(2, '0'); + const leftpad = (/** @type {number} */n) => String(n).padStart(2, '0'); return console.log(`${colors.gray([hours, minutes, seconds].map(leftpad).join(':'))} ${text}`); } -const log = Object.assign((text) => logWithTime(text), { - ok: (text) => logWithTime(colors.green(text)), - warn: (text) => logWithTime(colors.yellow(text)), - error: (text) => logWithTime(colors.red(text)), +const log = Object.assign((/** @type {string} */text) => logWithTime(text), { + ok: (/** @type {string} */text) => logWithTime(colors.green(text)), + warn: (/** @type {string} */text) => logWithTime(colors.yellow(text)), + error: (/** @type {string} */text) => logWithTime(colors.red(text)), }); +/** + * @param {string} dest + * @returns {Promise} + */ +async function pathExists(dest) { + try { + await fs.access(dest); + return true; + } catch (err) { + return false; + } +} + +/** + * @param {string} dir + * @returns {Promise} + */ +async function removeFolder(dir) { + if (await pathExists(dir)) { + await fs.rm(dir, {recursive: true}); + } +} + +/** + * @param {string} dest + * @returns {Promise} + */ +async function mkDirIfMissing(dest) { + const dir = path.dirname(dest); + if (!(await pathExists(dir))) { + await fs.mkdir(dir, {recursive: true}); + } +} + +/** + * @param {string} src + * @param {string} dest + * @returns {Promise} + */ +async function copyFile(src, dest) { + await mkDirIfMissing(dest); + await fs.copyFile(src, dest); +} + +/** + * @param {string} src + * @returns {Promise} + */ +async function readFile(src) { + return await fs.readFile(src, 'utf8'); +} + +/** + * @param {string} dest + * @param {string} content + * @returns {Promise} + */ +async function writeFile(dest, content) { + await mkDirIfMissing(dest); + await fs.writeFile(dest, content, 'utf8'); +} + +/** + * @param {string | string[]} patterns + * @returns {Promise} + */ +async function getPaths(patterns) { + const {globby} = await import('globby'); + return await globby(patterns); +} + +/** + * @param {number} delay + * @returns {Promise} + */ +function timeout(delay) { + return new Promise((resolve) => setTimeout(resolve, delay)); +} + +/** + * @param {string} url + * @returns {Promise<{buffer(): Buffer; text(encoding?: string): string; type(): string}>} + */ +function httpsRequest(url) { + return new Promise((resolve) => { + /** @type {any[]} */ + const data = []; + https.get(url, (response) => { + response + .on('data', (chunk) => data.push(chunk)) + .on('end', () => { + const buffer = Buffer.concat(data); + resolve({ + buffer: () => buffer, + text: (/** @type {BufferEncoding} */encoding = 'utf8') => buffer.toString(encoding), + type: () => response.headers['content-type'], + }); + }); + }); + }); +} + module.exports = { log, + copyFile, + pathExists, + readFile, + removeFolder, + writeFile, + getPaths, + httpsRequest, + timeout, }; diff --git a/tasks/zip.js b/tasks/zip.js index e89e5944f9bb..aaa483ee9c10 100644 --- a/tasks/zip.js +++ b/tasks/zip.js @@ -1,20 +1,23 @@ +// @ts-check const fs = require('fs'); -const globby = require('globby'); const yazl = require('yazl'); const {getDestDir, PLATFORM} = require('./paths'); const {createTask} = require('./task'); +const {getPaths} = require('./utils'); function archiveFiles({files, dest, cwd}) { return new Promise((resolve) => { const archive = new yazl.ZipFile(); files.forEach((file) => archive.addFile(file, file.startsWith(`${cwd}/`) ? file.substring(cwd.length + 1) : file)); - archive.outputStream.pipe(fs.createWriteStream(dest)).on('close', () => resolve()); + /** @type {any} */ + const writeStream = fs.createWriteStream(dest); + archive.outputStream.pipe(writeStream).on('close', () => resolve()); archive.end(); }); } async function archiveDirectory({dir, dest}) { - const files = await globby(`${dir}/**/*.*`); + const files = await getPaths(`${dir}/**/*.*`); await archiveFiles({files, dest, cwd: dir}); } diff --git a/tests/browser/coverage.js b/tests/browser/coverage.js index 503cb6fde90f..452637ff95d5 100644 --- a/tests/browser/coverage.js +++ b/tests/browser/coverage.js @@ -1,6 +1,6 @@ // @ts-check -const fs = require('fs-extra'); const path = require('path'); +const {writeFile} = require('../../tasks/utils'); /** @typedef {{text: string; covered: boolean}} CodePart */ @@ -114,7 +114,7 @@ async function generateHTMLCoverageReport(dir, info) { lines.push(''); lines.push(''); - await fs.outputFile(path.join(dir, `${name}.html`), lines.join('\n')); + await writeFile(path.join(dir, `${name}.html`), lines.join('\n')); } /** @@ -150,7 +150,7 @@ async function generateIndexHTMLCoveragePage(dir, info) { lines.push(''); lines.push(''); - await fs.outputFile(path.join(dir, 'index.html'), lines.join('\n')); + await writeFile(path.join(dir, 'index.html'), lines.join('\n')); } /** diff --git a/tests/browser/dynamic/inline-override.tests.ts b/tests/browser/dynamic/inline-override.tests.ts index 49ce3ee0a764..0558005f44db 100644 --- a/tests/browser/dynamic/inline-override.tests.ts +++ b/tests/browser/dynamic/inline-override.tests.ts @@ -1,4 +1,4 @@ -import {multiline} from '../../test-utils'; +import {multiline} from '../../support/test-utils'; describe('Inline style override', () => { const inlineStyleMarkup = multiline( diff --git a/tests/browser/dynamic/link-override.tests.ts b/tests/browser/dynamic/link-override.tests.ts index eb95d12daca6..4ac020fb3967 100644 --- a/tests/browser/dynamic/link-override.tests.ts +++ b/tests/browser/dynamic/link-override.tests.ts @@ -1,4 +1,4 @@ -import {multiline, timeout} from '../../test-utils'; +import {multiline, timeout} from '../../support/test-utils'; describe('Link override', () => { it('should override link style', async () => { diff --git a/tests/browser/dynamic/style-override.tests.ts b/tests/browser/dynamic/style-override.tests.ts index 931e1701067a..a2f34fda3c01 100644 --- a/tests/browser/dynamic/style-override.tests.ts +++ b/tests/browser/dynamic/style-override.tests.ts @@ -1,4 +1,4 @@ -import {multiline} from '../../test-utils'; +import {multiline} from '../../support/test-utils'; describe('Style override', () => { it('should override user agent style', async () => { diff --git a/tests/browser/e2e/devtools.tests.ts b/tests/browser/e2e/devtools.tests.ts index 2c197c9b6a1b..82028b747e30 100644 --- a/tests/browser/e2e/devtools.tests.ts +++ b/tests/browser/e2e/devtools.tests.ts @@ -1,4 +1,4 @@ -import {multiline, timeout} from '../../test-utils'; +import {multiline, timeout} from '../../support/test-utils'; async function loadBasicPage() { await loadTestPage({ diff --git a/tests/browser/e2e/toggle.tests.ts b/tests/browser/e2e/toggle.tests.ts index 38cae6ce88ef..8726b7b86697 100644 --- a/tests/browser/e2e/toggle.tests.ts +++ b/tests/browser/e2e/toggle.tests.ts @@ -1,6 +1,6 @@ -import {multiline, timeout} from '../../test-utils'; +import {multiline, timeout} from '../../support/test-utils'; -async function loadBasicPage() { +async function loadBasicPage(header = 'E2E test page') { await loadTestPage({ '/': multiline( '', @@ -11,7 +11,7 @@ async function loadBasicPage() { ' ', '', '', - '

E2E test page

', + `

${header}

`, '

Text

', ' Link', '', @@ -20,9 +20,14 @@ async function loadBasicPage() { }); } +async function emulateMedia(name: string, value: string) { + await page.emulateMediaFeatures([{name, value}]); + await backgroundUtils.emulateMedia(name, value); +} + describe('Toggling The Extension', () => { it('should turn On/Off', async () => { - await loadBasicPage(); + await loadBasicPage('Toggle on/off'); await expect(page.evaluate(() => getComputedStyle(document.documentElement).backgroundColor)).resolves.toBe('rgb(24, 26, 27)'); await expect(page.evaluate(() => getComputedStyle(document.documentElement).color)).resolves.toBe('rgb(232, 230, 227)'); @@ -32,7 +37,7 @@ describe('Toggling The Extension', () => { await expect(page.evaluate(() => getComputedStyle(document.querySelector('a')).color)).resolves.toBe('rgb(51, 145, 255)'); await popupUtils.click('.toggle__off'); - await timeout(1000); + await timeout(250); await expect(page.evaluate(() => getComputedStyle(document.documentElement).backgroundColor)).resolves.toBe('rgba(0, 0, 0, 0)'); await expect(page.evaluate(() => getComputedStyle(document.documentElement).color)).resolves.toBe('rgb(0, 0, 0)'); @@ -42,7 +47,47 @@ describe('Toggling The Extension', () => { await expect(page.evaluate(() => getComputedStyle(document.querySelector('a')).color)).resolves.toBe('rgb(0, 0, 238)'); await popupUtils.click('.toggle__on'); - await timeout(1000); + await timeout(250); + + await expect(page.evaluate(() => getComputedStyle(document.documentElement).backgroundColor)).resolves.toBe('rgb(24, 26, 27)'); + await expect(page.evaluate(() => getComputedStyle(document.documentElement).color)).resolves.toBe('rgb(232, 230, 227)'); + await expect(page.evaluate(() => getComputedStyle(document.body).backgroundColor)).resolves.toBe('rgb(24, 26, 27)'); + await expect(page.evaluate(() => getComputedStyle(document.body).color)).resolves.toBe('rgb(232, 230, 227)'); + await expect(page.evaluate(() => getComputedStyle(document.querySelector('h1')).color)).resolves.toBe('rgb(255, 26, 26)'); + await expect(page.evaluate(() => getComputedStyle(document.querySelector('a')).color)).resolves.toBe('rgb(51, 145, 255)'); + }); + + it('should follow system color scheme', async () => { + await loadBasicPage('Automation (color scheme)'); + + const automationMenuSelector = '.header__app-toggle__more-button'; + const automationSystemSelector = '.header__app-toggle__more-settings__system-dark-mode__checkbox .checkbox__input'; + + await emulateMedia('prefers-color-scheme', 'light'); + await expect(page.evaluate(() => matchMedia('(prefers-color-scheme: dark)').matches)).resolves.toBe(false); + + await expect(page.evaluate(() => getComputedStyle(document.documentElement).backgroundColor)).resolves.toBe('rgb(24, 26, 27)'); + await expect(page.evaluate(() => getComputedStyle(document.documentElement).color)).resolves.toBe('rgb(232, 230, 227)'); + await expect(page.evaluate(() => getComputedStyle(document.body).backgroundColor)).resolves.toBe('rgb(24, 26, 27)'); + await expect(page.evaluate(() => getComputedStyle(document.body).color)).resolves.toBe('rgb(232, 230, 227)'); + await expect(page.evaluate(() => getComputedStyle(document.querySelector('h1')).color)).resolves.toBe('rgb(255, 26, 26)'); + await expect(page.evaluate(() => getComputedStyle(document.querySelector('a')).color)).resolves.toBe('rgb(51, 145, 255)'); + + await popupUtils.click(automationMenuSelector); + await timeout(250); + await popupUtils.click(automationSystemSelector); + await timeout(250); + + await expect(page.evaluate(() => getComputedStyle(document.documentElement).backgroundColor)).resolves.toBe('rgba(0, 0, 0, 0)'); + await expect(page.evaluate(() => getComputedStyle(document.documentElement).color)).resolves.toBe('rgb(0, 0, 0)'); + await expect(page.evaluate(() => getComputedStyle(document.body).backgroundColor)).resolves.toBe('rgba(0, 0, 0, 0)'); + await expect(page.evaluate(() => getComputedStyle(document.body).color)).resolves.toBe('rgb(0, 0, 0)'); + await expect(page.evaluate(() => getComputedStyle(document.querySelector('h1')).color)).resolves.toBe('rgb(255, 0, 0)'); + await expect(page.evaluate(() => getComputedStyle(document.querySelector('a')).color)).resolves.toBe('rgb(0, 0, 238)'); + + await emulateMedia('prefers-color-scheme', 'dark'); + await expect(page.evaluate(() => matchMedia('(prefers-color-scheme: dark)').matches)).resolves.toBe(true); + await timeout(250); await expect(page.evaluate(() => getComputedStyle(document.documentElement).backgroundColor)).resolves.toBe('rgb(24, 26, 27)'); await expect(page.evaluate(() => getComputedStyle(document.documentElement).color)).resolves.toBe('rgb(232, 230, 227)'); @@ -50,5 +95,28 @@ describe('Toggling The Extension', () => { await expect(page.evaluate(() => getComputedStyle(document.body).color)).resolves.toBe('rgb(232, 230, 227)'); await expect(page.evaluate(() => getComputedStyle(document.querySelector('h1')).color)).resolves.toBe('rgb(255, 26, 26)'); await expect(page.evaluate(() => getComputedStyle(document.querySelector('a')).color)).resolves.toBe('rgb(51, 145, 255)'); + + await emulateMedia('prefers-color-scheme', 'light'); + await expect(page.evaluate(() => matchMedia('(prefers-color-scheme: dark)').matches)).resolves.toBe(false); + await timeout(250); + + await expect(page.evaluate(() => getComputedStyle(document.documentElement).backgroundColor)).resolves.toBe('rgba(0, 0, 0, 0)'); + await expect(page.evaluate(() => getComputedStyle(document.documentElement).color)).resolves.toBe('rgb(0, 0, 0)'); + await expect(page.evaluate(() => getComputedStyle(document.body).backgroundColor)).resolves.toBe('rgba(0, 0, 0, 0)'); + await expect(page.evaluate(() => getComputedStyle(document.body).color)).resolves.toBe('rgb(0, 0, 0)'); + await expect(page.evaluate(() => getComputedStyle(document.querySelector('h1')).color)).resolves.toBe('rgb(255, 0, 0)'); + await expect(page.evaluate(() => getComputedStyle(document.querySelector('a')).color)).resolves.toBe('rgb(0, 0, 238)'); + + await popupUtils.click(automationSystemSelector); + await timeout(250); + + await expect(page.evaluate(() => getComputedStyle(document.documentElement).backgroundColor)).resolves.toBe('rgb(24, 26, 27)'); + await expect(page.evaluate(() => getComputedStyle(document.documentElement).color)).resolves.toBe('rgb(232, 230, 227)'); + await expect(page.evaluate(() => getComputedStyle(document.body).backgroundColor)).resolves.toBe('rgb(24, 26, 27)'); + await expect(page.evaluate(() => getComputedStyle(document.body).color)).resolves.toBe('rgb(232, 230, 227)'); + await expect(page.evaluate(() => getComputedStyle(document.querySelector('h1')).color)).resolves.toBe('rgb(255, 26, 26)'); + await expect(page.evaluate(() => getComputedStyle(document.querySelector('a')).color)).resolves.toBe('rgb(51, 145, 255)'); + + await emulateMedia('prefers-color-scheme', 'dark'); }); }); diff --git a/tests/browser/environment.js b/tests/browser/environment.js index 97bf296d4c7b..ab804e5981c7 100644 --- a/tests/browser/environment.js +++ b/tests/browser/environment.js @@ -1,5 +1,4 @@ -// @ts-check -const fs = require('fs-extra'); +const fs = require('fs').promises; const JestNodeEnvironment = require('jest-environment-node'); const path = require('path'); const puppeteer = require('puppeteer-core'); @@ -111,31 +110,36 @@ class PuppeteerEnvironment extends JestNodeEnvironment { return page; } - async openPopupPage() { - let extensionPopup; + /** + * @param {string} path + * @returns {puppeteer.Page} + */ + async openExtensionPage(path) { if (this.global.product === 'chrome') { - extensionPopup = await this.openChromePage('/ui/popup/index.html'); - } else if (this.global.product === 'firefox') { - extensionPopup = await this.openFirefoxPage('/ui/popup/index.html'); + return await this.openChromePage(path); } - return extensionPopup; + if (this.global.product === 'firefox') { + return await this.openFirefoxPage(path); + } + return null; + } + + async openPopupPage() { + return await this.openExtensionPage('/ui/popup/index.html'); } async openDevtoolsPage() { - let extensionDevtools; - if (this.global.product === 'chrome') { - extensionDevtools = await this.openChromePage('/ui/devtools/index.html'); - } else if (this.global.product === 'firefox') { - extensionDevtools = await this.openFirefoxPage('/ui/devtools/index.html'); - } - return extensionDevtools; + return await this.openExtensionPage('/ui/devtools/index.html'); } - async openChromePage(path) { + async getBackgroundPage() { const targets = await this.browser.targets(); const backgroundTarget = targets.find((t) => t.type() === 'background_page'); - const backgroundPage = await backgroundTarget.page(); + return await backgroundTarget.page(); + } + async openChromePage(path) { + const backgroundPage = await this.getBackgroundPage(); const pageURL = backgroundPage.url().replace('/background/index.html', path); const extensionPage = await this.browser.newPage(); await extensionPage.goto(pageURL); @@ -222,6 +226,13 @@ class PuppeteerEnvironment extends JestNodeEnvironment { changeChromeStorage: async (region, data) => await sendToUIPage({type: 'changeChromeStorage', data: {region, data}}), getChromeStorage: async (region, keys) => await sendToUIPage({type: 'getChromeStorage', data: {region, keys}}), setDataIsMigratedForTesting: async (value) => await sendToUIPage({type: 'setDataIsMigratedForTesting', data: value}), + emulateMedia: async (name, value) => { + if (this.global.product === 'firefox') { + return; + } + const bg = await this.getBackgroundPage(); + await bg.emulateMediaFeatures([{name, value}]); + }, }; }); } @@ -229,23 +240,20 @@ class PuppeteerEnvironment extends JestNodeEnvironment { async teardown() { await super.teardown(); - if (this.global.product !== 'firefox') { + if (this.global.product !== 'firefox' && this.page?.coverage) { const coverage = await this.page.coverage.stopJSCoverage(); const dir = './tests/browser/coverage/'; await generateHTMLCoverageReports(dir, coverage); console.info('Coverage reports generated in', dir); } - await this.extensionPopup.close(); - await this.extensionDevtools.close(); - await this.page.close(); - await this.testServer.close(); - await this.corsServer.close(); - await this.popupTestServer.close(); - // TODO: Remove this hack, as this is a issue with clearing the tmp file of firefox profile - // Which will cause a error with puppeteer when it's not cleared. - // But the clearing currently doesn't work, so we need to wait for the issue to be fixed. - // await this.browser.close(); + await this.extensionPopup?.close(); + await this.extensionDevtools?.close(); + await this.page?.close(); + await this.testServer?.close(); + await this.corsServer?.close(); + await this.popupTestServer?.close(); + await this.browser?.close(); } } diff --git a/tests/browser/globals.d.ts b/tests/browser/globals.d.ts index 05568f609a2a..1153f09f6bcd 100644 --- a/tests/browser/globals.d.ts +++ b/tests/browser/globals.d.ts @@ -24,5 +24,6 @@ declare global { changeChromeStorage: (region: 'local' | 'sync', data: {[key: string]: any}) => Promise; getChromeStorage: (region: 'local' | 'sync', keys: string[]) => Promise<{[key: string]: any}>; setDataIsMigratedForTesting: (value: boolean) => Promise; + emulateMedia: (name: string, value: string) => Promise; }; } diff --git a/tests/browser/jest.config.chrome.js b/tests/browser/jest.config.chrome.js deleted file mode 100644 index e9f59a3f43cf..000000000000 --- a/tests/browser/jest.config.chrome.js +++ /dev/null @@ -1,9 +0,0 @@ -const jestConfig = require('./jest.config.shared'); - -module.exports = { - ...jestConfig, - globals: { - ...jestConfig.globals, - product: 'chrome', - }, -}; diff --git a/tests/browser/jest.config.firefox.js b/tests/browser/jest.config.firefox.js index 2ab318f9d8c8..89efc0a9bc68 100644 --- a/tests/browser/jest.config.firefox.js +++ b/tests/browser/jest.config.firefox.js @@ -1,9 +1,2 @@ -const jestConfig = require('./jest.config.shared'); - -module.exports = { - ...jestConfig, - globals: { - ...jestConfig.globals, - product: 'firefox', - }, -}; +module.exports = require('./jest.config'); +module.exports.globals.product = 'firefox'; diff --git a/tests/browser/jest.config.js b/tests/browser/jest.config.js index a8cb48a04805..f6941520c11f 100644 --- a/tests/browser/jest.config.js +++ b/tests/browser/jest.config.js @@ -1,6 +1,27 @@ -module.exports = { - projects: [ - 'tests/browser/jest.config.chrome.js', - 'tests/browser/jest.config.firefox.js', - ], +// @ts-check + +const {dirname} = require('path'); +const rootDir = dirname(require.resolve('../../package.json')); + +/** @type {import('@jest/types').Config.InitialOptions} */ +const config = { + rootDir, + testMatch: ['/tests/browser/**/*.tests.ts'], + moduleFileExtensions: ['ts', 'tsx', 'js'], + testEnvironment: '/tests/browser/environment.js', + verbose: true, + transform: {'^.+\\.ts(x?)$': 'ts-jest'}, + globals: { + 'ts-jest': {tsconfig: '/tests/browser/tsconfig.json'}, + __DEBUG__: false, + __TEST__: true, + product: 'chrome', + }, + setupFilesAfterEnv: ['jest-extended/all'], + collectCoverage: false, + coverageDirectory: 'coverage', + collectCoverageFrom: ['/src/**/*.{ts,tsx}'], + coveragePathIgnorePatterns: ['^.+\\.d\\.ts$'], }; + +module.exports = config; diff --git a/tests/browser/jest.config.shared.js b/tests/browser/jest.config.shared.js deleted file mode 100644 index b023cef47a19..000000000000 --- a/tests/browser/jest.config.shared.js +++ /dev/null @@ -1,27 +0,0 @@ -module.exports = { - testEnvironment: './environment.js', - verbose: true, - transform: { - '^.+\\.ts(x?)$': 'ts-jest' - }, - testRegex: 'tests/browser/.*\\.tests\\.ts(x?)$', - moduleFileExtensions: [ - 'ts', - 'tsx', - 'js' - ], - collectCoverage: false, - coverageDirectory: 'coverage', - collectCoverageFrom: [ - 'src/**/*.{ts,tsx}' - ], - coveragePathIgnorePatterns: [ - '^.+\\.d\\.ts$' - ], - globals: { - 'ts-jest': { - tsconfig: './tests/browser/tsconfig.json' - }, - __DEBUG__: false, - } -}; diff --git a/tests/browser/paths.js b/tests/browser/paths.js index a9f895c6ff77..e59ec977ad18 100644 --- a/tests/browser/paths.js +++ b/tests/browser/paths.js @@ -1,16 +1,24 @@ // @ts-check const {exec} = require('child_process'); -const fs = require('fs-extra'); +const fs = require('fs'); const path = require('path'); -async function winProgramFiles(relPath) { +/** + * @param {string} relPath + * @returns {string} + */ +function winProgramFiles(relPath) { const x64Path = path.join(process.env.PROGRAMFILES, relPath); - if (await fs.exists(x64Path)) { + if (fs.existsSync(x64Path)) { return x64Path; } return path.join(process.env['ProgramFiles(x86)'], relPath); } +/** + * @param {string} app + * @returns {Promise} + */ function linuxAppPath(app) { return new Promise((resolve, reject) => { exec(`which ${app}`, (err, result) => { @@ -31,7 +39,7 @@ async function getChromePath() { return '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome'; } if (process.platform === 'win32') { - return await winProgramFiles('Google\\Chrome\\Application\\chrome.exe'); + return winProgramFiles('Google\\Chrome\\Application\\chrome.exe'); } const possibleLinuxPaths = ['google-chrome', 'google-chrome-stable', 'chromium']; for (const possiblePath of possibleLinuxPaths) { @@ -54,7 +62,15 @@ async function getFirefoxPath() { if (process.platform === 'win32') { return await winProgramFiles('Firefox Nightly\\firefox.exe'); } - return await linuxAppPath('firefox-nightly'); + const possibleLinuxPaths = ['firefox-nightly', 'firefox']; + for (const possiblePath of possibleLinuxPaths) { + try { + return await linuxAppPath(possiblePath); + } catch (e) { + // ignore + } + } + throw new Error('Could not find firefox-nightly'); } const chromeExtensionDebugDir = path.join(__dirname, '../../build/debug/chrome'); diff --git a/tests/browser/server.js b/tests/browser/server.js index a4099a87df80..3ba936f2b368 100644 --- a/tests/browser/server.js +++ b/tests/browser/server.js @@ -20,6 +20,8 @@ async function createTestServer(/** @type {number} */port) { let server; /** @type {{[path: string]: string | import('http').RequestListener}} */ const paths = {}; + /** @type {Set} */ + const sockets = new Set(); /** @type {import('http').RequestListener} */ function handleRequest(req, res) { @@ -56,6 +58,11 @@ async function createTestServer(/** @type {number} */port) { server = http .createServer(handleRequest) .listen(port, () => resolve()); + + server.on('connection', (socket) => { + sockets.add(socket); + socket.on('close', () => sockets.delete(socket)); + }); }); } @@ -81,6 +88,9 @@ async function createTestServer(/** @type {number} */port) { server = null; resolve(); }); + sockets.forEach((socket) => { + socket.destroy(); + }); }); } diff --git a/tests/browser/tsconfig.json b/tests/browser/tsconfig.json index 8e51a41433e2..3a7c314f679f 100644 --- a/tests/browser/tsconfig.json +++ b/tests/browser/tsconfig.json @@ -1,18 +1,24 @@ { - "extends": "../../src/tsconfig", "compilerOptions": { - "esModuleInterop": true, - "module": "commonjs", - "outDir": "", + "target": "ES2019", + "module": "CommonJS", + "lib": [ + "ES2015", + "Dom" + ], "types": [ "chrome", "jest", "offscreencanvas", "puppeteer-core" ], - "lib": [ - "ES6", - "dom" - ] + "allowJs": true, + "downlevelIteration": true, + "esModuleInterop": true, + "jsx": "react", + "jsxFactory": "m", + "moduleResolution": "Node", + "noEmit": true, + "noImplicitAny": true, } } diff --git a/tests/config/jest.config.js b/tests/config/jest.config.js deleted file mode 100644 index 18c61a22e688..000000000000 --- a/tests/config/jest.config.js +++ /dev/null @@ -1,23 +0,0 @@ -module.exports = { - verbose: true, - testEnvironment: 'node', - transform: { - '^.+\\.ts$': 'ts-jest' - }, - testRegex: 'tests/config/.*\\.tests\\.ts$', - moduleFileExtensions: [ - 'ts', - 'js' - ], - rootDir: '../../', - collectCoverage: false, - coverageDirectory: 'tests/coverage', - collectCoverageFrom: [ - '/src/**/*.ts', - ], - globals: { - 'ts-jest': { - tsconfig: './tests/config/tsconfig.json' - } - } -}; diff --git a/tests/config/tsconfig.json b/tests/config/tsconfig.json deleted file mode 100644 index 8577f29983b2..000000000000 --- a/tests/config/tsconfig.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "extends": "../../src/tsconfig", - "compilerOptions": { - "module": "commonjs", - "outDir": "", - "types": [ - "jest", - "node" - ] - } -} diff --git a/tests/generators/utils/jest.config.js b/tests/generators/utils/jest.config.js deleted file mode 100644 index f3427709c17a..000000000000 --- a/tests/generators/utils/jest.config.js +++ /dev/null @@ -1,23 +0,0 @@ -module.exports = { - verbose: true, - testEnvironment: 'jsdom', - transform: { - '^.+\\.ts$': 'ts-jest' - }, - testRegex: 'tests/generators/utils/.*\\.tests\\.ts$', - moduleFileExtensions: [ - 'ts', - 'js' - ], - rootDir: '../../../', - collectCoverage: false, - coverageDirectory: 'tests/coverage', - collectCoverageFrom: [ - '/src/**/*.ts', - ], - globals: { - 'ts-jest': { - tsconfig: './tests/generators/utils/tsconfig.json' - } - } -}; diff --git a/tests/generators/utils/tsconfig.json b/tests/generators/utils/tsconfig.json deleted file mode 100644 index fb61cd27d282..000000000000 --- a/tests/generators/utils/tsconfig.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "extends": "../../../src/tsconfig", - "compilerOptions": { - "module": "commonjs", - "outDir": "", - "types": [ - "jest", - "node" - ] - } -} diff --git a/tests/inject/dynamic/color.tests.ts b/tests/inject/dynamic/color.tests.ts index 1dc70effc890..db29439e8024 100644 --- a/tests/inject/dynamic/color.tests.ts +++ b/tests/inject/dynamic/color.tests.ts @@ -1,7 +1,7 @@ -import '../polyfills'; +import '../support/polyfills'; import {DEFAULT_THEME} from '../../../src/defaults'; import {createOrUpdateDynamicTheme, removeDynamicTheme} from '../../../src/inject/dynamic-theme'; -import {multiline} from '../../test-utils'; +import {multiline} from '../support/test-utils'; const theme = { ...DEFAULT_THEME @@ -89,4 +89,26 @@ describe('COLOR PARSING', () => { createOrUpdateDynamicTheme(theme, null, false); expect(getComputedStyle(container.querySelector('h1')).backgroundColor).toBe('rgb(35, 38, 40)'); }); + + it('should handle gradient\'s cases with rgb(...) xx%', async () => { + container.innerHTML = multiline( + '', + '

Weird color Power!

', + ); + createOrUpdateDynamicTheme(theme, null, false); + expect(getComputedStyle(container.querySelector('h1')).backgroundImage).toBe('-webkit-linear-gradient(bottom, rgb(24, 26, 27) 15%, rgb(29, 32, 33) 85%)'); + }); + + it('should handle complex calc(...) cases', () => { + container.innerHTML = multiline( + '', + '

Weird color Power!

', + ); + createOrUpdateDynamicTheme(theme, null, false); + expect(getComputedStyle(container.querySelector('h1')).backgroundColor).toBe('rgb(28, 31, 32)'); + }); }); diff --git a/tests/inject/dynamic/fixes.tests.ts b/tests/inject/dynamic/fixes.tests.ts index 56370668e48d..1be4a6a4cbe5 100644 --- a/tests/inject/dynamic/fixes.tests.ts +++ b/tests/inject/dynamic/fixes.tests.ts @@ -1,9 +1,10 @@ -import '../polyfills'; +import '../support/polyfills'; import {DEFAULT_THEME} from '../../../src/defaults'; import {createOrUpdateDynamicTheme, removeDynamicTheme} from '../../../src/inject/dynamic-theme'; -import {multiline} from '../../test-utils'; +import {multiline, timeout} from '../support/test-utils'; import type {DynamicThemeFix} from '../../../src/definitions'; import {FilterMode} from '../../../src/generators/css-filter'; +import {removeNode} from '../../../src/inject/utils/dom'; let container: HTMLElement; @@ -15,6 +16,7 @@ beforeEach(() => { afterEach(() => { removeDynamicTheme(); container.innerHTML = ''; + removeNode(document.head.querySelector('meta[name="darkreader-lock"]')); }); describe('FIXES', () => { @@ -37,6 +39,7 @@ describe('FIXES', () => { css: '', ignoreInlineStyle: [], ignoreImageAnalysis: [], + disableStyleSheetsProxy: false, }; createOrUpdateDynamicTheme(DEFAULT_THEME, fixes, false); @@ -53,6 +56,7 @@ describe('FIXES', () => { css: '.text { color: red }', ignoreInlineStyle: [], ignoreImageAnalysis: [], + disableStyleSheetsProxy: false, }; createOrUpdateDynamicTheme(DEFAULT_THEME, fixes, false); @@ -69,9 +73,43 @@ describe('FIXES', () => { css: '', ignoreInlineStyle: ['.text'], ignoreImageAnalysis: [], + disableStyleSheetsProxy: false, }; createOrUpdateDynamicTheme(DEFAULT_THEME, fixes, false); expect(getComputedStyle(container.querySelector('.text')).backgroundColor).toBe('rgb(128, 0, 128)'); }); + + it('should ignore styling when darkreader-lock detected', async () => { + document.head.innerHTML = '', + container.innerHTML = multiline( + '', + ); + createOrUpdateDynamicTheme(DEFAULT_THEME, null, false); + + expect(getComputedStyle(document.body).backgroundColor).toBe('rgb(255, 192, 203)'); + }); + + it('should ignore styling when delayed darkreader-lock detected', async () => { + container.innerHTML = multiline( + '', + ); + createOrUpdateDynamicTheme(DEFAULT_THEME, null, false); + + expect(getComputedStyle(container).backgroundColor).toBe('rgb(89, 0, 16)'); + const metaElement: HTMLMetaElement = document.createElement('meta'); + metaElement.name = 'darkreader-lock'; + document.head.appendChild(metaElement); + await timeout(100); + + expect(getComputedStyle(container).backgroundColor).toBe('rgb(255, 192, 203)'); + }); }); diff --git a/tests/inject/dynamic/image-analysis.tests.ts b/tests/inject/dynamic/image-analysis.tests.ts index 015a1f3c09bf..943afcaf4085 100644 --- a/tests/inject/dynamic/image-analysis.tests.ts +++ b/tests/inject/dynamic/image-analysis.tests.ts @@ -1,8 +1,8 @@ -import '../polyfills'; +import '../support/polyfills'; import {DEFAULT_THEME} from '../../../src/defaults'; import {createOrUpdateDynamicTheme, removeDynamicTheme} from '../../../src/inject/dynamic-theme'; import {getImageDetails} from '../../../src/inject/dynamic-theme/image'; -import {multiline, timeout} from '../../test-utils'; +import {multiline, waitForEvent} from '../support/test-utils'; import type {DynamicThemeFix} from '../../../src/definitions'; const theme = { @@ -171,7 +171,7 @@ describe('IMAGE ANALYSIS', () => { '

Dark icon

', ); createOrUpdateDynamicTheme(theme, null, false); - await timeout(50); + await waitForEvent('__darkreader__test__asyncQueueComplete'); const bgImageValue = getComputedStyle(container.querySelector('i')).backgroundImage; const info = await getBgImageInfo(bgImageValue); expect(info.darkness).toBe(0); @@ -214,7 +214,7 @@ describe('IMAGE ANALYSIS', () => { '

Light background

', ); createOrUpdateDynamicTheme(theme, null, false); - await timeout(75); + await waitForEvent('__darkreader__test__asyncQueueComplete'); const bgImageValue = getComputedStyle(container.querySelector('h1')).backgroundImage; expect(bgImageValue).toBe('none'); }); @@ -232,10 +232,34 @@ describe('IMAGE ANALYSIS', () => { css: '', ignoreInlineStyle: ['.'], ignoreImageAnalysis: ['*'], - + disableStyleSheetsProxy: false, }; createOrUpdateDynamicTheme(theme, fixes, false); const backgroundImage = getComputedStyle(container.querySelector('i')).backgroundImage; expect(backgroundImage).toContain('data:'); }); + + it('should handle background-image with URL and gradient', async () => { + container.innerHTML = multiline( + '', + '

Weird color Power!

', + ); + createOrUpdateDynamicTheme(theme, null, false); + await waitForEvent('__darkreader__test__asyncQueueComplete'); + expect(getComputedStyle(container.querySelector('h1')).backgroundImage).toBe('url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB3aWR0aD0iOCIgaGVpZ2h0PSI4Ij48ZGVmcz48ZmlsdGVyIGlkPSJkYXJrcmVhZGVyLWltYWdlLWZpbHRlciI+PGZlQ29sb3JNYXRyaXggdHlwZT0ibWF0cml4IiB2YWx1ZXM9IjAuMzMzIC0wLjY2NyAtMC42NjcgMC4wMDAgMS4wMDAgLTAuNjY3IDAuMzMzIC0wLjY2NyAwLjAwMCAxLjAwMCAtMC42NjcgLTAuNjY3IDAuMzMzIDAuMDAwIDEuMDAwIDAuMDAwIDAuMDAwIDAuMDAwIDEuMDAwIDAuMDAwIiAvPjwvZmlsdGVyPjwvZGVmcz48aW1hZ2Ugd2lkdGg9IjgiIGhlaWdodD0iOCIgZmlsdGVyPSJ1cmwoI2RhcmtyZWFkZXItaW1hZ2UtZmlsdGVyKSIgeGxpbms6aHJlZj0iZGF0YTppbWFnZS9zdmcreG1sO2Jhc2U2NCxQSE4yWnlCNGJXeHVjejBpYUhSMGNEb3ZMM2QzZHk1M015NXZjbWN2TWpBd01DOXpkbWNpSUhacFpYZENiM2c5SWpBZ01DQTRJRGdpSUhkcFpIUm9QU0k0SWlCb1pXbG5hSFE5SWpnaVBnb2dJQ0FnUEhKbFkzUWdabWxzYkQwaWQyaHBkR1VpSUhkcFpIUm9QU0l4TURBbElpQm9aV2xuYUhROUlqRXdNQ1VpSUM4K0Nqd3ZjM1puUGc9PSIgLz48L3N2Zz4="), linear-gradient(rgb(204, 0, 0), rgb(0, 0, 0))'); + }); + + it('should handle background-image with URL and gradient (revered)', async () => { + container.innerHTML = multiline( + '', + '

Weird color Power!

', + ); + createOrUpdateDynamicTheme(theme, null, false); + await waitForEvent('__darkreader__test__asyncQueueComplete'); + expect(getComputedStyle(container.querySelector('h1')).backgroundImage).toBe('linear-gradient(rgb(204, 0, 0), rgb(0, 0, 0)), url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB3aWR0aD0iOCIgaGVpZ2h0PSI4Ij48ZGVmcz48ZmlsdGVyIGlkPSJkYXJrcmVhZGVyLWltYWdlLWZpbHRlciI+PGZlQ29sb3JNYXRyaXggdHlwZT0ibWF0cml4IiB2YWx1ZXM9IjAuMzMzIC0wLjY2NyAtMC42NjcgMC4wMDAgMS4wMDAgLTAuNjY3IDAuMzMzIC0wLjY2NyAwLjAwMCAxLjAwMCAtMC42NjcgLTAuNjY3IDAuMzMzIDAuMDAwIDEuMDAwIDAuMDAwIDAuMDAwIDAuMDAwIDEuMDAwIDAuMDAwIiAvPjwvZmlsdGVyPjwvZGVmcz48aW1hZ2Ugd2lkdGg9IjgiIGhlaWdodD0iOCIgZmlsdGVyPSJ1cmwoI2RhcmtyZWFkZXItaW1hZ2UtZmlsdGVyKSIgeGxpbms6aHJlZj0iZGF0YTppbWFnZS9zdmcreG1sO2Jhc2U2NCxQSE4yWnlCNGJXeHVjejBpYUhSMGNEb3ZMM2QzZHk1M015NXZjbWN2TWpBd01DOXpkbWNpSUhacFpYZENiM2c5SWpBZ01DQTRJRGdpSUhkcFpIUm9QU0k0SWlCb1pXbG5hSFE5SWpnaVBnb2dJQ0FnUEhKbFkzUWdabWxzYkQwaWQyaHBkR1VpSUhkcFpIUm9QU0l4TURBbElpQm9aV2xuYUhROUlqRXdNQ1VpSUM4K0Nqd3ZjM1puUGc9PSIgLz48L3N2Zz4=")'); + }); }); diff --git a/tests/inject/dynamic/inline-override.tests.ts b/tests/inject/dynamic/inline-override.tests.ts index 502546ce54c7..9858a08247e7 100644 --- a/tests/inject/dynamic/inline-override.tests.ts +++ b/tests/inject/dynamic/inline-override.tests.ts @@ -1,8 +1,7 @@ -import '../polyfills'; +import '../support/polyfills'; import {DEFAULT_THEME} from '../../../src/defaults'; import {createOrUpdateDynamicTheme, removeDynamicTheme} from '../../../src/inject/dynamic-theme'; -import {isChromium} from '../../../src/utils/platform'; -import {multiline, timeout} from '../../test-utils'; +import {multiline, timeout} from '../support/test-utils'; const theme = { ...DEFAULT_THEME, @@ -59,7 +58,8 @@ describe('INLINE STYLES', () => { container.innerHTML = 'Watch inline style'; createOrUpdateDynamicTheme(theme, null, false); const span = document.querySelector('span'); - expect(span.getAttribute('style')).toBe(`color: red; --darkreader-inline-color:${!isChromium ? ' ' : ''}#ff1a1a;`); + expect(span.getAttribute('style').startsWith('color: red; --darkreader-inline-color:')).toBeTrue(); + expect(span.getAttribute('style').endsWith('#ff1a1a;')).toBeTrue(); span.style.color = ''; await timeout(0); diff --git a/tests/inject/dynamic/link-override.tests.ts b/tests/inject/dynamic/link-override.tests.ts index 643c20682814..89d86053c9b0 100644 --- a/tests/inject/dynamic/link-override.tests.ts +++ b/tests/inject/dynamic/link-override.tests.ts @@ -1,9 +1,9 @@ import {DEFAULT_THEME} from '../../../src/defaults'; import {createOrUpdateDynamicTheme, removeDynamicTheme} from '../../../src/inject/dynamic-theme'; import {isSafari} from '../../../src/utils/platform'; -import {multiline, timeout} from '../../test-utils'; -import {stubChromeRuntimeMessage, resetChromeRuntimeMessageStub, stubBackgroundFetchResponse} from '../background-stub'; -import {getCSSEchoURL} from '../echo-client'; +import {multiline, timeout, waitForEvent} from '../support/test-utils'; +import {resetChromeRuntimeMessageStub, stubBackgroundFetchResponse, stubChromeRuntimeMessage} from '../support/background-stub'; +import {getCSSEchoURL} from '../support/echo-client'; const theme = { ...DEFAULT_THEME, @@ -23,12 +23,23 @@ function createStyleLink(href: string) { return link; } +function selectTestStyleLink() { + return document.querySelector('.testcase--link') as HTMLLinkElement; +} + function createCorsLink(content: string) { const url = getCSSEchoURL(content); stubBackgroundFetchResponse(url, content); return createStyleLink(url); } +async function waitForLinkLoading(link: HTMLLinkElement) { + return new Promise((resolve, reject) => { + link.addEventListener('load', resolve, {once: true}); + link.addEventListener('error', reject, {once: true}); + }); +} + beforeEach(() => { container = document.body; container.innerHTML = ''; @@ -70,7 +81,7 @@ describe('LINK STYLES', () => { ); createOrUpdateDynamicTheme(theme, null, false); - await timeout(50); + await waitForEvent('__darkreader__test__dynamicUpdateComplete'); expect(getComputedStyle(container.querySelector('h1')).backgroundColor).toBe('rgb(102, 102, 102)'); expect(getComputedStyle(container.querySelector('h1')).color).toBe('rgb(255, 255, 255)'); expect(getComputedStyle(container.querySelector('h1 strong')).color).toBe('rgb(255, 26, 26)'); @@ -89,7 +100,25 @@ describe('LINK STYLES', () => { ); createOrUpdateDynamicTheme(theme, null, false); - await timeout(100); + await waitForEvent('__darkreader__test__dynamicUpdateComplete'); + expect(getComputedStyle(container.querySelector('h1')).backgroundColor).toBe('rgb(102, 102, 102)'); + expect(getComputedStyle(container.querySelector('h1')).color).toBe('rgb(255, 255, 255)'); + expect(getComputedStyle(container.querySelector('h1 strong')).color).toBe('rgb(255, 26, 26)'); + }); + + it('should override cross-origin imports in linked CSS with capital @import', async () => { + const importedCSS = 'h1 { background: gray; }'; + const importedURL = getCSSEchoURL(importedCSS); + stubBackgroundFetchResponse(importedURL, importedCSS); + createCorsLink(multiline( + `@IMPORT "${importedURL}";`, + 'h1 strong { color: red; }', + )); + container.innerHTML = multiline( + '

Cross-origin import link override

', + ); + createOrUpdateDynamicTheme(theme, null, false); + await waitForEvent('__darkreader__test__dynamicUpdateComplete'); expect(getComputedStyle(container.querySelector('h1')).backgroundColor).toBe('rgb(102, 102, 102)'); expect(getComputedStyle(container.querySelector('h1')).color).toBe('rgb(255, 255, 255)'); expect(getComputedStyle(container.querySelector('h1 strong')).color).toBe('rgb(255, 26, 26)'); @@ -104,13 +133,13 @@ describe('LINK STYLES', () => { '

Loaded cross-origin link override

', ); - await timeout(50); + await waitForLinkLoading(selectTestStyleLink()); expect(getComputedStyle(container.querySelector('h1')).backgroundColor).toBe('rgb(128, 128, 128)'); expect(getComputedStyle(container.querySelector('h1')).color).toBe('rgb(0, 0, 0)'); expect(getComputedStyle(container.querySelector('h1 strong')).color).toBe('rgb(255, 0, 0)'); createOrUpdateDynamicTheme(theme, null, false); - await timeout(50); + await waitForEvent('__darkreader__test__dynamicUpdateComplete'); expect(getComputedStyle(container.querySelector('h1')).backgroundColor).toBe('rgb(102, 102, 102)'); expect(getComputedStyle(container.querySelector('h1')).color).toBe('rgb(255, 255, 255)'); expect(getComputedStyle(container.querySelector('h1 strong')).color).toBe('rgb(255, 26, 26)'); @@ -127,10 +156,10 @@ describe('LINK STYLES', () => { createOrUpdateDynamicTheme(theme, null, false); await timeout(50); - expect(document.querySelector('.testcase--link').nextElementSibling.classList.contains(isSafari ? 'darkreader--cors' : 'darkreader--sync')).toBe(true); + expect(selectTestStyleLink().nextElementSibling.classList.contains(isSafari ? 'darkreader--cors' : 'darkreader--sync')).toBe(true); link.disabled = true; await timeout(0); - expect(document.querySelector('.testcase--link').nextElementSibling.classList.contains(isSafari ? 'darkreader--cors' : 'darkreader--sync')).toBe(false); + expect(selectTestStyleLink().nextElementSibling.classList.contains(isSafari ? 'darkreader--cors' : 'darkreader--sync')).toBe(false); }); it("Shouldn't wait on link that won't be loaded", async () => { const link = createStyleLink(null); @@ -146,7 +175,7 @@ describe('LINK STYLES', () => { ); createOrUpdateDynamicTheme(theme, null, false); - await timeout(0); + await timeout(50); const h1 = document.querySelector('h1'); expect(getComputedStyle(h1).backgroundColor).toBe('rgb(102, 102, 102)'); expect(document.querySelector('.darkreader--fallback').textContent).toBe(''); @@ -165,7 +194,7 @@ describe('LINK STYLES', () => { ); createOrUpdateDynamicTheme(theme, null, false); - await timeout(100); + await waitForEvent('__darkreader__test__dynamicUpdateComplete'); expect(getComputedStyle(container.querySelector('h1')).backgroundColor).toBe('rgb(102, 102, 102)'); expect(getComputedStyle(container.querySelector('h1')).color).toBe('rgb(255, 255, 255)'); expect(getComputedStyle(container.querySelector('h1 strong')).color).toBe('rgb(255, 26, 26)'); @@ -185,7 +214,7 @@ describe('LINK STYLES', () => { ); createOrUpdateDynamicTheme(theme, null, false); - await timeout(100); + await timeout(1000); expect(getComputedStyle(container.querySelector('h1')).backgroundColor).toBe('rgb(102, 102, 102)'); expect(getComputedStyle(container.querySelector('h1')).color).toBe('rgb(255, 255, 255)'); expect(getComputedStyle(container.querySelector('h1 strong')).color).toBe('rgb(255, 26, 26)'); diff --git a/tests/inject/dynamic/media-query.tests.ts b/tests/inject/dynamic/media-query.tests.ts index 1b8bb562a0bc..c97f8a65b27f 100644 --- a/tests/inject/dynamic/media-query.tests.ts +++ b/tests/inject/dynamic/media-query.tests.ts @@ -1,7 +1,7 @@ -import '../polyfills'; +import '../support/polyfills'; import {DEFAULT_THEME} from '../../../src/defaults'; import {createOrUpdateDynamicTheme, removeDynamicTheme} from '../../../src/inject/dynamic-theme'; -import {multiline, timeout} from '../../test-utils'; +import {multiline, timeout} from '../support/test-utils'; const theme = { ...DEFAULT_THEME, diff --git a/tests/inject/dynamic/shadow-dom.tests.ts b/tests/inject/dynamic/shadow-dom.tests.ts index c75e6b3f80f8..36da95495451 100644 --- a/tests/inject/dynamic/shadow-dom.tests.ts +++ b/tests/inject/dynamic/shadow-dom.tests.ts @@ -1,7 +1,7 @@ -import '../polyfills'; +import '../support/polyfills'; import {DEFAULT_THEME} from '../../../src/defaults'; import {createOrUpdateDynamicTheme, removeDynamicTheme} from '../../../src/inject/dynamic-theme'; -import {multiline, timeout} from '../../test-utils'; +import {multiline, timeout} from '../support/test-utils'; import {isFirefox, isSafari} from '../../../src/utils/platform'; const theme = { diff --git a/tests/inject/dynamic/style-override.tests.ts b/tests/inject/dynamic/style-override.tests.ts index 4e392b1ea830..303db691a296 100644 --- a/tests/inject/dynamic/style-override.tests.ts +++ b/tests/inject/dynamic/style-override.tests.ts @@ -1,8 +1,8 @@ -import '../polyfills'; +import '../support/polyfills'; import {DEFAULT_THEME} from '../../../src/defaults'; import {createOrUpdateDynamicTheme, removeDynamicTheme} from '../../../src/inject/dynamic-theme'; import {createStyleSheetModifier} from '../../../src/inject/dynamic-theme/stylesheet-modifier'; -import {multiline, timeout} from '../../test-utils'; +import {multiline, timeout} from '../support/test-utils'; const theme = { ...DEFAULT_THEME, diff --git a/tests/inject/dynamic/variables.tests.ts b/tests/inject/dynamic/variables.tests.ts index 3db6bc638709..1b9e53a4c551 100644 --- a/tests/inject/dynamic/variables.tests.ts +++ b/tests/inject/dynamic/variables.tests.ts @@ -1,8 +1,8 @@ -import '../polyfills'; +import '../support/polyfills'; import {DEFAULT_THEME} from '../../../src/defaults'; import {isFirefox} from '../../../src/utils/platform'; import {createOrUpdateDynamicTheme, removeDynamicTheme} from '../../../src/inject/dynamic-theme'; -import {multiline, timeout} from '../../test-utils'; +import {multiline, timeout, waitForEvent} from '../support/test-utils'; const theme = { ...DEFAULT_THEME, @@ -844,7 +844,7 @@ describe('CSS VARIABLES OVERRIDE', () => { '', ); createOrUpdateDynamicTheme(theme, null, false); - await timeout(100); + await waitForEvent('__darkreader__test__asyncQueueComplete'); expect(getComputedStyle(container.querySelector('.icon1')).backgroundImage).toMatch(/^url\("data:image\/svg\+xml;base64,.*"\)$/); expect(getComputedStyle(container.querySelector('.icon2')).backgroundImage).toMatch(/^url\("data:image\/svg\+xml;base64,.*"\)$/); expect(getComputedStyle(container.querySelector('.icon3')).backgroundImage).toMatch(/^url\("data:image\/svg\+xml;base64,.*"\), url\("data:image\/svg\+xml;base64,.*"\)$/); @@ -872,7 +872,7 @@ describe('CSS VARIABLES OVERRIDE', () => { '

Mixed background

', ); createOrUpdateDynamicTheme(theme, null, false); - await timeout(100); + await waitForEvent('__darkreader__test__asyncQueueComplete'); expect(getComputedStyle(container.querySelector('.icon')).backgroundImage).toMatch(/^url\("data:image\/svg\+xml;base64,.*"\), linear-gradient\(rgb\(204, 0, 0\), rgb\(0, 0, 0\)\)$/); }); @@ -1262,4 +1262,19 @@ describe('CSS VARIABLES OVERRIDE', () => { expect(elementStyle.borderColor).toBe('rgb(91, 91, 91)'); } }); + + it('should modify inline variable', () => { + container.innerHTML = multiline( + '', + '

Raw values are spooky

', + ); + createOrUpdateDynamicTheme(theme, null, false); + + const elementStyle = getComputedStyle(container.querySelector('h1')); + expect(elementStyle.backgroundColor).toBe('rgb(204, 0, 0)'); + }); }); diff --git a/tests/inject/jest.config.js b/tests/inject/jest.config.js deleted file mode 100644 index 0569b84b16e4..000000000000 --- a/tests/inject/jest.config.js +++ /dev/null @@ -1,24 +0,0 @@ -module.exports = { - verbose: true, - testEnvironment: 'jsdom', - transform: { - '^.+\\.ts$': 'ts-jest' - }, - testRegex: 'tests/inject/.*\\.tests\\.ts$', - moduleFileExtensions: [ - 'ts', - 'js' - ], - rootDir: '../../', - collectCoverage: false, - coverageDirectory: 'tests/coverage', - collectCoverageFrom: [ - '/src/**/*.ts', - ], - globals: { - 'ts-jest': { - tsconfig: './tests/inject/tsconfig.json' - }, - __DEBUG__: false, - } -}; diff --git a/tests/inject/karma.conf.js b/tests/inject/karma.conf.js index cd3f994bfa78..22554a861ea2 100644 --- a/tests/inject/karma.conf.js +++ b/tests/inject/karma.conf.js @@ -1,20 +1,43 @@ -const fs = require('fs-extra'); +/** @typedef {import('karma').Config & Record} LocalConfig */ +/** @typedef {import('karma').ConfigOptions} ConfigOptions */ + +const fs = require('fs'); const os = require('os'); const rollupPluginIstanbul = require('rollup-plugin-istanbul2'); const rollupPluginNodeResolve = require('@rollup/plugin-node-resolve').default; const rollupPluginReplace = require('@rollup/plugin-replace'); -const rollupPluginTypescript = require('rollup-plugin-typescript2'); +const rollupPluginTypescript = require('@rollup/plugin-typescript'); const typescript = require('typescript'); +const {getTestDestDir, rootPath} = require('../../tasks/paths'); +const {createEchoServer} = require('./support/echo-server'); -module.exports = (config) => { - config.set({ - basePath: '../../', +/** + * @param {LocalConfig} config + * @param {Record} env + * @returns {ConfigOptions} + */ +function configureKarma(config, env) { + const headless = config.headless || env.KARMA_HEADLESS || false; + + /** @type {ConfigOptions} */ + let options = { + failOnFailingTestSuite: true, + failOnEmptyTestSuite: true, + basePath: '../..', frameworks: ['jasmine'], files: [ - 'tests/inject/customize.ts', - 'tests/inject/polyfills.ts', + 'tests/inject/support/customize.ts', + 'tests/inject/support/polyfills.ts', {pattern: 'tests/inject/**/*.tests.ts', watched: false}, ], + plugins: [ + 'karma-chrome-launcher', + 'karma-coverage', + 'karma-firefox-launcher', + 'karma-rollup-preprocessor', + 'karma-jasmine', + 'karma-spec-reporter', + ], preprocessors: { '**/*.+(ts|tsx)': ['rollup'], }, @@ -23,50 +46,98 @@ module.exports = (config) => { rollupPluginNodeResolve(), rollupPluginTypescript({ typescript, - tsconfig: 'src/tsconfig.json', - tsconfigOverride: { - compilerOptions: { - types: [ - 'chrome', - 'jasmine', - 'offscreencanvas' - ], - removeComments: false, - sourceMap: true, - }, - }, - clean: false, - cacheRoot: `${fs.realpathSync(os.tmpdir())}/darkreader_typescript_test_cache`, + tsconfig: rootPath('tests/inject/tsconfig.json'), + cacheDir: `${fs.realpathSync(os.tmpdir())}/darkreader_typescript_test_cache`, }), rollupPluginReplace({ preventAssignment: true, '__DEBUG__': 'false', '__PORT__': '-1', + '__TEST__': 'true', '__WATCH__': 'false', }), - rollupPluginIstanbul({ - exclude: ['tests/**/*.*', 'src/inject/dynamic-theme/stylesheet-proxy.ts'], - }), ], output: { + dir: getTestDestDir(), strict: true, format: 'iife', sourcemap: 'inline', }, }, - reporters: ['progress', 'coverage'], - coverageReporter: { - type: 'html', - dir: 'tests/inject/coverage/' - }, + reporters: ['spec'], port: 9876, colors: true, logLevel: config.LOG_INFO, autoWatch: true, - browsers: config.debug ? - ['Chrome'] : - ['Chrome', 'Firefox', process.platform === 'darwin' ? 'Safari' : null].filter(Boolean), - singleRun: config.debug ? false : true, - concurrency: config.debug ? Infinity : 1, - }); + browsers: headless + ? ['ChromeHeadless', 'FirefoxHeadless'] + : ['Chrome', 'Firefox', process.platform === 'darwin' ? 'Safari' : null].filter(Boolean), + singleRun: true, + concurrency: 1, + }; + + if (config.debug) { + options.browsers = ['Chrome']; + options.singleRun = false; + options.concurrency = Infinity; + options.logLevel = config.LOG_DEBUG; + } + + if (config.ci) { + options.customLaunchers = {}; + options.browsers = []; + + // Chrome + if (env.CHROME_TEST) { + options.customLaunchers['CIChromeHeadless'] = { + base: 'ChromeHeadless', + flags: ['--no-sandbox', '--disable-setuid-sandbox'] + }; + options.browsers.push('CIChromeHeadless'); + } + + // Firefox + if (env.FIREFOX_TEST) { + options.customLaunchers['CIFirefoxHeadless'] = { + base: 'FirefoxHeadless', + }; + options.browsers.push('CIFirefoxHeadless'); + } + + options.autoWatch = false; + options.singleRun = true; + options.concurrency = 1; + options.logLevel = config.LOG_DEBUG; + } + + if (config.coverage) { + const plugin = rollupPluginIstanbul({ + exclude: ['tests/**/*.*', 'src/inject/dynamic-theme/stylesheet-proxy.ts'], + }); + options.rollupPreprocessor.plugins.push(plugin); + options.reporters.push('coverage'); + options.coverageReporter = { + type: 'html', + dir: 'tests/inject/coverage/' + }; + } + + // HACK: Create CORS server here + // Previously a separate Karma runner file was used + const corsServerPort = 9966; + createEchoServer(corsServerPort).then(() => console.log(`CORS echo server running on port ${corsServerPort}`)); + + return options; +} + +/** + * @param {LocalConfig} config + * @returns {void} + */ +module.exports = (config) => { + config.set(configureKarma(config, process.env)); }; + +if (process.env.NODE_ENV === 'test') { + module.exports.configureKarma = configureKarma; +} diff --git a/tests/inject/run.js b/tests/inject/run.js deleted file mode 100644 index 236f4827e5f0..000000000000 --- a/tests/inject/run.js +++ /dev/null @@ -1,27 +0,0 @@ -// @ts-check -const karma = require('karma'); -const path = require('path'); -const {createEchoServer} = require('./echo-server'); - -const ECHO_SERVER_PORT = 9966; - -async function run() { - const args = process.argv.slice(2); - const debug = args.includes('--debug'); - const karmaConfig = karma.config.parseConfig(path.join(__dirname, './karma.conf.js'), /** @type {any} */({debug})); - - const echoServer = await createEchoServer(ECHO_SERVER_PORT); - const karmaServer = new karma.Server(/** @type {any} */(karmaConfig), () => { - echoServer.close(); - }); - karmaServer.start(); - - async function stop() { - await /** @type {any} */(karmaServer).stop(); - } - - process.on('exit', stop); - process.on('SIGINT', stop); -} - -run(); diff --git a/tests/inject/background-stub.ts b/tests/inject/support/background-stub.ts similarity index 91% rename from tests/inject/background-stub.ts rename to tests/inject/support/background-stub.ts index 3e134de514c7..2f910ca4d0e3 100644 --- a/tests/inject/background-stub.ts +++ b/tests/inject/support/background-stub.ts @@ -1,5 +1,5 @@ -import {MessageType} from '../../src/utils/message'; -import type {Message} from '../../src/definitions'; +import {MessageType} from '../../../src/utils/message'; +import type {Message} from '../../../src/definitions'; let nativeSendMessage: typeof chrome.runtime.sendMessage; const bgResponses = new Map(); diff --git a/tests/inject/customize.ts b/tests/inject/support/customize.ts similarity index 100% rename from tests/inject/customize.ts rename to tests/inject/support/customize.ts diff --git a/tests/inject/echo-client.ts b/tests/inject/support/echo-client.ts similarity index 100% rename from tests/inject/echo-client.ts rename to tests/inject/support/echo-client.ts diff --git a/tests/inject/echo-server.js b/tests/inject/support/echo-server.js similarity index 81% rename from tests/inject/echo-server.js rename to tests/inject/support/echo-server.js index 26490cd8a0c6..bb3525484ec4 100644 --- a/tests/inject/echo-server.js +++ b/tests/inject/support/echo-server.js @@ -1,7 +1,5 @@ // @ts-check const http = require('http'); -const url = require('url'); -const queryString = require('querystring'); async function createEchoServer(/** @type {number} */port) { /** @type {import('http').Server} */ @@ -9,7 +7,7 @@ async function createEchoServer(/** @type {number} */port) { /** @type {import('http').RequestListener} */ function handleRequest(req, res) { - const parsedURL = url.parse(req.url); + const parsedURL = new URL(req.url, `http://${req.headers.host}`); const pathName = parsedURL.pathname; if (pathName !== '/echo') { @@ -18,16 +16,16 @@ async function createEchoServer(/** @type {number} */port) { return; } - const parsedQuery = queryString.parse(parsedURL.query); - if (typeof parsedQuery.content !== 'string') { + const {searchParams} = parsedURL; + + const content = searchParams.get('content'); + if (!content) { res.statusCode = 500; res.end('Send content like /echo?type=text%2Fplain&content=XYZ'); return; } - const contentType = parsedQuery.type || 'text/plain'; - const content = parsedQuery.content; - + const contentType = searchParams.get('type') || 'text/plain'; res.statusCode = 200; res.setHeader('Content-Type', contentType); res.end(content, 'utf8'); diff --git a/tests/inject/polyfills.ts b/tests/inject/support/polyfills.ts similarity index 100% rename from tests/inject/polyfills.ts rename to tests/inject/support/polyfills.ts diff --git a/tests/inject/support/test-utils.ts b/tests/inject/support/test-utils.ts new file mode 100644 index 000000000000..c28b2e32d9cf --- /dev/null +++ b/tests/inject/support/test-utils.ts @@ -0,0 +1,15 @@ +// Loaded with HTML/DOM only + +export function multiline(...lines: string[]) { + return lines.join('\n'); +} + +export function timeout(delay: number) { + return new Promise((resolve) => setTimeout(resolve, delay)); +} + +export function waitForEvent(eventName: string) { + return new Promise((resolve) => { + document.addEventListener(eventName, resolve, {once: true}); + }); +} diff --git a/tests/inject/tsconfig.json b/tests/inject/tsconfig.json index e7c557a1de3e..3537d74cec24 100644 --- a/tests/inject/tsconfig.json +++ b/tests/inject/tsconfig.json @@ -1,12 +1,33 @@ { - "extends": "../../src/tsconfig", + "$schema": "https://json.schemastore.org/tsconfig", "compilerOptions": { - "module": "es2015", - "outDir": "", + "target": "ES2019", + "module": "ES2015", + "lib": [ + "ES2015", + "ES2017", + "DOM", + "DOM.Iterable" + ], "types": [ "chrome", - "jasmine", - "offscreencanvas" - ] - } + "offscreencanvas", + "jasmine" + ], + "allowJs": true, + "downlevelIteration": true, + "esModuleInterop": true, + "jsx": "react", + "jsxFactory": "m", + "moduleResolution": "Node", + "noEmit": true, + "noImplicitAny": true, + "removeComments": false, + "sourceMap": true, + "inlineSources": true, + "noEmitOnError": true + }, + "exclude": [ + "./coverage" + ] } diff --git a/tests/utils/url.tests.ts b/tests/inject/utils/url.tests.ts similarity index 91% rename from tests/utils/url.tests.ts rename to tests/inject/utils/url.tests.ts index 7ebdcad11ba9..84129e9c1d76 100644 --- a/tests/utils/url.tests.ts +++ b/tests/inject/utils/url.tests.ts @@ -1,7 +1,7 @@ -import {isURLEnabled, isURLMatched, isPDF, isFullyQualifiedDomain, getURLHostOrProtocol, getAbsoluteURL} from '../../src/utils/url'; -import type {UserSettings} from '../../src/definitions'; +import {isURLEnabled, isURLMatched, isPDF, isFullyQualifiedDomain, getURLHostOrProtocol, getAbsoluteURL} from '../../../src/utils/url'; +import type {UserSettings} from '../../../src/definitions'; -test('URL is enabled', () => { +it('URL is enabled', () => { // Not invert listed expect(isURLEnabled( 'https://mail.google.com/mail/u/0/', @@ -133,6 +133,28 @@ test('URL is enabled', () => { {isProtected: false, isInDarkList: false}, )).toBe(false); + // Dark theme detection + expect(isURLEnabled( + 'https://github.com/', + {siteList: [], siteListEnabled: [], applyToListedOnly: false, detectDarkTheme: true} as UserSettings, + {isProtected: false, isInDarkList: false, isDarkThemeDetected: true}, + )).toBe(false); + expect(isURLEnabled( + 'https://github.com/', + {siteList: [], siteListEnabled: [], applyToListedOnly: false, detectDarkTheme: false} as UserSettings, + {isProtected: false, isInDarkList: false, isDarkThemeDetected: true}, + )).toBe(true); + expect(isURLEnabled( + 'https://github.com/', + {siteList: [], siteListEnabled: [], applyToListedOnly: false, detectDarkTheme: true} as UserSettings, + {isProtected: false, isInDarkList: false, isDarkThemeDetected: false}, + )).toBe(true); + expect(isURLEnabled( + 'https://github.com/', + {siteList: [], siteListEnabled: ['github.com'], applyToListedOnly: false, detectDarkTheme: true} as UserSettings, + {isProtected: false, isInDarkList: false, isDarkThemeDetected: true}, + )).toBe(true); + // Test for PDF enabling expect(isPDF( 'https://www.google.com/file.pdf' @@ -247,17 +269,17 @@ test('URL is enabled', () => { )).toBe(true); }); -test('Get URL host or protocol', () => { +it('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,Hello')).toBe('data:'); - expect(getURLHostOrProtocol('file:///Users/index.html')).toBe('file:'); + expect(getURLHostOrProtocol('file:///Users/index.html')).toBe('/Users/index.html'); }); -test('Absolute URL', () => { +it('Absolute URL', () => { expect(getAbsoluteURL('https://www.google.com', 'image.jpg')).toBe('https://www.google.com/image.jpg'); expect(getAbsoluteURL('https://www.google.com', '/image.jpg')).toBe('https://www.google.com/image.jpg'); expect(getAbsoluteURL('https://www.google.com/path', '/image.jpg')).toBe('https://www.google.com/image.jpg'); @@ -279,7 +301,7 @@ test('Absolute URL', () => { expect(getAbsoluteURL('path/index.html', '/image.jpg?size=128')).toBe(`${location.origin}/image.jpg?size=128`); }); -test('Fully qualified domain', () => { +it('Fully qualified domain', () => { expect(isFullyQualifiedDomain('www.google.com')).toBe(true); expect(isFullyQualifiedDomain('*.google.com')).toBe(false); }); diff --git a/tests/jest.config.js b/tests/jest.config.js deleted file mode 100644 index dbf4ade2d135..000000000000 --- a/tests/jest.config.js +++ /dev/null @@ -1,8 +0,0 @@ -module.exports = { - projects: [ - 'tests/config/jest.config.js', - 'tests/utils/jest.config.js', - 'tests/generators/utils/jest.config.js', - ], - verbose: true, -}; diff --git a/tests/project/__snapshots__/tsconf.tests.ts.snap b/tests/project/__snapshots__/tsconf.tests.ts.snap new file mode 100644 index 000000000000..7ed63f9c4540 --- /dev/null +++ b/tests/project/__snapshots__/tsconf.tests.ts.snap @@ -0,0 +1,384 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`TypeScript project config file should parse and resolve correctly: src 1`] = ` +Object { + "compileOnSave": false, + "compilerOptions": Object { + "allowJs": true, + "baseUrl": "./", + "downlevelIteration": true, + "jsx": "react", + "jsxFactory": "m", + "lib": Array [ + "es6", + "es2017", + "dom", + "dom.iterable", + ], + "module": "es6", + "moduleResolution": "node", + "noEmit": true, + "noImplicitAny": true, + "resolveJsonModule": true, + "target": "es2019", + "types": Array [ + "chrome", + "offscreencanvas", + ], + }, + "files": Array [ + "./defaults.ts", + "./definitions.d.ts", + "./api/chrome.ts", + "./api/fetch.ts", + "./api/index.ts", + "./background/config-manager.ts", + "./background/devtools.ts", + "./background/extension.ts", + "./background/icon-manager.ts", + "./background/index.ts", + "./background/make-chromium-happy.ts", + "./background/messenger.ts", + "./background/newsmaker.ts", + "./background/tab-manager.ts", + "./background/user-storage.ts", + "./background/window-theme.ts", + "./background/utils/extension-api.ts", + "./background/utils/migration.ts", + "./background/utils/network.ts", + "./background/utils/state-manager.ts", + "./generators/css-filter.ts", + "./generators/dynamic-theme.ts", + "./generators/modify-colors.ts", + "./generators/static-theme.ts", + "./generators/svg-filter.ts", + "./generators/text-style.ts", + "./generators/theme-engines.ts", + "./generators/utils/format.ts", + "./generators/utils/matrix.ts", + "./generators/utils/parse.ts", + "./inject/detector.ts", + "./inject/fallback.ts", + "./inject/index.ts", + "./inject/style.ts", + "./inject/svg-filter.ts", + "./inject/dynamic-theme/adopted-style-manger.ts", + "./inject/dynamic-theme/css-collection.ts", + "./inject/dynamic-theme/css-rules.ts", + "./inject/dynamic-theme/image.ts", + "./inject/dynamic-theme/index.ts", + "./inject/dynamic-theme/inline-style.ts", + "./inject/dynamic-theme/meta-theme-color.ts", + "./inject/dynamic-theme/modify-css.ts", + "./inject/dynamic-theme/network.ts", + "./inject/dynamic-theme/style-manager.ts", + "./inject/dynamic-theme/stylesheet-modifier.ts", + "./inject/dynamic-theme/stylesheet-proxy.ts", + "./inject/dynamic-theme/variables.ts", + "./inject/dynamic-theme/watch.ts", + "./inject/utils/dom.ts", + "./inject/utils/watch-color-scheme.ts", + "./ui/utils.ts", + "./ui/connect/connector.ts", + "./ui/connect/mock.ts", + "./ui/controls/index.ts", + "./ui/controls/utils.ts", + "./ui/controls/button/index.tsx", + "./ui/controls/checkbox/index.tsx", + "./ui/controls/color-dropdown/index.tsx", + "./ui/controls/color-picker/hsb-picker.tsx", + "./ui/controls/color-picker/index.tsx", + "./ui/controls/dropdown/index.tsx", + "./ui/controls/message-box/index.tsx", + "./ui/controls/multi-switch/index.tsx", + "./ui/controls/nav-button/index.tsx", + "./ui/controls/overlay/index.ts", + "./ui/controls/reset-button/index.tsx", + "./ui/controls/select/index.tsx", + "./ui/controls/shortcut/index.tsx", + "./ui/controls/slider/index.tsx", + "./ui/controls/tab-panel/index.tsx", + "./ui/controls/tab-panel/tab.tsx", + "./ui/controls/text-list/index.tsx", + "./ui/controls/textbox/index.tsx", + "./ui/controls/time-range-picker/index.tsx", + "./ui/controls/toggle/index.tsx", + "./ui/controls/updown/index.tsx", + "./ui/controls/updown/track.tsx", + "./ui/controls/virtual-scroll/index.tsx", + "./ui/devtools/index.tsx", + "./ui/devtools/components/body.tsx", + "./ui/popup/compatibility.js", + "./ui/popup/index.tsx", + "./ui/popup/types.d.ts", + "./ui/popup/automation-page/index.tsx", + "./ui/popup/body/index.tsx", + "./ui/popup/check-button/index.tsx", + "./ui/popup/components/body.tsx", + "./ui/popup/components/custom-settings-toggle/index.tsx", + "./ui/popup/components/engine-switch/index.tsx", + "./ui/popup/components/filter-settings/index.tsx", + "./ui/popup/components/filter-settings/mode-toggle.tsx", + "./ui/popup/components/font-settings/index.tsx", + "./ui/popup/components/header/index.tsx", + "./ui/popup/components/header/more-toggle-settings.tsx", + "./ui/popup/components/loader/index.tsx", + "./ui/popup/components/more-settings/index.tsx", + "./ui/popup/components/news/index.tsx", + "./ui/popup/components/site-list-settings/index.tsx", + "./ui/popup/components/site-toggle/checkmark-icon.tsx", + "./ui/popup/components/site-toggle/index.tsx", + "./ui/popup/control-group/index.tsx", + "./ui/popup/main-page/app-switch.tsx", + "./ui/popup/main-page/help.tsx", + "./ui/popup/main-page/index.tsx", + "./ui/popup/main-page/site-toggle.tsx", + "./ui/popup/main-page/sun-moon-icon.tsx", + "./ui/popup/main-page/system-icon.tsx", + "./ui/popup/main-page/theme-group.tsx", + "./ui/popup/main-page/watch-icon.tsx", + "./ui/popup/manage-settings-page/export-settings.tsx", + "./ui/popup/manage-settings-page/export-theme.tsx", + "./ui/popup/manage-settings-page/fetch-news.tsx", + "./ui/popup/manage-settings-page/import-settings.tsx", + "./ui/popup/manage-settings-page/index.tsx", + "./ui/popup/manage-settings-page/reset-settings-button.tsx", + "./ui/popup/manage-settings-page/sync-config.tsx", + "./ui/popup/manage-settings-page/sync-settings.tsx", + "./ui/popup/news-section/index.tsx", + "./ui/popup/page-viewer/index.tsx", + "./ui/popup/settings-page/automation-button.tsx", + "./ui/popup/settings-page/change-browser-theme.tsx", + "./ui/popup/settings-page/context-menus.tsx", + "./ui/popup/settings-page/detect-dark-theme.tsx", + "./ui/popup/settings-page/devtools.tsx", + "./ui/popup/settings-page/enabled-by-default.tsx", + "./ui/popup/settings-page/index.tsx", + "./ui/popup/settings-page/mange-settings-button.tsx", + "./ui/popup/settings-page/site-list-button.tsx", + "./ui/popup/settings-page/version.tsx", + "./ui/popup/site-list-page/index.tsx", + "./ui/popup/site-list-page/site-list.tsx", + "./ui/popup/theme/utils.ts", + "./ui/popup/theme/controls/background-color.tsx", + "./ui/popup/theme/controls/brightness.tsx", + "./ui/popup/theme/controls/color-scheme.tsx", + "./ui/popup/theme/controls/contrast.tsx", + "./ui/popup/theme/controls/font-picker.tsx", + "./ui/popup/theme/controls/format.ts", + "./ui/popup/theme/controls/grayscale.tsx", + "./ui/popup/theme/controls/immediate-modify.tsx", + "./ui/popup/theme/controls/index.tsx", + "./ui/popup/theme/controls/mode.tsx", + "./ui/popup/theme/controls/reset-button.tsx", + "./ui/popup/theme/controls/scheme.tsx", + "./ui/popup/theme/controls/scrollbar.tsx", + "./ui/popup/theme/controls/selection.tsx", + "./ui/popup/theme/controls/sepia.tsx", + "./ui/popup/theme/controls/style-system-controls.tsx", + "./ui/popup/theme/controls/text-color.tsx", + "./ui/popup/theme/controls/text-stroke.tsx", + "./ui/popup/theme/controls/theme-control.tsx", + "./ui/popup/theme/controls/use-font.tsx", + "./ui/popup/theme/page/collapsible-panel.tsx", + "./ui/popup/theme/page/index.tsx", + "./ui/popup/theme/preset-picker/index.tsx", + "./ui/popup/utils/issues.ts", + "./ui/popup/utils/markdown.tsx", + "./ui/stylesheet-editor/index.tsx", + "./ui/stylesheet-editor/components/body.tsx", + "./utils/array.ts", + "./utils/async-queue.ts", + "./utils/color.ts", + "./utils/colorscheme-parser.ts", + "./utils/debounce.ts", + "./utils/ipv6.ts", + "./utils/links.ts", + "./utils/locales.ts", + "./utils/log.ts", + "./utils/math.ts", + "./utils/media-query.ts", + "./utils/message.ts", + "./utils/network.ts", + "./utils/parsing.ts", + "./utils/platform.ts", + "./utils/promise-barrier.ts", + "./utils/text.ts", + "./utils/throttle.ts", + "./utils/time.ts", + "./utils/uid.ts", + "./utils/url.ts", + ], +} +`; + +exports[`TypeScript project config file should parse and resolve correctly: src/api 1`] = ` +Object { + "compileOnSave": false, + "compilerOptions": Object { + "allowJs": true, + "baseUrl": "..", + "downlevelIteration": true, + "jsx": "react", + "jsxFactory": "m", + "lib": Array [ + "es6", + "es2017", + "dom", + "dom.iterable", + ], + "module": "es6", + "moduleResolution": "node", + "noEmit": true, + "noImplicitAny": true, + "resolveJsonModule": true, + "target": "es5", + "types": Array [ + "chrome", + "offscreencanvas", + ], + }, + "files": Array [ + "./chrome.ts", + "./fetch.ts", + "./index.ts", + ], +} +`; + +exports[`TypeScript project config file should parse and resolve correctly: tests/browser 1`] = ` +Object { + "compileOnSave": false, + "compilerOptions": Object { + "allowJs": true, + "downlevelIteration": true, + "esModuleInterop": true, + "jsx": "react", + "jsxFactory": "m", + "lib": Array [ + "es6", + "dom", + ], + "module": "commonjs", + "moduleResolution": "node", + "noEmit": true, + "noImplicitAny": true, + "target": "es2019", + "types": Array [ + "chrome", + "jest", + "offscreencanvas", + "puppeteer-core", + ], + }, + "files": Array [ + "./coverage.js", + "./environment.js", + "./globals.d.ts", + "./jest.config.js", + "./paths.js", + "./server.js", + "./dynamic/inline-override.tests.ts", + "./dynamic/link-override.tests.ts", + "./dynamic/style-override.tests.ts", + "./e2e/devtools.tests.ts", + "./e2e/toggle.tests.ts", + "./settings/migration.tests.ts", + "./settings/sitelist.tests.ts", + ], +} +`; + +exports[`TypeScript project config file should parse and resolve correctly: tests/inject 1`] = ` +Object { + "compileOnSave": false, + "compilerOptions": Object { + "allowJs": true, + "downlevelIteration": true, + "esModuleInterop": true, + "inlineSources": true, + "jsx": "react", + "jsxFactory": "m", + "lib": Array [ + "es6", + "es2017", + "dom", + "dom.iterable", + ], + "module": "es6", + "moduleResolution": "node", + "noEmit": true, + "noEmitOnError": true, + "noImplicitAny": true, + "removeComments": false, + "sourceMap": true, + "target": "es2019", + "types": Array [ + "chrome", + "offscreencanvas", + "jasmine", + ], + }, + "exclude": Array [ + "./coverage", + ], + "files": Array [ + "./karma.conf.ci.js", + "./karma.conf.js", + "./types.d.ts", + "./dynamic/color.tests.ts", + "./dynamic/fixes.tests.ts", + "./dynamic/image-analysis.tests.ts", + "./dynamic/inline-override.tests.ts", + "./dynamic/link-override.tests.ts", + "./dynamic/media-query.tests.ts", + "./dynamic/shadow-dom.tests.ts", + "./dynamic/style-override.tests.ts", + "./dynamic/variables.tests.ts", + "./support/background-stub.ts", + "./support/customize.ts", + "./support/polyfills.ts", + "./support/test-utils.ts", + "./types/karma-rollup-preprocessor.d.ts", + "./types/karma.d.ts", + "./types/rollup-plugin-istanbul2.d.ts", + "./utils/url.tests.ts", + ], +} +`; + +exports[`TypeScript project config file should parse and resolve correctly: tests/unit 1`] = ` +Object { + "compileOnSave": false, + "compilerOptions": Object { + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "inlineSourceMap": true, + "lib": Array [ + "esnext", + "dom", + ], + "module": "commonjs", + "noImplicitAny": true, + "skipLibCheck": true, + "target": "esnext", + "types": Array [ + "node", + "jest", + "jest-extended", + ], + }, + "files": Array [ + "./config/config.tests.ts", + "./config/locales.tests.ts", + "./generators/utils/parse.tests.ts", + "./utils/color.tests.ts", + "./utils/math.tests.ts", + "./utils/parsing.tests.ts", + "./utils/promise-barrier.tests.ts", + "./utils/text.tests.ts", + "./utils/time.tests.ts", + "./utils/uid.tests.ts", + ], +} +`; diff --git a/tests/project/build.tests.ts b/tests/project/build.tests.ts new file mode 100644 index 000000000000..617c2a3dbc3c --- /dev/null +++ b/tests/project/build.tests.ts @@ -0,0 +1,52 @@ +import {timeout} from '../support/test-utils'; +import {childClosed, watchStream} from './utils'; +import {join, resolve} from 'path'; +import {tmpdir} from 'os'; +import {mkdtemp} from 'fs/promises'; +import {fork} from 'child_process'; + +const rootPath = (path: string) => resolve(__dirname, '../..', path); +const buildModule = rootPath('tasks/build.js'); + +describe('tasks/build-js.js', () => { + it('should respond to SIGINT signals by exiting immediately', async () => { + expect.assertions(3); + const tmpDir: string = await mkdtemp(join(tmpdir(), 'darkreader')); + const wantToWaitNoMoreThan = 500; + + // Execute build + // Give it a chance to reach compilation stage + const child = fork(buildModule, ['--debug'], {cwd: tmpDir, silent: true}); + + // Wait for "clean" step to complete + await watchStream(child.stdout).forMatch(/ clean \(\d+ms\)/); + // Let "bundle-js" to get started + await timeout(500); + + // Fire! + child.kill('SIGINT'); + + // Wait for close + await childClosed(child, {timeout: wantToWaitNoMoreThan}); + + expect(child.killed).toBeTrue(); + expect(child.exitCode).toBeGreaterThan(0); + + // By now, "bundle-js" step should not have completed normally + expect((child.stdout.read() || '')).not.toMatch(/ bundle-js \(\d+ms\)/); + }); +}); + +describe('tasks/build.js', () => { + // Slow test (run using `npm run test:project`) + it('should build successfully from an unexpected working directory', async () => { + const tmpDir: string = await mkdtemp(join(tmpdir(), 'darkreader')); + + // Fire + const child = fork(buildModule, ['--debug', '--release', '--api'], {cwd: tmpDir, silent: true}); + + const {stdout} = await childClosed(child); + expect(stdout).toInclude('MISSION PASSED'); + expect(child.exitCode).toBe(0); + }, 120000); +}); diff --git a/tests/project/jest.config.js b/tests/project/jest.config.js new file mode 100644 index 000000000000..ff98041bab6d --- /dev/null +++ b/tests/project/jest.config.js @@ -0,0 +1,20 @@ +// @ts-check + +const {dirname} = require('path'); +const rootDir = dirname(require.resolve('../../package.json')); + +/** @type {import('@jest/types').Config.InitialOptions} */ +const config = { + rootDir, + testMatch: ['/tests/project/**/*.tests.ts'], + moduleFileExtensions: ['ts', 'tsx', 'js'], + transform: {'^.+\\.ts(x?)$': 'ts-jest'}, + globals: { + 'ts-jest': {tsconfig: '/tests/project/tsconfig.json'}, + __DEBUG__: false, + __TEST__: true, + }, + setupFilesAfterEnv: ['jest-extended/all'], +}; + +module.exports = config; diff --git a/tests/project/karma-conf.tests.ts b/tests/project/karma-conf.tests.ts new file mode 100644 index 000000000000..338f5f01c1ff --- /dev/null +++ b/tests/project/karma-conf.tests.ts @@ -0,0 +1,55 @@ +import type {Config, ConfigOptions} from 'karma'; +import {configureKarma} from '../inject/karma.conf'; +import {LOG_DEBUG, LOG_DISABLE, LOG_ERROR, LOG_INFO, LOG_WARN} from 'karma/lib/constants'; + +const CIChromeHeadless = {base: 'ChromeHeadless', flags: expect.any(Array)}; +const CIFirefoxHeadless = {base: 'FirefoxHeadless'}; + +declare type LocalConfig = Config & Record; +declare type TestCase = { env: Record; wantEntries: Array<[string, unknown]> }; + +const testCases: TestCase[] = [ + { + env: {}, + wantEntries: [ + ['customLaunchers', {}], + ['browsers', []], + ], + }, + { + env: {CHROME_TEST: '1'}, + wantEntries: [ + ['customLaunchers', {CIChromeHeadless}], + ['browsers', ['CIChromeHeadless']], + ], + }, + { + env: {FIREFOX_TEST: '1'}, + wantEntries: [ + ['customLaunchers', {CIFirefoxHeadless}], + ['browsers', ['CIFirefoxHeadless']], + ], + }, + { + env: {CHROME_TEST: '1', FIREFOX_TEST: '1'}, + wantEntries: [ + ['customLaunchers', {CIChromeHeadless, CIFirefoxHeadless}], + ['browsers', ['CIChromeHeadless', 'CIFirefoxHeadless']], + ], + }, +]; + +describe('Karma config tests', () => { + it.each(testCases)('should be informed by environment variables: $env', async ({env, wantEntries}) => { + const ciConfig: LocalConfig = { + ci: true, LOG_DISABLE, LOG_ERROR, LOG_WARN, LOG_INFO, LOG_DEBUG, set: () => { + return void 0; + }, + }; + + // Fire + const got: ConfigOptions = configureKarma(ciConfig, env); + + expect(got).toContainEntries(wantEntries); + }); +}); diff --git a/tests/project/tsconf.tests.ts b/tests/project/tsconf.tests.ts new file mode 100644 index 000000000000..b08156f9280b --- /dev/null +++ b/tests/project/tsconf.tests.ts @@ -0,0 +1,50 @@ +import ts, {ExitStatus} from 'typescript'; +import {dirname, join} from 'path'; +import {fork} from 'child_process'; +import {tmpdir} from 'os'; +import {mkdtemp} from 'fs/promises'; +import {childClosed} from './utils'; + +const rootDir = dirname(require.resolve('../../package.json')); +const tsc = require.resolve('typescript/bin/tsc'); + +const tsProjects: Array<{tsconfig: string}> = [ + // Browser extension + {tsconfig: 'src'}, + // API + {tsconfig: 'src/api'}, + // E2E tests (Jest, Puppeteer, Node.js) + {tsconfig: 'tests/browser'}, + // Browser tests (Karma, Jasmine) + {tsconfig: 'tests/inject'}, + // Unit tests (Jest, Node.js) + {tsconfig: 'tests/unit'}, +]; + +describe('TypeScript project config', () => { + it.each(tsProjects)('file should parse and resolve correctly: $tsconfig', async ({tsconfig}) => { + // Parse config from temp dir instead of root dir + const cwd = await mkdtemp(join(tmpdir(), 'darkreader')); + const project = join(rootDir, tsconfig, 'tsconfig.json'); + + // Fire + const child = fork(tsc, ['--project', project, '--showConfig'], {silent: true, cwd}); + + const {response} = await childClosed(child, {serialization: 'json'}); + expect(child.exitCode).toBe(ExitStatus.Success); + const config = ts.parseJsonConfigFileContent(response, ts.sys, project); + expect(config.raw).toMatchSnapshot(); + }, 100000); + + // Slow test (run using `npm run test:project`) + it.each(tsProjects)('should compile without errors: $tsconfig', async ({tsconfig}) => { + // Compile config from temp dir instead of root dir + const cwd = await mkdtemp(join(tmpdir(), 'darkreader')); + const project = join(rootDir, tsconfig, 'tsconfig.json'); + + // Fire + const child = fork(tsc, ['--project', project, '--noEmit'], {silent: true, cwd}); + await childClosed(child); + expect(child.exitCode).toBe(ExitStatus.Success); + }, 60000); +}); diff --git a/tests/project/tsconfig.json b/tests/project/tsconfig.json new file mode 100644 index 000000000000..72effbaac2fa --- /dev/null +++ b/tests/project/tsconfig.json @@ -0,0 +1,23 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "compilerOptions": { + "target": "ES2021", + "module": "CommonJS", + "lib": [ + "ES2021", + "Dom" + ], + "types": [ + "node", + "jest", + "jest-extended" + ], + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "noImplicitAny": true, + "inlineSourceMap": true, + "noEmit": true, + "allowJs": true + } +} diff --git a/tests/project/utils.ts b/tests/project/utils.ts new file mode 100644 index 000000000000..d0878b5d950b --- /dev/null +++ b/tests/project/utils.ts @@ -0,0 +1,58 @@ +import type {Readable} from 'stream'; +import {PassThrough} from 'stream'; +import type {ChildProcess} from 'child_process'; +import {once} from 'events'; +import getStream from 'get-stream'; +import {promiseWithTimeout} from '../support/test-utils'; + +export type ChildClosedOptions = getStream.OptionsWithEncoding & {serialization?: false | 'json'; timeout?: number}; + +export type ChildClosedPayload = {stdout: string; stderr: string; response?: any}; + +/** + * Returns a promise that resolves with a child process's close event + * Also handles character set decoding, deserialization from JSON, accepts a timeout in ms + * + * @example + * const child = fork('./script.js'); + * const {stdout, stderr, response} = await watchChild(child); + * const {exitCode} = child; + */ +export async function childClosed(child: ChildProcess, options?: ChildClosedOptions): Promise { + const deserialize = (output: string) => options?.serialization === 'json' ? JSON.parse(output) : output; + const collect = async (readable: Readable) => getStream(readable || new PassThrough(), options); + const childPromises = Promise.all([once(child, 'close'), collect(child.stdout), collect(child.stderr)]) + .then(([, stdout, stderr]) => ({stdout, stderr, response: deserialize(stdout)})); + if (options?.timeout) { + return promiseWithTimeout(options.timeout, childPromises); + } + return childPromises; +} + +/** + * Returns a promise that resolves when a certain condition has been met, based on the content of a stream. + * + * @example + * await watchStream(child.stdout).forMatch(/Config loaded/) + * thisRunsAfterConfigLoads(); + */ +export const watchStream = (readable: Readable, options?: {encoding: BufferEncoding}) => { + if (!readable.readableEncoding) { + readable.setEncoding(options?.encoding || 'utf-8'); + } + const forCondition = async (cb: {(value: string): boolean}) => { + await new Promise((resolve, reject) => { + readable.on('close', reject).on('data', (chunk: string) => { + if (chunk && cb(chunk)) { + resolve(); + } + }); + }); + }; + + const forMatch = async (regExp: RegExp) => { + return await forCondition((chunk: string) => chunk.match(regExp) != null); + }; + + return {forCondition, forMatch}; +}; diff --git a/tests/support/test-utils.ts b/tests/support/test-utils.ts new file mode 100644 index 000000000000..1146dbb7077c --- /dev/null +++ b/tests/support/test-utils.ts @@ -0,0 +1,29 @@ +import {dirname, join} from 'path'; + +export const rootDir: string = dirname(require.resolve('../../package.json')); + +export function rootPath(...paths: string[]) { + return join(rootDir, ...paths); +} + +export function multiline(...lines: string[]) { + return lines.join('\n'); +} + +export function timeout(delay: number) { + return new Promise((resolve) => setTimeout(resolve, delay)); +} + +export function promiseWithTimeout(ms: number, promise: Promise): Promise { + let id: ReturnType; + return Promise.race([promise, new Promise((_, reject) => { + id = setTimeout(() => reject(new TimeoutError(ms)), ms); + })]).finally(() => clearTimeout(id)); +} + +class TimeoutError extends Error { + constructor(delay: number) { + super(`timeout exceeded (${delay} ms)`); + this.name = 'TimeoutError'; + } +} diff --git a/tests/test-utils.ts b/tests/test-utils.ts deleted file mode 100644 index 27807ecfe2ab..000000000000 --- a/tests/test-utils.ts +++ /dev/null @@ -1,7 +0,0 @@ -export function multiline(...lines: string[]) { - return lines.join('\n'); -} - -export function timeout(delay: number) { - return new Promise((resolve) => setTimeout(resolve, delay)); -} diff --git a/tests/config/config.tests.ts b/tests/unit/config/config.tests.ts similarity index 89% rename from tests/config/config.tests.ts rename to tests/unit/config/config.tests.ts index 0c8c3235d4d9..2d208038d310 100644 --- a/tests/config/config.tests.ts +++ b/tests/unit/config/config.tests.ts @@ -1,16 +1,16 @@ import {readFile} from 'fs'; -import {resolve as resolvePath} from 'path'; -import {compareURLPatterns} from '../../src/utils/url'; -import {parseArray, formatArray, getTextDiffIndex, getTextPositionMessage} from '../../src/utils/text'; -import {parseInversionFixes, formatInversionFixes} from '../../src/generators/css-filter'; -import {parseDynamicThemeFixes, formatDynamicThemeFixes} from '../../src/generators/dynamic-theme'; -import {parseStaticThemes, formatStaticThemes} from '../../src/generators/static-theme'; -import type {StaticTheme} from '../../src/definitions'; -import {ParseColorSchemeConfig} from '../../src/utils/colorscheme-parser'; +import {compareURLPatterns} from '../../../src/utils/url'; +import {parseArray, formatArray, getTextDiffIndex, getTextPositionMessage} from '../../../src/utils/text'; +import {parseInversionFixes, formatInversionFixes} from '../../../src/generators/css-filter'; +import {parseDynamicThemeFixes, formatDynamicThemeFixes} from '../../../src/generators/dynamic-theme'; +import {parseStaticThemes, formatStaticThemes} from '../../../src/generators/static-theme'; +import type {StaticTheme} from '../../../src/definitions'; +import {ParseColorSchemeConfig} from '../../../src/utils/colorscheme-parser'; +import {rootPath} from '../../support/test-utils'; function readConfig(fileName: string) { return new Promise((resolve, reject) => { - readFile(resolvePath(__dirname, '../../src/config/', fileName), {encoding: 'utf-8'}, (err, data) => { + readFile(rootPath('src/config', fileName), {encoding: 'utf-8'}, (err, data) => { if (err) { reject(err); return; @@ -48,7 +48,7 @@ test('Dark Sites list', async () => { expect(sites.every(isURLPatternValid)).toBe(true); // sites are sorted alphabetically - expect(sites).toEqual(sites.slice().sort(compareURLPatterns)); + expect(sites.slice().sort(compareURLPatterns)).toEqual(sites); // sites are properly formatted expect(throwIfDifferent(file, formatArray(sites), 'Dark Sites list format error')).not.toThrow(); diff --git a/tests/config/locales.tests.ts b/tests/unit/config/locales.tests.ts similarity index 87% rename from tests/config/locales.tests.ts rename to tests/unit/config/locales.tests.ts index 75bf7d3c0ca6..bca129432c44 100644 --- a/tests/config/locales.tests.ts +++ b/tests/unit/config/locales.tests.ts @@ -1,9 +1,9 @@ import {readFile as fsReadFile, readdir as fsReadDir} from 'fs'; -import {resolve as resolvePath} from 'path'; +import {rootPath} from '../../support/test-utils'; function readDir(dir: string) { return new Promise((resolve, reject) => { - fsReadDir(resolvePath(__dirname, dir), (err, files) => { + fsReadDir(dir, (err, files) => { if (err) { reject(err); return; @@ -15,7 +15,7 @@ function readDir(dir: string) { function readLocale(name: string) { return new Promise((resolve, reject) => { - fsReadFile(resolvePath(__dirname, '../../src/_locales/', name), {encoding: 'utf-8'}, (err, data) => { + fsReadFile(rootPath('src/_locales', name), {encoding: 'utf-8'}, (err, data) => { if (err) { reject(err); return; @@ -26,7 +26,7 @@ function readLocale(name: string) { } test('Locales', async () => { - const files = await readDir('../../src/_locales'); + const files = await readDir(rootPath('src/_locales')); const enLocale = await readLocale('en.config'); const enLines = enLocale.split('\n'); const locales: string[] = []; diff --git a/tests/generators/utils/parse.tests.ts b/tests/unit/generators/utils/parse.tests.ts similarity index 99% rename from tests/generators/utils/parse.tests.ts rename to tests/unit/generators/utils/parse.tests.ts index d3ab1b1f4128..2a4ed9c36421 100644 --- a/tests/generators/utils/parse.tests.ts +++ b/tests/unit/generators/utils/parse.tests.ts @@ -1,5 +1,5 @@ -import {indexSitesFixesConfig, getSitesFixesFor} from '../../../src/generators/utils/parse'; -import type {SitesFixesParserOptions} from '../../../src/generators/utils/parse'; +import {indexSitesFixesConfig, getSitesFixesFor} from '../../../../src/generators/utils/parse'; +import type {SitesFixesParserOptions} from '../../../../src/generators/utils/parse'; test('Index config', () => { interface TestFix { diff --git a/tests/unit/jest.config.js b/tests/unit/jest.config.js new file mode 100644 index 000000000000..1f18701808c8 --- /dev/null +++ b/tests/unit/jest.config.js @@ -0,0 +1,20 @@ +// @ts-check + +const {dirname} = require('path'); +const rootDir = dirname(require.resolve('../../package.json')); + +/** @type {import('@jest/types').Config.InitialOptions} */ +const config = { + rootDir, + testMatch: ['/tests/unit/**/*.tests.ts'], + moduleFileExtensions: ['ts', 'tsx', 'js'], + transform: {'^.+\\.ts(x?)$': 'ts-jest'}, + globals: { + 'ts-jest': {tsconfig: '/tests/unit/tsconfig.json'}, + __DEBUG__: false, + __TEST__: true, + }, + setupFilesAfterEnv: ['jest-extended/all'], +}; + +module.exports = config; diff --git a/tests/unit/tsconfig.json b/tests/unit/tsconfig.json new file mode 100644 index 000000000000..877e099d9d9d --- /dev/null +++ b/tests/unit/tsconfig.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "compilerOptions": { + "target": "ESNext", + "module": "CommonJS", + "lib": [ + "ESNext", + "Dom" + ], + "types": [ + "node", + "jest", + "jest-extended" + ], + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "noImplicitAny": true, + "inlineSourceMap": true + } +} diff --git a/tests/utils/color.tests.ts b/tests/unit/utils/color.tests.ts similarity index 96% rename from tests/utils/color.tests.ts rename to tests/unit/utils/color.tests.ts index 67a21519b50a..ca89dade7554 100644 --- a/tests/utils/color.tests.ts +++ b/tests/unit/utils/color.tests.ts @@ -1,5 +1,5 @@ -import type {HSLA} from '../../src/utils/color'; -import {lowerCalcExpression, parse, hslToRGB, rgbToHSL, rgbToString, rgbToHexString, hslToString} from '../../src/utils/color'; +import type {HSLA} from '../../../src/utils/color'; +import {lowerCalcExpression, parse, hslToRGB, rgbToHSL, rgbToString, rgbToHexString, hslToString} from '../../../src/utils/color'; test('Color parsing', () => { expect(parse('rgb(255,0,153)')).toEqual({r: 255, g: 0, b: 153, a: 1}); @@ -98,4 +98,5 @@ test('Color conversion', () => { test('Lower calc expressions', () => { expect(lowerCalcExpression('hsl(0, 0%, calc(95% - 3%))')).toEqual('hsl(0, 0%, 92%)'); expect(lowerCalcExpression('hsl(0, calc(25% + 12%), calc(95% - 3%))')).toEqual('hsl(0, 37%, 92%)'); + expect(lowerCalcExpression('rgb(calc(216.75 + 153 * .15), calc(216.75 + 205 * .15), calc(216.75 + 255 * .15))')).toEqual('rgb(240, 248, 255)'); }); diff --git a/tests/utils/math.tests.ts b/tests/unit/utils/math.tests.ts similarity index 85% rename from tests/utils/math.tests.ts rename to tests/unit/utils/math.tests.ts index c9c54e39b7fe..46a1401ecb3d 100644 --- a/tests/utils/math.tests.ts +++ b/tests/unit/utils/math.tests.ts @@ -1,4 +1,4 @@ -import {scale, clamp, multiplyMatrices} from '../../src/utils/math'; +import {scale, clamp, multiplyMatrices} from '../../../src/utils/math'; test('Scale', () => { expect(scale(5, 0, 10, 0, 100)).toEqual(50); diff --git a/tests/unit/utils/parsing.tests.ts b/tests/unit/utils/parsing.tests.ts new file mode 100644 index 000000000000..41f00315c32a --- /dev/null +++ b/tests/unit/utils/parsing.tests.ts @@ -0,0 +1,61 @@ +import {parseGradient} from '../../../src/utils/parsing'; + +test('type gradients', () => { + expect(parseGradient('linear-gradient(rgb(200))')).toEqual([{ + typeGradient: 'linear-gradient', + match: 'rgb(200)', + offset: 17, + index: 0, + hasComma: false, + }]); + expect(parseGradient(`linear-gradient(217deg, rgba(255,0,0,.8), rgba(255,0,0,0) 70.71%), + linear-gradient(127deg, rgba(0,255,0,.8), rgba(0,255,0,0) 70.71%), + linear-gradient(336deg, rgba(0,0,255,.8), rgba(0,0,255,0) 70.71%);`)).toEqual([ + { + offset: 17, + match: '217deg, rgba(255,0,0,.8), rgba(255,0,0,0) 70.71%', + hasComma: true, + index: 0, + typeGradient: 'linear-gradient', + }, + { + typeGradient: 'linear-gradient', + match: '127deg, rgba(0,255,0,.8), rgba(0,255,0,0) 70.71%', + hasComma: true, + offset: 17, + index: 71, + }, + { + typeGradient: 'linear-gradient', + match: '336deg, rgba(0,0,255,.8), rgba(0,0,255,0) 70.71%', + hasComma: false, + offset: 17, + index: 142 + } + ]); + expect(parseGradient('radial-gradient(rgb(200))')).toEqual([{ + typeGradient: 'radial-gradient', + match: 'rgb(200)', + index: 0, + offset: 17, + hasComma: false, + + }]); + + expect(parseGradient('repeating-linear-gradient(transparent, #4d9f0c 40px), repeating-linear-gradient(0.25turn, transparent, #3f87a6 20px);')).toEqual([ + { + typeGradient: 'repeating-linear-gradient', + match: 'transparent, #4d9f0c 40px', + hasComma: true, + offset: 27, + index: 0, + }, + { + typeGradient: 'repeating-linear-gradient', + match: '0.25turn, transparent, #3f87a6 20px', + hasComma: false, + index: 54, + offset: 27, + } + ]); +}); diff --git a/tests/unit/utils/promise-barrier.tests.ts b/tests/unit/utils/promise-barrier.tests.ts new file mode 100644 index 000000000000..11578a432a86 --- /dev/null +++ b/tests/unit/utils/promise-barrier.tests.ts @@ -0,0 +1,97 @@ +import {PromiseBarrier} from '../../../src/utils/promise-barrier'; + +describe('Promise barrier utility', () => { + test('basic functionality', async () => { + const barrier = new PromiseBarrier(); + const fn1 = jest.fn(); + const fn2 = jest.fn(); + (async () => { + fn1(); + const result = await barrier.entry(); + fn2(result); + })(); + expect(fn1).toBeCalled(); + expect(fn2).not.toBeCalled(); + + expect(barrier.isPending()).toBe(true); + expect(barrier.isFulfilled()).toBe(false); + expect(barrier.isRejected()).toBe(false); + await barrier.resolve(2); + expect(barrier.isFulfilled()).toBe(true); + expect(barrier.isPending()).toBe(false); + expect(barrier.isRejected()).toBe(false); + expect(fn1).toBeCalledTimes(1); + expect(fn2).toBeCalledWith(2); + }); + + test('awaiting for barrier after it was settled', async () => { + const barrierFulfilled = new PromiseBarrier(); + expect(barrierFulfilled.isPending()).toBe(true); + expect(barrierFulfilled.isFulfilled()).toBe(false); + expect(barrierFulfilled.isRejected()).toBe(false); + const promise1 = barrierFulfilled.resolve('Hello World!'); + expect(barrierFulfilled.isFulfilled()).toBe(true); + expect(barrierFulfilled.isPending()).toBe(false); + expect(barrierFulfilled.isRejected()).toBe(false); + const fn1 = jest.fn(); + await (async () => fn1(await barrierFulfilled.entry()))(); + await promise1; + expect(fn1).toBeCalledWith('Hello World!'); + + const barrierRejected = new PromiseBarrier(); + const promise2 = barrierRejected.reject('rejection reason'); + const fn2 = jest.fn(); + await (async () => { + try { + await barrierRejected.entry(); + } catch (e) { + fn2(e); + } + })(); + await promise2; + expect(fn2).toBeCalledWith('rejection reason'); + }); + + test('resolving multiple times', async () => { + const barrierFulfilled = new PromiseBarrier(); + expect(barrierFulfilled.isPending()).toBe(true); + expect(barrierFulfilled.isFulfilled()).toBe(false); + expect(barrierFulfilled.isRejected()).toBe(false); + await barrierFulfilled.resolve('Hello World!'); + expect(barrierFulfilled.isFulfilled()).toBe(true); + expect(barrierFulfilled.isPending()).toBe(false); + expect(barrierFulfilled.isRejected()).toBe(false); + await barrierFulfilled.resolve('Hello World 2!'); + expect(barrierFulfilled.isFulfilled()).toBe(true); + expect(barrierFulfilled.isPending()).toBe(false); + expect(barrierFulfilled.isRejected()).toBe(false); + + const fn1 = jest.fn(); + await (async () => fn1(await barrierFulfilled.entry()))(); + + expect(fn1).toBeCalledWith('Hello World!'); + }); + + test('rejecting multiple times', async () => { + const barrierRejected = new PromiseBarrier(); + expect(barrierRejected.isPending()).toBe(true); + expect(barrierRejected.isFulfilled()).toBe(false); + expect(barrierRejected.isRejected()).toBe(false); + await barrierRejected.reject('rejection reason'); + expect(barrierRejected.isRejected()).toBe(true); + expect(barrierRejected.isPending()).toBe(false); + expect(barrierRejected.isFulfilled()).toBe(false); + await barrierRejected.reject('rejection reason 2'); + + const fn2 = jest.fn(); + await (async () => { + try { + await barrierRejected.entry(); + } catch (e) { + fn2(e); + } + })(); + + expect(fn2).toBeCalledWith('rejection reason'); + }); +}); diff --git a/tests/utils/text.tests.ts b/tests/unit/utils/text.tests.ts similarity index 98% rename from tests/utils/text.tests.ts rename to tests/unit/utils/text.tests.ts index f2b4bfb2a29e..b53b9d529da0 100644 --- a/tests/utils/text.tests.ts +++ b/tests/unit/utils/text.tests.ts @@ -1,4 +1,4 @@ -import {formatCSS, getParenthesesRange} from '../../src/utils/text'; +import {formatCSS, getParenthesesRange} from '../../../src/utils/text'; test('CSS formatting', () => { expect(formatCSS('div { color: red; }')) diff --git a/tests/utils/time.tests.ts b/tests/unit/utils/time.tests.ts similarity index 99% rename from tests/utils/time.tests.ts rename to tests/unit/utils/time.tests.ts index 921d8f7f8856..68f19d7d2b01 100644 --- a/tests/utils/time.tests.ts +++ b/tests/unit/utils/time.tests.ts @@ -1,4 +1,4 @@ -import {isInTimeIntervalLocal, nextTimeInterval, isNightAtLocation, nextTimeChangeAtLocation, parseTime, getDuration, getDurationInMinutes} from '../../src/utils/time'; +import {isInTimeIntervalLocal, nextTimeInterval, isNightAtLocation, nextTimeChangeAtLocation, parseTime, getDuration, getDurationInMinutes} from '../../../src/utils/time'; test('Time interval', () => { // isInTimeIntervalLocal is time-zone dependent diff --git a/tests/utils/uid.tests.ts b/tests/unit/utils/uid.tests.ts similarity index 94% rename from tests/utils/uid.tests.ts rename to tests/unit/utils/uid.tests.ts index b047da7bfc23..adf8f5757bed 100644 --- a/tests/utils/uid.tests.ts +++ b/tests/unit/utils/uid.tests.ts @@ -1,5 +1,5 @@ import {randomFillSync} from 'crypto'; -import {generateUID} from '../../src/utils/uid'; +import {generateUID} from '../../../src/utils/uid'; test('Unique identifier generation', () => { // Make sure we are not messing up global context for somebody else diff --git a/tests/unit/utils/validation.tests.ts b/tests/unit/utils/validation.tests.ts new file mode 100644 index 000000000000..19c9d4c3f742 --- /dev/null +++ b/tests/unit/utils/validation.tests.ts @@ -0,0 +1,202 @@ +import {validateSettings, validateTheme} from '../../../src/utils/validation'; +import {DEFAULT_SETTINGS, DEFAULT_THEME} from '../../../src/defaults'; +import type {Theme, UserSettings} from '../../../src/definitions'; + +test('Settings Validation', () => { + const defaultTheme = JSON.parse(JSON.stringify(DEFAULT_THEME)); + let themeValidation = validateTheme(defaultTheme); + expect(themeValidation.errors).toEqual([]); + expect(defaultTheme).toEqual(DEFAULT_THEME); + + const partTheme = { + brightness: 125, + contrast: -50, + }; + themeValidation = validateTheme(partTheme as any); + expect(themeValidation.errors.length).toBe(1); + expect(partTheme).toEqual({ + brightness: 125, + contrast: DEFAULT_THEME.contrast, + }); + + const wonkyTheme = { + mode: 'dark', + brightness: 250, + contrast: -50, + grayscale: false, + sepia: 105, + useFont: 'ok', + fontFamily: '', + textStroke: 2, + engine: 'dymanic', + stylesheet: 3, + darkSchemeBackgroundColor: 'red', + darkSchemeTextColor: '#abc12x', + lightSchemeBackgroundColor: '', + lightSchemeTextColor: '#ffffff00', + scrollbarColor: false, + selectionColor: 'green', + styleSystemControls: null as boolean, + lightColorScheme: '', + darkColorScheme: false, + immediateModify: 1, + }; + themeValidation = validateTheme(wonkyTheme as any); + expect(themeValidation.errors.length).toBeGreaterThan(0); + expect(wonkyTheme).toEqual(DEFAULT_THEME); + + const defaultSet = JSON.parse(JSON.stringify(DEFAULT_SETTINGS)); + let validation = validateSettings(defaultSet); + expect(validation.errors).toEqual([]); + expect(defaultSet).toEqual(DEFAULT_SETTINGS); + + const wonkySet = { + enabled: '', + fetchNews: null as boolean, + theme: { + mode: 'dark', + brightness: 250, + contrast: -50, + grayscale: false, + sepia: 105, + useFont: 'ok', + fontFamily: '', + textStroke: 2, + engine: 'dymanic', + stylesheet: 3, + darkSchemeBackgroundColor: 'red', + darkSchemeTextColor: '#abc12x', + lightSchemeBackgroundColor: '', + lightSchemeTextColor: '#ffffff00', + scrollbarColor: false, + selectionColor: 'green', + styleSystemControls: null as boolean, + lightColorScheme: '', + darkColorScheme: false, + immediateModify: 1, + }, + presets: [ + {id: '', name: 'P1', urls: ['a.com'], theme: {brightness: 100}}, + {id: 'p2', name: '', urls: ['a.com'], theme: {brightness: 100}}, + {id: 'p3', name: 'P3', urls: [], theme: {brightness: 100}}, + {id: 'p4', name: 'P4', urls: ['a.com'], theme: {brightness: -50}}, + {id: 'p5', name: 'P5', urls: ['a.com'], theme: {brightness: 100}}, + {id: 'p6', urls: ['a.com'], theme: {brightness: 100}}, + {id: 'p7', name: 'P7', urls: ['a.com'], theme: null}, + null, + ], + customThemes: [ + {url: [] as any[], theme: {brightness: 100}}, + {url: [''], theme: {brightness: 100}}, + {url: ['a.com'], theme: {brightness: 100}}, + {url: ['a.com'], theme: {brightness: -50}}, + {url: ['a.com']}, + {url: ['a.com'], theme: null}, + null, + ], + siteList: ['a.com', '', 'b.com'], + siteListEnabled: {0: 'a.com', 1: 'b.com'}, + applyToListedOnly: null as boolean, + changeBrowserTheme: 1, + syncSettings: null as boolean, + syncSitesFixes: 0, + automation: 'off', + automationBehaviour: 'Default', + time: { + activation: '10:00PM', + deactivation: '19:00', + }, + location: { + latitude: 59, + longitude: '5.3', + }, + previewNewDesign: '', + enableForPDF: null as boolean, + enableForProtectedPages: 'ok', + enableContextMenus: 'yes', + detectDarkTheme: 'no', + }; + validation = validateSettings(wonkySet as any); + expect(validation.errors.length).toBeGreaterThan(0); + expect(wonkySet).toEqual({ + ...DEFAULT_SETTINGS, + siteList: ['a.com', 'b.com'], + presets: [{id: 'p5', name: 'P5', urls: ['a.com'], theme: {brightness: 100}}], + customThemes: [{url: ['a.com'], theme: {brightness: 100}}], + }); + + const nullishSet = { + theme: null as any, + presets: null as any, + customThemes: null as any, + time: null as any, + location: null as any, + }; + validation = validateSettings(nullishSet); + expect(validation.errors.length).toBe(5); + expect(nullishSet).toEqual({ + theme: DEFAULT_THEME, + presets: DEFAULT_SETTINGS.presets, + customThemes: DEFAULT_SETTINGS.customThemes, + time: DEFAULT_SETTINGS.time, + location: DEFAULT_SETTINGS.location, + }); + + const validSet: UserSettings = { + enabled: true, + fetchNews: true, + theme: { + mode: 0, + brightness: 125, + contrast: 50, + grayscale: 25, + sepia: 5, + useFont: true, + fontFamily: 'Comic Sans', + textStroke: 0.5, + engine: 'dynamicTheme', + stylesheet: '.x { color: red; }', + darkSchemeBackgroundColor: '#abcdef', + darkSchemeTextColor: '#abc123', + lightSchemeBackgroundColor: '#ff0000', + lightSchemeTextColor: '#ffffff', + scrollbarColor: '', + selectionColor: 'auto', + styleSystemControls: false, + lightColorScheme: 'Lightness', + darkColorScheme: 'Darkness', + immediateModify: true, + }, + presets: [ + {id: 'p5', name: 'P5', urls: ['a.com'], theme: {brightness: 100} as Theme}, + ], + customThemes: [ + {url: ['a.com'], theme: {brightness: 100} as Theme}, + ], + siteList: ['a.com', 'b.com'], + siteListEnabled: ['c.com'], + applyToListedOnly: true, + changeBrowserTheme: true, + syncSettings: false, + syncSitesFixes: true, + automation: 'time', + automationBehaviour: 'Scheme', + time: { + activation: '18:00', + deactivation: '7:00', + }, + location: { + latitude: 59, + longitude: 53, + }, + previewNewDesign: true, + enableForPDF: false, + enableForProtectedPages: true, + enableContextMenus: true, + detectDarkTheme: true, + }; + const validSetCopy = JSON.parse(JSON.stringify(validSet)); + validation = validateSettings(validSet); + expect(validation.errors).toEqual([]); + expect(validSet).toEqual(validSetCopy); +}); diff --git a/tests/utils/jest.config.js b/tests/utils/jest.config.js deleted file mode 100644 index ed12a8408e60..000000000000 --- a/tests/utils/jest.config.js +++ /dev/null @@ -1,23 +0,0 @@ -module.exports = { - verbose: true, - testEnvironment: 'jsdom', - transform: { - '^.+\\.ts$': 'ts-jest' - }, - testRegex: 'tests/utils/.*\\.tests\\.ts$', - moduleFileExtensions: [ - 'ts', - 'js' - ], - rootDir: '../../', - collectCoverage: false, - coverageDirectory: 'tests/coverage', - collectCoverageFrom: [ - '/src/**/*.ts', - ], - globals: { - 'ts-jest': { - tsconfig: './tests/utils/tsconfig.json' - } - } -}; diff --git a/tests/utils/promise-barrier.tests.ts b/tests/utils/promise-barrier.tests.ts deleted file mode 100644 index f54ec9d56c14..000000000000 --- a/tests/utils/promise-barrier.tests.ts +++ /dev/null @@ -1,89 +0,0 @@ -import {PromiseBarrier} from '../../src/utils/promise-barrier'; - -test('Promise barrier utility', async () => { - const barrier = new PromiseBarrier(); - const fn1 = jest.fn(); - const fn2 = jest.fn(); - (async () => { - fn1(); - const result = await barrier.entry(); - fn2(result); - })(); - expect(fn1).toBeCalled(); - expect(fn2).not.toBeCalled(); - - expect(barrier.isPending()).toBe(true); - expect(barrier.isFulfilled()).toBe(false); - expect(barrier.isRejected()).toBe(false); - await barrier.resolve(2); - expect(barrier.isFulfilled()).toBe(true); - expect(barrier.isPending()).toBe(false); - expect(barrier.isRejected()).toBe(false); - expect(fn1).toBeCalledTimes(1); - expect(fn2).toBeCalledWith(2); -}); - -test('Promise barrier utility: awaiting for barrier after it was settled', async () => { - const barrierFulfilled = new PromiseBarrier(); - expect(barrierFulfilled.isPending()).toBe(true); - expect(barrierFulfilled.isFulfilled()).toBe(false); - expect(barrierFulfilled.isRejected()).toBe(false); - const promise1 = barrierFulfilled.resolve('Hello World!'); - expect(barrierFulfilled.isFulfilled()).toBe(true); - expect(barrierFulfilled.isPending()).toBe(false); - expect(barrierFulfilled.isRejected()).toBe(false); - const fn1 = jest.fn(); - (async () => fn1(await barrierFulfilled.entry()))(); - await promise1; - expect(fn1).toBeCalledWith('Hello World!'); - - const barrierRejected = new PromiseBarrier(); - const promise2 = barrierRejected.reject('rejection reason'); - const fn2 = jest.fn(); - (async () => { - try { - await barrierRejected.entry(); - } catch (e) { - fn2(e); - } - })(); - await promise2; - expect(fn2).toBeCalledWith('rejection reason'); -}); - -test('Promise barrier utility: resolving multiple times', async () => { - const barrierFulfilled = new PromiseBarrier(); - expect(barrierFulfilled.isPending()).toBe(true); - expect(barrierFulfilled.isFulfilled()).toBe(false); - expect(barrierFulfilled.isRejected()).toBe(false); - barrierFulfilled.resolve('Hello World!'); - expect(barrierFulfilled.isFulfilled()).toBe(true); - expect(barrierFulfilled.isPending()).toBe(false); - expect(barrierFulfilled.isRejected()).toBe(false); - barrierFulfilled.resolve('Hello World 2!'); - expect(barrierFulfilled.isFulfilled()).toBe(true); - expect(barrierFulfilled.isPending()).toBe(false); - expect(barrierFulfilled.isRejected()).toBe(false); - const fn1 = jest.fn(); - (async () => fn1(await barrierFulfilled.entry()))(); - setTimeout(() => expect(fn1).toBeCalledWith('Hello World!')); - - const barrierRejected = new PromiseBarrier(); - expect(barrierRejected.isPending()).toBe(true); - expect(barrierRejected.isFulfilled()).toBe(false); - expect(barrierRejected.isRejected()).toBe(false); - await barrierRejected.reject('rejection reason'); - expect(barrierRejected.isRejected()).toBe(true); - expect(barrierRejected.isPending()).toBe(false); - expect(barrierRejected.isFulfilled()).toBe(false); - barrierRejected.reject('rejection reason 2'); - const fn2 = jest.fn(); - (async () => { - try { - await barrierRejected.entry(); - } catch (e) { - fn2(e); - } - })(); - setTimeout(() => expect(fn2).toBeCalledWith('rejection reason')); -}); diff --git a/tests/utils/tsconfig.json b/tests/utils/tsconfig.json deleted file mode 100644 index 8577f29983b2..000000000000 --- a/tests/utils/tsconfig.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "extends": "../../src/tsconfig", - "compilerOptions": { - "module": "commonjs", - "outDir": "", - "types": [ - "jest", - "node" - ] - } -}