diff --git a/.babelrc.js b/.babelrc.js index ea52011..33f80a6 100644 --- a/.babelrc.js +++ b/.babelrc.js @@ -3,7 +3,7 @@ * @param {import('@babel/core').ConfigAPI} api * @returns */ -module.exports = api => { + module.exports = api => { const BABEL_ENV = api.env() let targets = {} @@ -13,7 +13,7 @@ module.exports = api => { targets = 'last 1 chrome version, last 1 firefox version, last 1 safari version' } else if (BABEL_ENV === 'production') { - targets = '>0.2%, not dead, not op_mini all' + targets = 'last 1 chrome version, last 1 firefox version, last 1 safari version' } /** diff --git a/.eslintrc.js b/.eslintrc.js index f64dc8b..a1e18b6 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -14,6 +14,7 @@ const eslintConfig = { 'plugin:import/typescript', 'plugin:@typescript-eslint/recommended', 'plugin:prettier/recommended', + 'plugin:react-hooks/recommended', ], parser: '@typescript-eslint/parser', parserOptions: { @@ -27,6 +28,10 @@ const eslintConfig = { react: { version: 'detect', }, + 'import/resolver': { + typescript: true, + node: true, + }, }, plugins: ['react', '@typescript-eslint'], rules: { @@ -103,6 +108,8 @@ const eslintConfig = { '@typescript-eslint/explicit-module-boundary-types': 'off', '@typescript-eslint/explicit-function-return-type': 'off', '@typescript-eslint/explicit-member-accessibility': 'off', + + 'prefer-const': 'warn', }, overrides: [ { @@ -112,6 +119,12 @@ const eslintConfig = { '@typescript-eslint/explicit-member-accessibility': ['error'], }, }, + { + files: ['*.js'], + rules: { + '@typescript-eslint/no-var-requires': ['off'], + }, + }, ], ignorePatterns: ['**/node_modules/**', 'dist', 'lib', '**/__snapshots__/**'], } diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..3d118b8 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,47 @@ +name: Release + +on: + push: + branches: + - master + +jobs: + release: + name: Release + environment: release + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Setup Environment + uses: pnpm/action-setup@v2.1.0 + with: + version: 6.26.1 + + - name: Setup Node.js + uses: actions/setup-node@v2 + with: + node-version: '14' + cache: 'pnpm' + + - name: Install dependencies + run: pnpm install + + - name: Lint + run: pnpm lint + + - name: Build + run: pnpm build + + - name: Release + env: + PRIVATE_KEY: ${{ secrets.PRIVATE_KEY }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GIT_AUTHOR_NAME: github-actions + GIT_AUTHOR_EMAIL: 41898282+github-actions[bot]@users.noreply.github.com + GIT_COMMITTER_NAME: github-actions + GIT_COMMITTER_EMAIL: 41898282+github-actions[bot]@users.noreply.github.com + run: npx semantic-release diff --git a/.gitignore b/.gitignore index 0bccca1..486c849 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,9 @@ node_modules/ # OS X temporary files .DS_Store + +dist +*.pem + +# WebStorm +.idea \ No newline at end of file diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..d7df89c --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["esbenp.prettier-vscode", "dbaeumer.vscode-eslint"] +} diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..8fa47f9 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,16 @@ +{ + // 使用 IntelliSense 了解相关属性。 + // 悬停以查看现有属性的描述。 + // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "pwa-node", + "request": "launch", + "name": "Launch Program", + "skipFiles": ["/**"], + "program": "${workspaceFolder}/node_modules/webpack/bin/webpack.js", + "args": ["serve", "--node-env=development"] + } + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..6b2ec93 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,17 @@ +{ + "eslint.format.enable": true, + "eslint.packageManager": "pnpm", + "[typescript]": { + "editor.defaultFormatter": "dbaeumer.vscode-eslint" + }, + "[typescriptreact]": { + "editor.defaultFormatter": "dbaeumer.vscode-eslint" + }, + "json.schemas": [ + { + // @see https://github.com/GoogleChrome/chrome-types/issues/7 + "fileMatch": ["manifest.json"], + "url": "https://json.schemastore.org/chrome-manifest" + } + ] +} diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..69a5f43 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,802 @@ +## [0.14.4](https://github.com/XYShaoKang/refined-leetcode/compare/v0.14.3...v0.14.4) (2024-09-29) + + +### Bug Fixes + +* lint ([103374e](https://github.com/XYShaoKang/refined-leetcode/commit/103374e9a1edbd85747351667cfd8917738b164a)) +* 修复题库页评分过滤失效 ([3e73745](https://github.com/XYShaoKang/refined-leetcode/commit/3e73745f9bfae624ace4d8b35546487790b3f7a0)) + +## [0.14.3](https://github.com/XYShaoKang/refined-leetcode/compare/v0.14.2...v0.14.3) (2024-09-22) + + +### Bug Fixes + +* lint ([8778b17](https://github.com/XYShaoKang/refined-leetcode/commit/8778b17a5016a5818f2f667cfc65d71084a64999)) +* 预测列不显示 ([7e32285](https://github.com/XYShaoKang/refined-leetcode/commit/7e3228517de34e0a19fab21153dfda0c922ab095)) + +## [0.14.2](https://github.com/XYShaoKang/refined-leetcode/compare/v0.14.1...v0.14.2) (2024-09-21) + + +### Bug Fixes + +* 修复切换问题 ([49f03fe](https://github.com/XYShaoKang/refined-leetcode/commit/49f03fe85f22f301d29bd3ee3d66f452710e58a4)) + +## [0.14.1](https://github.com/XYShaoKang/refined-leetcode/compare/v0.14.0...v0.14.1) (2024-09-17) + + +### Bug Fixes + +* 修复一些bug ([770a064](https://github.com/XYShaoKang/refined-leetcode/commit/770a0643202be8498505eab898100171618276f2)) + +# [0.14.0](https://github.com/XYShaoKang/refined-leetcode/compare/v0.13.5...v0.14.0) (2024-09-15) + + +### Bug Fixes + +* fix lint ([ae42c5e](https://github.com/XYShaoKang/refined-leetcode/commit/ae42c5e0e1e345d391d89f86e37a82e18656a3e2)) + + +### Features + +* 适配新版排行版 ([d0d179e](https://github.com/XYShaoKang/refined-leetcode/commit/d0d179eaf6b1cd2efde0f12b0b7e57ae4124ffdc)) + +## [0.13.5](https://github.com/XYShaoKang/refined-leetcode/compare/v0.13.4...v0.13.5) (2023-12-07) + + +### Bug Fixes + +* **problemset:** 修复本地题目过滤失效 ([186c5c8](https://github.com/XYShaoKang/refined-leetcode/commit/186c5c88d05de5a05194fdc02538bd40f1405d5c)) + +## [0.13.4](https://github.com/XYShaoKang/refined-leetcode/compare/v0.13.3...v0.13.4) (2023-11-04) + + +### Bug Fixes + +* **background:** 更新 lccn.lbao.site 的 api 地址 ([1cab345](https://github.com/XYShaoKang/refined-leetcode/commit/1cab3456f8e3eed3d88a34e6b4b1e9023030ec02)) + +## [0.13.3](https://github.com/XYShaoKang/refined-leetcode/compare/v0.13.2...v0.13.3) (2023-10-14) + + +### Bug Fixes + +* **problems:** 去掉提示 ([6814cc1](https://github.com/XYShaoKang/refined-leetcode/commit/6814cc17e33d4ed8d6d91b0fe8fff7d7077a1eb6)) + +## [0.13.2](https://github.com/XYShaoKang/refined-leetcode/compare/v0.13.1...v0.13.2) (2023-10-14) + + +### Bug Fixes + +* **problems:** 自定义布局选项默认关闭 ([29f6564](https://github.com/XYShaoKang/refined-leetcode/commit/29f6564887efa9c6a3f87ec755e95b43450b73cc)) + +## [0.13.1](https://github.com/XYShaoKang/refined-leetcode/compare/v0.13.0...v0.13.1) (2023-10-14) + + +### Bug Fixes + +* **problems:** 添加提示 ([fea4829](https://github.com/XYShaoKang/refined-leetcode/commit/fea4829540a56072330801e8328a78021cd7b5cf)) + +# [0.13.0](https://github.com/XYShaoKang/refined-leetcode/compare/v0.12.22...v0.13.0) (2023-10-14) + + +### Bug Fixes + +* **problems:** 优化一下页面判断逻辑 ([711ae8b](https://github.com/XYShaoKang/refined-leetcode/commit/711ae8b72b1340168ccaa32e1d63fff9c158aed8)) +* 修复代码格式 ([e8d2cee](https://github.com/XYShaoKang/refined-leetcode/commit/e8d2ceee9df9198063a3d2e9653d646c96d6d766)) + + +### Features + +* 添加竞赛答题页自定义布局功能 ([bf5c00f](https://github.com/XYShaoKang/refined-leetcode/commit/bf5c00f3af97856b164ad2109fe4baab4c40a21c)) + +## [0.12.22](https://github.com/XYShaoKang/refined-leetcode/compare/v0.12.21...v0.12.22) (2023-09-20) + + +### Bug Fixes + +* **problemset:** 修复元素的查找 ([253ec7d](https://github.com/XYShaoKang/refined-leetcode/commit/253ec7d054d1b3748f5a0580baf892014021e8ea)) +* **problems:** 修复从灵动布局退回到两栏布局时,定时器失效 ([38a6887](https://github.com/XYShaoKang/refined-leetcode/commit/38a6887d2e7486bcd3bcbbc6639d0df4e324fdd0)) +* 修复判断题库页是否加载 ([6b3ac3e](https://github.com/XYShaoKang/refined-leetcode/commit/6b3ac3efa5ef140743895dd1c2d65c9aa0a045c4)) + +## [0.12.21](https://github.com/XYShaoKang/refined-leetcode/compare/v0.12.20...v0.12.21) (2023-08-25) + + +### Bug Fixes + +* 修复题库页评分组件不加载 ([20f4d24](https://github.com/XYShaoKang/refined-leetcode/commit/20f4d2492cc3f44df5b89fa3deade07dfe54db42)) + +## [0.12.20](https://github.com/XYShaoKang/refined-leetcode/compare/v0.12.19...v0.12.20) (2023-07-16) + + +### Reverts + +* Revert "fix(problems): 修复灵动布局下编辑器元素的查找" ([829db5a](https://github.com/XYShaoKang/refined-leetcode/commit/829db5a42db24df18c4073a46a77ae8a3db442c7)) + +## [0.12.19](https://github.com/XYShaoKang/refined-leetcode/compare/v0.12.18...v0.12.19) (2023-07-16) + + +### Bug Fixes + +* **problems:** 修复灵动布局下不显示备注的情况 ([9ce24a3](https://github.com/XYShaoKang/refined-leetcode/commit/9ce24a326fd2a9764e55aa795012ba126bec61e3)) +* **problems:** 修复灵动布局下编辑器元素的查找 ([bb16aad](https://github.com/XYShaoKang/refined-leetcode/commit/bb16aadba6ec7ea2e93edbab787bbb121a779aae)) + +## [0.12.18](https://github.com/XYShaoKang/refined-leetcode/compare/v0.12.17...v0.12.18) (2023-07-16) + + +### Bug Fixes + +* **problems:** 修复查找编辑器元素的逻辑 ([3bd5397](https://github.com/XYShaoKang/refined-leetcode/commit/3bd5397796bbffd76db685e2821c74ee190adf69)) + +## [0.12.17](https://github.com/XYShaoKang/refined-leetcode/compare/v0.12.16...v0.12.17) (2023-07-15) + + +### Bug Fixes + +* **problems:** 修复查找编辑器元素的逻辑 ([cc17c91](https://github.com/XYShaoKang/refined-leetcode/commit/cc17c91b5a2c5ea0d8af5a898a207999d0044091)) + +## [0.12.16](https://github.com/XYShaoKang/refined-leetcode/compare/v0.12.15...v0.12.16) (2023-07-15) + + +### Bug Fixes + +* **problems:** 修复查找编辑器元素的逻辑 ([379a757](https://github.com/XYShaoKang/refined-leetcode/commit/379a757d723ffeed7aea0f4b6c0e6ed4a5421a98)) + +## [0.12.15](https://github.com/XYShaoKang/refined-leetcode/compare/v0.12.14...v0.12.15) (2023-07-13) + + +### Bug Fixes + +* **problems:** 修复快捷键提交 ([8ed9257](https://github.com/XYShaoKang/refined-leetcode/commit/8ed9257d6005896e2759472dea47532a70accec6)) + +## [0.12.14](https://github.com/XYShaoKang/refined-leetcode/compare/v0.12.13...v0.12.14) (2023-07-12) + + +### Bug Fixes + +* **random:** 官方已经修复了随机一题,可以不用提供这些功能了 ([87a81b4](https://github.com/XYShaoKang/refined-leetcode/commit/87a81b4dd2a37bc516cb150a3ccb27a008dfcced)) + +## [0.12.13](https://github.com/XYShaoKang/refined-leetcode/compare/v0.12.12...v0.12.13) (2023-07-12) + + +### Bug Fixes + +* **problems:** 新版题解不会在新开一页 ([2f4b182](https://github.com/XYShaoKang/refined-leetcode/commit/2f4b1829cfbefb4723b969b7410b0a87ce54b1bb)) + +## [0.12.12](https://github.com/XYShaoKang/refined-leetcode/compare/v0.12.11...v0.12.12) (2023-07-12) + + +### Bug Fixes + +* **problems:** 计时器适配灵动布局 ([10796ce](https://github.com/XYShaoKang/refined-leetcode/commit/10796ce537857c29d2da56e621f02cc570af17ff)) + +## [0.12.11](https://github.com/XYShaoKang/refined-leetcode/compare/v0.12.10...v0.12.11) (2023-07-02) + + +### Bug Fixes + +* **problems:** 增加时钟更新频率 ([6ac0008](https://github.com/XYShaoKang/refined-leetcode/commit/6ac00088f8167693898f5736d6508ec1065e4c94)) +* **ranking:** 如果还没 AK 则排名还有可能发生变化 ([d33c1c7](https://github.com/XYShaoKang/refined-leetcode/commit/d33c1c7cc185498473f0b86a16cadb23db4ea121)) + +## [0.12.10](https://github.com/XYShaoKang/refined-leetcode/compare/v0.12.9...v0.12.10) (2023-05-20) + + +### Bug Fixes + +* **ranking:** 优化提示信息 ([ee0f859](https://github.com/XYShaoKang/refined-leetcode/commit/ee0f859d63152974840c4ae7ee7b9529807defce)) + +## [0.12.9](https://github.com/XYShaoKang/refined-leetcode/compare/v0.12.8...v0.12.9) (2023-05-20) + + +### Bug Fixes + +* **ranking:** 优化RK/Exp的呈现 ([187ec85](https://github.com/XYShaoKang/refined-leetcode/commit/187ec857380c055e39c79d6c3c58d5f23b3cf34a)) + +## [0.12.8](https://github.com/XYShaoKang/refined-leetcode/compare/v0.12.7...v0.12.8) (2023-04-22) + + +### Bug Fixes + +* **problemset:** 修复题库页的题单列表([#9](https://github.com/XYShaoKang/refined-leetcode/issues/9)) ([c3bb6df](https://github.com/XYShaoKang/refined-leetcode/commit/c3bb6dfb47f324517e82a3fb195853fb9f201ae7)) + +## [0.12.7](https://github.com/XYShaoKang/refined-leetcode/compare/v0.12.6...v0.12.7) (2023-04-22) + + +### Bug Fixes + +* **home:** 修复点击删除时会关闭面板 ([ebeefd5](https://github.com/XYShaoKang/refined-leetcode/commit/ebeefd5a3affc0f43fd1d0ae958af92e2a35e4d0)) +* **ranking:** 添加当前实时排名 ([1946599](https://github.com/XYShaoKang/refined-leetcode/commit/1946599747e6695d1321629e4d1193e5371b029b)) + +## [0.12.6](https://github.com/XYShaoKang/refined-leetcode/compare/v0.12.5...v0.12.6) (2023-04-16) + + +### Bug Fixes + +* **ranking:** 修复对于第一次参赛的选手,获取初始分数错误 ([70e5603](https://github.com/XYShaoKang/refined-leetcode/commit/70e5603dbd2de38310cdc1345bcbc37ea16d3510)) +* **ranking:** 当 delta 不存在时,则不需要显示 delta 和 newRating ([a8b3e8b](https://github.com/XYShaoKang/refined-leetcode/commit/a8b3e8be990b6da963f36543a06fd3d2d13193c6)) +* **ranking:** 添加关于实时预测的提示信息 ([05e12f0](https://github.com/XYShaoKang/refined-leetcode/commit/05e12f0d75f55aa0fe941cee0159fda0f00497e6)) +* **ranking:** 添加期望排名 ([e6972b1](https://github.com/XYShaoKang/refined-leetcode/commit/e6972b10acb060d94c00f2180d811afe34907a45)) + +## [0.12.5](https://github.com/XYShaoKang/refined-leetcode/compare/v0.12.4...v0.12.5) (2023-03-20) + + +### Bug Fixes + +* **ranking:** 对于相同分数相同时间的选手,按照相同排名处理 ([797f22c](https://github.com/XYShaoKang/refined-leetcode/commit/797f22c12fb4a650157d44bab9c3a61ac285d91e)) +* **ranking:** 预处理 erank 提升性能,并使用 FFT 来优化预处理的性能 ([4ad361a](https://github.com/XYShaoKang/refined-leetcode/commit/4ad361adc2a54785cccec7d00fe6436bdbe70e48)) + +## [0.12.4](https://github.com/XYShaoKang/refined-leetcode/compare/v0.12.3...v0.12.4) (2023-03-19) + + +### Bug Fixes + +* **ranking:** 计算排名错误 ([96506b6](https://github.com/XYShaoKang/refined-leetcode/commit/96506b6285f51984613730f7f6d3bdb090828354)) + +## [0.12.3](https://github.com/XYShaoKang/refined-leetcode/compare/v0.12.2...v0.12.3) (2023-03-19) + + +### Bug Fixes + +* **background:** 修复缓存 ([3ec4ade](https://github.com/XYShaoKang/refined-leetcode/commit/3ec4ade3be1a0af1ecd51ef17c6c90bc05e746ee)) +* **background:** 请求预测数据添加重试机制 ([7423ed9](https://github.com/XYShaoKang/refined-leetcode/commit/7423ed9d20a6d7ffbc7081c5e47961319d55c9d1)) +* **ranking:** 修复没有获取到数据的错误 ([c824642](https://github.com/XYShaoKang/refined-leetcode/commit/c824642c3accc4675ef02f6fb76e0b621e85bc1d)) +* **ranking:** 统一获取用户预测数据 ([8865628](https://github.com/XYShaoKang/refined-leetcode/commit/8865628ad6185d7b3577e9b825897b1f8f66b8d0)) + +## [0.12.2](https://github.com/XYShaoKang/refined-leetcode/compare/v0.12.1...v0.12.2) (2023-03-17) + + +### Bug Fixes + +* 修复生成脚本格式 ([d4d8d44](https://github.com/XYShaoKang/refined-leetcode/commit/d4d8d44b8cd300491d045f8ba243e117779f9263)) + +## [0.12.1](https://github.com/XYShaoKang/refined-leetcode/compare/v0.12.0...v0.12.1) (2023-03-17) + + +### Bug Fixes + +* 修复编译后函数名被修改,导致worker运行错误 ([53e5e83](https://github.com/XYShaoKang/refined-leetcode/commit/53e5e83360bff7d75224244aeb097c60aa2af6f2)) + +# [0.12.0](https://github.com/XYShaoKang/refined-leetcode/compare/v0.11.13...v0.12.0) (2023-03-17) + + +### Bug Fixes + +* **home:** 点击黑名单之外的区域时,关闭黑名单列表 ([f926a20](https://github.com/XYShaoKang/refined-leetcode/commit/f926a2030ec9e4f4779280d1ea5ace1628fe7274)) +* **home:** 调整列表样式 ([bb49837](https://github.com/XYShaoKang/refined-leetcode/commit/bb49837f35f6d1429340322f807803a78025ed3e)) +* **problem-list:** 调整鼠标悬浮时的样式 ([4fb1bb4](https://github.com/XYShaoKang/refined-leetcode/commit/4fb1bb4fde2a6b33b7e80a10cd471970cfe08495)) +* **problemset:** 修复当评分关闭时表头中的标题出现错位现象 ([f8069db](https://github.com/XYShaoKang/refined-leetcode/commit/f8069dbd994b8e26574cd90f679ee75e997830c0)) +* **problems:** 使用图标替代文字 ([4df66af](https://github.com/XYShaoKang/refined-leetcode/commit/4df66af983f4892c2b6cdc50f0545741ba8b691a)) +* **problems:** 修复禁用快捷键选项 ([c131073](https://github.com/XYShaoKang/refined-leetcode/commit/c13107319370cf235ecf92afef27dc956f62fdf9)) +* **problems:** 切换题目时重新计时 ([ea46c2a](https://github.com/XYShaoKang/refined-leetcode/commit/ea46c2a59467ba3d304c9936895c6a173a2fb5ea)) +* **problems:** 完善计时器卸载和加载的逻辑 ([dade54c](https://github.com/XYShaoKang/refined-leetcode/commit/dade54c6e8ac36bb919317427333b306767a7c0b)) +* **problems:** 调整计时器样式 ([0f077b3](https://github.com/XYShaoKang/refined-leetcode/commit/0f077b3e8db4559c9e212e4144560f6520c4b5e6)) +* **problems:** 随机一题按钮消失 ([0373563](https://github.com/XYShaoKang/refined-leetcode/commit/0373563815d59232616ee7d871d5e42009e73417)) +* **ranking:** 当显示预测积分时,增加榜单的宽度 ([b4b0dfe](https://github.com/XYShaoKang/refined-leetcode/commit/b4b0dfe42fc03f4b576227156cc9500820b346f4)) +* **ranking:** 添加提示文本 ([14a19cf](https://github.com/XYShaoKang/refined-leetcode/commit/14a19cfd4cfd84c799e37b30de0556263f7a93d2)) +* **ranking:** 调整预测积分样式 ([477939a](https://github.com/XYShaoKang/refined-leetcode/commit/477939ae7bd455d796256f6716dde58fcb074578)) +* 修复 useObserverAncestor 逻辑 ([deffc02](https://github.com/XYShaoKang/refined-leetcode/commit/deffc027f55c49759bc0ef0a41d6726a3061d130)) +* 修复弹出框的偏移量 ([a55a49d](https://github.com/XYShaoKang/refined-leetcode/commit/a55a49da139f41242f9ff597ac2777d7b7dd484c)) +* 修复快捷键提交偶尔失效 ([26c3db0](https://github.com/XYShaoKang/refined-leetcode/commit/26c3db0d0207856025d1d5a9047827a3ada1c961)) +* 调整按钮和输入框的样式 ([acc47ff](https://github.com/XYShaoKang/refined-leetcode/commit/acc47ffb2b53d01c01d13a1a9311c0c164480f01)) + + +### Features + +* 添加实时预测功能 ([20fbd6d](https://github.com/XYShaoKang/refined-leetcode/commit/20fbd6ddb64b3f698a091a509c7799a28f3fab18)) + +## [0.11.13](https://github.com/XYShaoKang/refined-leetcode/compare/v0.11.12...v0.11.13) (2023-03-10) + + +### Bug Fixes + +* 测试 crx.zip 打包 ([c8d7117](https://github.com/XYShaoKang/refined-leetcode/commit/c8d7117a8bf32236604f423d903589103ab2b9f1)) + +## [0.11.12](https://github.com/XYShaoKang/refined-leetcode/compare/v0.11.11...v0.11.12) (2023-03-09) + + +### Bug Fixes + +* 修复重新加载的逻辑 ([b2a9b7c](https://github.com/XYShaoKang/refined-leetcode/commit/b2a9b7cfdcf5517543ed3ba4ae00cb172d40ebfa)) + +## [0.11.11](https://github.com/XYShaoKang/refined-leetcode/compare/v0.11.10...v0.11.11) (2023-03-09) + + +### Bug Fixes + +* **home:** 元素不应该超出窗口底部 ([efb04ea](https://github.com/XYShaoKang/refined-leetcode/commit/efb04ea11c38fe6b0394434501820ba059ec35b5)) +* **problems:** 修复快捷键提交 ([db72fc3](https://github.com/XYShaoKang/refined-leetcode/commit/db72fc3627ff33592c33c5efa5b9fa0c71aee1dc)) +* **problems:** 官方已经修复了导航 ([757bbd5](https://github.com/XYShaoKang/refined-leetcode/commit/757bbd564cd6046d46bcc6055a2cb070a16a7ffd)) +* **problems:** 计时器组件有概率会消失 ([6aa22c4](https://github.com/XYShaoKang/refined-leetcode/commit/6aa22c40f9d9042820da16c7f4218e7c606b2ada)) + +## [0.11.10](https://github.com/XYShaoKang/refined-leetcode/compare/v0.11.9...v0.11.10) (2023-02-19) + + +### Bug Fixes + +* **problems:** 控制台左右切换时导致计时器失效 ([d3ef330](https://github.com/XYShaoKang/refined-leetcode/commit/d3ef3307f3d4848e9b4110d39d6a2842143ad2b9)) +* **ranking:** 优化性能 ([80baafd](https://github.com/XYShaoKang/refined-leetcode/commit/80baafd56e70f54d48bfdc5d4fdd9d6f9aa843c1)) +* **ranking:** 修复页面切换问题 ([13c29a7](https://github.com/XYShaoKang/refined-leetcode/commit/13c29a779854fe80cb2b20fc5c9c2e26de82a9ec)) + +## [0.11.9](https://github.com/XYShaoKang/refined-leetcode/compare/v0.11.8...v0.11.9) (2023-02-15) + + +### Bug Fixes + +* **problemset:** 选择算法分类时题目数跟力扣原生不一致 ([c575c9b](https://github.com/XYShaoKang/refined-leetcode/commit/c575c9bae66542ee23a49f2a573d2433631190e2)) + +## [0.11.8](https://github.com/XYShaoKang/refined-leetcode/compare/v0.11.7...v0.11.8) (2023-02-14) + + +### Bug Fixes + +* **problem-list:** 题单页带custom参数的url刷新后不需要等待重定向 ([044f62e](https://github.com/XYShaoKang/refined-leetcode/commit/044f62eacc5ff9712c9934031adb2624d03c1b17)) +* **problemset:** 避免在组件被卸载后触发自定义排序 ([058d8c3](https://github.com/XYShaoKang/refined-leetcode/commit/058d8c3359f0f4f0397402b56df13cd70f81012e)) +* 自定义过滤中添加是否包含会员题目的选项 ([5b9a80a](https://github.com/XYShaoKang/refined-leetcode/commit/5b9a80a0adb339d199c186385084ae5b746182ae)) + +## [0.11.7](https://github.com/XYShaoKang/refined-leetcode/compare/v0.11.6...v0.11.7) (2023-02-12) + + +### Bug Fixes + +* **problem-list:** 题单页题目评分功能开关失效 ([89891e1](https://github.com/XYShaoKang/refined-leetcode/commit/89891e1c1383648ec2280b925ad3a4535f58f82b)) +* **problems:** 只有新版答题页需要修复导航 ([90b2f19](https://github.com/XYShaoKang/refined-leetcode/commit/90b2f1904ad28a81ab1e1259bd7462dc63fb1204)) +* 修复路由错误 ([ccefc85](https://github.com/XYShaoKang/refined-leetcode/commit/ccefc85a6a3496fd757cd5dbe7a8c24fffe6fdac)) +* 只有在启用相关功能的时候,才去拦截对应的请求 ([9a58510](https://github.com/XYShaoKang/refined-leetcode/commit/9a58510d2ba5380a4aae282d752211f2de38fc70)) + +## [0.11.6](https://github.com/XYShaoKang/refined-leetcode/compare/v0.11.5...v0.11.6) (2023-02-08) + + +### Bug Fixes + +* **problem-list:** 进行删除添加题单等操作时会导致收起题单列表 ([2bf33e1](https://github.com/XYShaoKang/refined-leetcode/commit/2bf33e12f5e25f145a243265b7d8611be1a201b4)) +* **problems:** 文字换行导致样式被破坏 ([0e4f052](https://github.com/XYShaoKang/refined-leetcode/commit/0e4f052947cd20eb9a47b45c95ec37e8a41a016a)) +* **problems:** 随机题目时测试样例不会跟着变化 ([6b40bbe](https://github.com/XYShaoKang/refined-leetcode/commit/6b40bbef4e1632502c71243089ea91a0bec64240)) +* **ranking:** 周赛时会去替换错误图标 ([80bdaee](https://github.com/XYShaoKang/refined-leetcode/commit/80bdaee61d9caf21f8b0318beb4440de427b2971)) +* **ranking:** 鼠标无法移动到提示 ([da04b0f](https://github.com/XYShaoKang/refined-leetcode/commit/da04b0f6bda679d57cb79e30adf6567eb5e571b3)) +* urlchange ([63c665b](https://github.com/XYShaoKang/refined-leetcode/commit/63c665b6b8ebbc07ff45d1ac63be0fbb05e39b94)) +* 修复题单页和题库页互相跳转问题 ([8278d6c](https://github.com/XYShaoKang/refined-leetcode/commit/8278d6c3aaf53eb47dd25d76197ed150abfb2f74)) +* 在题库页和题单页跳转的时候有时候题单列表会发生错位 ([e4d0025](https://github.com/XYShaoKang/refined-leetcode/commit/e4d002500aac0824ffd59f71c5ad106641ce657e)) + +## [0.11.5](https://github.com/XYShaoKang/refined-leetcode/compare/v0.11.4...v0.11.5) (2023-02-03) + + +### Bug Fixes + +* **options:** 触发 options 的获取 ([783969d](https://github.com/XYShaoKang/refined-leetcode/commit/783969d14263b6fe285427c9616c8bbf78741585)) + +## [0.11.4](https://github.com/XYShaoKang/refined-leetcode/compare/v0.11.3...v0.11.4) (2023-02-02) + + +### Bug Fixes + +* **ranking:** 显示旧分数 ([dde0326](https://github.com/XYShaoKang/refined-leetcode/commit/dde0326bc0108938ff71a7f09705f31da90c7ced)) +* 修复默认语言 ([2fcd1a6](https://github.com/XYShaoKang/refined-leetcode/commit/2fcd1a6601f5a354e3ef0f6b716ca445866be7a1)) + +## [0.11.3](https://github.com/XYShaoKang/refined-leetcode/compare/v0.11.2...v0.11.3) (2023-02-02) + + +### Bug Fixes + +* manifest 中添加默认语言 ([d987ccd](https://github.com/XYShaoKang/refined-leetcode/commit/d987ccdf634acd267848f0b53cdea03a0a62f7b1)) +* **problem-list:** 切换到新的题单列表 ([ff319a7](https://github.com/XYShaoKang/refined-leetcode/commit/ff319a772aae0ed7203c0f8efba41497b69caf18)) +* **raking:** 显示预测新分数 ([bd9ec93](https://github.com/XYShaoKang/refined-leetcode/commit/bd9ec939ded7e88bbce1e130cf9d018d4dab472d)) +* **ranking:** 切换页面时,预测分数不刷新 ([ecf82f5](https://github.com/XYShaoKang/refined-leetcode/commit/ecf82f55a27e3401658bcf73a9b90d4a96b87b85)) + +## [0.11.2](https://github.com/XYShaoKang/refined-leetcode/compare/v0.11.1...v0.11.2) (2023-02-01) + + +### Bug Fixes + +* **problemset:** 修复评分的过滤和排序 ([3ef9edf](https://github.com/XYShaoKang/refined-leetcode/commit/3ef9edf4e8885f2a8f312071a15548fd9f84390b)) + +## [0.11.1](https://github.com/XYShaoKang/refined-leetcode/compare/v0.11.0...v0.11.1) (2023-01-30) + + +### Bug Fixes + +* **options:** 修复点击事件 ([cb2fdec](https://github.com/XYShaoKang/refined-leetcode/commit/cb2fdec4027cc8668f5d0bc8da041a786c6d263c)) +* 处理默认配置 ([ff26875](https://github.com/XYShaoKang/refined-leetcode/commit/ff26875e6c02831e4d731d3bab315c1a8bd1b537)) + +# [0.11.0](https://github.com/XYShaoKang/refined-leetcode/compare/v0.10.2...v0.11.0) (2023-01-30) + + +### Features + +* 添加功能开关配置 ([7e4029f](https://github.com/XYShaoKang/refined-leetcode/commit/7e4029f6eda54263c75f62403eed68df7a38d91d)) + +## [0.10.2](https://github.com/XYShaoKang/refined-leetcode/compare/v0.10.1...v0.10.2) (2023-01-27) + + +### Bug Fixes + +* **problems:** 只有在打开设置对话框之后才能获取到设置的元素 ([bfed3e7](https://github.com/XYShaoKang/refined-leetcode/commit/bfed3e707ed4f31b341ff4dfbdb35c561e678881)) +* 修复 cdn 在某些地区无法使用的问题 ([af13784](https://github.com/XYShaoKang/refined-leetcode/commit/af1378478dbc36fd5113e33701ded3af7843fe9c)) +* 添加 homepage_url ([29dc087](https://github.com/XYShaoKang/refined-leetcode/commit/29dc087e4cda41763a02ab4d4d3c05d6a20b4d7a)) + +## [0.10.1](https://github.com/XYShaoKang/refined-leetcode/compare/v0.10.0...v0.10.1) (2023-01-16) + + +### Bug Fixes + +* **problem-list:** 在审核中的题单可以删除 ([df0aec9](https://github.com/XYShaoKang/refined-leetcode/commit/df0aec942dc55d213d909105a57241e1c3a44451)) +* **problemset:** 修复显示文本 ([cbc82f8](https://github.com/XYShaoKang/refined-leetcode/commit/cbc82f89401eaacf9d337d586cba4123a5307f10)) +* 修复跳转逻辑 ([6f97f4e](https://github.com/XYShaoKang/refined-leetcode/commit/6f97f4e102ef35ce752bb266db04358ade8a3763)) + +# [0.10.0](https://github.com/XYShaoKang/refined-leetcode/compare/v0.9.3...v0.10.0) (2023-01-16) + + +### Bug Fixes + +* **home:** 禁用按钮后无法显示提示文本 ([2ccf2b8](https://github.com/XYShaoKang/refined-leetcode/commit/2ccf2b835fd62a49b302ab2f146724b5033b5993)) +* **problem-list:** 修复下方的外边距 ([ecd8827](https://github.com/XYShaoKang/refined-leetcode/commit/ecd8827e6755da463202f4043242f5fdde19fd69)) +* **problem-list:** 修复前端路由跳转的逻辑 ([12caf9e](https://github.com/XYShaoKang/refined-leetcode/commit/12caf9ed1b8b560b080233327faf8f616d0736c9)) +* **problem-list:** 修复收藏夹数据的加载顺序 ([e2e4a89](https://github.com/XYShaoKang/refined-leetcode/commit/e2e4a8962a273b713ecda6a6a66793d5a1ea68b4)) +* **problem-list:** 修复随机按钮 ([7729ae4](https://github.com/XYShaoKang/refined-leetcode/commit/7729ae4243c76b15183df78d42ee0e1ad0a240be)) +* **problem-list:** 题单页中的随机一题自动选择是否过滤会员题 ([61ce171](https://github.com/XYShaoKang/refined-leetcode/commit/61ce17152d511e2b7a4acae96170618b5ada7cce)) +* **problemset:** 新增将筛选出的题目添加到某个题单的功能 ([ee6ecb1](https://github.com/XYShaoKang/refined-leetcode/commit/ee6ecb18460f190a3cc3382b121f3f65c34c2499)) +* **problemset:** 更新显示文本 ([3e91429](https://github.com/XYShaoKang/refined-leetcode/commit/3e91429b5354951a91938b280c56726825e07def)) +* **problemset:** 更新题目状态 ([6fa0462](https://github.com/XYShaoKang/refined-leetcode/commit/6fa04629994b999a63a92e6565e718447340fa75)) +* **problemset:** 适配题单页 ([8c5450d](https://github.com/XYShaoKang/refined-leetcode/commit/8c5450d692479a7f582574a22a8f49eb1896b0fd)) +* **problems:** 添加比赛答题页中禁用快捷键的选项 ([c7e79f4](https://github.com/XYShaoKang/refined-leetcode/commit/c7e79f4b11eef3fe36bcdfde139a020744ccc527)) +* 修复其他页面中关于是否新版 UI 的判断 ([2363206](https://github.com/XYShaoKang/refined-leetcode/commit/2363206149b3bc9db6fc9283c9714ad8e585b46e)) +* 修复自定义题单侧边栏加载错位问题 ([1edf47a](https://github.com/XYShaoKang/refined-leetcode/commit/1edf47a1301f78e96b2f9a5a0bbfe67a2cb855a5)) +* 未登录的状态下无法操作 ([74334a3](https://github.com/XYShaoKang/refined-leetcode/commit/74334a32ef9e9a08d95d2ff63c41a521a79bd3ed)) +* 页面滚动时弹出框不会跟着移动 ([975f039](https://github.com/XYShaoKang/refined-leetcode/commit/975f039e4218212cc5ab5e8e354cd9b71902fde0)) + + +### Features + +* **problemset:** 添加题目评分 ([bfdbe1a](https://github.com/XYShaoKang/refined-leetcode/commit/bfdbe1a7f1275fc7d836c2db61954a3520db4508)) + +## [0.9.3](https://github.com/XYShaoKang/refined-leetcode/compare/v0.9.2...v0.9.3) (2023-01-03) + + +### Bug Fixes + +* **problem-list:** 修复样式 ([e959001](https://github.com/XYShaoKang/refined-leetcode/commit/e95900197259ce55b7b01c16a7927581c20f5050)) + +## [0.9.2](https://github.com/XYShaoKang/refined-leetcode/compare/v0.9.1...v0.9.2) (2023-01-02) + + +### Bug Fixes + +* **problem-list:** 修复题单页中的随机一题按钮 ([9f9f44b](https://github.com/XYShaoKang/refined-leetcode/commit/9f9f44b94132533b5b0802dbfd0e9eb78666010b)) +* **problems:** 修复答题页内点击题单名称会跳转到题库的问题 ([787fe54](https://github.com/XYShaoKang/refined-leetcode/commit/787fe5446156c29ca1c6f7ce96c743b646a4d867)) +* 修复选项显示文本 ([c8fab2a](https://github.com/XYShaoKang/refined-leetcode/commit/c8fab2aa0e9b3eb349e7c1335a27221730a2c2fa)) + +## [0.9.1](https://github.com/XYShaoKang/refined-leetcode/compare/v0.9.0...v0.9.1) (2023-01-02) + + +### Bug Fixes + +* **problem-list:** 完善保存按钮的动画 ([c2d87e3](https://github.com/XYShaoKang/refined-leetcode/commit/c2d87e317d84a004995cd3d53f7526f57d32faeb)) +* **problem-list:** 完善添加新题单的流程 ([07d4da5](https://github.com/XYShaoKang/refined-leetcode/commit/07d4da5060f3e156253bbc02c0acc11463c6d5d3)) + +# [0.9.0](https://github.com/XYShaoKang/refined-leetcode/compare/v0.8.5...v0.9.0) (2023-01-02) + + +### Bug Fixes + +* 修复按钮禁用的属性 ([4a9a49b](https://github.com/XYShaoKang/refined-leetcode/commit/4a9a49b14901156a0cb747c6197cf6f4e4070302)) + + +### Features + +* **problem-list:** 题单侧边栏 ([dbc0fb4](https://github.com/XYShaoKang/refined-leetcode/commit/dbc0fb491a92429a8e4daf93940e1369d976861a)) + +## [0.8.5](https://github.com/XYShaoKang/refined-leetcode/compare/v0.8.4...v0.8.5) (2022-12-30) + + +### Bug Fixes + +* **problems:** 修复 currentTitleSlug 获取错误 ([4fc1a83](https://github.com/XYShaoKang/refined-leetcode/commit/4fc1a83dae5256fa55ee13871ee3f569e536dda5)) +* **problems:** 修复查找定时器挂载元素错误 ([e55cd21](https://github.com/XYShaoKang/refined-leetcode/commit/e55cd211967c7f654234f49ec0a8b77e788ae76e)) +* **problems:** 修复随机一题选项的配色 ([30535e2](https://github.com/XYShaoKang/refined-leetcode/commit/30535e2946798105f6401c781abcd4b9a2c21184)) +* **problems:** 添加随机一题的选项 ([f1df66e](https://github.com/XYShaoKang/refined-leetcode/commit/f1df66ea14b87d55f430bda4507969c824ae3b57)) +* **utils:** 当题单中包含较多题目时,需分页获取所有题目 ([ae5bfdc](https://github.com/XYShaoKang/refined-leetcode/commit/ae5bfdc18b908380c2e5262cbc3e277106e207fe)) + +## [0.8.4](https://github.com/XYShaoKang/refined-leetcode/compare/v0.8.3...v0.8.4) (2022-12-18) + + +### Bug Fixes + +* **problems:** 随机一题 ([4a112c8](https://github.com/XYShaoKang/refined-leetcode/commit/4a112c8788341b45e0bc48a42080df20e7c6b9cf)) +* **problems:** 题单内部随机 ([c890cc2](https://github.com/XYShaoKang/refined-leetcode/commit/c890cc2db2126704fd94781ad72f808026d173ca)) +* 添加缓存的过期时间 ([1786bab](https://github.com/XYShaoKang/refined-leetcode/commit/1786bab573a415c6f03e34aa53000ba78bb1be6a)) +* 添加获取 globalData api ([d125d14](https://github.com/XYShaoKang/refined-leetcode/commit/d125d1439bd4e473a6d8834e0bb032bdf553b1b1)) + +## [0.8.3](https://github.com/XYShaoKang/refined-leetcode/compare/v0.8.2...v0.8.3) (2022-12-03) + + +### Bug Fixes + +* **home:** 修复点击`加载更多`按钮时有些帖子不会隐藏 ([62969a5](https://github.com/XYShaoKang/refined-leetcode/commit/62969a50f7328027fe2eac93ae656b1a523929ea)) +* **home:** 定位问题 ([10d20ef](https://github.com/XYShaoKang/refined-leetcode/commit/10d20ef223196880dcc62f92ec7d01393f62e0e2)) +* **home:** 点击列表中的用户名可跳转至对应的主页 ([eca9f88](https://github.com/XYShaoKang/refined-leetcode/commit/eca9f8816eb8ad56c6ea2f63db8d5dd3f999885a)) + +## [0.8.2](https://github.com/XYShaoKang/refined-leetcode/compare/v0.8.1...v0.8.2) (2022-11-26) + + +### Bug Fixes + +* **ranking:** 切换积分预测数据源 ([ff7abde](https://github.com/XYShaoKang/refined-leetcode/commit/ff7abde0839adea486b3617a74e94dd367b60a90)) + +## [0.8.1](https://github.com/XYShaoKang/refined-leetcode/compare/v0.8.0...v0.8.1) (2022-11-14) + + +### Bug Fixes + +* **problems:** 修复跳转到另外一题后计时组件不加载 ([6a94be5](https://github.com/XYShaoKang/refined-leetcode/commit/6a94be527038e8d3f2cc689c248810f10f9a58f1)) + +# [0.8.0](https://github.com/XYShaoKang/refined-leetcode/compare/v0.7.2...v0.8.0) (2022-11-14) + + +### Bug Fixes + +* **problems:** 官方已经阻止了新版答题页中保存页面的弹窗 ([35b04d1](https://github.com/XYShaoKang/refined-leetcode/commit/35b04d1780d2ad71e4d01968961f46e64f5ede7f)) +* **ranking:** 卸载 bug ([78df940](https://github.com/XYShaoKang/refined-leetcode/commit/78df940248d248239d37b7066b5bc4f5e2b0bf3e)) +* **useHover:** 有些情况下无法有效的清除状态 ([2e55907](https://github.com/XYShaoKang/refined-leetcode/commit/2e55907418ddd0955b250b08080e4f0b843be7cf)) + + +### Features + +* **home:** 快捷添加黑名单 ([11df967](https://github.com/XYShaoKang/refined-leetcode/commit/11df9674910ecf3df9bd8b2b9e7665b57c178bae)) + +## [0.7.2](https://github.com/XYShaoKang/refined-leetcode/compare/v0.7.1...v0.7.2) (2022-11-02) + + +### Bug Fixes + +* **home:** 调整加载逻辑 ([122aae3](https://github.com/XYShaoKang/refined-leetcode/commit/122aae316d210c7ab16b4da17fdcfad8c9ab9627)) +* **problems:** 修复加载逻辑,防止多次加载组件 ([cc92f45](https://github.com/XYShaoKang/refined-leetcode/commit/cc92f45e6e64268fe966acb30b412a34cc5b9462)) + +## [0.7.1](https://github.com/XYShaoKang/refined-leetcode/compare/v0.7.0...v0.7.1) (2022-11-02) + + +### Bug Fixes + +* **home:** 隐藏失败 ([fc9b6f3](https://github.com/XYShaoKang/refined-leetcode/commit/fc9b6f317dec8e152413fa09a853dcdabfd6473d)) +* **problems:** 屏蔽答题页中保存页面的快捷键 ([92adcb8](https://github.com/XYShaoKang/refined-leetcode/commit/92adcb8f9958adf78d4ecfeb81b943f059b4beeb)) +* **problems:** 添加随机一题按钮 ([6b41799](https://github.com/XYShaoKang/refined-leetcode/commit/6b4179972539ced37fb0ea02387fa48498208d59)) + +# [0.7.0](https://github.com/XYShaoKang/refined-leetcode/compare/v0.6.5...v0.7.0) (2022-10-30) + + +### Bug Fixes + +* **home:** 修复首页 urlchange 事件 ([d642525](https://github.com/XYShaoKang/refined-leetcode/commit/d64252556e919e5009d12ff849c1365c0c3ffdf3)) +* **problems:** 修复从题库的随机一题跳转到答题页 ([6a159f1](https://github.com/XYShaoKang/refined-leetcode/commit/6a159f1307283cc28d978ed277c7e2f47a0c698c)) +* **problems:** 修复新版UI从答题页到题解的跳转逻辑 ([0c7f808](https://github.com/XYShaoKang/refined-leetcode/commit/0c7f80803b90008a5fddf18eba53cffa23734fcf)) +* **problems:** 修复答题页的判定 ([56ce958](https://github.com/XYShaoKang/refined-leetcode/commit/56ce958188f5da0bbb0acbfefec2acd9265ccc4f)) +* **problems:** 计时组件只需要在普通答题页显示 ([f017bcb](https://github.com/XYShaoKang/refined-leetcode/commit/f017bcba202c91d7950b40fffc472518809e1311)) +* **problems:** 适配新版 UI ([e3c02ac](https://github.com/XYShaoKang/refined-leetcode/commit/e3c02ac2dbb874d80a3233906c12b695417770a8)) +* **ranking:** 完善图标的加载逻辑 ([0adc964](https://github.com/XYShaoKang/refined-leetcode/commit/0adc964398ae59fd497477bcac84c6d4fdb6af0d)) +* **ranking:** 正确捕获因网络原因导致的 fetch 请求错误 ([249126d](https://github.com/XYShaoKang/refined-leetcode/commit/249126d1019f3b8f9b3e8a27accf0701475bbdd7)) +* **ranking:** 添加请求防抖,防止在快速切换页面时,请求过多无用的数据 ([8916344](https://github.com/XYShaoKang/refined-leetcode/commit/891634420ec47956ec3ae4ebcf07186498026f42)) +* **ranking:** 错误的修改了缓存数据,导致下次获取到错误的数据 ([b8d4fd0](https://github.com/XYShaoKang/refined-leetcode/commit/b8d4fd071abffa56d3c6e3695352d144f51a8327)) + + +### Features + +* 添加首页黑名单功能 ([ba89d78](https://github.com/XYShaoKang/refined-leetcode/commit/ba89d78d1bdbfb89a9363a8012e1a0f1de3e95c1)) + + +### Performance Improvements + +* **problems:** 添加按钮功能提示 ([811b8dd](https://github.com/XYShaoKang/refined-leetcode/commit/811b8dda54832673fa4ed8a6b7136cfcf29d6017)) + +## [0.6.5](https://github.com/XYShaoKang/refined-leetcode/compare/v0.6.4...v0.6.5) (2022-06-05) + + +### Bug Fixes + +* 修复预测数据顺序 ([f73b208](https://github.com/XYShaoKang/refined-leetcode/commit/f73b208b9d2abf654c3056d76f3b2531ddf92a34)) + + +### Performance Improvements + +* 添加超时设置 ([6799dd1](https://github.com/XYShaoKang/refined-leetcode/commit/6799dd109cbff0d54a2c00e0c4a63c29a69ac13c)) + +## [0.6.4](https://github.com/XYShaoKang/refined-leetcode/compare/v0.6.3...v0.6.4) (2022-06-04) + + +### Bug Fixes + +* 将获取图标数据和预测数据的逻辑解耦 ([#5](https://github.com/XYShaoKang/refined-leetcode/issues/5)) ([051462a](https://github.com/XYShaoKang/refined-leetcode/commit/051462a1369afb956e72e82e2f9dcc0e6abce9c5)) + +## [0.6.3](https://github.com/XYShaoKang/refined-leetcode/compare/v0.6.2...v0.6.3) (2022-05-23) + + +### Bug Fixes + +* **background:** 跳转预测 API 顺序 ([ddb6774](https://github.com/XYShaoKang/refined-leetcode/commit/ddb677411e6915547891a8c545e9d7397bac8f16)) + +## [0.6.2](https://github.com/XYShaoKang/refined-leetcode/compare/v0.6.1...v0.6.2) (2022-05-13) + + +### Bug Fixes + +* **useHook:** 处理当 ref 发生变化的逻辑 ([7114d13](https://github.com/XYShaoKang/refined-leetcode/commit/7114d13e3fb401ac4f1bc1380975224cbcbfd515)) + +## [0.6.1](https://github.com/XYShaoKang/refined-leetcode/compare/v0.6.0...v0.6.1) (2022-05-12) + + +### Bug Fixes + +* 重置按钮显示错位 ([5456549](https://github.com/XYShaoKang/refined-leetcode/commit/54565491fc6c896fc2c8c452c99366db3f8da057)) + +# [0.6.0](https://github.com/XYShaoKang/refined-leetcode/compare/v0.5.4...v0.6.0) (2022-05-11) + + +### Features + +* 在计时过程添加重置功能 ([fb73682](https://github.com/XYShaoKang/refined-leetcode/commit/fb736820e4729397c399cd4d4e3f98e0872e3e2e)) + +## [0.5.4](https://github.com/XYShaoKang/refined-leetcode/compare/v0.5.3...v0.5.4) (2022-05-09) + + +### Bug Fixes + +* 修复按钮卸载逻辑 ([4e84f11](https://github.com/XYShaoKang/refined-leetcode/commit/4e84f1160862164c33794b2eb1f6846a6e448072)) + +## [0.5.3](https://github.com/XYShaoKang/refined-leetcode/compare/v0.5.2...v0.5.3) (2022-05-07) + + +### Bug Fixes + +* **problems:** 修复页面内跳转 ([e232a9b](https://github.com/XYShaoKang/refined-leetcode/commit/e232a9beb807a2df26d4ef3ef60c08574710c183)) + +## [0.5.2](https://github.com/XYShaoKang/refined-leetcode/compare/v0.5.1...v0.5.2) (2022-05-06) + + +### Bug Fixes + +* **ranking:** 提升提示组件的层级防止被图标组件挡住 ([441fe6b](https://github.com/XYShaoKang/refined-leetcode/commit/441fe6b2406da9cc361be37d174f6c418c0b2e97)) +* 修复 findElement 返回类型 ([6a2fdfd](https://github.com/XYShaoKang/refined-leetcode/commit/6a2fdfd99ce71f520330657af3675a20137d11c6)) +* 修复域名错误 ([6fb3e7f](https://github.com/XYShaoKang/refined-leetcode/commit/6fb3e7facb6d560ba947fe6ec98b3626bf1589ed)) + +## [0.5.1](https://github.com/XYShaoKang/refined-leetcode/compare/v0.5.0...v0.5.1) (2022-05-06) + + +### Bug Fixes + +* 完善组件卸载时取消事件注册的逻辑 ([427aca0](https://github.com/XYShaoKang/refined-leetcode/commit/427aca0ad3a2680e99351262e763b60b73b6f30c)) + + +### Performance Improvements + +* 添加对快捷键提交代码的支持 ([ea9a7d8](https://github.com/XYShaoKang/refined-leetcode/commit/ea9a7d8cd4f8161db8e1cad6367e996ead65f139)) + +# [0.5.0](https://github.com/XYShaoKang/refined-leetcode/compare/v0.4.3...v0.5.0) (2022-04-30) + + +### Features + +* 添加对 leetcode.cn 域名的支持 ([ff20e2e](https://github.com/XYShaoKang/refined-leetcode/commit/ff20e2e05a638a7931d7c0bdf22d7dffd996abb5)) + +## [0.4.3](https://github.com/XYShaoKang/refined-leetcode/compare/v0.4.2...v0.4.3) (2022-03-21) + + +### Bug Fixes + +* 偶尔自动添加备注功能失效 ([20dffdd](https://github.com/XYShaoKang/refined-leetcode/commit/20dffdd66972f22d6b90bf1f4201de90e4422769)) +* 延迟加载预测页 ([cc2b651](https://github.com/XYShaoKang/refined-leetcode/commit/cc2b651bf011e0b7eda65afb3e6e6bc4ff523023)) +* 找到正确的图标元素 ([1304e03](https://github.com/XYShaoKang/refined-leetcode/commit/1304e03cac42aa67156e6ec107c557876dbf3d2b)) + +## [0.4.2](https://github.com/XYShaoKang/refined-leetcode/compare/v0.4.1...v0.4.2) (2022-03-11) + + +### Bug Fixes + +* 偶尔自动添加备注的功能失效 ([2f7c534](https://github.com/XYShaoKang/refined-leetcode/commit/2f7c534854a6a4034cbd06765f12c329587d234e)) + +## [0.4.1](https://github.com/XYShaoKang/refined-leetcode/compare/v0.4.0...v0.4.1) (2022-03-10) + + +### Bug Fixes + +* 偶尔会出现无法显示备注的情况 ([b8c5614](https://github.com/XYShaoKang/refined-leetcode/commit/b8c561408ec3918bb49b0b83b872a9bebcfae71c)) + +# [0.4.0](https://github.com/XYShaoKang/refined-leetcode/compare/v0.3.2...v0.4.0) (2022-03-09) + + +### Features + +* 排名页面替换代码图标为对应的语言图标 ([19ace87](https://github.com/XYShaoKang/refined-leetcode/commit/19ace87d698e856affbc7912a34fec0f531aa8d1)) + +## [0.3.2](https://github.com/XYShaoKang/refined-leetcode/compare/v0.3.1...v0.3.2) (2022-03-04) + + +### Bug Fixes + +* 删除目前不需要的模块 ([1accdaf](https://github.com/XYShaoKang/refined-leetcode/commit/1accdaf257576059e2a4c69af8fc6d3a1cb1c7b0)) + +## [0.3.1](https://github.com/XYShaoKang/refined-leetcode/compare/v0.3.0...v0.3.1) (2022-03-04) + + +### Bug Fixes + +* 清理一些目前不需要的权限 ([4f123ff](https://github.com/XYShaoKang/refined-leetcode/commit/4f123ff59df3a726111e6049f48f16d62469ae57)) + +# [0.3.0](https://github.com/XYShaoKang/refined-leetcode/compare/v0.2.6...v0.3.0) (2022-03-04) + + +### Features + +* use new name ([cdf4aeb](https://github.com/XYShaoKang/refined-leetcode/commit/cdf4aeb271172c3e39f3fcda5ec41d81f240d2df)) + +## [0.2.6](https://github.com/XYShaoKang/leetcode-extend/compare/v0.2.5...v0.2.6) (2022-03-02) + + +### Bug Fixes + +* manifest name ([c54a86d](https://github.com/XYShaoKang/leetcode-extend/commit/c54a86db4c9b572da12102650a71d737623b6be9)) + +## [0.2.5](https://github.com/XYShaoKang/leetcode-extend/compare/v0.2.4...v0.2.5) (2022-03-02) + + +### Bug Fixes + +* 参数错误 ([ffb74b2](https://github.com/XYShaoKang/leetcode-extend/commit/ffb74b2181b3f6ec5a6fca1f71f7f0b7f98ef1ae)) + +## [0.2.4](https://github.com/XYShaoKang/leetcode-extend/compare/v0.2.3...v0.2.4) (2022-03-01) + + +### Bug Fixes + +* 修复加载组件时机 ([5c7c3a2](https://github.com/XYShaoKang/leetcode-extend/commit/5c7c3a2f75102b8a18b63bd3cd04d5e7d47a46b3)) + +## [0.2.3](https://github.com/XYShaoKang/leetcode-extend/compare/v0.2.2...v0.2.3) (2022-03-01) + + +### Bug Fixes + +* 修复排名页组件的加载和卸载逻辑 ([745b48f](https://github.com/XYShaoKang/leetcode-extend/commit/745b48f196bbb72dfb237eef97e1f7575e542002)) + +## [0.2.2](https://github.com/XYShaoKang/leetcode-extend/compare/v0.2.1...v0.2.2) (2022-02-28) + + +### Bug Fixes + +* add redundant api ([115467f](https://github.com/XYShaoKang/leetcode-extend/commit/115467f29921d42b78e4fae7e87b1b1fac2af7ab)) + +## [0.2.1](https://github.com/XYShaoKang/leetcode-extend/compare/v0.2.0...v0.2.1) (2022-02-24) + + +### Bug Fixes + +* 页数应该从 1 开始 ([b4b0715](https://github.com/XYShaoKang/leetcode-extend/commit/b4b071512ba93b6c95bfcbd510a814a110e43266)) + +# [0.2.0](https://github.com/XYShaoKang/leetcode-extend/compare/v0.1.0...v0.2.0) (2022-02-24) + + +### Bug Fixes + +* 限制只在答题页加载计时器 ([78bbd9a](https://github.com/XYShaoKang/leetcode-extend/commit/78bbd9ad1a3ac54b901200d43725a6f21c722cb9)) + + +### Features + +* 竞赛排名页面显示对应的预测分数 ([a59e531](https://github.com/XYShaoKang/leetcode-extend/commit/a59e531640a5d35c48c157aabad0c4fef3999257)) + +# 0.1.0 (2022-02-24) + + +### Bug Fixes + +* 修复备注组件更新失效 ([1444d31](https://github.com/XYShaoKang/leetcode-extend/commit/1444d311bee68aaf3ac741c440ad09a33f989109)) +* 修复无法获取刚提交的 submission ([600b42c](https://github.com/XYShaoKang/leetcode-extend/commit/600b42c270b2fe7c82e976015d187fa5a5e9052e)) +* 修复时间分布图中没有数据的情况 ([9fb4ff2](https://github.com/XYShaoKang/leetcode-extend/commit/9fb4ff23b619071d073be4a1aac94faf5469b7aa)) +* 修复有时候不出现按钮的情况 ([0d0eaa8](https://github.com/XYShaoKang/leetcode-extend/commit/0d0eaa818a0f102edf0ad9a6c1c5535ff37f23d9)) +* 当提交测试需要比较长时间造成检测失败 ([fc0696e](https://github.com/XYShaoKang/leetcode-extend/commit/fc0696ea776571628ca602492f00d50c58aabbf0)) +* 有时无法自动显示标记 ([ba68edd](https://github.com/XYShaoKang/leetcode-extend/commit/ba68edddcd5fac9d4e19ccbb479735b4fb339146)) + + +### Features + +* 添加答题页计时功能 ([716f1b7](https://github.com/XYShaoKang/leetcode-extend/commit/716f1b741bbf9c04c932140aba63c04bd62792ed)) +* 自动添加标记 ([54b3f98](https://github.com/XYShaoKang/leetcode-extend/commit/54b3f98dbd94ab788b1cb727f47c46dd204e5a55)) +* 重构成浏览器扩展项目 ([71cc458](https://github.com/XYShaoKang/leetcode-extend/commit/71cc458dfe1ac1ee1c6ca4bb999d7b216b82d1d0)) + + +### Performance Improvements + +* 提升刷新标记的性能 ([120976f](https://github.com/XYShaoKang/leetcode-extend/commit/120976f4cf90d1e1b8de9e4622b4c10b2c3ff9ac)) diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..0908324 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021-present, XYShaoKang + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md index 8b17e6a..10afc4c 100644 --- a/README.md +++ b/README.md @@ -1,112 +1,100 @@ -# 力扣扩展 +[![semantic-release][semantic-release-image]][semantic-release-url] [![GitHub Action][actions-release-image]][actions-release-url] [![](https://img.shields.io/chrome-web-store/v/kmpinnjkedaidpojenkiooddkeplniel.svg)][chrome-store-url] [![](https://img.shields.io/badge/dynamic/json?label=edge%20add-on&prefix=v&query=%24.version&url=https%3A%2F%2Fmicrosoftedge.microsoft.com%2Faddons%2Fgetproductdetailsbycrxid%2Figmccckalbaoifpohffkgfdagpgdangl)][edge-store-url] -> 注意: 我不确定力扣官方对于爬取提交记录中的代码的行为是怎样的态度,所以提醒一下,使用此扩展最好是使用小号进行,以避免影响正常账号的使用. -> -> 默认所有使用此扩展的,人均已了解其中的风险.所有因使用此扩展而产生的问题,本人概不负责,也与本人无关! - -## 安装使用 +# Refined LeetCode -需要先在浏览器里安装 [Tampermonkey](https://www.tampermonkey.net/) 或者 [Violentmonkey](https://violentmonkey.github.io/) 扩展,然后打开使用下面其中一个链接安装: +> 添加一些有用和有意思的功能,增强 LeetCode-cn 刷题体验 -- [GitHub 链接](https://github.com/XYShaoKang/leetcode-extend/raw/master/dist/main.user.js) -- 如果访问不了 GitHub 可以使用这个 [FastGit 链接](https://hub.fastgit.org/XYShaoKang/leetcode-extend/raw/master/dist/main.user.js) +[![chrome-store-badge][chrome-store-badge]][chrome-store-url] [![edge-store-badge][edge-store-badge]][edge-store-url] -## 功能 +[semantic-release-image]: https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg +[semantic-release-url]: https://github.com/semantic-release/semantic-release +[actions-release-image]: https://github.com/XYShaoKang/refined-leetcode/actions/workflows/release.yml/badge.svg?branch=master +[actions-release-url]: https://github.com/XYShaoKang/refined-leetcode/actions/workflows/release.yml?query=branch%3Amaster +[chrome-store-badge]: ./docs/assets/trynow.png +[chrome-store-url]: https://chrome.google.com/webstore/detail/refined-leetcode/kmpinnjkedaidpojenkiooddkeplniel +[edge-store-badge]: ./docs/assets/get_it_from_edge.png +[edge-store-url]: https://microsoftedge.microsoft.com/addons/detail/refined-leetcode/igmccckalbaoifpohffkgfdagpgdangl -- [提交记录下载](#提交记录下载) -- [答题页计时](#答题页计时) +Refined LeetCode 是一个 Chrome 浏览器。理论上来说大多数基于 Chromium 开发浏览器都能支持,比如像 Microsoft Edge、Opera、Yanda 等浏览器。 -### 提交记录下载 +> 我建了个 QQ 群:250316825,有兴趣可以加这个群,在群里进行反馈和交流。 -> 支持下载国服和外服在提交记录页面,下载时间分布图和内存分布图中的代码,保存到一个 Markdown 文件 +## 功能 -安装好之后,进入力扣的提交记录页面(选择一个题目 -> 提交记录 -> 点击提交结果列中的链接),右上角能看到如下按钮 +各功能的使用说明和视频演示,可以点击链接查看 -> 外服也在同样的位置 +- [答题页](./docs/%E7%AD%94%E9%A2%98%E9%A1%B5.md) + - 计时组件(已适配新版答 + - 新版答题页 + - 随机一题按钮 + - 比赛答题页 + - 快捷键的禁用选项 + - 自定义布局 +- [竞赛排名页面](./docs/%E7%AB%9E%E8%B5%9B%E6%8E%92%E5%90%8D%E9%A1%B5.md) + - 显示排名预测 + - 显示对应代码的图标 + - 实时预测 +- [首页帖子黑名单功能](./docs/%E9%A6%96%E9%A1%B5%E5%B8%96%E5%AD%90%E9%BB%91%E5%90%8D%E5%8D%95.md) +- [题单管理](./docs/%E9%A2%98%E5%8D%95%E7%AE%A1%E7%90%86.md) + - 题单侧边栏 + - 题目评分 +- [配置选项](./docs/%E9%85%8D%E7%BD%AE%E9%80%89%E9%A1%B9.md) 控制各个功能的开关 -![](docs/assets/submission-detail-download.png) +## 安装 -按钮左边可以选择下载哪些代码,分布图里的代码,或者内存分布图里面的代码,或者两个都选,然后点击选择,可以下载 +有两种安装方式,通过在线商店安装,或者通过离线安装。 -点击下载之后,会显示下载进度 +### 在线安装 -![](docs/assets/submission-detail-download-progress.png) +可以通过从 [Chrome Web Store][chrome-store-url] 安装。另外我也在 [Microsoft Edge Addons][edge-store-url] 发布了这款扩展,如果使用 Microsoft Edge 浏览器,并且无法访问谷歌的话,可以从这里安装。但微软的审核会长一些,有可能会比谷歌商店慢上一些版本,所以即使使用 Microsoft Edge 浏览器,也比较推荐从[Chrome Web Store][chrome-store-url]安装,可以获得更及时的更新 -> 在频繁调用之后,会返回`429 Too Many Requests`的错误,这时需要等一下,再去请求.这个 API 容忍度好像比较低,需要等的久一些,测试过比较久的每次需要等一分钟左右才能再次成功请求,所以如果发现进度停住了,不要着急,耐心等一下,如果需要下载的数量比较多的时候,挂着过几分钟在回来看看. +> 推荐直接通过在线安装的方式来安装,比较方便,并且当扩展有更新的时候,会自动更新到最新版本。 > -> 比如两数之和这题 TypeScript 的代码总共有 405 个,下载完成总共花了 6 分钟 - -此功能源码 [Download.tsx](./src/page/submissions-detail/Download.tsx) - -### 答题页计时 - -> 2022-01-02 添加 - -进入答题页时,自动开始计时,第一次提交成功之后会停止计时,并显示所用时间 - -计时器位于页面右下角,提交和执行代码按钮的左边. - -目前提供三种操作,分别是在计时阶段: - -提供隐藏时钟的操作 - -![](docs/assets/hidden.png) - -重新显示时钟的操作 - -![](docs/assets/show.png) - -以及在结束之后,重新开始的操作 - -![](docs/assets/restart.png) - -> 2022-01-03 自动添加标记的功能 - -当成功提交之后,会将当前所有时间自动添加到对应提交的标记中 +> 但因为提交到商店需要进行审核,有时需要进行一些时间的等待,这时如果想要尝鲜,或者是因为某些原因无法连接到商店,可以尝试进行按照下面的方式进行「离线安装」,不过这样如果想要获取更新就需要每次手动来下载一下了。 -![](docs/assets/mark.png) +### 离线安装 -此功能源码 [Clock.tsx](./src/page/problems/Clock.tsx) +离线安装支持以下两种方式 -## 开发 +- 解压文件夹 +- crx 文件 -首先需要安装 [Tampermonkey](https://www.tampermonkey.net/) 或者 [Violentmonkey](https://violentmonkey.github.io/) 扩展 +#### 启用开发者模式 -以及 [Node.js](https://nodejs.org/en/download/)(>=v14) +1. 打开 Chrome 浏览器 +2. 转到 `chrome://extensions/` 页面,直接在地址栏输入 `chrome://extensions/` 即可 +3. 切换页面右上角的开发者模式为启用的状态,并「刷新页面」 -### 下载 +> 测试的时候,发现有时候不用「刷新页面」,后续也可以正常操作,但为了防止意外,最好是刷新一下页面 -```sh -git clone https://github.com/XYShaoKang/leetcode-extend.git -cd leetcode-extend -``` +#### 解压文件夹 -### 安装依赖 +从 https://github.com/XYShaoKang/refined-leetcode/releases 下载最新版本的 `refined-leetcode-v[xxx].zip`,解压 `refined-leetcode-v[xxx].zip` (其中 xxx 表示版本号) -包管理工具,我推荐使用的是 [pnpm](https://pnpm.io/),不过使用 `yarn` 和 `npm` 也可以 +- 方式 1: 直接将前面解压的 refined-leetcode 文件夹拖入 `chrome://extensions/` 页面即可 +- 方式 2: + 1. 点击页面左上角的 `加载以解压的扩展程序` 按钮 + 2. 选择上面解压的 refined-leetcode 文件夹,再点击确定即可 -```sh -pnpm install # 或者 yarn 或者 npm install -``` +操作视频 -### 运行 +https://user-images.githubusercontent.com/38753204/226101191-9be75d42-c218-4005-b718-6aa43790f134.mov -```sh -pnpm dev # 或者 yarn dev 或者 npm run dev -``` +#### crx 文件 -然后打开 http://localhost:9000/ ,应该会自动跳转到安装脚本的界面. +从 https://github.com/XYShaoKang/refined-leetcode/releases 下载最新版本的 `refined-leetcode-[xxx].crx` 文件,或者 `refined-leetcode-[xxx].crx.zip` 进行解压 (其中 xxx 表示版本号) -> 另外记得如果有安装了正式版的脚本,需要先把正式版的关掉,不然会出现两个按钮 +- 直接将 crx 文件拖入 `chrome://extensions/` 页面,会弹出一个提示,点击`添加扩展程序`按钮即可 -### 热加载 +操作视频 -开发模式下,我已经配置好了[热加载](https://webpack.js.org/concepts/hot-module-replacement/),在开发模式下运行,每次源码的修改,会实时反应到页面中,非常方便 +https://user-images.githubusercontent.com/38753204/226101189-92b915dd-e1ef-4173-882e-70ec0fecdc53.mov -### 编译 +## 相关项目 -```sh -pnpm build # 或者 yarn build 或者 npm run build -``` +感谢 leetcode.cn 力扣,提供了一个体验非常好的刷题平台,另外感谢以下相关项目提供的数据支持 -编译好之后,会在 dist 文件夹下生成 `main.user.js` 文件,可以直接拖到浏览器中安装 +- https://github.com/baoliay2008/lccn_predictor 力扣竞赛评分预测项目,也是扩展目前使用的预测数据源 +- https://github.com/zerotrac/leetcode_problem_rating 力扣题目评分项目,也是扩展中题目评分的数据源 +- https://github.com/SysSn13/leetcode-rating-predictor 力扣竞赛评分预测预测,是之前使用的预测数据源 +- 评分功能中,对应评分的颜色参考 https://clist.by/problems/ 和 https://codeforces.com/ 中对应等级的颜色 diff --git a/config/ChromeExtensionsDevHMRPlugin/BackgroundLoadScriptRuntimeModule.js b/config/ChromeExtensionsDevHMRPlugin/BackgroundLoadScriptRuntimeModule.js new file mode 100644 index 0000000..292dec9 --- /dev/null +++ b/config/ChromeExtensionsDevHMRPlugin/BackgroundLoadScriptRuntimeModule.js @@ -0,0 +1,219 @@ +/* + MIT License http://www.opensource.org/licenses/mit-license.php +*/ + +/** + * @see https://github.com/webpack/webpack/blob/13a3bc13736e3b7066779623939e9fdaec7bc06b/lib/runtime/LoadScriptRuntimeModule.js + */ + +'use strict' + +const { SyncWaterfallHook } = require('tapable') +const { + Compilation, + RuntimeGlobals, + Template, + RuntimeModule, +} = require('webpack') + +/** @typedef {import("../Chunk")} Chunk */ +/** @typedef {import("../Compiler")} Compiler */ + +/** + * @typedef {Object} LoadScriptCompilationHooks + * @property {SyncWaterfallHook<[string, Chunk]>} createScript + */ + +/** @type {WeakMap} */ +const compilationHooksMap = new WeakMap() + +class LoadScriptRuntimeModule extends RuntimeModule { + /** + * @param {Compilation} compilation the compilation + * @returns {LoadScriptCompilationHooks} hooks + */ + static getCompilationHooks(compilation) { + if (!(compilation instanceof Compilation)) { + throw new TypeError( + "The 'compilation' argument must be an instance of Compilation" + ) + } + let hooks = compilationHooksMap.get(compilation) + if (hooks === undefined) { + hooks = { + createScript: new SyncWaterfallHook(['source', 'chunk']), + } + compilationHooksMap.set(compilation, hooks) + } + return hooks + } + + /** + * @param {boolean=} withCreateScriptUrl use create script url for trusted types + */ + constructor(withCreateScriptUrl) { + super('load script') + this._withCreateScriptUrl = withCreateScriptUrl + } + + /** + * @returns {string} runtime code + */ + generate() { + const { compilation } = this + const { runtimeTemplate, outputOptions } = compilation + const { + scriptType, + chunkLoadTimeout: loadTimeout, + crossOriginLoading, + uniqueName, + charset, + } = outputOptions + const fn = RuntimeGlobals.loadScript + + const { createScript } = + LoadScriptRuntimeModule.getCompilationHooks(compilation) + + const code = Template.asString([ + "script = document.createElement('script');", + scriptType ? `script.type = ${JSON.stringify(scriptType)};` : '', + charset ? "script.charset = 'utf-8';" : '', + `script.timeout = ${loadTimeout / 1000};`, + `if (${RuntimeGlobals.scriptNonce}) {`, + Template.indent( + `script.setAttribute("nonce", ${RuntimeGlobals.scriptNonce});` + ), + '}', + uniqueName + ? 'script.setAttribute("data-webpack", dataWebpackPrefix + key);' + : '', + `script.src = ${ + this._withCreateScriptUrl + ? `${RuntimeGlobals.createScriptUrl}(url)` + : 'url' + };`, + crossOriginLoading + ? Template.asString([ + "if (script.src.indexOf(window.location.origin + '/') !== 0) {", + Template.indent( + `script.crossOrigin = ${JSON.stringify(crossOriginLoading)};` + ), + '}', + ]) + : '', + ]) + const res = ` + var inProgress = {}; + ${ + uniqueName + ? `var dataWebpackPrefix = ${JSON.stringify(uniqueName + ':')};` + : '// data-webpack is not used as build has no uniqueName' + } + // loadScript function to load a script via script tag + ${fn} = (url, done, key, chunkId) => { + if(inProgress[url]) { inProgress[url].push(done); return; } + // var script, needAttach; + // if(key !== undefined) { + // var scripts = document.getElementsByTagName("script"); + // for(var i = 0; i < scripts.length; i++) { + // var s = scripts[i]; + // if(s.getAttribute("src") == url || s.getAttribute("data-webpack") == // dataWebpackPrefix + key) { script = s; break; } + // } + // } + // if(!script) { + // needAttach = true; + // script = document.createElement('script'); + + // script.charset = 'utf-8'; + // script.timeout = 120; + // if (__webpack_require__.nc) { + // script.setAttribute("nonce", __webpack_require__.nc); + // } + // script.setAttribute("data-webpack", dataWebpackPrefix + key); + // script.src = url; + // } + inProgress[url] = [done]; + var onScriptComplete = (prev, event) => { + // avoid mem leaks in IE. + // script.onerror = script.onload = null; + // clearTimeout(timeout); + var doneFns = inProgress[url]; + delete inProgress[url]; + // script.parentNode && script.parentNode.removeChild(script); + doneFns && doneFns.forEach((fn) => (fn(event))); + if(prev) return prev(event); + } + ; + // chrome.runtime.sendMessage({type: 'hot-update',url},function(response) { console.log(response) }) + //chrome.runtime.reload() + // var timeout = setTimeout(onScriptComplete.bind(null, undefined, { type: 'timeout', target: script }), 120000); + // script.onerror = onScriptComplete.bind(null, script.onerror); + // script.onload = onScriptComplete.bind(null, script.onload); + // needAttach && document.head.appendChild(script); + }; + ` + + if (res) { + return res + } + + return Template.asString([ + 'var inProgress = {};', + uniqueName + ? `var dataWebpackPrefix = ${JSON.stringify(uniqueName + ':')};` + : '// data-webpack is not used as build has no uniqueName', + '// loadScript function to load a script via script tag', + `${fn} = ${runtimeTemplate.basicFunction('url, done, key, chunkId', [ + 'if(inProgress[url]) { inProgress[url].push(done); return; }', + 'var script, needAttach;', + 'if(key !== undefined) {', + Template.indent([ + 'var scripts = document.getElementsByTagName("script");', + 'for(var i = 0; i < scripts.length; i++) {', + Template.indent([ + 'var s = scripts[i];', + `if(s.getAttribute("src") == url${ + uniqueName + ? ' || s.getAttribute("data-webpack") == dataWebpackPrefix + key' + : '' + }) { script = s; break; }`, + ]), + '}', + ]), + '}', + 'if(!script) {', + Template.indent([ + 'needAttach = true;', + createScript.call(code, this.chunk), + ]), + '}', + 'inProgress[url] = [done];', + 'var onScriptComplete = ' + + runtimeTemplate.basicFunction( + 'prev, event', + Template.asString([ + '// avoid mem leaks in IE.', + '//script.onerror = script.onload = null;', + '//clearTimeout(timeout);', + 'var doneFns = inProgress[url];', + 'delete inProgress[url];', + '//script.parentNode && script.parentNode.removeChild(script);', + `doneFns && doneFns.forEach(${runtimeTemplate.returningFunction( + 'fn(event)', + 'fn' + )});`, + 'if(prev) return prev(event);', + ]) + ), + ';', + `//var timeout = setTimeout(onScriptComplete.bind(null, undefined, { type: 'timeout', target: script }), ${loadTimeout});`, + '//script.onerror = onScriptComplete.bind(null, script.onerror);', + '//script.onload = onScriptComplete.bind(null, script.onload);', + "chrome.runtime.sendMessage({type: 'hot-update',url},function(response) { console.log(response.data) })", + '//needAttach && document.head.appendChild(script);', + ])};`, + ]) + } +} + +module.exports = LoadScriptRuntimeModule diff --git a/config/ChromeExtensionsDevHMRPlugin/ContentLoadScriptRuntimeModule.js b/config/ChromeExtensionsDevHMRPlugin/ContentLoadScriptRuntimeModule.js new file mode 100644 index 0000000..81288c1 --- /dev/null +++ b/config/ChromeExtensionsDevHMRPlugin/ContentLoadScriptRuntimeModule.js @@ -0,0 +1,219 @@ +/* + MIT License http://www.opensource.org/licenses/mit-license.php +*/ + +/** + * @see https://github.com/webpack/webpack/blob/13a3bc13736e3b7066779623939e9fdaec7bc06b/lib/runtime/LoadScriptRuntimeModule.js + */ + +'use strict' + +const { SyncWaterfallHook } = require('tapable') +const { + Compilation, + RuntimeGlobals, + Template, + RuntimeModule, +} = require('webpack') + +/** @typedef {import("../Chunk")} Chunk */ +/** @typedef {import("../Compiler")} Compiler */ + +/** + * @typedef {Object} LoadScriptCompilationHooks + * @property {SyncWaterfallHook<[string, Chunk]>} createScript + */ + +/** @type {WeakMap} */ +const compilationHooksMap = new WeakMap() + +class LoadScriptRuntimeModule extends RuntimeModule { + /** + * @param {Compilation} compilation the compilation + * @returns {LoadScriptCompilationHooks} hooks + */ + static getCompilationHooks(compilation) { + if (!(compilation instanceof Compilation)) { + throw new TypeError( + "The 'compilation' argument must be an instance of Compilation" + ) + } + let hooks = compilationHooksMap.get(compilation) + if (hooks === undefined) { + hooks = { + createScript: new SyncWaterfallHook(['source', 'chunk']), + } + compilationHooksMap.set(compilation, hooks) + } + return hooks + } + + /** + * @param {boolean=} withCreateScriptUrl use create script url for trusted types + */ + constructor(withCreateScriptUrl) { + super('load script') + this._withCreateScriptUrl = withCreateScriptUrl + } + + /** + * @returns {string} runtime code + */ + generate() { + const { compilation } = this + const { runtimeTemplate, outputOptions } = compilation + const { + scriptType, + chunkLoadTimeout: loadTimeout, + crossOriginLoading, + uniqueName, + charset, + } = outputOptions + const fn = RuntimeGlobals.loadScript + + const { createScript } = + LoadScriptRuntimeModule.getCompilationHooks(compilation) + + const code = Template.asString([ + "script = document.createElement('script');", + scriptType ? `script.type = ${JSON.stringify(scriptType)};` : '', + charset ? "script.charset = 'utf-8';" : '', + `script.timeout = ${loadTimeout / 1000};`, + `if (${RuntimeGlobals.scriptNonce}) {`, + Template.indent( + `script.setAttribute("nonce", ${RuntimeGlobals.scriptNonce});` + ), + '}', + uniqueName + ? 'script.setAttribute("data-webpack", dataWebpackPrefix + key);' + : '', + `script.src = ${ + this._withCreateScriptUrl + ? `${RuntimeGlobals.createScriptUrl}(url)` + : 'url' + };`, + crossOriginLoading + ? Template.asString([ + "if (script.src.indexOf(window.location.origin + '/') !== 0) {", + Template.indent( + `script.crossOrigin = ${JSON.stringify(crossOriginLoading)};` + ), + '}', + ]) + : '', + ]) + const res = ` + var inProgress = {}; + ${ + uniqueName + ? `var dataWebpackPrefix = ${JSON.stringify(uniqueName + ':')};` + : '// data-webpack is not used as build has no uniqueName' + } + // loadScript function to load a script via script tag + ${fn} = (url, done, key, chunkId) => { + if(inProgress[url]) { inProgress[url].push(done); return; } + // var script, needAttach; + // if(key !== undefined) { + // var scripts = document.getElementsByTagName("script"); + // for(var i = 0; i < scripts.length; i++) { + // var s = scripts[i]; + // if(s.getAttribute("src") == url || s.getAttribute("data-webpack") == // dataWebpackPrefix + key) { script = s; break; } + // } + // } + // if(!script) { + // needAttach = true; + // script = document.createElement('script'); + + // script.charset = 'utf-8'; + // script.timeout = 120; + // if (__webpack_require__.nc) { + // script.setAttribute("nonce", __webpack_require__.nc); + // } + // script.setAttribute("data-webpack", dataWebpackPrefix + key); + // script.src = url; + // } + inProgress[url] = [done]; + var onScriptComplete = (prev, event) => { + // avoid mem leaks in IE. + //script.onerror = script.onload = null; + //clearTimeout(timeout); + var doneFns = inProgress[url]; + delete inProgress[url]; + //script.parentNode && script.parentNode.removeChild(script); + doneFns && doneFns.forEach((fn) => (fn(event))); + if(prev) return prev(event); + } + ; + chrome.runtime.sendMessage({type: 'hot-update',url}) + //chrome.runtime.reload() + //var timeout = setTimeout(onScriptComplete.bind(null, undefined, { type: 'timeout', target: script }), 120000); + //script.onerror = onScriptComplete.bind(null, script.onerror); + //script.onload = onScriptComplete.bind(null, script.onload); + //needAttach && document.head.appendChild(script); + }; + ` + + if (res) { + return res + } + + return Template.asString([ + 'var inProgress = {};', + uniqueName + ? `var dataWebpackPrefix = ${JSON.stringify(uniqueName + ':')};` + : '// data-webpack is not used as build has no uniqueName', + '// loadScript function to load a script via script tag', + `${fn} = ${runtimeTemplate.basicFunction('url, done, key, chunkId', [ + 'if(inProgress[url]) { inProgress[url].push(done); return; }', + 'var script, needAttach;', + 'if(key !== undefined) {', + Template.indent([ + 'var scripts = document.getElementsByTagName("script");', + 'for(var i = 0; i < scripts.length; i++) {', + Template.indent([ + 'var s = scripts[i];', + `if(s.getAttribute("src") == url${ + uniqueName + ? ' || s.getAttribute("data-webpack") == dataWebpackPrefix + key' + : '' + }) { script = s; break; }`, + ]), + '}', + ]), + '}', + 'if(!script) {', + Template.indent([ + 'needAttach = true;', + createScript.call(code, this.chunk), + ]), + '}', + 'inProgress[url] = [done];', + 'var onScriptComplete = ' + + runtimeTemplate.basicFunction( + 'prev, event', + Template.asString([ + '// avoid mem leaks in IE.', + '//script.onerror = script.onload = null;', + '//clearTimeout(timeout);', + 'var doneFns = inProgress[url];', + 'delete inProgress[url];', + '//script.parentNode && script.parentNode.removeChild(script);', + `doneFns && doneFns.forEach(${runtimeTemplate.returningFunction( + 'fn(event)', + 'fn' + )});`, + 'if(prev) return prev(event);', + ]) + ), + ';', + `//var timeout = setTimeout(onScriptComplete.bind(null, undefined, { type: 'timeout', target: script }), ${loadTimeout});`, + '//script.onerror = onScriptComplete.bind(null, script.onerror);', + '//script.onload = onScriptComplete.bind(null, script.onload);', + "chrome.runtime.sendMessage({type: 'hot-update',url},function(response) { console.log(response.data) })", + '//needAttach && document.head.appendChild(script);', + ])};`, + ]) + } +} + +module.exports = LoadScriptRuntimeModule diff --git a/config/ChromeExtensionsDevHMRPlugin/LoadScriptRuntimeModule.js b/config/ChromeExtensionsDevHMRPlugin/LoadScriptRuntimeModule.js new file mode 100644 index 0000000..ab7cccd --- /dev/null +++ b/config/ChromeExtensionsDevHMRPlugin/LoadScriptRuntimeModule.js @@ -0,0 +1,219 @@ +/* + MIT License http://www.opensource.org/licenses/mit-license.php +*/ + +/** + * @see https://github.com/webpack/webpack/blob/13a3bc13736e3b7066779623939e9fdaec7bc06b/lib/runtime/LoadScriptRuntimeModule.js + */ + +'use strict' + +const { SyncWaterfallHook } = require('tapable') +const { + Compilation, + RuntimeGlobals, + Template, + RuntimeModule, +} = require('webpack') + +/** @typedef {import("../Chunk")} Chunk */ +/** @typedef {import("../Compiler")} Compiler */ + +/** + * @typedef {Object} LoadScriptCompilationHooks + * @property {SyncWaterfallHook<[string, Chunk]>} createScript + */ + +/** @type {WeakMap} */ +const compilationHooksMap = new WeakMap() + +class LoadScriptRuntimeModule extends RuntimeModule { + /** + * @param {Compilation} compilation the compilation + * @returns {LoadScriptCompilationHooks} hooks + */ + static getCompilationHooks(compilation) { + if (!(compilation instanceof Compilation)) { + throw new TypeError( + "The 'compilation' argument must be an instance of Compilation" + ) + } + let hooks = compilationHooksMap.get(compilation) + if (hooks === undefined) { + hooks = { + createScript: new SyncWaterfallHook(['source', 'chunk']), + } + compilationHooksMap.set(compilation, hooks) + } + return hooks + } + + /** + * @param {boolean=} withCreateScriptUrl use create script url for trusted types + */ + constructor(withCreateScriptUrl) { + super('load script') + this._withCreateScriptUrl = withCreateScriptUrl + } + + /** + * @returns {string} runtime code + */ + generate() { + const { compilation } = this + const { runtimeTemplate, outputOptions } = compilation + const { + scriptType, + chunkLoadTimeout: loadTimeout, + crossOriginLoading, + uniqueName, + charset, + } = outputOptions + const fn = RuntimeGlobals.loadScript + + const { createScript } = + LoadScriptRuntimeModule.getCompilationHooks(compilation) + + const code = Template.asString([ + "script = document.createElement('script');", + scriptType ? `script.type = ${JSON.stringify(scriptType)};` : '', + charset ? "script.charset = 'utf-8';" : '', + `script.timeout = ${loadTimeout / 1000};`, + `if (${RuntimeGlobals.scriptNonce}) {`, + Template.indent( + `script.setAttribute("nonce", ${RuntimeGlobals.scriptNonce});` + ), + '}', + uniqueName + ? 'script.setAttribute("data-webpack", dataWebpackPrefix + key);' + : '', + `script.src = ${ + this._withCreateScriptUrl + ? `${RuntimeGlobals.createScriptUrl}(url)` + : 'url' + };`, + crossOriginLoading + ? Template.asString([ + "if (script.src.indexOf(window.location.origin + '/') !== 0) {", + Template.indent( + `script.crossOrigin = ${JSON.stringify(crossOriginLoading)};` + ), + '}', + ]) + : '', + ]) + const res = ` + var inProgress = {}; + ${ + uniqueName + ? `var dataWebpackPrefix = ${JSON.stringify(uniqueName + ':')};` + : '// data-webpack is not used as build has no uniqueName' + } + // loadScript function to load a script via script tag + ${fn} = (url, done, key, chunkId) => { + if(inProgress[url]) { inProgress[url].push(done); return; } + // var script, needAttach; + // if(key !== undefined) { + // var scripts = document.getElementsByTagName("script"); + // for(var i = 0; i < scripts.length; i++) { + // var s = scripts[i]; + // if(s.getAttribute("src") == url || s.getAttribute("data-webpack") == // dataWebpackPrefix + key) { script = s; break; } + // } + // } + // if(!script) { + // needAttach = true; + // script = document.createElement('script'); + + // script.charset = 'utf-8'; + // script.timeout = 120; + // if (__webpack_require__.nc) { + // script.setAttribute("nonce", __webpack_require__.nc); + // } + // script.setAttribute("data-webpack", dataWebpackPrefix + key); + // script.src = url; + // } + inProgress[url] = [done]; + var onScriptComplete = (prev, event) => { + // avoid mem leaks in IE. + //script.onerror = script.onload = null; + //clearTimeout(timeout); + var doneFns = inProgress[url]; + delete inProgress[url]; + //script.parentNode && script.parentNode.removeChild(script); + doneFns && doneFns.forEach((fn) => (fn(event))); + if(prev) return prev(event); + } + ; + chrome.runtime.sendMessage({type: 'hot-update',url},function(response) { console.log(response) }) + //chrome.runtime.reload() + //var timeout = setTimeout(onScriptComplete.bind(null, undefined, { type: 'timeout', target: script }), 120000); + //script.onerror = onScriptComplete.bind(null, script.onerror); + //script.onload = onScriptComplete.bind(null, script.onload); + //needAttach && document.head.appendChild(script); + }; + ` + + if (res) { + return res + } + + return Template.asString([ + 'var inProgress = {};', + uniqueName + ? `var dataWebpackPrefix = ${JSON.stringify(uniqueName + ':')};` + : '// data-webpack is not used as build has no uniqueName', + '// loadScript function to load a script via script tag', + `${fn} = ${runtimeTemplate.basicFunction('url, done, key, chunkId', [ + 'if(inProgress[url]) { inProgress[url].push(done); return; }', + 'var script, needAttach;', + 'if(key !== undefined) {', + Template.indent([ + 'var scripts = document.getElementsByTagName("script");', + 'for(var i = 0; i < scripts.length; i++) {', + Template.indent([ + 'var s = scripts[i];', + `if(s.getAttribute("src") == url${ + uniqueName + ? ' || s.getAttribute("data-webpack") == dataWebpackPrefix + key' + : '' + }) { script = s; break; }`, + ]), + '}', + ]), + '}', + 'if(!script) {', + Template.indent([ + 'needAttach = true;', + createScript.call(code, this.chunk), + ]), + '}', + 'inProgress[url] = [done];', + 'var onScriptComplete = ' + + runtimeTemplate.basicFunction( + 'prev, event', + Template.asString([ + '// avoid mem leaks in IE.', + '//script.onerror = script.onload = null;', + '//clearTimeout(timeout);', + 'var doneFns = inProgress[url];', + 'delete inProgress[url];', + '//script.parentNode && script.parentNode.removeChild(script);', + `doneFns && doneFns.forEach(${runtimeTemplate.returningFunction( + 'fn(event)', + 'fn' + )});`, + 'if(prev) return prev(event);', + ]) + ), + ';', + `//var timeout = setTimeout(onScriptComplete.bind(null, undefined, { type: 'timeout', target: script }), ${loadTimeout});`, + '//script.onerror = onScriptComplete.bind(null, script.onerror);', + '//script.onload = onScriptComplete.bind(null, script.onload);', + "chrome.runtime.sendMessage({type: 'hot-update',url},function(response) { console.log(response.data) })", + '//needAttach && document.head.appendChild(script);', + ])};`, + ]) + } +} + +module.exports = LoadScriptRuntimeModule diff --git a/config/ChromeExtensionsDevHMRPlugin/index.js b/config/ChromeExtensionsDevHMRPlugin/index.js new file mode 100644 index 0000000..07135f6 --- /dev/null +++ b/config/ChromeExtensionsDevHMRPlugin/index.js @@ -0,0 +1,57 @@ +/** + * @ee https://github.com/webpack/webpack/blob/13a3bc13736e3b7066779623939e9fdaec7bc06b/lib/RuntimePlugin.js#L361 + */ +const { RuntimeGlobals } = require('webpack') +const ContentLoadScriptRuntimeModule = require('./ContentLoadScriptRuntimeModule') +const BackgroundLoadScriptRuntimeModule = require('./BackgroundLoadScriptRuntimeModule') +const DefaultLoadScriptRuntimeModule = require('webpack/lib/runtime/LoadScriptRuntimeModule') + +class ChromeExtensionsDevHMRPlugin { + constructor(options) { + this.options = options + } + apply(compiler) { + if (compiler.hooks) { + compiler.hooks.thisCompilation.tap( + 'ChromeExtensionsDevHMRPlugin', + compilation => { + compilation.hooks.runtimeRequirementInTree + .for(RuntimeGlobals.loadScript) + .tap('RuntimePlugin', (chunk, set) => { + const withCreateScriptUrl = + !!compilation.outputOptions.trustedTypes + if (withCreateScriptUrl) { + set.add(RuntimeGlobals.createScriptUrl) + } + + switch (chunk.name) { + case 'content-load': + compilation.addRuntimeModule( + chunk, + new ContentLoadScriptRuntimeModule(withCreateScriptUrl) + ) + break + case 'background': + compilation.addRuntimeModule( + chunk, + new BackgroundLoadScriptRuntimeModule(withCreateScriptUrl) + ) + break + + default: + compilation.addRuntimeModule( + chunk, + new DefaultLoadScriptRuntimeModule(withCreateScriptUrl) + ) + break + } + + return true + }) + } + ) + } + } +} + +module.exports = ChromeExtensionsDevHMRPlugin diff --git a/config/common.js b/config/common.js index e2ee492..2dfa915 100644 --- a/config/common.js +++ b/config/common.js @@ -1,20 +1,32 @@ /* eslint-disable @typescript-eslint/no-var-requires */ const path = require('path') -const UserscriptPlugin = require('../src/userscriptPlugin') +const HtmlWebpackPlugin = require('html-webpack-plugin') +const CopyPlugin = require('copy-webpack-plugin') /** * @type {import('webpack').Configuration} */ const common = { - entry: path.join(__dirname, '../src/index.tsx'), + entry: { + popup: path.join(__dirname, '../src/popup/index.tsx'), + options: path.join(__dirname, '../src/options/index.tsx'), + content: path.join(__dirname, '../src/content/index.tsx'), + 'content-load': path.join(__dirname, '../src/content/load.ts'), + background: path.join(__dirname, '../src/background/index.ts'), + }, output: { - filename: 'main.user.js', + filename: '[name].bundle.js', path: path.join(__dirname, '../dist'), + publicPath: '/', clean: true, }, resolve: { + alias: { + 'react/jsx-runtime': 'react/jsx-runtime.js', + '@': path.join(__dirname, '../src/content'), + src: path.join(__dirname, '../src'), + }, extensions: ['.js', '.jsx', '.ts', '.tsx'], - fallback: { path: false }, }, module: { rules: [ @@ -33,7 +45,27 @@ const common = { }, ], }, - plugins: [new UserscriptPlugin()], + plugins: [ + new HtmlWebpackPlugin({ + template: path.join(__dirname, '../public', 'options.html'), + chunks: ['options'], + filename: 'options.html', + publicPath: '/', + }), + new HtmlWebpackPlugin({ + template: path.join(__dirname, '../public', 'popup.html'), + chunks: ['popup'], + filename: 'popup.html', + publicPath: '/', + }), + new CopyPlugin({ + patterns: [ + { from: 'icons/*.png', context: path.resolve('public') }, + { from: 'file-icons/*.svg', context: path.resolve('public') }, + { from: '_locales', context: path.resolve('public'), to: '_locales' }, + ], + }), + ], } module.exports = { common } diff --git a/config/development.js b/config/development.js index c96ca9e..65f8fb2 100644 --- a/config/development.js +++ b/config/development.js @@ -1,37 +1,89 @@ /* eslint-disable @typescript-eslint/no-var-requires */ const path = require('path') +const webpack = require('webpack') const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin') +const CopyPlugin = require('copy-webpack-plugin') + +const ChromeExtensionsDevHMRPlugin = require('./ChromeExtensionsDevHMRPlugin') /** * @type {import('webpack').Configuration} */ -const development = { - target: 'web', +const development = env => ({ output: { - publicPath: 'http://localhost:9000/', + publicPath: 'http://localhost:9100/', + }, + entry: { + options: [ + 'webpack/hot/dev-server.js', + 'webpack-dev-server/client/index.js?hot=true&protocol=ws&hostname=localhost&port=9100', + path.join(__dirname, '../src/options/index.tsx'), + ], + popup: [ + 'webpack/hot/dev-server.js', + 'webpack-dev-server/client/index.js?hot=true&protocol=ws&hostname=localhost&port=9100', + path.join(__dirname, '../src/popup/index.tsx'), + ], + content: [ + 'webpack/hot/dev-server.js', + 'webpack-dev-server/client/index.js?hot=true&protocol=ws&hostname=localhost&port=9100', + path.join(__dirname, '../src/content/index.tsx'), + ], + 'content-load': [ + 'webpack/hot/dev-server.js', + 'webpack-dev-server/client/index.js?hot=true&protocol=ws&hostname=localhost&port=9100', + path.join(__dirname, '../src/content/load.ts'), + ], }, devServer: { + static: { + directory: path.join(__dirname, '../dist'), + watch: false, + }, host: 'localhost', - port: 9000, - hot: true, + port: 9100, + hot: false, + devMiddleware: { + writeToDisk: true, + }, allowedHosts: 'all', headers: { 'Access-Control-Allow-Origin': '*', }, - onBeforeSetupMiddleware: devServer => { - devServer.app.get('/', (req, res) => res.redirect('/main.user.js')) - }, - static: false, + client: false, }, plugins: [ - new ReactRefreshWebpackPlugin({ - exclude: /node_modules/, - include: path.resolve(__dirname, '../src'), - overlay: false, + new ReactRefreshWebpackPlugin({ overlay: false }), + new webpack.SourceMapDevToolPlugin({ + publicPath: 'http://localhost:9100/', + }), + new ChromeExtensionsDevHMRPlugin(), + new webpack.HotModuleReplacementPlugin(), + new CopyPlugin({ + patterns: [{ from: 'public/manifest-dev.json', to: 'manifest.json' }], + }), + new webpack.DefinePlugin({ + REFINED_LEETCODE_LOG_LEVEL: env.LOG_LEVEL + ? JSON.stringify(env.LOG_LEVEL) + : JSON.stringify('debug'), + }), + new webpack.BannerPlugin({ + banner: file => { + if (file.filename === 'content.bundle.js') { + return ` + const frame = document.createElement('frame') + frame.style.display = 'none' + document.body.append(frame) + const console = frame.contentWindow.console + window.console = console;` + } + return '' + }, + raw: true, }), ], - devtool: 'eval-source-map', + devtool: false, mode: 'development', -} +}) module.exports = { development } diff --git a/config/production.js b/config/production.js index 10f6707..c6e6421 100644 --- a/config/production.js +++ b/config/production.js @@ -1,15 +1,21 @@ -/* eslint-disable @typescript-eslint/no-var-requires */ +const CopyPlugin = require('copy-webpack-plugin') +const webpack = require('webpack') /** * @type {import('webpack').Configuration} */ -const production = { - devtool: 'source-map', +const production = env => ({ + plugins: [ + new CopyPlugin({ + patterns: [{ from: 'public/manifest.json', to: 'manifest.json' }], + }), + new webpack.DefinePlugin({ + REFINED_LEETCODE_LOG_LEVEL: env.LOG_LEVEL + ? JSON.stringify(env.LOG_LEVEL) + : JSON.stringify('error'), + }), + ], mode: 'production', - externals: { - react: 'React', - 'react-dom': 'ReactDOM', - }, -} +}) module.exports = { production } diff --git a/dist/main.user.js b/dist/main.user.js deleted file mode 100644 index 11915b8..0000000 --- a/dist/main.user.js +++ /dev/null @@ -1,15 +0,0 @@ -// ==UserScript== -// @name leetcode-extend -// @namespace https://github.com/xyshaokang/leetcode-extend -// @version 0.0.19 -// @description 力扣扩展 -// @author XYShaoKang -// @match https://leetcode-cn.com/* -// @match https://leetcode.com/* -// @require https://unpkg.com/react@17/umd/react.production.min.js -// @require https://unpkg.com/react-dom@17/umd/react-dom.production.min.js -// ==/UserScript== - -/*! For license information please see main.user.js.LICENSE.txt */ -(()=>{var __webpack_modules__={733:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";__webpack_require__.d(__webpack_exports__,{E:()=>LeetCodeApi});var _utils__WEBPACK_IMPORTED_MODULE_0__=__webpack_require__(559);function ownKeys(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function _objectSpread(e){for(var t=1;t1&&void 0!==o[1]?o[1]:40,n=o.length>2&&void 0!==o[2]?o[2]:0,i={operationName:"submissions",variables:{offset:n,limit:r,lastKey:null,questionSlug:t},query:"\n query submissions(\n $offset: Int!\n $limit: Int!\n $lastKey: String\n $questionSlug: String!\n ) {\n submissionList(\n offset: $offset\n limit: $limit\n lastKey: $lastKey\n questionSlug: $questionSlug\n ) {\n lastKey\n hasNext\n submissions {\n id\n statusDisplay\n lang\n runtime\n timestamp\n url\n isPending\n memory\n __typename\n }\n __typename\n }\n }\n "},e.abrupt("return",this.graphqlApi({body:i}).then((function(e){return e.data.submissionList})));case 4:case"end":return e.stop()}}),e,this)}))),function(e){return _getSubmissions.apply(this,arguments)})},{key:"getSubmissionDetailByLocal",value:(_getSubmissionDetailByLocal=_asyncToGenerator(regeneratorRuntime.mark((function e(t){var r;return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return r={operationName:"mySubmissionDetail",variables:{id:t},query:"\n query mySubmissionDetail($id: ID!) {\n submissionDetail(submissionId: $id) {\n id\n code\n runtime\n memory\n rawMemory\n statusDisplay\n timestamp\n lang\n passedTestCaseCnt\n totalTestCaseCnt\n sourceUrl\n question {\n titleSlug\n title\n translatedTitle\n questionId\n __typename\n }\n ... on GeneralSubmissionNode {\n outputDetail {\n codeOutput\n expectedOutput\n input\n compileError\n runtimeError\n lastTestcase\n __typename\n }\n __typename\n }\n submissionComment {\n comment\n flagType\n __typename\n }\n __typename\n }\n }\n "},e.abrupt("return",this.graphqlApi({body:r}).then((function(e){return e.data.submissionDetail})));case 2:case"end":return e.stop()}}),e,this)}))),function(e){return _getSubmissionDetailByLocal.apply(this,arguments)})},{key:"getDistributionLocal",value:(_getDistributionLocal=_asyncToGenerator(regeneratorRuntime.mark((function e(t){var r,n,i,o;return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return r="/submissions/api/runtime_distribution/".concat(t,"/"),e.next=3,this.baseApi(r).then((function(e){var t=e.runtime_distribution_formatted;return t?JSON.parse(t):null}));case 3:return n=e.sent,i="/submissions/api/memory_distribution/".concat(t,"/"),e.next=7,this.baseApi(i).then((function(e){var t=e.memory_distribution_formatted;return t?JSON.parse(t):null}));case 7:return o=e.sent,e.abrupt("return",{runtimeDistribution:n,memoryDistribution:o});case 9:case"end":return e.stop()}}),e,this)}))),function(e){return _getDistributionLocal.apply(this,arguments)})},{key:"getSubmissionDetailByGlobal",value:function(){var _getSubmissionDetailByGlobal=_asyncToGenerator(regeneratorRuntime.mark((function _callee5(submissionId){var _text$match,text,dataText,data;return regeneratorRuntime.wrap((function _callee5$(_context5){for(;;)switch(_context5.prev=_context5.next){case 0:return _context5.next=2,fetch("https://leetcode.com/submissions/detail/".concat(submissionId,"/"),{headers:{accept:"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"},referrer:"https://leetcode.com/",referrerPolicy:"strict-origin-when-cross-origin",body:null,method:"GET",mode:"cors",credentials:"include"}).then((function(e){return e.text()}));case 2:return text=_context5.sent,dataText=null===(_text$match=text.match(/var pageData = ([\d\D]+?});/))||void 0===_text$match?void 0:_text$match[1],data=eval("(function (){return ".concat(dataText,"})()")),_context5.abrupt("return",data);case 6:case"end":return _context5.stop()}}),_callee5)})));function getSubmissionDetailByGlobal(e){return _getSubmissionDetailByGlobal.apply(this,arguments)}return getSubmissionDetailByGlobal}()},{key:"getSubmissionDetail",value:(_getSubmissionDetail=_asyncToGenerator(regeneratorRuntime.mark((function e(t){var r,n,i,o,a;return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:if(!/leetcode-cn\.com/.test(this.REGION_URL)){e.next=12;break}return e.next=3,this.getSubmissionDetailByLocal(t);case 3:return r=e.sent,e.next=6,this.getDistributionLocal(t);case 6:return n=e.sent,i=n.runtimeDistribution,o=n.memoryDistribution,e.abrupt("return",_objectSpread(_objectSpread({},r),{},{questionId:r.question.questionId,runtimeDistribution:i||{lang:r.lang,distribution:[]},memoryDistribution:o||{lang:r.lang,distribution:[]}}));case 12:return e.next=14,this.getSubmissionDetailByGlobal(t);case 14:return a=e.sent,e.abrupt("return",{id:a.submissionId,code:a.submissionCode,runtime:a.runtime,memory:a.submissionData.memory,rawMemory:a.memory,statusDisplay:(0,_utils__WEBPACK_IMPORTED_MODULE_0__.fU)(a.submissionData.status_code),lang:a.getLangDisplay,passedTestCaseCnt:Number(a.submissionData.total_correct),totalTestCaseCnt:Number(a.submissionData.total_testcases),sourceUrl:a.editCodeUrl,questionId:a.questionId,runtimeDistribution:JSON.parse(a.runtimeDistributionFormatted),memoryDistribution:JSON.parse(a.memoryDistributionFormatted)});case 16:case"end":return e.stop()}}),e,this)}))),function(e){return _getSubmissionDetail.apply(this,arguments)})},{key:"getCodeByTime",value:function(e,t,r){var n="/submissions/api/detail/".concat(t,"/").concat(e,"/").concat(r,"/");return this.baseApi(n).then((function(e){return e.code}))}},{key:"getCodeByMemory",value:function(e,t,r){var n="/submissions/api/detail/".concat(t,"/").concat(e,"/memory/").concat(r,"/");return this.baseApi(n).then((function(e){return e.code}))}},{key:"check",value:function(e){var t="/submissions/detail/".concat(e,"/check/");return this.baseApi(t)}},{key:"submissionCreateOrUpdateSubmissionComment",value:function(e,t,r){var n={operationName:"submissionCreateOrUpdateSubmissionComment",variables:{submissionId:e,flagType:t,comment:r},query:"\n mutation submissionCreateOrUpdateSubmissionComment(\n $submissionId: ID!\n $flagType: SubmissionFlagTypeEnum!\n $comment: String!\n ) {\n submissionCreateOrUpdateSubmissionComment(\n comment: $comment\n flagType: $flagType\n submissionId: $submissionId\n ) {\n ok\n __typename\n }\n }\n "};return this.graphqlApi({body:n}).then((function(e){return e.data.submissionCreateOrUpdateSubmissionComment}))}}]),LeetCodeApi}()},559:(e,t,r)=>{"use strict";function n(e){return n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},n(e)}function i(e){return new Promise((function(t){setTimeout(t,e)}))}function o(e,t){var r=t.method,n=t.body,a=arguments.length>2&&void 0!==arguments[2]?arguments[2]:1;r=r||"POST";var s=3e3,c=5;return fetch("".concat(e,"/graphql/"),{headers:{"content-type":"application/json"},referrer:"".concat(e,"/"),referrerPolicy:"strict-origin-when-cross-origin",body:JSON.stringify(n),method:r,mode:"cors",credentials:"include"}).then((function(t){if(200===t.status)return t.json();if(429===t.status){if(console.log("超出接口限制,休息一下,等待第".concat(a,"次重试...")),a>c)throw new Error("已重试 ".concat(c," 次,仍然无法获取,可能力扣君生气了,晚点在试试吧..."));return i(s).then((function(){return o(e,{method:r,body:n},a+1)}))}throw new Error("未知状态: ".concat(t.status))}))}function a(e){return"object"===n(e)&&null!==e}function s(e,t){var r,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"GET",o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:null,c=arguments.length>4&&void 0!==arguments[4]?arguments[4]:1,u=2e4,l=10;return r="GET"===(n=n.toUpperCase())?null:a(o)?JSON.stringify(o):o,fetch(e+t,{headers:{accept:"application/json, text/plain, */*"},referrer:"REGION_URL",referrerPolicy:"strict-origin-when-cross-origin",body:r,method:n,mode:"cors",credentials:"include"}).then((function(r){if(200===r.status)return r.json();if(429===r.status){if(console.log("超出接口限制,休息一下,等待第".concat(c,"次重试...")),c>l)throw new Error("已重试 ".concat(l," 次,仍然无法获取,可能力扣君生气了,晚点在试试吧..."));return i(u).then((function(){return s(e,t,n,o,c+1)}))}throw new Error("未知状态: ".concat(r.status))}))}function c(e){switch(e){case 10:return"Accepted";case 11:return"Wrong Answer";case 12:return"Memory Limit Exceeded";case 13:return"Output Limit Exceeded";case 14:return"Time Limit Exceeded";case 15:return"Runtime Error";case 16:return"Internal Error";case 20:return"Compile Error";case 21:return"Unknown Error";case 30:return"Timeout";default:return"Invalid Error Code"}}r.d(t,{_v:()=>i,g1:()=>o,ul:()=>s,fU:()=>c})},185:e=>{"use strict";function t(e,t,i){e instanceof RegExp&&(e=r(e,i)),t instanceof RegExp&&(t=r(t,i));var o=n(e,t,i);return o&&{start:o[0],end:o[1],pre:i.slice(0,o[0]),body:i.slice(o[0]+e.length,o[1]),post:i.slice(o[1]+t.length)}}function r(e,t){var r=t.match(e);return r?r[0]:null}function n(e,t,r){var n,i,o,a,s,c=r.indexOf(e),u=r.indexOf(t,c+1),l=c;if(c>=0&&u>0){if(e===t)return[c,u];for(n=[],o=r.length;l>=0&&!s;)l==c?(n.push(l),c=r.indexOf(e,l+1)):1==n.length?s=[n.pop(),u]:((i=n.pop())=0?c:u;n.length&&(s=[o,a])}return s}e.exports=t,t.range=n},816:(e,t,r)=>{var n=r(593),i=r(185);e.exports=function(e){return e?("{}"===e.substr(0,2)&&(e="\\{\\}"+e.substr(2)),y(function(e){return e.split("\\\\").join(o).split("\\{").join(a).split("\\}").join(s).split("\\,").join(c).split("\\.").join(u)}(e),!0).map(f)):[]};var o="\0SLASH"+Math.random()+"\0",a="\0OPEN"+Math.random()+"\0",s="\0CLOSE"+Math.random()+"\0",c="\0COMMA"+Math.random()+"\0",u="\0PERIOD"+Math.random()+"\0";function l(e){return parseInt(e,10)==e?parseInt(e,10):e.charCodeAt(0)}function f(e){return e.split(o).join("\\").split(a).join("{").split(s).join("}").split(c).join(",").split(u).join(".")}function p(e){if(!e)return[""];var t=[],r=i("{","}",e);if(!r)return e.split(",");var n=r.pre,o=r.body,a=r.post,s=n.split(",");s[s.length-1]+="{"+o+"}";var c=p(a);return a.length&&(s[s.length-1]+=c.shift(),s.push.apply(s,c)),t.push.apply(t,s),t}function d(e){return"{"+e+"}"}function h(e){return/^-?0\d/.test(e)}function m(e,t){return e<=t}function g(e,t){return e>=t}function y(e,t){var r=[],o=i("{","}",e);if(!o||/\$$/.test(o.pre))return[e];var a,c=/^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(o.body),u=/^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(o.body),f=c||u,b=o.body.indexOf(",")>=0;if(!f&&!b)return o.post.match(/,.*\}/)?y(e=o.pre+"{"+o.body+s+o.post):[e];if(f)a=o.body.split(/\.\./);else if(1===(a=p(o.body)).length&&1===(a=y(a[0],!1).map(d)).length)return(_=o.post.length?y(o.post,!1):[""]).map((function(e){return o.pre+a[0]+e}));var v,w=o.pre,_=o.post.length?y(o.post,!1):[""];if(f){var S=l(a[0]),x=l(a[1]),k=Math.max(a[0].length,a[1].length),C=3==a.length?Math.abs(l(a[2])):1,O=m;x0){var I=new Array(P+1).join("0");E=j<0?"-"+I+E.slice(1):I+E}}v.push(E)}}else v=n(a,(function(e){return y(e,!1)}));for(var R=0;R{e.exports=function(e,r){for(var n=[],i=0;i{"use strict";var n=r(237),i={childContextTypes:!0,contextType:!0,contextTypes:!0,defaultProps:!0,displayName:!0,getDefaultProps:!0,getDerivedStateFromError:!0,getDerivedStateFromProps:!0,mixins:!0,propTypes:!0,type:!0},o={name:!0,length:!0,prototype:!0,caller:!0,callee:!0,arguments:!0,arity:!0},a={$$typeof:!0,compare:!0,defaultProps:!0,displayName:!0,propTypes:!0,type:!0},s={};function c(e){return n.isMemo(e)?a:s[e.$$typeof]||i}s[n.ForwardRef]={$$typeof:!0,render:!0,defaultProps:!0,displayName:!0,propTypes:!0},s[n.Memo]=a;var u=Object.defineProperty,l=Object.getOwnPropertyNames,f=Object.getOwnPropertySymbols,p=Object.getOwnPropertyDescriptor,d=Object.getPrototypeOf,h=Object.prototype;e.exports=function e(t,r,n){if("string"!=typeof r){if(h){var i=d(r);i&&i!==h&&e(t,i,n)}var a=l(r);f&&(a=a.concat(f(r)));for(var s=c(t),m=c(r),g=0;g{e.exports=p,p.Minimatch=d;var n={sep:"/"};try{n=r(61)}catch(e){}var i=p.GLOBSTAR=d.GLOBSTAR={},o=r(816),a={"!":{open:"(?:(?!(?:",close:"))[^/]*?)"},"?":{open:"(?:",close:")?"},"+":{open:"(?:",close:")+"},"*":{open:"(?:",close:")*"},"@":{open:"(?:",close:")"}},s="[^/]",c="[^/]*?",u="().*{}+?[]^$\\!".split("").reduce((function(e,t){return e[t]=!0,e}),{}),l=/\/+/;function f(e,t){e=e||{},t=t||{};var r={};return Object.keys(t).forEach((function(e){r[e]=t[e]})),Object.keys(e).forEach((function(t){r[t]=e[t]})),r}function p(e,t,r){if("string"!=typeof t)throw new TypeError("glob pattern string required");return r||(r={}),!(!r.nocomment&&"#"===t.charAt(0))&&(""===t.trim()?""===e:new d(t,r).match(e))}function d(e,t){if(!(this instanceof d))return new d(e,t);if("string"!=typeof e)throw new TypeError("glob pattern string required");t||(t={}),e=e.trim(),"/"!==n.sep&&(e=e.split(n.sep).join("/")),this.options=t,this.set=[],this.pattern=e,this.regexp=null,this.negate=!1,this.comment=!1,this.empty=!1,this.make()}function h(e,t){if(t||(t=this instanceof d?this.options:{}),void 0===(e=void 0===e?this.pattern:e))throw new TypeError("undefined pattern");return t.nobrace||!e.match(/\{.*\}/)?[e]:o(e)}p.filter=function(e,t){return t=t||{},function(r,n,i){return p(r,e,t)}},p.defaults=function(e){if(!e||!Object.keys(e).length)return p;var t=p,r=function(r,n,i){return t.minimatch(r,n,f(e,i))};return r.Minimatch=function(r,n){return new t.Minimatch(r,f(e,n))},r},d.defaults=function(e){return e&&Object.keys(e).length?p.defaults(e).Minimatch:d},d.prototype.debug=function(){},d.prototype.make=function(){if(!this._made){var e=this.pattern,t=this.options;if(t.nocomment||"#"!==e.charAt(0))if(e){this.parseNegate();var r=this.globSet=this.braceExpand();t.debug&&(this.debug=console.error),this.debug(this.pattern,r),r=this.globParts=r.map((function(e){return e.split(l)})),this.debug(this.pattern,r),r=r.map((function(e,t,r){return e.map(this.parse,this)}),this),this.debug(this.pattern,r),r=r.filter((function(e){return-1===e.indexOf(!1)})),this.debug(this.pattern,r),this.set=r}else this.empty=!0;else this.comment=!0}},d.prototype.parseNegate=function(){var e=this.pattern,t=!1,r=0;if(!this.options.nonegate){for(var n=0,i=e.length;n65536)throw new TypeError("pattern is too long");var r=this.options;if(!r.noglobstar&&"**"===e)return i;if(""===e)return"";var n,o="",l=!!r.nocase,f=!1,p=[],d=[],h=!1,g=-1,y=-1,b="."===e.charAt(0)?"":r.dot?"(?!(?:^|\\/)\\.{1,2}(?:$|\\/))":"(?!\\.)",v=this;function w(){if(n){switch(n){case"*":o+=c,l=!0;break;case"?":o+=s,l=!0;break;default:o+="\\"+n}v.debug("clearStateChar %j %j",n,o),n=!1}}for(var _,S=0,x=e.length;S-1;P--){var I=d[P],R=o.slice(0,I.reStart),D=o.slice(I.reStart,I.reEnd-8),$=o.slice(I.reEnd-8,I.reEnd),T=o.slice(I.reEnd);$+=T;var M=R.split("(").length-1,L=T;for(S=0;S=0&&!(i=e[o]);o--);for(o=0;o>> no match, partial?",e,p,t,d),p!==s))}if("string"==typeof l?(u=n.nocase?f.toLowerCase()===l.toLowerCase():f===l,this.debug("string match",l,f,u)):(u=f.match(l),this.debug("pattern match",l,f,u)),!u)return!1}if(o===s&&a===c)return!0;if(o===s)return r;if(a===c)return o===s-1&&""===e[o];throw new Error("wtf?")}},767:e=>{"use strict";var t=Object.getOwnPropertySymbols,r=Object.prototype.hasOwnProperty,n=Object.prototype.propertyIsEnumerable;function i(e){if(null==e)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(e)}e.exports=function(){try{if(!Object.assign)return!1;var e=new String("abc");if(e[5]="de","5"===Object.getOwnPropertyNames(e)[0])return!1;for(var t={},r=0;r<10;r++)t["_"+String.fromCharCode(r)]=r;if("0123456789"!==Object.getOwnPropertyNames(t).map((function(e){return t[e]})).join(""))return!1;var n={};return"abcdefghijklmnopqrst".split("").forEach((function(e){n[e]=e})),"abcdefghijklmnopqrst"===Object.keys(Object.assign({},n)).join("")}catch(e){return!1}}()?Object.assign:function(e,o){for(var a,s,c=i(e),u=1;u{"use strict";var r="function"==typeof Symbol&&Symbol.for,n=r?Symbol.for("react.element"):60103,i=r?Symbol.for("react.portal"):60106,o=r?Symbol.for("react.fragment"):60107,a=r?Symbol.for("react.strict_mode"):60108,s=r?Symbol.for("react.profiler"):60114,c=r?Symbol.for("react.provider"):60109,u=r?Symbol.for("react.context"):60110,l=r?Symbol.for("react.async_mode"):60111,f=r?Symbol.for("react.concurrent_mode"):60111,p=r?Symbol.for("react.forward_ref"):60112,d=r?Symbol.for("react.suspense"):60113,h=r?Symbol.for("react.suspense_list"):60120,m=r?Symbol.for("react.memo"):60115,g=r?Symbol.for("react.lazy"):60116,y=r?Symbol.for("react.block"):60121,b=r?Symbol.for("react.fundamental"):60117,v=r?Symbol.for("react.responder"):60118,w=r?Symbol.for("react.scope"):60119;function _(e){if("object"==typeof e&&null!==e){var t=e.$$typeof;switch(t){case n:switch(e=e.type){case l:case f:case o:case s:case a:case d:return e;default:switch(e=e&&e.$$typeof){case u:case p:case g:case m:case c:return e;default:return t}}case i:return t}}}function S(e){return _(e)===f}t.AsyncMode=l,t.ConcurrentMode=f,t.ContextConsumer=u,t.ContextProvider=c,t.Element=n,t.ForwardRef=p,t.Fragment=o,t.Lazy=g,t.Memo=m,t.Portal=i,t.Profiler=s,t.StrictMode=a,t.Suspense=d,t.isAsyncMode=function(e){return S(e)||_(e)===l},t.isConcurrentMode=S,t.isContextConsumer=function(e){return _(e)===u},t.isContextProvider=function(e){return _(e)===c},t.isElement=function(e){return"object"==typeof e&&null!==e&&e.$$typeof===n},t.isForwardRef=function(e){return _(e)===p},t.isFragment=function(e){return _(e)===o},t.isLazy=function(e){return _(e)===g},t.isMemo=function(e){return _(e)===m},t.isPortal=function(e){return _(e)===i},t.isProfiler=function(e){return _(e)===s},t.isStrictMode=function(e){return _(e)===a},t.isSuspense=function(e){return _(e)===d},t.isValidElementType=function(e){return"string"==typeof e||"function"==typeof e||e===o||e===f||e===s||e===a||e===d||e===h||"object"==typeof e&&null!==e&&(e.$$typeof===g||e.$$typeof===m||e.$$typeof===c||e.$$typeof===u||e.$$typeof===p||e.$$typeof===b||e.$$typeof===v||e.$$typeof===w||e.$$typeof===y)},t.typeOf=_},237:(e,t,r)=>{"use strict";e.exports=r(198)},841:(e,t)=>{"use strict";var r=60103,n=60106,i=60107,o=60108,a=60114,s=60109,c=60110,u=60112,l=60113,f=60120,p=60115,d=60116,h=60121,m=60122,g=60117,y=60129,b=60131;if("function"==typeof Symbol&&Symbol.for){var v=Symbol.for;r=v("react.element"),n=v("react.portal"),i=v("react.fragment"),o=v("react.strict_mode"),a=v("react.profiler"),s=v("react.provider"),c=v("react.context"),u=v("react.forward_ref"),l=v("react.suspense"),f=v("react.suspense_list"),p=v("react.memo"),d=v("react.lazy"),h=v("react.block"),m=v("react.server.block"),g=v("react.fundamental"),y=v("react.debug_trace_mode"),b=v("react.legacy_hidden")}t.isValidElementType=function(e){return"string"==typeof e||"function"==typeof e||e===i||e===a||e===y||e===o||e===l||e===f||e===b||"object"==typeof e&&null!==e&&(e.$$typeof===d||e.$$typeof===p||e.$$typeof===s||e.$$typeof===c||e.$$typeof===u||e.$$typeof===g||e.$$typeof===h||e[0]===m)},t.typeOf=function(e){if("object"==typeof e&&null!==e){var t=e.$$typeof;switch(t){case r:switch(e=e.type){case i:case a:case o:case l:case f:return e;default:switch(e=e&&e.$$typeof){case c:case u:case d:case p:case s:return e;default:return t}}case n:return t}}}},679:(e,t,r)=>{"use strict";e.exports=r(841)},945:(e,t,r)=>{"use strict";r(767);var n=r(363),i=60103;if("function"==typeof Symbol&&Symbol.for){var o=Symbol.for;i=o("react.element"),o("react.fragment")}var a=n.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,s=Object.prototype.hasOwnProperty,c={key:!0,ref:!0,__self:!0,__source:!0};function u(e,t,r){var n,o={},u=null,l=null;for(n in void 0!==r&&(u=""+r),void 0!==t.key&&(u=""+t.key),void 0!==t.ref&&(l=t.ref),t)s.call(t,n)&&!c.hasOwnProperty(n)&&(o[n]=t[n]);if(e&&e.defaultProps)for(n in t=e.defaultProps)void 0===o[n]&&(o[n]=t[n]);return{$$typeof:i,type:e,key:u,ref:l,props:o,_owner:a.current}}t.jsx=u,t.jsxs=u},637:(e,t,r)=>{"use strict";e.exports=r(945)},631:e=>{e.exports=function(e,t,r,n){var i=r?r.call(n,e,t):void 0;if(void 0!==i)return!!i;if(e===t)return!0;if("object"!=typeof e||!e||"object"!=typeof t||!t)return!1;var o=Object.keys(e),a=Object.keys(t);if(o.length!==a.length)return!1;for(var s=Object.prototype.hasOwnProperty.bind(t),c=0;c{"use strict";e.exports=React},61:()=>{}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var r=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](r,r.exports,__webpack_require__),r.exports}__webpack_require__.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return __webpack_require__.d(t,{a:t}),t},__webpack_require__.d=(e,t)=>{for(var r in t)__webpack_require__.o(t,r)&&!__webpack_require__.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var __webpack_exports__={};(()=>{"use strict";var e=__webpack_require__(363),t=__webpack_require__.n(e);const r=ReactDOM;var n=__webpack_require__(426),i=__webpack_require__.n(n),o=__webpack_require__(679),a=__webpack_require__(631),s=__webpack_require__.n(a);const c=function(e){function t(e,n,c,u,p){for(var d,h,m,g,w,S=0,x=0,k=0,C=0,O=0,R=0,$=m=d=0,M=0,L=0,N=0,q=0,B=c.length,z=B-1,G="",U="",F="",H="";Md)&&(q=(G=G.replace(" ",":")).length),0n&&(n=(t=t.trim()).charCodeAt(0)),n){case 38:return t.replace(g,"$1"+e.trim());case 58:return e.trim()+t.replace(g,"$1"+e.trim());default:if(0<1*r&&0c.charCodeAt(8))break;case 115:a=a.replace(c,"-webkit-"+c)+";"+a;break;case 207:case 102:a=a.replace(c,"-webkit-"+(102n.charCodeAt(0)&&(n=n.trim()),n=[n],01?t-1:0),n=1;n0?" Args: "+r.join(", "):""))}var A=function(){function e(e){this.groupSizes=new Uint32Array(512),this.length=512,this.tag=e}var t=e.prototype;return t.indexOfGroup=function(e){for(var t=0,r=0;r=this.groupSizes.length){for(var r=this.groupSizes,n=r.length,i=n;e>=i;)(i<<=1)<0&&O(16,""+e);this.groupSizes=new Uint32Array(i),this.groupSizes.set(r),this.length=i;for(var o=n;o=this.length||0===this.groupSizes[e])return t;for(var r=this.groupSizes[e],n=this.indexOfGroup(e),i=n+r,o=n;o=P&&(P=t+1),j.set(e,t),E.set(t,e)},$="style["+x+'][data-styled-version="5.3.3"]',T=new RegExp("^"+x+'\\.g(\\d+)\\[id="([\\w\\d-]+)"\\].*?"([^"]*)'),M=function(e,t,r){for(var n,i=r.split(","),o=0,a=i.length;o=0;r--){var n=t[r];if(n&&1===n.nodeType&&n.hasAttribute(x))return n}}(r),o=void 0!==i?i.nextSibling:null;n.setAttribute(x,"active"),n.setAttribute("data-styled-version","5.3.3");var a=N();return a&&n.setAttribute("nonce",a),r.insertBefore(n,o),n},B=function(){function e(e){var t=this.element=q(e);t.appendChild(document.createTextNode("")),this.sheet=function(e){if(e.sheet)return e.sheet;for(var t=document.styleSheets,r=0,n=t.length;r=0){var r=document.createTextNode(t),n=this.nodes[e];return this.element.insertBefore(r,n||null),this.length++,!0}return!1},t.deleteRule=function(e){this.element.removeChild(this.nodes[e]),this.length--},t.getRule=function(e){return e0&&(u+=e+",")})),n+=""+s+c+'{content:"'+u+'"}/*!sc*/\n'}}}return n}(this)},e}(),W=/(a)(d)/gi,Y=function(e){return String.fromCharCode(e+(e>25?39:97))};function K(e){var t,r="";for(t=Math.abs(e);t>52;t=t/52|0)r=Y(t%52)+r;return(Y(t%52)+r).replace(W,"$1-$2")}var Q=function(e,t){for(var r=t.length;r;)e=33*e^t.charCodeAt(--r);return e},V=function(e){return Q(5381,e)};function J(e){for(var t=0;t>>0);if(!t.hasNameForId(n,a)){var s=r(o,"."+a,void 0,n);t.insertRules(n,a,s)}i.push(a),this.staticRulesId=a}else{for(var c=this.rules.length,u=Q(this.baseHash,r.hash),l="",f=0;f>>0);if(!t.hasNameForId(n,m)){var g=r(l,"."+m,void 0,n);t.insertRules(n,m,g)}i.push(m)}}return i.join(" ")},e}(),ee=/^\s*\/\/.*$/gm,te=[":","[",".","#"];function re(e){var t,r,n,i,o=void 0===e?v:e,a=o.options,s=void 0===a?v:a,u=o.plugins,l=void 0===u?b:u,f=new c(s),p=[],d=function(e){function t(t){if(t)try{e(t+"}")}catch(e){}}return function(r,n,i,o,a,s,c,u,l,f){switch(r){case 1:if(0===l&&64===n.charCodeAt(0))return e(n+";"),"";break;case 2:if(0===u)return n+"/*|*/";break;case 3:switch(u){case 102:case 112:return e(i[0]+n),"";default:return n+(0===f?"/*|*/":"")}case-2:n.split("/*|*/}").forEach(t)}}}((function(e){p.push(e)})),h=function(e,n,o){return 0===n&&-1!==te.indexOf(o[r.length])||o.match(i)?e:"."+t};function m(e,o,a,s){void 0===s&&(s="&");var c=e.replace(ee,""),u=o&&a?a+" "+o+" { "+c+" }":c;return t=s,r=o,n=new RegExp("\\"+r+"\\b","g"),i=new RegExp("(\\"+r+"\\b){2,}"),f(a||!o?"":o,u)}return f.use([].concat(l,[function(e,t,i){2===e&&i.length&&i[0].lastIndexOf(r)>0&&(i[0]=i[0].replace(n,h))},d,function(e){if(-2===e){var t=p;return p=[],t}}])),m.hash=l.length?l.reduce((function(e,t){return t.name||O(15),Q(e,t.name)}),5381).toString():"",m}var ne=t().createContext(),ie=(ne.Consumer,t().createContext()),oe=(ie.Consumer,new H),ae=re();function se(){return(0,e.useContext)(ne)||oe}function ce(r){var n=(0,e.useState)(r.stylisPlugins),i=n[0],o=n[1],a=se(),c=(0,e.useMemo)((function(){var e=a;return r.sheet?e=r.sheet:r.target&&(e=e.reconstructWithOptions({target:r.target},!1)),r.disableCSSOMInjection&&(e=e.reconstructWithOptions({useCSSOMInjection:!1})),e}),[r.disableCSSOMInjection,r.sheet,r.target]),u=(0,e.useMemo)((function(){return re({options:{prefix:!r.disableVendorPrefixes},plugins:i})}),[r.disableVendorPrefixes,i]);return(0,e.useEffect)((function(){s()(i,r.stylisPlugins)||o(r.stylisPlugins)}),[r.stylisPlugins]),t().createElement(ne.Provider,{value:c},t().createElement(ie.Provider,{value:u},r.children))}var ue=function(){function e(e,t){var r=this;this.inject=function(e,t){void 0===t&&(t=ae);var n=r.name+t.hash;e.hasNameForId(r.id,n)||e.insertRules(r.id,n,t(r.rules,n,"@keyframes"))},this.toString=function(){return O(12,String(r.name))},this.name=e,this.id="sc-keyframes-"+e,this.rules=t}return e.prototype.getName=function(e){return void 0===e&&(e=ae),this.name+e.hash},e}(),le=/([A-Z])/,fe=/([A-Z])/g,pe=/^ms-/,de=function(e){return"-"+e.toLowerCase()};function he(e){return le.test(e)?e.replace(fe,de).replace(pe,"-ms-"):e}var me=function(e){return null==e||!1===e||""===e};function ge(e,t,r,n){if(Array.isArray(e)){for(var i,o=[],a=0,s=e.length;a1?t-1:0),n=1;n?@[\\\]^`{|}~-]+/g,we=/(^-|-$)/g;function _e(e){return e.replace(ve,"-").replace(we,"")}function Se(e){return"string"==typeof e&&!0}var xe=function(e){return"function"==typeof e||"object"==typeof e&&null!==e&&!Array.isArray(e)},ke=function(e){return"__proto__"!==e&&"constructor"!==e&&"prototype"!==e};function Ce(e,t,r){var n=e[r];xe(t)&&xe(n)?Oe(n,t):e[r]=t}function Oe(e){for(var t=arguments.length,r=new Array(t>1?t-1:0),n=1;n>>0)}("5.3.3"+r+je[r]);return t?t+"-"+n:n}(n.displayName,n.parentComponentId):u,p=n.displayName,d=void 0===p?function(e){return Se(e)?"styled."+e:"Styled("+_(e)+")"}(r):p,g=n.displayName&&n.componentId?_e(n.displayName)+"-"+n.componentId:n.componentId||l,y=o&&r.attrs?Array.prototype.concat(r.attrs,c).filter(Boolean):c,x=n.shouldForwardProp;o&&r.shouldForwardProp&&(x=n.shouldForwardProp?function(e,t,i){return r.shouldForwardProp(e,t,i)&&n.shouldForwardProp(e,t,i)}:r.shouldForwardProp);var k,C=new Z(i,g,o?r.componentStyle:void 0),O=C.isStatic&&0===c.length,A=function(t,r){return function(t,r,n,i){var o=t.attrs,a=t.componentStyle,s=t.defaultProps,c=t.foldedComponentIds,u=t.shouldForwardProp,l=t.styledComponentId,p=t.target,d=function(e,t,r){void 0===e&&(e=v);var n=m({},t,{theme:e}),i={};return r.forEach((function(e){var t,r,o,a=e;for(t in w(a)&&(a=a(n)),a)n[t]=i[t]="className"===t?(r=i[t],o=a[t],r&&o?r+" "+o:r||o):a[t]})),[n,i]}(function(e,t,r){return void 0===r&&(r=v),e.theme!==r.theme&&e.theme||t||r.theme}(r,(0,e.useContext)(Ae),s)||v,r,o),h=d[0],g=d[1],y=function(t,r,n,i){var o=se(),a=(0,e.useContext)(ie)||ae;return r?t.generateAndInjectStyles(v,o,a):t.generateAndInjectStyles(n,o,a)}(a,i,h),b=n,_=g.$as||r.$as||g.as||r.as||p,S=Se(_),x=g!==r?m({},r,{},g):r,k={};for(var C in x)"$"!==C[0]&&"as"!==C&&("forwardedAs"===C?k.as=x[C]:(u?u(C,f,_):!S||f(C))&&(k[C]=x[C]));return r.style&&g.style!==r.style&&(k.style=m({},r.style,{},g.style)),k.className=Array.prototype.concat(c,l,y!==l?y:null,r.className,g.className).filter(Boolean).join(" "),k.ref=b,(0,e.createElement)(_,k)}(k,t,r,O)};return A.displayName=d,(k=t().forwardRef(A)).attrs=y,k.componentStyle=C,k.displayName=d,k.shouldForwardProp=x,k.foldedComponentIds=o?Array.prototype.concat(r.foldedComponentIds,r.styledComponentId):b,k.styledComponentId=g,k.target=o?r.target:r,k.withComponent=function(e){var t=n.componentId,r=function(e,t){if(null==e)return{};var r,n,i={},o=Object.keys(e);for(n=0;n=0||(i[r]=e[r]);return i}(n,["componentId"]),o=t&&t+"-"+(Se(e)?e:_e(_(e)));return Ee(e,m({},r,{attrs:y,componentId:o}),i)},Object.defineProperty(k,"defaultProps",{get:function(){return this._foldedDefaultProps},set:function(e){this._foldedDefaultProps=o?Oe({},r.defaultProps,e):e}}),k.toString=function(){return"."+k.styledComponentId},a&&h()(k,r,{attrs:!0,componentStyle:!0,displayName:!0,foldedComponentIds:!0,shouldForwardProp:!0,styledComponentId:!0,target:!0,withComponent:!0}),k}var Pe,Ie=function(e){return function e(t,r,n){if(void 0===n&&(n=v),!(0,o.isValidElementType)(r))return O(1,String(r));var i=function(){return t(r,n,be.apply(void 0,arguments))};return i.withConfig=function(i){return e(t,r,m({},n,{},i))},i.attrs=function(i){return e(t,r,m({},n,{attrs:Array.prototype.concat(n.attrs,i).filter(Boolean)}))},i}(Ee,e)};["a","abbr","address","area","article","aside","audio","b","base","bdi","bdo","big","blockquote","body","br","button","canvas","caption","cite","code","col","colgroup","data","datalist","dd","del","details","dfn","dialog","div","dl","dt","em","embed","fieldset","figcaption","figure","footer","form","h1","h2","h3","h4","h5","h6","head","header","hgroup","hr","html","i","iframe","img","input","ins","kbd","keygen","label","legend","li","link","main","map","mark","marquee","menu","menuitem","meta","meter","nav","noscript","object","ol","optgroup","option","output","p","param","picture","pre","progress","q","rp","rt","ruby","s","samp","script","section","select","small","source","span","strong","style","sub","summary","sup","table","tbody","td","textarea","tfoot","th","thead","time","title","tr","track","u","ul","var","video","wbr","circle","clipPath","defs","ellipse","foreignObject","g","image","line","linearGradient","marker","mask","path","pattern","polygon","polyline","radialGradient","rect","stop","svg","text","textPath","tspan"].forEach((function(e){Ie[e]=Ie(e)})),Pe=function(e,t){this.rules=e,this.componentId=t,this.isStatic=J(e),H.registerId(this.componentId+1)}.prototype,Pe.createStyles=function(e,t,r,n){var i=n(ge(this.rules,t,r,n).join(""),""),o=this.componentId+e;r.insertRules(o,o,i)},Pe.removeStyles=function(e,t){t.clearRules(this.componentId+e)},Pe.renderStyles=function(e,t,r,n){e>2&&H.registerId(this.componentId+e),this.removeStyles(e,r),this.createStyles(e,t,r,n)},function(){var e=function(){var e=this;this._emitSheetCSS=function(){var t=e.instance.toString();if(!t)return"";var r=N();return""},this.getStyleTags=function(){return e.sealed?O(2):e._emitSheetCSS()},this.getStyleElement=function(){var r;if(e.sealed)return O(2);var n=((r={})[x]="",r["data-styled-version"]="5.3.3",r.dangerouslySetInnerHTML={__html:e.instance.toString()},r),i=N();return i&&(n.nonce=i),[t().createElement("style",m({},n,{key:"sc-0-0"}))]},this.seal=function(){e.sealed=!0},this.instance=new H({isServer:!0}),this.sealed=!1}.prototype;e.collectStyles=function(e){return this.sealed?O(2):t().createElement(ce,{sheet:this.instance},e)},e.interleaveWithNodeStream=function(e){return O(3)}}();const Re=Ie;var De=__webpack_require__(733);function $e(e,t){var r="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(!r){if(Array.isArray(e)||(r=function(e,t){if(e){if("string"==typeof e)return Te(e,t);var r=Object.prototype.toString.call(e).slice(8,-1);return"Object"===r&&e.constructor&&(r=e.constructor.name),"Map"===r||"Set"===r?Array.from(e):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?Te(e,t):void 0}}(e))||t&&e&&"number"==typeof e.length){r&&(e=r);var n=0,i=function(){};return{s:i,n:function(){return n>=e.length?{done:!0}:{done:!1,value:e[n++]}},e:function(e){function t(t){return e.apply(this,arguments)}return t.toString=function(){return e.toString()},t}((function(e){throw e})),f:i}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,a=!0,s=!1;return{s:function(){r=r.call(e)},n:function(){var e=r.next();return a=e.done,e},e:function(e){function t(t){return e.apply(this,arguments)}return t.toString=function(){return e.toString()},t}((function(e){s=!0,o=e})),f:function(){try{a||null==r.return||r.return()}finally{if(s)throw o}}}}function Te(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=new Array(t);r1&&void 0!==arguments[1]?arguments[1]:"contest.md",r=new Blob([e],{type:"text/plain"}),n=URL.createObjectURL(r),i=document.createElement("a");i.href=n,i.download=t,document.body.appendChild(i),i.click(),document.body.removeChild(i)}function Le(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:function(e){return e.length>0},r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:1e4,n=100;return new Promise((function(i,o){var a=setInterval((function(){var s=document.querySelectorAll(e);t(s)&&(clearInterval(a),i(s)),r<=0&&(clearInterval(a),o("超时")),r-=n}),n)}))}function Ne(e){var t,r,n=function(e){for(var t in e)if(Reflect.hasOwnProperty.call(e,t)&&/^__reactFiber\$/.test(t))return Reflect.get(e,t);return null}(null===(t=document.querySelectorAll('[data-row-key="'.concat(e,'"]')))||void 0===t?void 0:t[0]);n?(function(e,t){if(Array.isArray(e)||(e=[e]),!t)throw new Error("The lack of complete");for(var r=e.map((function(e){return{path:[e.name],node:e.node}})),n=0,i=new Set;n=e.length?{done:!0}:{done:!1,value:e[n++]}},e:function(e){throw e},f:i}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,a=!0,s=!1;return{s:function(){r=r.call(e)},n:function(){var e=r.next();return a=e.done,e},e:function(e){s=!0,o=e},f:function(){try{a||null==r.return||r.return()}finally{if(s)throw o}}}}function Fe(e,t,r,n,i,o,a){try{var s=e[o](a),c=s.value}catch(e){return void r(e)}s.done?t(c):Promise.resolve(c).then(n,i)}function He(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function We(e){for(var t=1;te.length)&&(t=e.length);for(var r=0,n=new Array(t);r>>0,"%"):"下载"})]})};var tt,rt,nt,it=__webpack_require__(559);function ot(e,t,r,n,i,o,a){try{var s=e[o](a),c=s.value}catch(e){return void r(e)}s.done?t(c):Promise.resolve(c).then(n,i)}function at(e){return function(){var t=this,r=arguments;return new Promise((function(n,i){var o=e.apply(t,r);function a(e){ot(o,n,i,a,s,"next",e)}function s(e){ot(o,n,i,a,s,"throw",e)}a(void 0)}))}}function st(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var r=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=r){var n,i,o=[],a=!0,s=!1;try{for(r=r.call(e);!(a=(n=r.next()).done)&&(o.push(n.value),!t||o.length!==t);a=!0);}catch(e){s=!0,i=e}finally{try{a||null==r.return||r.return()}finally{if(s)throw i}}return o}}(e,t)||function(e,t){if(e){if("string"==typeof e)return ct(e,t);var r=Object.prototype.toString.call(e).slice(8,-1);return"Object"===r&&e.constructor&&(r=e.constructor.name),"Map"===r||"Set"===r?Array.from(e):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?ct(e,t):void 0}}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function ct(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=new Array(t);re.length)&&(t=e.length);for(var r=0,n=new Array(t);r0&&void 0!==c[0]?c[0]:1,i=c.length>1&&void 0!==c[1]?c[1]:new Date,!(n>10)){e.next=4;break}throw new Error("获取 SubmissionId 失败");case 4:return e.next=6,(0,it._v)(500);case 6:return e.next=8,r.getSubmissions(t);case 8:if(o=e.sent,a=o.submissions,s=a.find((function(e){var t=e.timestamp;return"Pending"===e.isPending||new Date(1e3*(Number(t)+2))>=i}))){e.next=15;break}return e.abrupt("return",f(n+1,i));case 15:return e.abrupt("return",s.id);case 16:case"end":return e.stop()}}),e)}))),p.apply(this,arguments)}function d(e){return h.apply(this,arguments)}function h(){return h=ft(regeneratorRuntime.mark((function e(t){var n,i,o=arguments;return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:if(!((n=o.length>1&&void 0!==o[1]?o[1]:1)>10)){e.next=3;break}throw new Error("获取提交状态结果超时");case 3:return e.next=5,(0,it._v)(1e3+500*n);case 5:return e.next=7,r.check(t);case 7:if("SUCCESS"!==(i=e.sent).state){e.next=12;break}return e.abrupt("return",i);case 12:return e.next=14,d(t,n+1);case 14:return e.abrupt("return",e.sent);case 15:case"end":return e.stop()}}),e)}))),h.apply(this,arguments)}return(0,e.useEffect)((function(){var e=null;return ft(regeneratorRuntime.mark((function t(){var n,i;return regeneratorRuntime.wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return t.next=2,Le(".submit__-6u9");case 2:n=t.sent[0],i=function(){var e=ft(regeneratorRuntime.mark((function e(){var t;return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,f();case 2:return t=e.sent,e.next=5,d(t);case 5:"Accepted"===e.sent.status_msg&&(u(function(){var e=ft(regeneratorRuntime.mark((function e(n){return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,r.submissionCreateOrUpdateSubmissionComment(t,"RED",n.map((function(e){return e.toString().padStart(2,"0")})).join(" : "));case 2:return e.next=4,(0,it._v)(1e3);case 4:Ne(t);case 5:case"end":return e.stop()}}),e)})));return function(t){return e.apply(this,arguments)}}()),o(!1));case 7:case"end":return e.stop()}}),e)})));return function(){return e.apply(this,arguments)}}(),n.addEventListener("click",i),e=function(){n.removeEventListener("click",i)};case 6:case"end":return t.stop()}}),t)})))(),function(){e&&e()}}),[]),(0,Ge.jsxs)(mt,{children:[!i&&(0,Ge.jsx)(gt,{children:"".concat(c?"本次耗时: ":"").concat(s.map((function(e){return e.toString().padStart(2,"0")})).join(" : "))}),c?(0,Ge.jsx)(yt,{onClick:l,children:"重新开始"}):(0,Ge.jsx)(yt,{onClick:function(){o((function(e){return!e}))},style:i?{borderTopLeftRadius:3,borderBottomLeftRadius:3}:{},children:i?"显示计时":"隐藏"})]})};function vt(e,t,r,n,i,o,a){try{var s=e[o](a),c=s.value}catch(e){return void r(e)}s.done?t(c):Promise.resolve(c).then(n,i)}function wt(e){return function(){var t=this,r=arguments;return new Promise((function(n,i){var o=e.apply(t,r);function a(e){vt(o,n,i,a,s,"next",e)}function s(e){vt(o,n,i,a,s,"throw",e)}a(void 0)}))}}function _t(t){if(t&&t instanceof HTMLElement){t.style.display="flex",t.style.justifyContent="space-between";var n=document.createElement("div");t.append(n),(0,r.render)((0,Ge.jsx)(e.StrictMode,{children:(0,Ge.jsx)(et,{})}),n)}}i()(location.href,"https://leetcode-cn.com/submissions/detail/**")&&(window.onload=wt(regeneratorRuntime.mark((function e(){var t,r,n;return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,Le(".css-smuvek-Main");case 2:n=e.sent,_t(null===(t=n[0])||void 0===t||null===(r=t.children)||void 0===r?void 0:r[0]);case 4:case"end":return e.stop()}}),e)})))),i()(location.href,"https://leetcode.com/submissions/detail/**")&&(window.onload=wt(regeneratorRuntime.mark((function e(){return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,Le("#submission-app>.row>div:first-child");case 2:_t(e.sent[0]);case 4:case"end":return e.stop()}}),e)})))),i()(location.href,"https://leetcode-cn.com/problems/**")&&(window.onload=wt(regeneratorRuntime.mark((function t(){var n,i;return regeneratorRuntime.wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return t.next=2,Le(".container__Kjnx>.action__KaAP");case 2:(n=t.sent[0])&&n instanceof HTMLElement&&(i=document.createElement("div"),n.prepend(i),i.style.display="flex",i.style.alignItems="center",i.style.flexShrink="0",(0,r.render)((0,Ge.jsx)(e.StrictMode,{children:(0,Ge.jsx)(bt,{})}),i));case 4:case"end":return t.stop()}}),t)}))))})()})(); -//# sourceMappingURL=main.user.js.map \ No newline at end of file diff --git a/dist/main.user.js.LICENSE.txt b/dist/main.user.js.LICENSE.txt deleted file mode 100644 index 018b99b..0000000 --- a/dist/main.user.js.LICENSE.txt +++ /dev/null @@ -1,32 +0,0 @@ -/* -object-assign -(c) Sindre Sorhus -@license MIT -*/ - -/** @license React v16.13.1 - * react-is.production.min.js - * - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -/** @license React v17.0.2 - * react-is.production.min.js - * - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -/** @license React v17.0.2 - * react-jsx-runtime.production.min.js - * - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ diff --git a/dist/main.user.js.map b/dist/main.user.js.map deleted file mode 100644 index 54257cf..0000000 --- a/dist/main.user.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"main.user.js","mappings":"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","sources":["webpack://leetcode-extend/./src/leetcode-api/index.ts","webpack://leetcode-extend/./src/leetcode-api/utils.ts","webpack://leetcode-extend/./node_modules/.pnpm/balanced-match@1.0.2/node_modules/balanced-match/index.js","webpack://leetcode-extend/./node_modules/.pnpm/brace-expansion@1.1.11/node_modules/brace-expansion/index.js","webpack://leetcode-extend/./node_modules/.pnpm/concat-map@0.0.1/node_modules/concat-map/index.js","webpack://leetcode-extend/./node_modules/.pnpm/hoist-non-react-statics@3.3.2/node_modules/hoist-non-react-statics/dist/hoist-non-react-statics.cjs.js","webpack://leetcode-extend/./node_modules/.pnpm/minimatch@3.0.4/node_modules/minimatch/minimatch.js","webpack://leetcode-extend/./node_modules/.pnpm/object-assign@4.1.1/node_modules/object-assign/index.js","webpack://leetcode-extend/./node_modules/.pnpm/react-is@16.13.1/node_modules/react-is/cjs/react-is.production.min.js","webpack://leetcode-extend/./node_modules/.pnpm/react-is@16.13.1/node_modules/react-is/index.js","webpack://leetcode-extend/./node_modules/.pnpm/react-is@17.0.2/node_modules/react-is/cjs/react-is.production.min.js","webpack://leetcode-extend/./node_modules/.pnpm/react-is@17.0.2/node_modules/react-is/index.js","webpack://leetcode-extend/./node_modules/.pnpm/react@17.0.2/node_modules/react/cjs/react-jsx-runtime.production.min.js","webpack://leetcode-extend/./node_modules/.pnpm/react@17.0.2/node_modules/react/jsx-runtime.js","webpack://leetcode-extend/./node_modules/.pnpm/shallowequal@1.1.0/node_modules/shallowequal/index.js","webpack://leetcode-extend/external var \"React\"","webpack://leetcode-extend/webpack/bootstrap","webpack://leetcode-extend/webpack/runtime/compat get default export","webpack://leetcode-extend/webpack/runtime/define property getters","webpack://leetcode-extend/webpack/runtime/hasOwnProperty shorthand","webpack://leetcode-extend/external var \"ReactDOM\"","webpack://leetcode-extend/./node_modules/.pnpm/@emotion+stylis@0.8.5/node_modules/@emotion/stylis/dist/stylis.browser.esm.js","webpack://leetcode-extend/./node_modules/.pnpm/@emotion+unitless@0.7.5/node_modules/@emotion/unitless/dist/unitless.browser.esm.js","webpack://leetcode-extend/./node_modules/.pnpm/@emotion+is-prop-valid@0.8.8/node_modules/@emotion/is-prop-valid/dist/is-prop-valid.browser.esm.js","webpack://leetcode-extend/./node_modules/.pnpm/@emotion+memoize@0.7.4/node_modules/@emotion/memoize/dist/memoize.browser.esm.js","webpack://leetcode-extend/./node_modules/.pnpm/styled-components@5.3.3_281a4fa50a045c9112baf635f3bc27a7/node_modules/styled-components/dist/styled-components.browser.esm.js","webpack://leetcode-extend/./src/utils.ts","webpack://leetcode-extend/./src/page/submissions-detail/Download.tsx","webpack://leetcode-extend/./src/page/problems/useTimer.ts","webpack://leetcode-extend/./src/page/problems/Clock.tsx","webpack://leetcode-extend/./src/index.tsx"],"sourcesContent":["import { baseApi, globalGetStatusText, graphqlApi } from './utils'\n\ninterface GlobalSubmissionDetail {\n submissionData: {\n status_code: number\n runtime: string\n memory: string\n total_correct: string\n total_testcases: string\n compare_result: string\n input_formatted: string\n input: string\n expected_output: string\n code_output: string\n last_testcase: string\n }\n questionId: string\n submissionId: string\n sessionId: string\n getLangDisplay: string\n submissionCode: string\n editCodeUrl: string\n checkUrl: string\n runtimeDistributionFormatted: string\n memoryDistributionFormatted: string\n langs: []\n runtime: string\n memory: string\n enableMemoryDistribution: string\n nonSufficientMsg: string\n}\n\nexport type SuccessCheckReturnType = {\n status_code: number\n lang: string\n run_success: boolean\n status_runtime: string\n memory: number\n question_id: string\n elapsed_time: number\n compare_result: string\n code_output: string\n std_output: string\n last_testcase: string\n expected_output: string\n task_finish_time: number\n task_name: string\n finished: boolean\n state: 'SUCCESS'\n fast_submit: boolean\n total_correct: number\n total_testcases: number\n submission_id: string\n status_memory: string\n memory_percentile: number\n pretty_lang: string\n} & (\n | {\n status_msg: 'Accepted'\n runtime_percentile: number\n memory_percentile: number\n }\n | {\n status_msg: 'Wrong Answer'\n runtime_percentile: null\n memory_percentile: null\n input_formatted: string\n input: string\n }\n)\n\ntype CheckReturnType =\n | { state: 'STARTED' }\n | { state: 'PENDING' }\n | SuccessCheckReturnType\n\nclass LeetCodeApi {\n public graphqlApi: (\n { method, body }: { method?: string; body?: unknown },\n retry?: number\n ) => Promise\n public baseApi: (\n url: string,\n method?: string | undefined,\n body?: object | null | undefined,\n retry?: number | undefined\n ) => Promise\n public REGION_URL: string\n\n public constructor(REGION_URL: string) {\n this.REGION_URL = REGION_URL\n this.graphqlApi = graphqlApi.bind(null, REGION_URL)\n this.baseApi = baseApi.bind(null, REGION_URL)\n }\n\n public async getAllQuestions(): Promise<\n {\n translatedTitle: string\n title: string\n questionFrontendId: string\n titleSlug: string\n questionId: string\n categoryTitle: string\n isPaidOnly: boolean\n status: string\n difficulty: string\n __typename: string\n }[]\n > {\n const cache = localStorage.getItem('lc-extend:allQuestions')\n if (cache) {\n try {\n const res = JSON.parse(cache)\n return res\n } catch (error) {\n console.log('解析缓存失败')\n }\n }\n const body = {\n operationName: 'allQuestions',\n variables: {},\n query: /* GraphQL */ `\n query allQuestions {\n allQuestions {\n title\n titleSlug\n translatedTitle\n questionId\n questionFrontendId\n status\n difficulty\n isPaidOnly\n categoryTitle\n __typename\n }\n }\n `,\n }\n\n return this.graphqlApi({ body }).then(data => {\n const res = data?.data?.allQuestions\n if (res) {\n localStorage.setItem('lc-extend:allQuestions', JSON.stringify(res))\n return res\n }\n throw new Error('获取题目列表失败,返回结果为: ' + JSON.stringify(data))\n })\n }\n\n public async getSubmissions(\n questionSlug: string,\n limit = 40,\n offset = 0\n ): Promise<{\n lastKey: string\n hasNext: boolean\n submissions: {\n id: string\n statusDisplay: string\n lang: string\n runtime: string\n timestamp: string\n url: string\n isPending: string\n memory: string\n submissionComment: {\n comment: string\n flagType: string\n __typename: string\n }\n __typename: string\n }[]\n __typename: string\n }> {\n const body = {\n operationName: 'submissions',\n variables: {\n offset,\n limit,\n lastKey: null,\n questionSlug,\n },\n query: /* GraphQL */ `\n query submissions(\n $offset: Int!\n $limit: Int!\n $lastKey: String\n $questionSlug: String!\n ) {\n submissionList(\n offset: $offset\n limit: $limit\n lastKey: $lastKey\n questionSlug: $questionSlug\n ) {\n lastKey\n hasNext\n submissions {\n id\n statusDisplay\n lang\n runtime\n timestamp\n url\n isPending\n memory\n __typename\n }\n __typename\n }\n }\n `,\n }\n return this.graphqlApi({ body }).then(({ data }) => data.submissionList)\n }\n\n private async getSubmissionDetailByLocal(submissionId: string): Promise<{\n id: string\n code: string\n runtime: string\n memory: string\n rawMemory: string\n statusDisplay: string\n timestamp: number\n lang: string\n passedTestCaseCnt: number\n totalTestCaseCnt: number\n sourceUrl: string\n question: {\n titleSlug: string\n title: string\n translatedTitle: string\n questionId: string\n __typename: string\n }\n outputDetail: {\n codeOutput: string\n expectedOutput: string\n input: string\n compileError: string\n runtimeError: string\n lastTestcase: string\n __typename: string\n }\n __typename: string\n submissionComment: null\n }> {\n const body = {\n operationName: 'mySubmissionDetail',\n variables: { id: submissionId },\n query: /* GraphQL */ `\n query mySubmissionDetail($id: ID!) {\n submissionDetail(submissionId: $id) {\n id\n code\n runtime\n memory\n rawMemory\n statusDisplay\n timestamp\n lang\n passedTestCaseCnt\n totalTestCaseCnt\n sourceUrl\n question {\n titleSlug\n title\n translatedTitle\n questionId\n __typename\n }\n ... on GeneralSubmissionNode {\n outputDetail {\n codeOutput\n expectedOutput\n input\n compileError\n runtimeError\n lastTestcase\n __typename\n }\n __typename\n }\n submissionComment {\n comment\n flagType\n __typename\n }\n __typename\n }\n }\n `,\n }\n\n return this.graphqlApi({ body }).then(({ data }) => data.submissionDetail)\n }\n private async getDistributionLocal(submissionId: string): Promise<{\n runtimeDistribution: {\n lang: string\n distribution: [string, number][]\n } | null\n memoryDistribution: {\n lang: string\n distribution: [string, number][]\n } | null\n }> {\n const runtimeApi = `/submissions/api/runtime_distribution/${submissionId}/`\n const runtimeDistribution = await this.baseApi(runtimeApi).then(\n ({ runtime_distribution_formatted }) =>\n runtime_distribution_formatted\n ? JSON.parse(runtime_distribution_formatted)\n : null\n )\n const memoryApi = `/submissions/api/memory_distribution/${submissionId}/`\n const memoryDistribution = await this.baseApi(memoryApi).then(\n ({ memory_distribution_formatted }) =>\n memory_distribution_formatted\n ? JSON.parse(memory_distribution_formatted)\n : null\n )\n\n return { runtimeDistribution, memoryDistribution }\n }\n\n private async getSubmissionDetailByGlobal(\n submissionId: string\n ): Promise {\n const text = await fetch(\n `https://leetcode.com/submissions/detail/${submissionId}/`,\n {\n headers: {\n accept:\n 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',\n },\n referrer: 'https://leetcode.com/',\n referrerPolicy: 'strict-origin-when-cross-origin',\n body: null,\n method: 'GET',\n mode: 'cors',\n credentials: 'include',\n }\n ).then(res => res.text())\n\n const dataText = text.match(/var pageData = ([\\d\\D]+?});/)?.[1]\n\n const data = eval(`(function (){return ${dataText}})()`)\n\n return data\n }\n\n public async getSubmissionDetail(submissionId: string): Promise<{\n id: string // submissionId\n code: string // submissionCode\n runtime: string // runtime\n memory: string // submissionData.memory\n rawMemory: string // memory\n statusDisplay: string // status_code\n // timestamp: string\n lang: string // getLangDisplay\n passedTestCaseCnt: number // submissionData.total_correct\n totalTestCaseCnt: number // submissionData.total_testcases\n sourceUrl: string // editCodeUrl\n questionId: string\n runtimeDistribution?: { lang: string; distribution: [string, number][] }\n memoryDistribution?: { lang: string; distribution: [string, number][] }\n }> {\n if (/leetcode-cn\\.com/.test(this.REGION_URL)) {\n const data = await this.getSubmissionDetailByLocal(submissionId)\n const { runtimeDistribution, memoryDistribution } =\n await this.getDistributionLocal(submissionId)\n return {\n ...data,\n questionId: data.question.questionId,\n runtimeDistribution: runtimeDistribution\n ? runtimeDistribution\n : { lang: data.lang, distribution: [] },\n memoryDistribution: memoryDistribution\n ? memoryDistribution\n : {\n lang: data.lang,\n distribution: [],\n },\n }\n } else {\n const data = await this.getSubmissionDetailByGlobal(submissionId)\n return {\n id: data.submissionId,\n code: data.submissionCode,\n runtime: data.runtime,\n memory: data.submissionData.memory,\n rawMemory: data.memory,\n statusDisplay: globalGetStatusText(data.submissionData.status_code),\n lang: data.getLangDisplay,\n passedTestCaseCnt: Number(data.submissionData.total_correct),\n totalTestCaseCnt: Number(data.submissionData.total_testcases),\n sourceUrl: data.editCodeUrl,\n questionId: data.questionId,\n runtimeDistribution: JSON.parse(data.runtimeDistributionFormatted),\n memoryDistribution: JSON.parse(data.memoryDistributionFormatted),\n }\n }\n }\n\n public getCodeByTime(\n lang: string,\n questionId: string,\n time: string\n ): Promise {\n const api = `/submissions/api/detail/${questionId}/${lang}/${time}/`\n\n return this.baseApi(api).then(data => data.code)\n }\n\n public getCodeByMemory(\n lang: string,\n questionId: string,\n memory: string\n ): Promise {\n const api = `/submissions/api/detail/${questionId}/${lang}/memory/${memory}/`\n\n return this.baseApi(api).then(data => data.code)\n }\n\n public check(submissionId: string): Promise {\n const api = `/submissions/detail/${submissionId}/check/`\n return this.baseApi(api)\n }\n\n public submissionCreateOrUpdateSubmissionComment(\n submissionId: string,\n flagType: 'BLUE' | 'ORANGE' | 'GREEN' | 'PURPLE' | 'RED',\n comment: string\n ): Promise<{ ok: boolean; __typename: string }> {\n const body = {\n operationName: 'submissionCreateOrUpdateSubmissionComment',\n variables: {\n submissionId: submissionId,\n flagType: flagType,\n comment: comment,\n },\n query: /* GraphQL */ `\n mutation submissionCreateOrUpdateSubmissionComment(\n $submissionId: ID!\n $flagType: SubmissionFlagTypeEnum!\n $comment: String!\n ) {\n submissionCreateOrUpdateSubmissionComment(\n comment: $comment\n flagType: $flagType\n submissionId: $submissionId\n ) {\n ok\n __typename\n }\n }\n `,\n }\n\n return this.graphqlApi({ body }).then(\n ({ data }) => data.submissionCreateOrUpdateSubmissionComment\n )\n }\n}\n\nexport { LeetCodeApi }\n","/**\n * 延时函数\n *\n * @param time 时间\n * @returns\n */\nfunction sleep(time: number): Promise {\n return new Promise(function (resolve) {\n setTimeout(resolve, time)\n })\n}\n\nfunction graphqlApi(\n REGION_URL: string,\n { method, body }: { method?: string; body?: unknown },\n retry = 1\n): Promise {\n method = method || 'POST'\n const RETRY_TIME = 3000,\n RETRY_COUNT = 5\n return fetch(`${REGION_URL}/graphql/`, {\n headers: {\n 'content-type': 'application/json',\n },\n referrer: `${REGION_URL}/`,\n referrerPolicy: 'strict-origin-when-cross-origin',\n body: JSON.stringify(body),\n method,\n mode: 'cors',\n credentials: 'include',\n }).then(res => {\n if (res.status === 200) {\n return res.json()\n }\n\n if (res.status === 429) {\n console.log(`超出接口限制,休息一下,等待第${retry}次重试...`)\n if (retry > RETRY_COUNT) {\n throw new Error(\n `已重试 ${RETRY_COUNT} 次,仍然无法获取,可能力扣君生气了,晚点在试试吧...`\n )\n }\n // 触发限制之后,等一会儿在进行请求\n return sleep(RETRY_TIME).then(() =>\n graphqlApi(REGION_URL, { method, body }, retry + 1)\n )\n }\n\n throw new Error(`未知状态: ${res.status}`)\n })\n}\n\nfunction isObject(obj: any): obj is object {\n return typeof obj === 'object' && obj !== null\n}\n\nfunction baseApi(\n REGION_URL: string,\n url: string,\n method = 'GET',\n body: null | object = null,\n retry = 1\n): Promise {\n const RETRY_TIME = 20000,\n RETRY_COUNT = 10\n\n method = method.toUpperCase()\n let bodyStr: null | string\n\n if (method === 'GET') {\n bodyStr = null\n } else {\n bodyStr = isObject(body) ? JSON.stringify(body) : body\n }\n\n return fetch(REGION_URL + url, {\n headers: {\n accept: 'application/json, text/plain, */*',\n },\n referrer: `REGION_URL`,\n referrerPolicy: 'strict-origin-when-cross-origin',\n body: bodyStr,\n method,\n mode: 'cors',\n credentials: 'include',\n }).then(res => {\n if (res.status === 200) {\n return res.json()\n }\n\n if (res.status === 429) {\n console.log(`超出接口限制,休息一下,等待第${retry}次重试...`)\n if (retry > RETRY_COUNT) {\n throw new Error(\n `已重试 ${RETRY_COUNT} 次,仍然无法获取,可能力扣君生气了,晚点在试试吧...`\n )\n }\n // 触发限制之后,等一会儿在进行请求\n return sleep(RETRY_TIME).then(() =>\n baseApi(REGION_URL, url, method, body, retry + 1)\n )\n }\n\n throw new Error(`未知状态: ${res.status}`)\n })\n}\n\nfunction globalGetStatusText(e: number): string {\n switch (e) {\n case 10:\n return 'Accepted'\n case 11:\n return 'Wrong Answer'\n case 12:\n return 'Memory Limit Exceeded'\n case 13:\n return 'Output Limit Exceeded'\n case 14:\n return 'Time Limit Exceeded'\n case 15:\n return 'Runtime Error'\n case 16:\n return 'Internal Error'\n case 20:\n return 'Compile Error'\n case 21:\n return 'Unknown Error'\n case 30:\n return 'Timeout'\n default:\n return 'Invalid Error Code'\n }\n}\n\nexport { sleep, graphqlApi, baseApi, globalGetStatusText }\n","'use strict';\nmodule.exports = balanced;\nfunction balanced(a, b, str) {\n if (a instanceof RegExp) a = maybeMatch(a, str);\n if (b instanceof RegExp) b = maybeMatch(b, str);\n\n var r = range(a, b, str);\n\n return r && {\n start: r[0],\n end: r[1],\n pre: str.slice(0, r[0]),\n body: str.slice(r[0] + a.length, r[1]),\n post: str.slice(r[1] + b.length)\n };\n}\n\nfunction maybeMatch(reg, str) {\n var m = str.match(reg);\n return m ? m[0] : null;\n}\n\nbalanced.range = range;\nfunction range(a, b, str) {\n var begs, beg, left, right, result;\n var ai = str.indexOf(a);\n var bi = str.indexOf(b, ai + 1);\n var i = ai;\n\n if (ai >= 0 && bi > 0) {\n if(a===b) {\n return [ai, bi];\n }\n begs = [];\n left = str.length;\n\n while (i >= 0 && !result) {\n if (i == ai) {\n begs.push(i);\n ai = str.indexOf(a, i + 1);\n } else if (begs.length == 1) {\n result = [ begs.pop(), bi ];\n } else {\n beg = begs.pop();\n if (beg < left) {\n left = beg;\n right = bi;\n }\n\n bi = str.indexOf(b, i + 1);\n }\n\n i = ai < bi && ai >= 0 ? ai : bi;\n }\n\n if (begs.length) {\n result = [ left, right ];\n }\n }\n\n return result;\n}\n","var concatMap = require('concat-map');\nvar balanced = require('balanced-match');\n\nmodule.exports = expandTop;\n\nvar escSlash = '\\0SLASH'+Math.random()+'\\0';\nvar escOpen = '\\0OPEN'+Math.random()+'\\0';\nvar escClose = '\\0CLOSE'+Math.random()+'\\0';\nvar escComma = '\\0COMMA'+Math.random()+'\\0';\nvar escPeriod = '\\0PERIOD'+Math.random()+'\\0';\n\nfunction numeric(str) {\n return parseInt(str, 10) == str\n ? parseInt(str, 10)\n : str.charCodeAt(0);\n}\n\nfunction escapeBraces(str) {\n return str.split('\\\\\\\\').join(escSlash)\n .split('\\\\{').join(escOpen)\n .split('\\\\}').join(escClose)\n .split('\\\\,').join(escComma)\n .split('\\\\.').join(escPeriod);\n}\n\nfunction unescapeBraces(str) {\n return str.split(escSlash).join('\\\\')\n .split(escOpen).join('{')\n .split(escClose).join('}')\n .split(escComma).join(',')\n .split(escPeriod).join('.');\n}\n\n\n// Basically just str.split(\",\"), but handling cases\n// where we have nested braced sections, which should be\n// treated as individual members, like {a,{b,c},d}\nfunction parseCommaParts(str) {\n if (!str)\n return [''];\n\n var parts = [];\n var m = balanced('{', '}', str);\n\n if (!m)\n return str.split(',');\n\n var pre = m.pre;\n var body = m.body;\n var post = m.post;\n var p = pre.split(',');\n\n p[p.length-1] += '{' + body + '}';\n var postParts = parseCommaParts(post);\n if (post.length) {\n p[p.length-1] += postParts.shift();\n p.push.apply(p, postParts);\n }\n\n parts.push.apply(parts, p);\n\n return parts;\n}\n\nfunction expandTop(str) {\n if (!str)\n return [];\n\n // I don't know why Bash 4.3 does this, but it does.\n // Anything starting with {} will have the first two bytes preserved\n // but *only* at the top level, so {},a}b will not expand to anything,\n // but a{},b}c will be expanded to [a}c,abc].\n // One could argue that this is a bug in Bash, but since the goal of\n // this module is to match Bash's rules, we escape a leading {}\n if (str.substr(0, 2) === '{}') {\n str = '\\\\{\\\\}' + str.substr(2);\n }\n\n return expand(escapeBraces(str), true).map(unescapeBraces);\n}\n\nfunction identity(e) {\n return e;\n}\n\nfunction embrace(str) {\n return '{' + str + '}';\n}\nfunction isPadded(el) {\n return /^-?0\\d/.test(el);\n}\n\nfunction lte(i, y) {\n return i <= y;\n}\nfunction gte(i, y) {\n return i >= y;\n}\n\nfunction expand(str, isTop) {\n var expansions = [];\n\n var m = balanced('{', '}', str);\n if (!m || /\\$$/.test(m.pre)) return [str];\n\n var isNumericSequence = /^-?\\d+\\.\\.-?\\d+(?:\\.\\.-?\\d+)?$/.test(m.body);\n var isAlphaSequence = /^[a-zA-Z]\\.\\.[a-zA-Z](?:\\.\\.-?\\d+)?$/.test(m.body);\n var isSequence = isNumericSequence || isAlphaSequence;\n var isOptions = m.body.indexOf(',') >= 0;\n if (!isSequence && !isOptions) {\n // {a},b}\n if (m.post.match(/,.*\\}/)) {\n str = m.pre + '{' + m.body + escClose + m.post;\n return expand(str);\n }\n return [str];\n }\n\n var n;\n if (isSequence) {\n n = m.body.split(/\\.\\./);\n } else {\n n = parseCommaParts(m.body);\n if (n.length === 1) {\n // x{{a,b}}y ==> x{a}y x{b}y\n n = expand(n[0], false).map(embrace);\n if (n.length === 1) {\n var post = m.post.length\n ? expand(m.post, false)\n : [''];\n return post.map(function(p) {\n return m.pre + n[0] + p;\n });\n }\n }\n }\n\n // at this point, n is the parts, and we know it's not a comma set\n // with a single entry.\n\n // no need to expand pre, since it is guaranteed to be free of brace-sets\n var pre = m.pre;\n var post = m.post.length\n ? expand(m.post, false)\n : [''];\n\n var N;\n\n if (isSequence) {\n var x = numeric(n[0]);\n var y = numeric(n[1]);\n var width = Math.max(n[0].length, n[1].length)\n var incr = n.length == 3\n ? Math.abs(numeric(n[2]))\n : 1;\n var test = lte;\n var reverse = y < x;\n if (reverse) {\n incr *= -1;\n test = gte;\n }\n var pad = n.some(isPadded);\n\n N = [];\n\n for (var i = x; test(i, y); i += incr) {\n var c;\n if (isAlphaSequence) {\n c = String.fromCharCode(i);\n if (c === '\\\\')\n c = '';\n } else {\n c = String(i);\n if (pad) {\n var need = width - c.length;\n if (need > 0) {\n var z = new Array(need + 1).join('0');\n if (i < 0)\n c = '-' + z + c.slice(1);\n else\n c = z + c;\n }\n }\n }\n N.push(c);\n }\n } else {\n N = concatMap(n, function(el) { return expand(el, false) });\n }\n\n for (var j = 0; j < N.length; j++) {\n for (var k = 0; k < post.length; k++) {\n var expansion = pre + N[j] + post[k];\n if (!isTop || isSequence || expansion)\n expansions.push(expansion);\n }\n }\n\n return expansions;\n}\n\n","module.exports = function (xs, fn) {\n var res = [];\n for (var i = 0; i < xs.length; i++) {\n var x = fn(xs[i], i);\n if (isArray(x)) res.push.apply(res, x);\n else res.push(x);\n }\n return res;\n};\n\nvar isArray = Array.isArray || function (xs) {\n return Object.prototype.toString.call(xs) === '[object Array]';\n};\n","'use strict';\n\nvar reactIs = require('react-is');\n\n/**\n * Copyright 2015, Yahoo! Inc.\n * Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.\n */\nvar REACT_STATICS = {\n childContextTypes: true,\n contextType: true,\n contextTypes: true,\n defaultProps: true,\n displayName: true,\n getDefaultProps: true,\n getDerivedStateFromError: true,\n getDerivedStateFromProps: true,\n mixins: true,\n propTypes: true,\n type: true\n};\nvar KNOWN_STATICS = {\n name: true,\n length: true,\n prototype: true,\n caller: true,\n callee: true,\n arguments: true,\n arity: true\n};\nvar FORWARD_REF_STATICS = {\n '$$typeof': true,\n render: true,\n defaultProps: true,\n displayName: true,\n propTypes: true\n};\nvar MEMO_STATICS = {\n '$$typeof': true,\n compare: true,\n defaultProps: true,\n displayName: true,\n propTypes: true,\n type: true\n};\nvar TYPE_STATICS = {};\nTYPE_STATICS[reactIs.ForwardRef] = FORWARD_REF_STATICS;\nTYPE_STATICS[reactIs.Memo] = MEMO_STATICS;\n\nfunction getStatics(component) {\n // React v16.11 and below\n if (reactIs.isMemo(component)) {\n return MEMO_STATICS;\n } // React v16.12 and above\n\n\n return TYPE_STATICS[component['$$typeof']] || REACT_STATICS;\n}\n\nvar defineProperty = Object.defineProperty;\nvar getOwnPropertyNames = Object.getOwnPropertyNames;\nvar getOwnPropertySymbols = Object.getOwnPropertySymbols;\nvar getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\nvar getPrototypeOf = Object.getPrototypeOf;\nvar objectPrototype = Object.prototype;\nfunction hoistNonReactStatics(targetComponent, sourceComponent, blacklist) {\n if (typeof sourceComponent !== 'string') {\n // don't hoist over string (html) components\n if (objectPrototype) {\n var inheritedComponent = getPrototypeOf(sourceComponent);\n\n if (inheritedComponent && inheritedComponent !== objectPrototype) {\n hoistNonReactStatics(targetComponent, inheritedComponent, blacklist);\n }\n }\n\n var keys = getOwnPropertyNames(sourceComponent);\n\n if (getOwnPropertySymbols) {\n keys = keys.concat(getOwnPropertySymbols(sourceComponent));\n }\n\n var targetStatics = getStatics(targetComponent);\n var sourceStatics = getStatics(sourceComponent);\n\n for (var i = 0; i < keys.length; ++i) {\n var key = keys[i];\n\n if (!KNOWN_STATICS[key] && !(blacklist && blacklist[key]) && !(sourceStatics && sourceStatics[key]) && !(targetStatics && targetStatics[key])) {\n var descriptor = getOwnPropertyDescriptor(sourceComponent, key);\n\n try {\n // Avoid failures from read-only properties\n defineProperty(targetComponent, key, descriptor);\n } catch (e) {}\n }\n }\n }\n\n return targetComponent;\n}\n\nmodule.exports = hoistNonReactStatics;\n","module.exports = minimatch\nminimatch.Minimatch = Minimatch\n\nvar path = { sep: '/' }\ntry {\n path = require('path')\n} catch (er) {}\n\nvar GLOBSTAR = minimatch.GLOBSTAR = Minimatch.GLOBSTAR = {}\nvar expand = require('brace-expansion')\n\nvar plTypes = {\n '!': { open: '(?:(?!(?:', close: '))[^/]*?)'},\n '?': { open: '(?:', close: ')?' },\n '+': { open: '(?:', close: ')+' },\n '*': { open: '(?:', close: ')*' },\n '@': { open: '(?:', close: ')' }\n}\n\n// any single thing other than /\n// don't need to escape / when using new RegExp()\nvar qmark = '[^/]'\n\n// * => any number of characters\nvar star = qmark + '*?'\n\n// ** when dots are allowed. Anything goes, except .. and .\n// not (^ or / followed by one or two dots followed by $ or /),\n// followed by anything, any number of times.\nvar twoStarDot = '(?:(?!(?:\\\\\\/|^)(?:\\\\.{1,2})($|\\\\\\/)).)*?'\n\n// not a ^ or / followed by a dot,\n// followed by anything, any number of times.\nvar twoStarNoDot = '(?:(?!(?:\\\\\\/|^)\\\\.).)*?'\n\n// characters that need to be escaped in RegExp.\nvar reSpecials = charSet('().*{}+?[]^$\\\\!')\n\n// \"abc\" -> { a:true, b:true, c:true }\nfunction charSet (s) {\n return s.split('').reduce(function (set, c) {\n set[c] = true\n return set\n }, {})\n}\n\n// normalizes slashes.\nvar slashSplit = /\\/+/\n\nminimatch.filter = filter\nfunction filter (pattern, options) {\n options = options || {}\n return function (p, i, list) {\n return minimatch(p, pattern, options)\n }\n}\n\nfunction ext (a, b) {\n a = a || {}\n b = b || {}\n var t = {}\n Object.keys(b).forEach(function (k) {\n t[k] = b[k]\n })\n Object.keys(a).forEach(function (k) {\n t[k] = a[k]\n })\n return t\n}\n\nminimatch.defaults = function (def) {\n if (!def || !Object.keys(def).length) return minimatch\n\n var orig = minimatch\n\n var m = function minimatch (p, pattern, options) {\n return orig.minimatch(p, pattern, ext(def, options))\n }\n\n m.Minimatch = function Minimatch (pattern, options) {\n return new orig.Minimatch(pattern, ext(def, options))\n }\n\n return m\n}\n\nMinimatch.defaults = function (def) {\n if (!def || !Object.keys(def).length) return Minimatch\n return minimatch.defaults(def).Minimatch\n}\n\nfunction minimatch (p, pattern, options) {\n if (typeof pattern !== 'string') {\n throw new TypeError('glob pattern string required')\n }\n\n if (!options) options = {}\n\n // shortcut: comments match nothing.\n if (!options.nocomment && pattern.charAt(0) === '#') {\n return false\n }\n\n // \"\" only matches \"\"\n if (pattern.trim() === '') return p === ''\n\n return new Minimatch(pattern, options).match(p)\n}\n\nfunction Minimatch (pattern, options) {\n if (!(this instanceof Minimatch)) {\n return new Minimatch(pattern, options)\n }\n\n if (typeof pattern !== 'string') {\n throw new TypeError('glob pattern string required')\n }\n\n if (!options) options = {}\n pattern = pattern.trim()\n\n // windows support: need to use /, not \\\n if (path.sep !== '/') {\n pattern = pattern.split(path.sep).join('/')\n }\n\n this.options = options\n this.set = []\n this.pattern = pattern\n this.regexp = null\n this.negate = false\n this.comment = false\n this.empty = false\n\n // make the set of regexps etc.\n this.make()\n}\n\nMinimatch.prototype.debug = function () {}\n\nMinimatch.prototype.make = make\nfunction make () {\n // don't do it more than once.\n if (this._made) return\n\n var pattern = this.pattern\n var options = this.options\n\n // empty patterns and comments match nothing.\n if (!options.nocomment && pattern.charAt(0) === '#') {\n this.comment = true\n return\n }\n if (!pattern) {\n this.empty = true\n return\n }\n\n // step 1: figure out negation, etc.\n this.parseNegate()\n\n // step 2: expand braces\n var set = this.globSet = this.braceExpand()\n\n if (options.debug) this.debug = console.error\n\n this.debug(this.pattern, set)\n\n // step 3: now we have a set, so turn each one into a series of path-portion\n // matching patterns.\n // These will be regexps, except in the case of \"**\", which is\n // set to the GLOBSTAR object for globstar behavior,\n // and will not contain any / characters\n set = this.globParts = set.map(function (s) {\n return s.split(slashSplit)\n })\n\n this.debug(this.pattern, set)\n\n // glob --> regexps\n set = set.map(function (s, si, set) {\n return s.map(this.parse, this)\n }, this)\n\n this.debug(this.pattern, set)\n\n // filter out everything that didn't compile properly.\n set = set.filter(function (s) {\n return s.indexOf(false) === -1\n })\n\n this.debug(this.pattern, set)\n\n this.set = set\n}\n\nMinimatch.prototype.parseNegate = parseNegate\nfunction parseNegate () {\n var pattern = this.pattern\n var negate = false\n var options = this.options\n var negateOffset = 0\n\n if (options.nonegate) return\n\n for (var i = 0, l = pattern.length\n ; i < l && pattern.charAt(i) === '!'\n ; i++) {\n negate = !negate\n negateOffset++\n }\n\n if (negateOffset) this.pattern = pattern.substr(negateOffset)\n this.negate = negate\n}\n\n// Brace expansion:\n// a{b,c}d -> abd acd\n// a{b,}c -> abc ac\n// a{0..3}d -> a0d a1d a2d a3d\n// a{b,c{d,e}f}g -> abg acdfg acefg\n// a{b,c}d{e,f}g -> abdeg acdeg abdeg abdfg\n//\n// Invalid sets are not expanded.\n// a{2..}b -> a{2..}b\n// a{b}c -> a{b}c\nminimatch.braceExpand = function (pattern, options) {\n return braceExpand(pattern, options)\n}\n\nMinimatch.prototype.braceExpand = braceExpand\n\nfunction braceExpand (pattern, options) {\n if (!options) {\n if (this instanceof Minimatch) {\n options = this.options\n } else {\n options = {}\n }\n }\n\n pattern = typeof pattern === 'undefined'\n ? this.pattern : pattern\n\n if (typeof pattern === 'undefined') {\n throw new TypeError('undefined pattern')\n }\n\n if (options.nobrace ||\n !pattern.match(/\\{.*\\}/)) {\n // shortcut. no need to expand.\n return [pattern]\n }\n\n return expand(pattern)\n}\n\n// parse a component of the expanded set.\n// At this point, no pattern may contain \"/\" in it\n// so we're going to return a 2d array, where each entry is the full\n// pattern, split on '/', and then turned into a regular expression.\n// A regexp is made at the end which joins each array with an\n// escaped /, and another full one which joins each regexp with |.\n//\n// Following the lead of Bash 4.1, note that \"**\" only has special meaning\n// when it is the *only* thing in a path portion. Otherwise, any series\n// of * is equivalent to a single *. Globstar behavior is enabled by\n// default, and can be disabled by setting options.noglobstar.\nMinimatch.prototype.parse = parse\nvar SUBPARSE = {}\nfunction parse (pattern, isSub) {\n if (pattern.length > 1024 * 64) {\n throw new TypeError('pattern is too long')\n }\n\n var options = this.options\n\n // shortcuts\n if (!options.noglobstar && pattern === '**') return GLOBSTAR\n if (pattern === '') return ''\n\n var re = ''\n var hasMagic = !!options.nocase\n var escaping = false\n // ? => one single character\n var patternListStack = []\n var negativeLists = []\n var stateChar\n var inClass = false\n var reClassStart = -1\n var classStart = -1\n // . and .. never match anything that doesn't start with .,\n // even when options.dot is set.\n var patternStart = pattern.charAt(0) === '.' ? '' // anything\n // not (start or / followed by . or .. followed by / or end)\n : options.dot ? '(?!(?:^|\\\\\\/)\\\\.{1,2}(?:$|\\\\\\/))'\n : '(?!\\\\.)'\n var self = this\n\n function clearStateChar () {\n if (stateChar) {\n // we had some state-tracking character\n // that wasn't consumed by this pass.\n switch (stateChar) {\n case '*':\n re += star\n hasMagic = true\n break\n case '?':\n re += qmark\n hasMagic = true\n break\n default:\n re += '\\\\' + stateChar\n break\n }\n self.debug('clearStateChar %j %j', stateChar, re)\n stateChar = false\n }\n }\n\n for (var i = 0, len = pattern.length, c\n ; (i < len) && (c = pattern.charAt(i))\n ; i++) {\n this.debug('%s\\t%s %s %j', pattern, i, re, c)\n\n // skip over any that are escaped.\n if (escaping && reSpecials[c]) {\n re += '\\\\' + c\n escaping = false\n continue\n }\n\n switch (c) {\n case '/':\n // completely not allowed, even escaped.\n // Should already be path-split by now.\n return false\n\n case '\\\\':\n clearStateChar()\n escaping = true\n continue\n\n // the various stateChar values\n // for the \"extglob\" stuff.\n case '?':\n case '*':\n case '+':\n case '@':\n case '!':\n this.debug('%s\\t%s %s %j <-- stateChar', pattern, i, re, c)\n\n // all of those are literals inside a class, except that\n // the glob [!a] means [^a] in regexp\n if (inClass) {\n this.debug(' in class')\n if (c === '!' && i === classStart + 1) c = '^'\n re += c\n continue\n }\n\n // if we already have a stateChar, then it means\n // that there was something like ** or +? in there.\n // Handle the stateChar, then proceed with this one.\n self.debug('call clearStateChar %j', stateChar)\n clearStateChar()\n stateChar = c\n // if extglob is disabled, then +(asdf|foo) isn't a thing.\n // just clear the statechar *now*, rather than even diving into\n // the patternList stuff.\n if (options.noext) clearStateChar()\n continue\n\n case '(':\n if (inClass) {\n re += '('\n continue\n }\n\n if (!stateChar) {\n re += '\\\\('\n continue\n }\n\n patternListStack.push({\n type: stateChar,\n start: i - 1,\n reStart: re.length,\n open: plTypes[stateChar].open,\n close: plTypes[stateChar].close\n })\n // negation is (?:(?!js)[^/]*)\n re += stateChar === '!' ? '(?:(?!(?:' : '(?:'\n this.debug('plType %j %j', stateChar, re)\n stateChar = false\n continue\n\n case ')':\n if (inClass || !patternListStack.length) {\n re += '\\\\)'\n continue\n }\n\n clearStateChar()\n hasMagic = true\n var pl = patternListStack.pop()\n // negation is (?:(?!js)[^/]*)\n // The others are (?:)\n re += pl.close\n if (pl.type === '!') {\n negativeLists.push(pl)\n }\n pl.reEnd = re.length\n continue\n\n case '|':\n if (inClass || !patternListStack.length || escaping) {\n re += '\\\\|'\n escaping = false\n continue\n }\n\n clearStateChar()\n re += '|'\n continue\n\n // these are mostly the same in regexp and glob\n case '[':\n // swallow any state-tracking char before the [\n clearStateChar()\n\n if (inClass) {\n re += '\\\\' + c\n continue\n }\n\n inClass = true\n classStart = i\n reClassStart = re.length\n re += c\n continue\n\n case ']':\n // a right bracket shall lose its special\n // meaning and represent itself in\n // a bracket expression if it occurs\n // first in the list. -- POSIX.2 2.8.3.2\n if (i === classStart + 1 || !inClass) {\n re += '\\\\' + c\n escaping = false\n continue\n }\n\n // handle the case where we left a class open.\n // \"[z-a]\" is valid, equivalent to \"\\[z-a\\]\"\n if (inClass) {\n // split where the last [ was, make sure we don't have\n // an invalid re. if so, re-walk the contents of the\n // would-be class to re-translate any characters that\n // were passed through as-is\n // TODO: It would probably be faster to determine this\n // without a try/catch and a new RegExp, but it's tricky\n // to do safely. For now, this is safe and works.\n var cs = pattern.substring(classStart + 1, i)\n try {\n RegExp('[' + cs + ']')\n } catch (er) {\n // not a valid class!\n var sp = this.parse(cs, SUBPARSE)\n re = re.substr(0, reClassStart) + '\\\\[' + sp[0] + '\\\\]'\n hasMagic = hasMagic || sp[1]\n inClass = false\n continue\n }\n }\n\n // finish up the class.\n hasMagic = true\n inClass = false\n re += c\n continue\n\n default:\n // swallow any state char that wasn't consumed\n clearStateChar()\n\n if (escaping) {\n // no need\n escaping = false\n } else if (reSpecials[c]\n && !(c === '^' && inClass)) {\n re += '\\\\'\n }\n\n re += c\n\n } // switch\n } // for\n\n // handle the case where we left a class open.\n // \"[abc\" is valid, equivalent to \"\\[abc\"\n if (inClass) {\n // split where the last [ was, and escape it\n // this is a huge pita. We now have to re-walk\n // the contents of the would-be class to re-translate\n // any characters that were passed through as-is\n cs = pattern.substr(classStart + 1)\n sp = this.parse(cs, SUBPARSE)\n re = re.substr(0, reClassStart) + '\\\\[' + sp[0]\n hasMagic = hasMagic || sp[1]\n }\n\n // handle the case where we had a +( thing at the *end*\n // of the pattern.\n // each pattern list stack adds 3 chars, and we need to go through\n // and escape any | chars that were passed through as-is for the regexp.\n // Go through and escape them, taking care not to double-escape any\n // | chars that were already escaped.\n for (pl = patternListStack.pop(); pl; pl = patternListStack.pop()) {\n var tail = re.slice(pl.reStart + pl.open.length)\n this.debug('setting tail', re, pl)\n // maybe some even number of \\, then maybe 1 \\, followed by a |\n tail = tail.replace(/((?:\\\\{2}){0,64})(\\\\?)\\|/g, function (_, $1, $2) {\n if (!$2) {\n // the | isn't already escaped, so escape it.\n $2 = '\\\\'\n }\n\n // need to escape all those slashes *again*, without escaping the\n // one that we need for escaping the | character. As it works out,\n // escaping an even number of slashes can be done by simply repeating\n // it exactly after itself. That's why this trick works.\n //\n // I am sorry that you have to see this.\n return $1 + $1 + $2 + '|'\n })\n\n this.debug('tail=%j\\n %s', tail, tail, pl, re)\n var t = pl.type === '*' ? star\n : pl.type === '?' ? qmark\n : '\\\\' + pl.type\n\n hasMagic = true\n re = re.slice(0, pl.reStart) + t + '\\\\(' + tail\n }\n\n // handle trailing things that only matter at the very end.\n clearStateChar()\n if (escaping) {\n // trailing \\\\\n re += '\\\\\\\\'\n }\n\n // only need to apply the nodot start if the re starts with\n // something that could conceivably capture a dot\n var addPatternStart = false\n switch (re.charAt(0)) {\n case '.':\n case '[':\n case '(': addPatternStart = true\n }\n\n // Hack to work around lack of negative lookbehind in JS\n // A pattern like: *.!(x).!(y|z) needs to ensure that a name\n // like 'a.xyz.yz' doesn't match. So, the first negative\n // lookahead, has to look ALL the way ahead, to the end of\n // the pattern.\n for (var n = negativeLists.length - 1; n > -1; n--) {\n var nl = negativeLists[n]\n\n var nlBefore = re.slice(0, nl.reStart)\n var nlFirst = re.slice(nl.reStart, nl.reEnd - 8)\n var nlLast = re.slice(nl.reEnd - 8, nl.reEnd)\n var nlAfter = re.slice(nl.reEnd)\n\n nlLast += nlAfter\n\n // Handle nested stuff like *(*.js|!(*.json)), where open parens\n // mean that we should *not* include the ) in the bit that is considered\n // \"after\" the negated section.\n var openParensBefore = nlBefore.split('(').length - 1\n var cleanAfter = nlAfter\n for (i = 0; i < openParensBefore; i++) {\n cleanAfter = cleanAfter.replace(/\\)[+*?]?/, '')\n }\n nlAfter = cleanAfter\n\n var dollar = ''\n if (nlAfter === '' && isSub !== SUBPARSE) {\n dollar = '$'\n }\n var newRe = nlBefore + nlFirst + nlAfter + dollar + nlLast\n re = newRe\n }\n\n // if the re is not \"\" at this point, then we need to make sure\n // it doesn't match against an empty path part.\n // Otherwise a/* will match a/, which it should not.\n if (re !== '' && hasMagic) {\n re = '(?=.)' + re\n }\n\n if (addPatternStart) {\n re = patternStart + re\n }\n\n // parsing just a piece of a larger pattern.\n if (isSub === SUBPARSE) {\n return [re, hasMagic]\n }\n\n // skip the regexp for non-magical patterns\n // unescape anything in it, though, so that it'll be\n // an exact match against a file etc.\n if (!hasMagic) {\n return globUnescape(pattern)\n }\n\n var flags = options.nocase ? 'i' : ''\n try {\n var regExp = new RegExp('^' + re + '$', flags)\n } catch (er) {\n // If it was an invalid regular expression, then it can't match\n // anything. This trick looks for a character after the end of\n // the string, which is of course impossible, except in multi-line\n // mode, but it's not a /m regex.\n return new RegExp('$.')\n }\n\n regExp._glob = pattern\n regExp._src = re\n\n return regExp\n}\n\nminimatch.makeRe = function (pattern, options) {\n return new Minimatch(pattern, options || {}).makeRe()\n}\n\nMinimatch.prototype.makeRe = makeRe\nfunction makeRe () {\n if (this.regexp || this.regexp === false) return this.regexp\n\n // at this point, this.set is a 2d array of partial\n // pattern strings, or \"**\".\n //\n // It's better to use .match(). This function shouldn't\n // be used, really, but it's pretty convenient sometimes,\n // when you just want to work with a regex.\n var set = this.set\n\n if (!set.length) {\n this.regexp = false\n return this.regexp\n }\n var options = this.options\n\n var twoStar = options.noglobstar ? star\n : options.dot ? twoStarDot\n : twoStarNoDot\n var flags = options.nocase ? 'i' : ''\n\n var re = set.map(function (pattern) {\n return pattern.map(function (p) {\n return (p === GLOBSTAR) ? twoStar\n : (typeof p === 'string') ? regExpEscape(p)\n : p._src\n }).join('\\\\\\/')\n }).join('|')\n\n // must match entire pattern\n // ending in a * or ** will make it less strict.\n re = '^(?:' + re + ')$'\n\n // can match anything, as long as it's not this.\n if (this.negate) re = '^(?!' + re + ').*$'\n\n try {\n this.regexp = new RegExp(re, flags)\n } catch (ex) {\n this.regexp = false\n }\n return this.regexp\n}\n\nminimatch.match = function (list, pattern, options) {\n options = options || {}\n var mm = new Minimatch(pattern, options)\n list = list.filter(function (f) {\n return mm.match(f)\n })\n if (mm.options.nonull && !list.length) {\n list.push(pattern)\n }\n return list\n}\n\nMinimatch.prototype.match = match\nfunction match (f, partial) {\n this.debug('match', f, this.pattern)\n // short-circuit in the case of busted things.\n // comments, etc.\n if (this.comment) return false\n if (this.empty) return f === ''\n\n if (f === '/' && partial) return true\n\n var options = this.options\n\n // windows: need to use /, not \\\n if (path.sep !== '/') {\n f = f.split(path.sep).join('/')\n }\n\n // treat the test path as a set of pathparts.\n f = f.split(slashSplit)\n this.debug(this.pattern, 'split', f)\n\n // just ONE of the pattern sets in this.set needs to match\n // in order for it to be valid. If negating, then just one\n // match means that we have failed.\n // Either way, return on the first hit.\n\n var set = this.set\n this.debug(this.pattern, 'set', set)\n\n // Find the basename of the path by looking for the last non-empty segment\n var filename\n var i\n for (i = f.length - 1; i >= 0; i--) {\n filename = f[i]\n if (filename) break\n }\n\n for (i = 0; i < set.length; i++) {\n var pattern = set[i]\n var file = f\n if (options.matchBase && pattern.length === 1) {\n file = [filename]\n }\n var hit = this.matchOne(file, pattern, partial)\n if (hit) {\n if (options.flipNegate) return true\n return !this.negate\n }\n }\n\n // didn't get any hits. this is success if it's a negative\n // pattern, failure otherwise.\n if (options.flipNegate) return false\n return this.negate\n}\n\n// set partial to true to test if, for example,\n// \"/a/b\" matches the start of \"/*/b/*/d\"\n// Partial means, if you run out of file before you run\n// out of pattern, then that's fine, as long as all\n// the parts match.\nMinimatch.prototype.matchOne = function (file, pattern, partial) {\n var options = this.options\n\n this.debug('matchOne',\n { 'this': this, file: file, pattern: pattern })\n\n this.debug('matchOne', file.length, pattern.length)\n\n for (var fi = 0,\n pi = 0,\n fl = file.length,\n pl = pattern.length\n ; (fi < fl) && (pi < pl)\n ; fi++, pi++) {\n this.debug('matchOne loop')\n var p = pattern[pi]\n var f = file[fi]\n\n this.debug(pattern, p, f)\n\n // should be impossible.\n // some invalid regexp stuff in the set.\n if (p === false) return false\n\n if (p === GLOBSTAR) {\n this.debug('GLOBSTAR', [pattern, p, f])\n\n // \"**\"\n // a/**/b/**/c would match the following:\n // a/b/x/y/z/c\n // a/x/y/z/b/c\n // a/b/x/b/x/c\n // a/b/c\n // To do this, take the rest of the pattern after\n // the **, and see if it would match the file remainder.\n // If so, return success.\n // If not, the ** \"swallows\" a segment, and try again.\n // This is recursively awful.\n //\n // a/**/b/**/c matching a/b/x/y/z/c\n // - a matches a\n // - doublestar\n // - matchOne(b/x/y/z/c, b/**/c)\n // - b matches b\n // - doublestar\n // - matchOne(x/y/z/c, c) -> no\n // - matchOne(y/z/c, c) -> no\n // - matchOne(z/c, c) -> no\n // - matchOne(c, c) yes, hit\n var fr = fi\n var pr = pi + 1\n if (pr === pl) {\n this.debug('** at the end')\n // a ** at the end will just swallow the rest.\n // We have found a match.\n // however, it will not swallow /.x, unless\n // options.dot is set.\n // . and .. are *never* matched by **, for explosively\n // exponential reasons.\n for (; fi < fl; fi++) {\n if (file[fi] === '.' || file[fi] === '..' ||\n (!options.dot && file[fi].charAt(0) === '.')) return false\n }\n return true\n }\n\n // ok, let's see if we can swallow whatever we can.\n while (fr < fl) {\n var swallowee = file[fr]\n\n this.debug('\\nglobstar while', file, fr, pattern, pr, swallowee)\n\n // XXX remove this slice. Just pass the start index.\n if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) {\n this.debug('globstar found match!', fr, fl, swallowee)\n // found a match.\n return true\n } else {\n // can't swallow \".\" or \"..\" ever.\n // can only swallow \".foo\" when explicitly asked.\n if (swallowee === '.' || swallowee === '..' ||\n (!options.dot && swallowee.charAt(0) === '.')) {\n this.debug('dot detected!', file, fr, pattern, pr)\n break\n }\n\n // ** swallows a segment, and continue.\n this.debug('globstar swallow a segment, and continue')\n fr++\n }\n }\n\n // no match was found.\n // However, in partial mode, we can't say this is necessarily over.\n // If there's more *pattern* left, then\n if (partial) {\n // ran out of file\n this.debug('\\n>>> no match, partial?', file, fr, pattern, pr)\n if (fr === fl) return true\n }\n return false\n }\n\n // something other than **\n // non-magic patterns just have to match exactly\n // patterns with magic have been turned into regexps.\n var hit\n if (typeof p === 'string') {\n if (options.nocase) {\n hit = f.toLowerCase() === p.toLowerCase()\n } else {\n hit = f === p\n }\n this.debug('string match', p, f, hit)\n } else {\n hit = f.match(p)\n this.debug('pattern match', p, f, hit)\n }\n\n if (!hit) return false\n }\n\n // Note: ending in / means that we'll get a final \"\"\n // at the end of the pattern. This can only match a\n // corresponding \"\" at the end of the file.\n // If the file ends in /, then it can only match a\n // a pattern that ends in /, unless the pattern just\n // doesn't have any more for it. But, a/b/ should *not*\n // match \"a/b/*\", even though \"\" matches against the\n // [^/]*? pattern, except in partial mode, where it might\n // simply not be reached yet.\n // However, a/b/ should still satisfy a/*\n\n // now either we fell off the end of the pattern, or we're done.\n if (fi === fl && pi === pl) {\n // ran out of pattern and filename at the same time.\n // an exact hit!\n return true\n } else if (fi === fl) {\n // ran out of file, but still had pattern left.\n // this is ok if we're doing the match as part of\n // a glob fs traversal.\n return partial\n } else if (pi === pl) {\n // ran out of pattern, still have file left.\n // this is only acceptable if we're on the very last\n // empty segment of a file with a trailing slash.\n // a/* should match a/b/\n var emptyFileEnd = (fi === fl - 1) && (file[fi] === '')\n return emptyFileEnd\n }\n\n // should be unreachable.\n throw new Error('wtf?')\n}\n\n// replace stuff like \\* with *\nfunction globUnescape (s) {\n return s.replace(/\\\\(.)/g, '$1')\n}\n\nfunction regExpEscape (s) {\n return s.replace(/[-[\\]{}()*+?.,\\\\^$|#\\s]/g, '\\\\$&')\n}\n","/*\nobject-assign\n(c) Sindre Sorhus\n@license MIT\n*/\n\n'use strict';\n/* eslint-disable no-unused-vars */\nvar getOwnPropertySymbols = Object.getOwnPropertySymbols;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\nvar propIsEnumerable = Object.prototype.propertyIsEnumerable;\n\nfunction toObject(val) {\n\tif (val === null || val === undefined) {\n\t\tthrow new TypeError('Object.assign cannot be called with null or undefined');\n\t}\n\n\treturn Object(val);\n}\n\nfunction shouldUseNative() {\n\ttry {\n\t\tif (!Object.assign) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Detect buggy property enumeration order in older V8 versions.\n\n\t\t// https://bugs.chromium.org/p/v8/issues/detail?id=4118\n\t\tvar test1 = new String('abc'); // eslint-disable-line no-new-wrappers\n\t\ttest1[5] = 'de';\n\t\tif (Object.getOwnPropertyNames(test1)[0] === '5') {\n\t\t\treturn false;\n\t\t}\n\n\t\t// https://bugs.chromium.org/p/v8/issues/detail?id=3056\n\t\tvar test2 = {};\n\t\tfor (var i = 0; i < 10; i++) {\n\t\t\ttest2['_' + String.fromCharCode(i)] = i;\n\t\t}\n\t\tvar order2 = Object.getOwnPropertyNames(test2).map(function (n) {\n\t\t\treturn test2[n];\n\t\t});\n\t\tif (order2.join('') !== '0123456789') {\n\t\t\treturn false;\n\t\t}\n\n\t\t// https://bugs.chromium.org/p/v8/issues/detail?id=3056\n\t\tvar test3 = {};\n\t\t'abcdefghijklmnopqrst'.split('').forEach(function (letter) {\n\t\t\ttest3[letter] = letter;\n\t\t});\n\t\tif (Object.keys(Object.assign({}, test3)).join('') !==\n\t\t\t\t'abcdefghijklmnopqrst') {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t} catch (err) {\n\t\t// We don't expect any of the above to throw, but better to be safe.\n\t\treturn false;\n\t}\n}\n\nmodule.exports = shouldUseNative() ? Object.assign : function (target, source) {\n\tvar from;\n\tvar to = toObject(target);\n\tvar symbols;\n\n\tfor (var s = 1; s < arguments.length; s++) {\n\t\tfrom = Object(arguments[s]);\n\n\t\tfor (var key in from) {\n\t\t\tif (hasOwnProperty.call(from, key)) {\n\t\t\t\tto[key] = from[key];\n\t\t\t}\n\t\t}\n\n\t\tif (getOwnPropertySymbols) {\n\t\t\tsymbols = getOwnPropertySymbols(from);\n\t\t\tfor (var i = 0; i < symbols.length; i++) {\n\t\t\t\tif (propIsEnumerable.call(from, symbols[i])) {\n\t\t\t\t\tto[symbols[i]] = from[symbols[i]];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn to;\n};\n","/** @license React v16.13.1\n * react-is.production.min.js\n *\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';var b=\"function\"===typeof Symbol&&Symbol.for,c=b?Symbol.for(\"react.element\"):60103,d=b?Symbol.for(\"react.portal\"):60106,e=b?Symbol.for(\"react.fragment\"):60107,f=b?Symbol.for(\"react.strict_mode\"):60108,g=b?Symbol.for(\"react.profiler\"):60114,h=b?Symbol.for(\"react.provider\"):60109,k=b?Symbol.for(\"react.context\"):60110,l=b?Symbol.for(\"react.async_mode\"):60111,m=b?Symbol.for(\"react.concurrent_mode\"):60111,n=b?Symbol.for(\"react.forward_ref\"):60112,p=b?Symbol.for(\"react.suspense\"):60113,q=b?\nSymbol.for(\"react.suspense_list\"):60120,r=b?Symbol.for(\"react.memo\"):60115,t=b?Symbol.for(\"react.lazy\"):60116,v=b?Symbol.for(\"react.block\"):60121,w=b?Symbol.for(\"react.fundamental\"):60117,x=b?Symbol.for(\"react.responder\"):60118,y=b?Symbol.for(\"react.scope\"):60119;\nfunction z(a){if(\"object\"===typeof a&&null!==a){var u=a.$$typeof;switch(u){case c:switch(a=a.type,a){case l:case m:case e:case g:case f:case p:return a;default:switch(a=a&&a.$$typeof,a){case k:case n:case t:case r:case h:return a;default:return u}}case d:return u}}}function A(a){return z(a)===m}exports.AsyncMode=l;exports.ConcurrentMode=m;exports.ContextConsumer=k;exports.ContextProvider=h;exports.Element=c;exports.ForwardRef=n;exports.Fragment=e;exports.Lazy=t;exports.Memo=r;exports.Portal=d;\nexports.Profiler=g;exports.StrictMode=f;exports.Suspense=p;exports.isAsyncMode=function(a){return A(a)||z(a)===l};exports.isConcurrentMode=A;exports.isContextConsumer=function(a){return z(a)===k};exports.isContextProvider=function(a){return z(a)===h};exports.isElement=function(a){return\"object\"===typeof a&&null!==a&&a.$$typeof===c};exports.isForwardRef=function(a){return z(a)===n};exports.isFragment=function(a){return z(a)===e};exports.isLazy=function(a){return z(a)===t};\nexports.isMemo=function(a){return z(a)===r};exports.isPortal=function(a){return z(a)===d};exports.isProfiler=function(a){return z(a)===g};exports.isStrictMode=function(a){return z(a)===f};exports.isSuspense=function(a){return z(a)===p};\nexports.isValidElementType=function(a){return\"string\"===typeof a||\"function\"===typeof a||a===e||a===m||a===g||a===f||a===p||a===q||\"object\"===typeof a&&null!==a&&(a.$$typeof===t||a.$$typeof===r||a.$$typeof===h||a.$$typeof===k||a.$$typeof===n||a.$$typeof===w||a.$$typeof===x||a.$$typeof===y||a.$$typeof===v)};exports.typeOf=z;\n","'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n module.exports = require('./cjs/react-is.production.min.js');\n} else {\n module.exports = require('./cjs/react-is.development.js');\n}\n","/** @license React v17.0.2\n * react-is.production.min.js\n *\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n'use strict';var b=60103,c=60106,d=60107,e=60108,f=60114,g=60109,h=60110,k=60112,l=60113,m=60120,n=60115,p=60116,q=60121,r=60122,u=60117,v=60129,w=60131;\nif(\"function\"===typeof Symbol&&Symbol.for){var x=Symbol.for;b=x(\"react.element\");c=x(\"react.portal\");d=x(\"react.fragment\");e=x(\"react.strict_mode\");f=x(\"react.profiler\");g=x(\"react.provider\");h=x(\"react.context\");k=x(\"react.forward_ref\");l=x(\"react.suspense\");m=x(\"react.suspense_list\");n=x(\"react.memo\");p=x(\"react.lazy\");q=x(\"react.block\");r=x(\"react.server.block\");u=x(\"react.fundamental\");v=x(\"react.debug_trace_mode\");w=x(\"react.legacy_hidden\")}\nfunction y(a){if(\"object\"===typeof a&&null!==a){var t=a.$$typeof;switch(t){case b:switch(a=a.type,a){case d:case f:case e:case l:case m:return a;default:switch(a=a&&a.$$typeof,a){case h:case k:case p:case n:case g:return a;default:return t}}case c:return t}}}var z=g,A=b,B=k,C=d,D=p,E=n,F=c,G=f,H=e,I=l;exports.ContextConsumer=h;exports.ContextProvider=z;exports.Element=A;exports.ForwardRef=B;exports.Fragment=C;exports.Lazy=D;exports.Memo=E;exports.Portal=F;exports.Profiler=G;exports.StrictMode=H;\nexports.Suspense=I;exports.isAsyncMode=function(){return!1};exports.isConcurrentMode=function(){return!1};exports.isContextConsumer=function(a){return y(a)===h};exports.isContextProvider=function(a){return y(a)===g};exports.isElement=function(a){return\"object\"===typeof a&&null!==a&&a.$$typeof===b};exports.isForwardRef=function(a){return y(a)===k};exports.isFragment=function(a){return y(a)===d};exports.isLazy=function(a){return y(a)===p};exports.isMemo=function(a){return y(a)===n};\nexports.isPortal=function(a){return y(a)===c};exports.isProfiler=function(a){return y(a)===f};exports.isStrictMode=function(a){return y(a)===e};exports.isSuspense=function(a){return y(a)===l};exports.isValidElementType=function(a){return\"string\"===typeof a||\"function\"===typeof a||a===d||a===f||a===v||a===e||a===l||a===m||a===w||\"object\"===typeof a&&null!==a&&(a.$$typeof===p||a.$$typeof===n||a.$$typeof===g||a.$$typeof===h||a.$$typeof===k||a.$$typeof===u||a.$$typeof===q||a[0]===r)?!0:!1};\nexports.typeOf=y;\n","'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n module.exports = require('./cjs/react-is.production.min.js');\n} else {\n module.exports = require('./cjs/react-is.development.js');\n}\n","/** @license React v17.0.2\n * react-jsx-runtime.production.min.js\n *\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n'use strict';require(\"object-assign\");var f=require(\"react\"),g=60103;exports.Fragment=60107;if(\"function\"===typeof Symbol&&Symbol.for){var h=Symbol.for;g=h(\"react.element\");exports.Fragment=h(\"react.fragment\")}var m=f.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,n=Object.prototype.hasOwnProperty,p={key:!0,ref:!0,__self:!0,__source:!0};\nfunction q(c,a,k){var b,d={},e=null,l=null;void 0!==k&&(e=\"\"+k);void 0!==a.key&&(e=\"\"+a.key);void 0!==a.ref&&(l=a.ref);for(b in a)n.call(a,b)&&!p.hasOwnProperty(b)&&(d[b]=a[b]);if(c&&c.defaultProps)for(b in a=c.defaultProps,a)void 0===d[b]&&(d[b]=a[b]);return{$$typeof:g,type:c,key:e,ref:l,props:d,_owner:m.current}}exports.jsx=q;exports.jsxs=q;\n","'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n module.exports = require('./cjs/react-jsx-runtime.production.min.js');\n} else {\n module.exports = require('./cjs/react-jsx-runtime.development.js');\n}\n","//\n\nmodule.exports = function shallowEqual(objA, objB, compare, compareContext) {\n var ret = compare ? compare.call(compareContext, objA, objB) : void 0;\n\n if (ret !== void 0) {\n return !!ret;\n }\n\n if (objA === objB) {\n return true;\n }\n\n if (typeof objA !== \"object\" || !objA || typeof objB !== \"object\" || !objB) {\n return false;\n }\n\n var keysA = Object.keys(objA);\n var keysB = Object.keys(objB);\n\n if (keysA.length !== keysB.length) {\n return false;\n }\n\n var bHasOwnProperty = Object.prototype.hasOwnProperty.bind(objB);\n\n // Test for A's keys different from B.\n for (var idx = 0; idx < keysA.length; idx++) {\n var key = keysA[idx];\n\n if (!bHasOwnProperty(key)) {\n return false;\n }\n\n var valueA = objA[key];\n var valueB = objB[key];\n\n ret = compare ? compare.call(compareContext, valueA, valueB, key) : void 0;\n\n if (ret === false || (ret === void 0 && valueA !== valueB)) {\n return false;\n }\n }\n\n return true;\n};\n","module.exports = React;","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","const __WEBPACK_NAMESPACE_OBJECT__ = ReactDOM;","function stylis_min (W) {\n function M(d, c, e, h, a) {\n for (var m = 0, b = 0, v = 0, n = 0, q, g, x = 0, K = 0, k, u = k = q = 0, l = 0, r = 0, I = 0, t = 0, B = e.length, J = B - 1, y, f = '', p = '', F = '', G = '', C; l < B;) {\n g = e.charCodeAt(l);\n l === J && 0 !== b + n + v + m && (0 !== b && (g = 47 === b ? 10 : 47), n = v = m = 0, B++, J++);\n\n if (0 === b + n + v + m) {\n if (l === J && (0 < r && (f = f.replace(N, '')), 0 < f.trim().length)) {\n switch (g) {\n case 32:\n case 9:\n case 59:\n case 13:\n case 10:\n break;\n\n default:\n f += e.charAt(l);\n }\n\n g = 59;\n }\n\n switch (g) {\n case 123:\n f = f.trim();\n q = f.charCodeAt(0);\n k = 1;\n\n for (t = ++l; l < B;) {\n switch (g = e.charCodeAt(l)) {\n case 123:\n k++;\n break;\n\n case 125:\n k--;\n break;\n\n case 47:\n switch (g = e.charCodeAt(l + 1)) {\n case 42:\n case 47:\n a: {\n for (u = l + 1; u < J; ++u) {\n switch (e.charCodeAt(u)) {\n case 47:\n if (42 === g && 42 === e.charCodeAt(u - 1) && l + 2 !== u) {\n l = u + 1;\n break a;\n }\n\n break;\n\n case 10:\n if (47 === g) {\n l = u + 1;\n break a;\n }\n\n }\n }\n\n l = u;\n }\n\n }\n\n break;\n\n case 91:\n g++;\n\n case 40:\n g++;\n\n case 34:\n case 39:\n for (; l++ < J && e.charCodeAt(l) !== g;) {\n }\n\n }\n\n if (0 === k) break;\n l++;\n }\n\n k = e.substring(t, l);\n 0 === q && (q = (f = f.replace(ca, '').trim()).charCodeAt(0));\n\n switch (q) {\n case 64:\n 0 < r && (f = f.replace(N, ''));\n g = f.charCodeAt(1);\n\n switch (g) {\n case 100:\n case 109:\n case 115:\n case 45:\n r = c;\n break;\n\n default:\n r = O;\n }\n\n k = M(c, r, k, g, a + 1);\n t = k.length;\n 0 < A && (r = X(O, f, I), C = H(3, k, r, c, D, z, t, g, a, h), f = r.join(''), void 0 !== C && 0 === (t = (k = C.trim()).length) && (g = 0, k = ''));\n if (0 < t) switch (g) {\n case 115:\n f = f.replace(da, ea);\n\n case 100:\n case 109:\n case 45:\n k = f + '{' + k + '}';\n break;\n\n case 107:\n f = f.replace(fa, '$1 $2');\n k = f + '{' + k + '}';\n k = 1 === w || 2 === w && L('@' + k, 3) ? '@-webkit-' + k + '@' + k : '@' + k;\n break;\n\n default:\n k = f + k, 112 === h && (k = (p += k, ''));\n } else k = '';\n break;\n\n default:\n k = M(c, X(c, f, I), k, h, a + 1);\n }\n\n F += k;\n k = I = r = u = q = 0;\n f = '';\n g = e.charCodeAt(++l);\n break;\n\n case 125:\n case 59:\n f = (0 < r ? f.replace(N, '') : f).trim();\n if (1 < (t = f.length)) switch (0 === u && (q = f.charCodeAt(0), 45 === q || 96 < q && 123 > q) && (t = (f = f.replace(' ', ':')).length), 0 < A && void 0 !== (C = H(1, f, c, d, D, z, p.length, h, a, h)) && 0 === (t = (f = C.trim()).length) && (f = '\\x00\\x00'), q = f.charCodeAt(0), g = f.charCodeAt(1), q) {\n case 0:\n break;\n\n case 64:\n if (105 === g || 99 === g) {\n G += f + e.charAt(l);\n break;\n }\n\n default:\n 58 !== f.charCodeAt(t - 1) && (p += P(f, q, g, f.charCodeAt(2)));\n }\n I = r = u = q = 0;\n f = '';\n g = e.charCodeAt(++l);\n }\n }\n\n switch (g) {\n case 13:\n case 10:\n 47 === b ? b = 0 : 0 === 1 + q && 107 !== h && 0 < f.length && (r = 1, f += '\\x00');\n 0 < A * Y && H(0, f, c, d, D, z, p.length, h, a, h);\n z = 1;\n D++;\n break;\n\n case 59:\n case 125:\n if (0 === b + n + v + m) {\n z++;\n break;\n }\n\n default:\n z++;\n y = e.charAt(l);\n\n switch (g) {\n case 9:\n case 32:\n if (0 === n + m + b) switch (x) {\n case 44:\n case 58:\n case 9:\n case 32:\n y = '';\n break;\n\n default:\n 32 !== g && (y = ' ');\n }\n break;\n\n case 0:\n y = '\\\\0';\n break;\n\n case 12:\n y = '\\\\f';\n break;\n\n case 11:\n y = '\\\\v';\n break;\n\n case 38:\n 0 === n + b + m && (r = I = 1, y = '\\f' + y);\n break;\n\n case 108:\n if (0 === n + b + m + E && 0 < u) switch (l - u) {\n case 2:\n 112 === x && 58 === e.charCodeAt(l - 3) && (E = x);\n\n case 8:\n 111 === K && (E = K);\n }\n break;\n\n case 58:\n 0 === n + b + m && (u = l);\n break;\n\n case 44:\n 0 === b + v + n + m && (r = 1, y += '\\r');\n break;\n\n case 34:\n case 39:\n 0 === b && (n = n === g ? 0 : 0 === n ? g : n);\n break;\n\n case 91:\n 0 === n + b + v && m++;\n break;\n\n case 93:\n 0 === n + b + v && m--;\n break;\n\n case 41:\n 0 === n + b + m && v--;\n break;\n\n case 40:\n if (0 === n + b + m) {\n if (0 === q) switch (2 * x + 3 * K) {\n case 533:\n break;\n\n default:\n q = 1;\n }\n v++;\n }\n\n break;\n\n case 64:\n 0 === b + v + n + m + u + k && (k = 1);\n break;\n\n case 42:\n case 47:\n if (!(0 < n + m + v)) switch (b) {\n case 0:\n switch (2 * g + 3 * e.charCodeAt(l + 1)) {\n case 235:\n b = 47;\n break;\n\n case 220:\n t = l, b = 42;\n }\n\n break;\n\n case 42:\n 47 === g && 42 === x && t + 2 !== l && (33 === e.charCodeAt(t + 2) && (p += e.substring(t, l + 1)), y = '', b = 0);\n }\n }\n\n 0 === b && (f += y);\n }\n\n K = x;\n x = g;\n l++;\n }\n\n t = p.length;\n\n if (0 < t) {\n r = c;\n if (0 < A && (C = H(2, p, r, d, D, z, t, h, a, h), void 0 !== C && 0 === (p = C).length)) return G + p + F;\n p = r.join(',') + '{' + p + '}';\n\n if (0 !== w * E) {\n 2 !== w || L(p, 2) || (E = 0);\n\n switch (E) {\n case 111:\n p = p.replace(ha, ':-moz-$1') + p;\n break;\n\n case 112:\n p = p.replace(Q, '::-webkit-input-$1') + p.replace(Q, '::-moz-$1') + p.replace(Q, ':-ms-input-$1') + p;\n }\n\n E = 0;\n }\n }\n\n return G + p + F;\n }\n\n function X(d, c, e) {\n var h = c.trim().split(ia);\n c = h;\n var a = h.length,\n m = d.length;\n\n switch (m) {\n case 0:\n case 1:\n var b = 0;\n\n for (d = 0 === m ? '' : d[0] + ' '; b < a; ++b) {\n c[b] = Z(d, c[b], e).trim();\n }\n\n break;\n\n default:\n var v = b = 0;\n\n for (c = []; b < a; ++b) {\n for (var n = 0; n < m; ++n) {\n c[v++] = Z(d[n] + ' ', h[b], e).trim();\n }\n }\n\n }\n\n return c;\n }\n\n function Z(d, c, e) {\n var h = c.charCodeAt(0);\n 33 > h && (h = (c = c.trim()).charCodeAt(0));\n\n switch (h) {\n case 38:\n return c.replace(F, '$1' + d.trim());\n\n case 58:\n return d.trim() + c.replace(F, '$1' + d.trim());\n\n default:\n if (0 < 1 * e && 0 < c.indexOf('\\f')) return c.replace(F, (58 === d.charCodeAt(0) ? '' : '$1') + d.trim());\n }\n\n return d + c;\n }\n\n function P(d, c, e, h) {\n var a = d + ';',\n m = 2 * c + 3 * e + 4 * h;\n\n if (944 === m) {\n d = a.indexOf(':', 9) + 1;\n var b = a.substring(d, a.length - 1).trim();\n b = a.substring(0, d).trim() + b + ';';\n return 1 === w || 2 === w && L(b, 1) ? '-webkit-' + b + b : b;\n }\n\n if (0 === w || 2 === w && !L(a, 1)) return a;\n\n switch (m) {\n case 1015:\n return 97 === a.charCodeAt(10) ? '-webkit-' + a + a : a;\n\n case 951:\n return 116 === a.charCodeAt(3) ? '-webkit-' + a + a : a;\n\n case 963:\n return 110 === a.charCodeAt(5) ? '-webkit-' + a + a : a;\n\n case 1009:\n if (100 !== a.charCodeAt(4)) break;\n\n case 969:\n case 942:\n return '-webkit-' + a + a;\n\n case 978:\n return '-webkit-' + a + '-moz-' + a + a;\n\n case 1019:\n case 983:\n return '-webkit-' + a + '-moz-' + a + '-ms-' + a + a;\n\n case 883:\n if (45 === a.charCodeAt(8)) return '-webkit-' + a + a;\n if (0 < a.indexOf('image-set(', 11)) return a.replace(ja, '$1-webkit-$2') + a;\n break;\n\n case 932:\n if (45 === a.charCodeAt(4)) switch (a.charCodeAt(5)) {\n case 103:\n return '-webkit-box-' + a.replace('-grow', '') + '-webkit-' + a + '-ms-' + a.replace('grow', 'positive') + a;\n\n case 115:\n return '-webkit-' + a + '-ms-' + a.replace('shrink', 'negative') + a;\n\n case 98:\n return '-webkit-' + a + '-ms-' + a.replace('basis', 'preferred-size') + a;\n }\n return '-webkit-' + a + '-ms-' + a + a;\n\n case 964:\n return '-webkit-' + a + '-ms-flex-' + a + a;\n\n case 1023:\n if (99 !== a.charCodeAt(8)) break;\n b = a.substring(a.indexOf(':', 15)).replace('flex-', '').replace('space-between', 'justify');\n return '-webkit-box-pack' + b + '-webkit-' + a + '-ms-flex-pack' + b + a;\n\n case 1005:\n return ka.test(a) ? a.replace(aa, ':-webkit-') + a.replace(aa, ':-moz-') + a : a;\n\n case 1e3:\n b = a.substring(13).trim();\n c = b.indexOf('-') + 1;\n\n switch (b.charCodeAt(0) + b.charCodeAt(c)) {\n case 226:\n b = a.replace(G, 'tb');\n break;\n\n case 232:\n b = a.replace(G, 'tb-rl');\n break;\n\n case 220:\n b = a.replace(G, 'lr');\n break;\n\n default:\n return a;\n }\n\n return '-webkit-' + a + '-ms-' + b + a;\n\n case 1017:\n if (-1 === a.indexOf('sticky', 9)) break;\n\n case 975:\n c = (a = d).length - 10;\n b = (33 === a.charCodeAt(c) ? a.substring(0, c) : a).substring(d.indexOf(':', 7) + 1).trim();\n\n switch (m = b.charCodeAt(0) + (b.charCodeAt(7) | 0)) {\n case 203:\n if (111 > b.charCodeAt(8)) break;\n\n case 115:\n a = a.replace(b, '-webkit-' + b) + ';' + a;\n break;\n\n case 207:\n case 102:\n a = a.replace(b, '-webkit-' + (102 < m ? 'inline-' : '') + 'box') + ';' + a.replace(b, '-webkit-' + b) + ';' + a.replace(b, '-ms-' + b + 'box') + ';' + a;\n }\n\n return a + ';';\n\n case 938:\n if (45 === a.charCodeAt(5)) switch (a.charCodeAt(6)) {\n case 105:\n return b = a.replace('-items', ''), '-webkit-' + a + '-webkit-box-' + b + '-ms-flex-' + b + a;\n\n case 115:\n return '-webkit-' + a + '-ms-flex-item-' + a.replace(ba, '') + a;\n\n default:\n return '-webkit-' + a + '-ms-flex-line-pack' + a.replace('align-content', '').replace(ba, '') + a;\n }\n break;\n\n case 973:\n case 989:\n if (45 !== a.charCodeAt(3) || 122 === a.charCodeAt(4)) break;\n\n case 931:\n case 953:\n if (!0 === la.test(d)) return 115 === (b = d.substring(d.indexOf(':') + 1)).charCodeAt(0) ? P(d.replace('stretch', 'fill-available'), c, e, h).replace(':fill-available', ':stretch') : a.replace(b, '-webkit-' + b) + a.replace(b, '-moz-' + b.replace('fill-', '')) + a;\n break;\n\n case 962:\n if (a = '-webkit-' + a + (102 === a.charCodeAt(5) ? '-ms-' + a : '') + a, 211 === e + h && 105 === a.charCodeAt(13) && 0 < a.indexOf('transform', 10)) return a.substring(0, a.indexOf(';', 27) + 1).replace(ma, '$1-webkit-$2') + a;\n }\n\n return a;\n }\n\n function L(d, c) {\n var e = d.indexOf(1 === c ? ':' : '{'),\n h = d.substring(0, 3 !== c ? e : 10);\n e = d.substring(e + 1, d.length - 1);\n return R(2 !== c ? h : h.replace(na, '$1'), e, c);\n }\n\n function ea(d, c) {\n var e = P(c, c.charCodeAt(0), c.charCodeAt(1), c.charCodeAt(2));\n return e !== c + ';' ? e.replace(oa, ' or ($1)').substring(4) : '(' + c + ')';\n }\n\n function H(d, c, e, h, a, m, b, v, n, q) {\n for (var g = 0, x = c, w; g < A; ++g) {\n switch (w = S[g].call(B, d, x, e, h, a, m, b, v, n, q)) {\n case void 0:\n case !1:\n case !0:\n case null:\n break;\n\n default:\n x = w;\n }\n }\n\n if (x !== c) return x;\n }\n\n function T(d) {\n switch (d) {\n case void 0:\n case null:\n A = S.length = 0;\n break;\n\n default:\n if ('function' === typeof d) S[A++] = d;else if ('object' === typeof d) for (var c = 0, e = d.length; c < e; ++c) {\n T(d[c]);\n } else Y = !!d | 0;\n }\n\n return T;\n }\n\n function U(d) {\n d = d.prefix;\n void 0 !== d && (R = null, d ? 'function' !== typeof d ? w = 1 : (w = 2, R = d) : w = 0);\n return U;\n }\n\n function B(d, c) {\n var e = d;\n 33 > e.charCodeAt(0) && (e = e.trim());\n V = e;\n e = [V];\n\n if (0 < A) {\n var h = H(-1, c, e, e, D, z, 0, 0, 0, 0);\n void 0 !== h && 'string' === typeof h && (c = h);\n }\n\n var a = M(O, e, c, 0, 0);\n 0 < A && (h = H(-2, a, e, e, D, z, a.length, 0, 0, 0), void 0 !== h && (a = h));\n V = '';\n E = 0;\n z = D = 1;\n return a;\n }\n\n var ca = /^\\0+/g,\n N = /[\\0\\r\\f]/g,\n aa = /: */g,\n ka = /zoo|gra/,\n ma = /([,: ])(transform)/g,\n ia = /,\\r+?/g,\n F = /([\\t\\r\\n ])*\\f?&/g,\n fa = /@(k\\w+)\\s*(\\S*)\\s*/,\n Q = /::(place)/g,\n ha = /:(read-only)/g,\n G = /[svh]\\w+-[tblr]{2}/,\n da = /\\(\\s*(.*)\\s*\\)/g,\n oa = /([\\s\\S]*?);/g,\n ba = /-self|flex-/g,\n na = /[^]*?(:[rp][el]a[\\w-]+)[^]*/,\n la = /stretch|:\\s*\\w+\\-(?:conte|avail)/,\n ja = /([^-])(image-set\\()/,\n z = 1,\n D = 1,\n E = 0,\n w = 1,\n O = [],\n S = [],\n A = 0,\n R = null,\n Y = 0,\n V = '';\n B.use = T;\n B.set = U;\n void 0 !== W && U(W);\n return B;\n}\n\nexport default stylis_min;\n","var unitlessKeys = {\n animationIterationCount: 1,\n borderImageOutset: 1,\n borderImageSlice: 1,\n borderImageWidth: 1,\n boxFlex: 1,\n boxFlexGroup: 1,\n boxOrdinalGroup: 1,\n columnCount: 1,\n columns: 1,\n flex: 1,\n flexGrow: 1,\n flexPositive: 1,\n flexShrink: 1,\n flexNegative: 1,\n flexOrder: 1,\n gridRow: 1,\n gridRowEnd: 1,\n gridRowSpan: 1,\n gridRowStart: 1,\n gridColumn: 1,\n gridColumnEnd: 1,\n gridColumnSpan: 1,\n gridColumnStart: 1,\n msGridRow: 1,\n msGridRowSpan: 1,\n msGridColumn: 1,\n msGridColumnSpan: 1,\n fontWeight: 1,\n lineHeight: 1,\n opacity: 1,\n order: 1,\n orphans: 1,\n tabSize: 1,\n widows: 1,\n zIndex: 1,\n zoom: 1,\n WebkitLineClamp: 1,\n // SVG-related properties\n fillOpacity: 1,\n floodOpacity: 1,\n stopOpacity: 1,\n strokeDasharray: 1,\n strokeDashoffset: 1,\n strokeMiterlimit: 1,\n strokeOpacity: 1,\n strokeWidth: 1\n};\n\nexport default unitlessKeys;\n","import memoize from '@emotion/memoize';\n\nvar reactPropsRegex = /^((children|dangerouslySetInnerHTML|key|ref|autoFocus|defaultValue|defaultChecked|innerHTML|suppressContentEditableWarning|suppressHydrationWarning|valueLink|accept|acceptCharset|accessKey|action|allow|allowUserMedia|allowPaymentRequest|allowFullScreen|allowTransparency|alt|async|autoComplete|autoPlay|capture|cellPadding|cellSpacing|challenge|charSet|checked|cite|classID|className|cols|colSpan|content|contentEditable|contextMenu|controls|controlsList|coords|crossOrigin|data|dateTime|decoding|default|defer|dir|disabled|disablePictureInPicture|download|draggable|encType|form|formAction|formEncType|formMethod|formNoValidate|formTarget|frameBorder|headers|height|hidden|high|href|hrefLang|htmlFor|httpEquiv|id|inputMode|integrity|is|keyParams|keyType|kind|label|lang|list|loading|loop|low|marginHeight|marginWidth|max|maxLength|media|mediaGroup|method|min|minLength|multiple|muted|name|nonce|noValidate|open|optimum|pattern|placeholder|playsInline|poster|preload|profile|radioGroup|readOnly|referrerPolicy|rel|required|reversed|role|rows|rowSpan|sandbox|scope|scoped|scrolling|seamless|selected|shape|size|sizes|slot|span|spellCheck|src|srcDoc|srcLang|srcSet|start|step|style|summary|tabIndex|target|title|type|useMap|value|width|wmode|wrap|about|datatype|inlist|prefix|property|resource|typeof|vocab|autoCapitalize|autoCorrect|autoSave|color|inert|itemProp|itemScope|itemType|itemID|itemRef|on|results|security|unselectable|accentHeight|accumulate|additive|alignmentBaseline|allowReorder|alphabetic|amplitude|arabicForm|ascent|attributeName|attributeType|autoReverse|azimuth|baseFrequency|baselineShift|baseProfile|bbox|begin|bias|by|calcMode|capHeight|clip|clipPathUnits|clipPath|clipRule|colorInterpolation|colorInterpolationFilters|colorProfile|colorRendering|contentScriptType|contentStyleType|cursor|cx|cy|d|decelerate|descent|diffuseConstant|direction|display|divisor|dominantBaseline|dur|dx|dy|edgeMode|elevation|enableBackground|end|exponent|externalResourcesRequired|fill|fillOpacity|fillRule|filter|filterRes|filterUnits|floodColor|floodOpacity|focusable|fontFamily|fontSize|fontSizeAdjust|fontStretch|fontStyle|fontVariant|fontWeight|format|from|fr|fx|fy|g1|g2|glyphName|glyphOrientationHorizontal|glyphOrientationVertical|glyphRef|gradientTransform|gradientUnits|hanging|horizAdvX|horizOriginX|ideographic|imageRendering|in|in2|intercept|k|k1|k2|k3|k4|kernelMatrix|kernelUnitLength|kerning|keyPoints|keySplines|keyTimes|lengthAdjust|letterSpacing|lightingColor|limitingConeAngle|local|markerEnd|markerMid|markerStart|markerHeight|markerUnits|markerWidth|mask|maskContentUnits|maskUnits|mathematical|mode|numOctaves|offset|opacity|operator|order|orient|orientation|origin|overflow|overlinePosition|overlineThickness|panose1|paintOrder|pathLength|patternContentUnits|patternTransform|patternUnits|pointerEvents|points|pointsAtX|pointsAtY|pointsAtZ|preserveAlpha|preserveAspectRatio|primitiveUnits|r|radius|refX|refY|renderingIntent|repeatCount|repeatDur|requiredExtensions|requiredFeatures|restart|result|rotate|rx|ry|scale|seed|shapeRendering|slope|spacing|specularConstant|specularExponent|speed|spreadMethod|startOffset|stdDeviation|stemh|stemv|stitchTiles|stopColor|stopOpacity|strikethroughPosition|strikethroughThickness|string|stroke|strokeDasharray|strokeDashoffset|strokeLinecap|strokeLinejoin|strokeMiterlimit|strokeOpacity|strokeWidth|surfaceScale|systemLanguage|tableValues|targetX|targetY|textAnchor|textDecoration|textRendering|textLength|to|transform|u1|u2|underlinePosition|underlineThickness|unicode|unicodeBidi|unicodeRange|unitsPerEm|vAlphabetic|vHanging|vIdeographic|vMathematical|values|vectorEffect|version|vertAdvY|vertOriginX|vertOriginY|viewBox|viewTarget|visibility|widths|wordSpacing|writingMode|x|xHeight|x1|x2|xChannelSelector|xlinkActuate|xlinkArcrole|xlinkHref|xlinkRole|xlinkShow|xlinkTitle|xlinkType|xmlBase|xmlns|xmlnsXlink|xmlLang|xmlSpace|y|y1|y2|yChannelSelector|z|zoomAndPan|for|class|autofocus)|(([Dd][Aa][Tt][Aa]|[Aa][Rr][Ii][Aa]|x)-.*))$/; // https://esbench.com/bench/5bfee68a4cd7e6009ef61d23\n\nvar index = memoize(function (prop) {\n return reactPropsRegex.test(prop) || prop.charCodeAt(0) === 111\n /* o */\n && prop.charCodeAt(1) === 110\n /* n */\n && prop.charCodeAt(2) < 91;\n}\n/* Z+1 */\n);\n\nexport default index;\n","function memoize(fn) {\n var cache = {};\n return function (arg) {\n if (cache[arg] === undefined) cache[arg] = fn(arg);\n return cache[arg];\n };\n}\n\nexport default memoize;\n","import{typeOf as e,isElement as t,isValidElementType as n}from\"react-is\";import r,{useState as o,useContext as s,useMemo as i,useEffect as a,useRef as c,createElement as u,useDebugValue as l,useLayoutEffect as d}from\"react\";import h from\"shallowequal\";import p from\"@emotion/stylis\";import f from\"@emotion/unitless\";import m from\"@emotion/is-prop-valid\";import y from\"hoist-non-react-statics\";function v(){return(v=Object.assign||function(e){for(var t=1;t ({})}\\n```\\n\\n',8:'ThemeProvider: Please make your \"theme\" prop an object.\\n\\n',9:\"Missing document ``\\n\\n\",10:\"Cannot find a StyleSheet instance. Usually this happens if there are multiple copies of styled-components loaded at once. Check out this issue for how to troubleshoot and fix the common cases where this situation can happen: https://github.com/styled-components/styled-components/issues/1941#issuecomment-417862021\\n\\n\",11:\"_This error was replaced with a dev-time warning, it will be deleted for v4 final._ [createGlobalStyle] received children which will not be rendered. Please use the component without passing children elements.\\n\\n\",12:\"It seems you are interpolating a keyframe declaration (%s) into an untagged string. This was supported in styled-components v3, but is not longer supported in v4 as keyframes are now injected on-demand. Please wrap your string in the css\\\\`\\\\` helper which ensures the styles are injected correctly. See https://www.styled-components.com/docs/api#css\\n\\n\",13:\"%s is not a styled component and cannot be referred to via component selector. See https://www.styled-components.com/docs/advanced#referring-to-other-components for more details.\\n\\n\",14:'ThemeProvider: \"theme\" prop is required.\\n\\n',15:\"A stylis plugin has been supplied that is not named. We need a name for each plugin to be able to prevent styling collisions between different stylis configurations within the same app. Before you pass your plugin to ``, please make sure each plugin is uniquely-named, e.g.\\n\\n```js\\nObject.defineProperty(importedPlugin, 'name', { value: 'some-unique-name' });\\n```\\n\\n\",16:\"Reached the limit of how many styled components may be created at group %s.\\nYou may only create up to 1,073,741,824 components. If you're creating components dynamically,\\nas for instance in your render method then you may be running into this limitation.\\n\\n\",17:\"CSSStyleSheet could not be found on HTMLStyleElement.\\nHas styled-components' style tag been unmounted or altered by another script?\\n\"}:{};function D(){for(var e=arguments.length<=0?void 0:arguments[0],t=[],n=1,r=arguments.length;n1?t-1:0),r=1;r0?\" Args: \"+n.join(\", \"):\"\")):new Error(D.apply(void 0,[R[e]].concat(n)).trim())}var T=function(){function e(e){this.groupSizes=new Uint32Array(512),this.length=512,this.tag=e}var t=e.prototype;return t.indexOfGroup=function(e){for(var t=0,n=0;n=this.groupSizes.length){for(var n=this.groupSizes,r=n.length,o=r;e>=o;)(o<<=1)<0&&j(16,\"\"+e);this.groupSizes=new Uint32Array(o),this.groupSizes.set(n),this.length=o;for(var s=r;s=this.length||0===this.groupSizes[e])return t;for(var n=this.groupSizes[e],r=this.indexOfGroup(e),o=r+n,s=r;s1<<30)&&j(16,\"\"+t),x.set(e,t),k.set(t,e),t},z=function(e){return k.get(e)},M=function(e,t){t>=V&&(V=t+1),x.set(e,t),k.set(t,e)},G=\"style[\"+A+'][data-styled-version=\"5.3.3\"]',L=new RegExp(\"^\"+A+'\\\\.g(\\\\d+)\\\\[id=\"([\\\\w\\\\d-]+)\"\\\\].*?\"([^\"]*)'),F=function(e,t,n){for(var r,o=n.split(\",\"),s=0,i=o.length;s=0;n--){var r=t[n];if(r&&1===r.nodeType&&r.hasAttribute(A))return r}}(n),s=void 0!==o?o.nextSibling:null;r.setAttribute(A,\"active\"),r.setAttribute(\"data-styled-version\",\"5.3.3\");var i=q();return i&&r.setAttribute(\"nonce\",i),n.insertBefore(r,s),r},$=function(){function e(e){var t=this.element=H(e);t.appendChild(document.createTextNode(\"\")),this.sheet=function(e){if(e.sheet)return e.sheet;for(var t=document.styleSheets,n=0,r=t.length;n=0){var n=document.createTextNode(t),r=this.nodes[e];return this.element.insertBefore(n,r||null),this.length++,!0}return!1},t.deleteRule=function(e){this.element.removeChild(this.nodes[e]),this.length--},t.getRule=function(e){return e0&&(u+=e+\",\")})),r+=\"\"+a+c+'{content:\"'+u+'\"}/*!sc*/\\n'}}}return r}(this)},e}(),K=/(a)(d)/gi,Q=function(e){return String.fromCharCode(e+(e>25?39:97))};function ee(e){var t,n=\"\";for(t=Math.abs(e);t>52;t=t/52|0)n=Q(t%52)+n;return(Q(t%52)+n).replace(K,\"$1-$2\")}var te=function(e,t){for(var n=t.length;n;)e=33*e^t.charCodeAt(--n);return e},ne=function(e){return te(5381,e)};function re(e){for(var t=0;t>>0);if(!t.hasNameForId(r,i)){var a=n(s,\".\"+i,void 0,r);t.insertRules(r,i,a)}o.push(i),this.staticRulesId=i}else{for(var c=this.rules.length,u=te(this.baseHash,n.hash),l=\"\",d=0;d>>0);if(!t.hasNameForId(r,m)){var y=n(l,\".\"+m,void 0,r);t.insertRules(r,m,y)}o.push(m)}}return o.join(\" \")},e}(),ie=/^\\s*\\/\\/.*$/gm,ae=[\":\",\"[\",\".\",\"#\"];function ce(e){var t,n,r,o,s=void 0===e?E:e,i=s.options,a=void 0===i?E:i,c=s.plugins,u=void 0===c?w:c,l=new p(a),d=[],h=function(e){function t(t){if(t)try{e(t+\"}\")}catch(e){}}return function(n,r,o,s,i,a,c,u,l,d){switch(n){case 1:if(0===l&&64===r.charCodeAt(0))return e(r+\";\"),\"\";break;case 2:if(0===u)return r+\"/*|*/\";break;case 3:switch(u){case 102:case 112:return e(o[0]+r),\"\";default:return r+(0===d?\"/*|*/\":\"\")}case-2:r.split(\"/*|*/}\").forEach(t)}}}((function(e){d.push(e)})),f=function(e,r,s){return 0===r&&-1!==ae.indexOf(s[n.length])||s.match(o)?e:\".\"+t};function m(e,s,i,a){void 0===a&&(a=\"&\");var c=e.replace(ie,\"\"),u=s&&i?i+\" \"+s+\" { \"+c+\" }\":c;return t=a,n=s,r=new RegExp(\"\\\\\"+n+\"\\\\b\",\"g\"),o=new RegExp(\"(\\\\\"+n+\"\\\\b){2,}\"),l(i||!s?\"\":s,u)}return l.use([].concat(u,[function(e,t,o){2===e&&o.length&&o[0].lastIndexOf(n)>0&&(o[0]=o[0].replace(r,f))},h,function(e){if(-2===e){var t=d;return d=[],t}}])),m.hash=u.length?u.reduce((function(e,t){return t.name||j(15),te(e,t.name)}),5381).toString():\"\",m}var ue=r.createContext(),le=ue.Consumer,de=r.createContext(),he=(de.Consumer,new Z),pe=ce();function fe(){return s(ue)||he}function me(){return s(de)||pe}function ye(e){var t=o(e.stylisPlugins),n=t[0],s=t[1],c=fe(),u=i((function(){var t=c;return e.sheet?t=e.sheet:e.target&&(t=t.reconstructWithOptions({target:e.target},!1)),e.disableCSSOMInjection&&(t=t.reconstructWithOptions({useCSSOMInjection:!1})),t}),[e.disableCSSOMInjection,e.sheet,e.target]),l=i((function(){return ce({options:{prefix:!e.disableVendorPrefixes},plugins:n})}),[e.disableVendorPrefixes,n]);return a((function(){h(n,e.stylisPlugins)||s(e.stylisPlugins)}),[e.stylisPlugins]),r.createElement(ue.Provider,{value:u},r.createElement(de.Provider,{value:l},\"production\"!==process.env.NODE_ENV?r.Children.only(e.children):e.children))}var ve=function(){function e(e,t){var n=this;this.inject=function(e,t){void 0===t&&(t=pe);var r=n.name+t.hash;e.hasNameForId(n.id,r)||e.insertRules(n.id,r,t(n.rules,r,\"@keyframes\"))},this.toString=function(){return j(12,String(n.name))},this.name=e,this.id=\"sc-keyframes-\"+e,this.rules=t}return e.prototype.getName=function(e){return void 0===e&&(e=pe),this.name+e.hash},e}(),ge=/([A-Z])/,Se=/([A-Z])/g,we=/^ms-/,Ee=function(e){return\"-\"+e.toLowerCase()};function be(e){return ge.test(e)?e.replace(Se,Ee).replace(we,\"-ms-\"):e}var _e=function(e){return null==e||!1===e||\"\"===e};function Ne(e,n,r,o){if(Array.isArray(e)){for(var s,i=[],a=0,c=e.length;a1?t-1:0),r=1;r1?t-1:0),i=1;i?@[\\\\\\]^`{|}~-]+/g,je=/(^-|-$)/g;function Te(e){return e.replace(De,\"-\").replace(je,\"\")}var xe=function(e){return ee(ne(e)>>>0)};function ke(e){return\"string\"==typeof e&&(\"production\"===process.env.NODE_ENV||e.charAt(0)===e.charAt(0).toLowerCase())}var Ve=function(e){return\"function\"==typeof e||\"object\"==typeof e&&null!==e&&!Array.isArray(e)},Be=function(e){return\"__proto__\"!==e&&\"constructor\"!==e&&\"prototype\"!==e};function ze(e,t,n){var r=e[n];Ve(t)&&Ve(r)?Me(r,t):e[n]=t}function Me(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),r=1;r=0||(o[n]=e[n]);return o}(t,[\"componentId\"]),s=r&&r+\"-\"+(ke(e)?e:Te(_(e)));return qe(e,v({},o,{attrs:S,componentId:s}),n)},Object.defineProperty(C,\"defaultProps\",{get:function(){return this._foldedDefaultProps},set:function(t){this._foldedDefaultProps=o?Me({},e.defaultProps,t):t}}),\"production\"!==process.env.NODE_ENV&&(Oe(f,g),C.warnTooManyClasses=function(e,t){var n={},r=!1;return function(o){if(!r&&(n[o]=!0,Object.keys(n).length>=200)){var s=t?' with the id of \"'+t+'\"':\"\";console.warn(\"Over 200 classes were generated for component \"+e+s+\".\\nConsider using the attrs method, together with a style object for frequently changed styles.\\nExample:\\n const Component = styled.div.attrs(props => ({\\n style: {\\n background: props.background,\\n },\\n }))`width: 100%;`\\n\\n \"),r=!0,n={}}}}(f,g)),C.toString=function(){return\".\"+C.styledComponentId},i&&y(C,e,{attrs:!0,componentStyle:!0,displayName:!0,foldedComponentIds:!0,shouldForwardProp:!0,styledComponentId:!0,target:!0,withComponent:!0}),C}var He=function(e){return function e(t,r,o){if(void 0===o&&(o=E),!n(r))return j(1,String(r));var s=function(){return t(r,o,Ce.apply(void 0,arguments))};return s.withConfig=function(n){return e(t,r,v({},o,{},n))},s.attrs=function(n){return e(t,r,v({},o,{attrs:Array.prototype.concat(o.attrs,n).filter(Boolean)}))},s}(qe,e)};[\"a\",\"abbr\",\"address\",\"area\",\"article\",\"aside\",\"audio\",\"b\",\"base\",\"bdi\",\"bdo\",\"big\",\"blockquote\",\"body\",\"br\",\"button\",\"canvas\",\"caption\",\"cite\",\"code\",\"col\",\"colgroup\",\"data\",\"datalist\",\"dd\",\"del\",\"details\",\"dfn\",\"dialog\",\"div\",\"dl\",\"dt\",\"em\",\"embed\",\"fieldset\",\"figcaption\",\"figure\",\"footer\",\"form\",\"h1\",\"h2\",\"h3\",\"h4\",\"h5\",\"h6\",\"head\",\"header\",\"hgroup\",\"hr\",\"html\",\"i\",\"iframe\",\"img\",\"input\",\"ins\",\"kbd\",\"keygen\",\"label\",\"legend\",\"li\",\"link\",\"main\",\"map\",\"mark\",\"marquee\",\"menu\",\"menuitem\",\"meta\",\"meter\",\"nav\",\"noscript\",\"object\",\"ol\",\"optgroup\",\"option\",\"output\",\"p\",\"param\",\"picture\",\"pre\",\"progress\",\"q\",\"rp\",\"rt\",\"ruby\",\"s\",\"samp\",\"script\",\"section\",\"select\",\"small\",\"source\",\"span\",\"strong\",\"style\",\"sub\",\"summary\",\"sup\",\"table\",\"tbody\",\"td\",\"textarea\",\"tfoot\",\"th\",\"thead\",\"time\",\"title\",\"tr\",\"track\",\"u\",\"ul\",\"var\",\"video\",\"wbr\",\"circle\",\"clipPath\",\"defs\",\"ellipse\",\"foreignObject\",\"g\",\"image\",\"line\",\"linearGradient\",\"marker\",\"mask\",\"path\",\"pattern\",\"polygon\",\"polyline\",\"radialGradient\",\"rect\",\"stop\",\"svg\",\"text\",\"textPath\",\"tspan\"].forEach((function(e){He[e]=He(e)}));var $e=function(){function e(e,t){this.rules=e,this.componentId=t,this.isStatic=re(e),Z.registerId(this.componentId+1)}var t=e.prototype;return t.createStyles=function(e,t,n,r){var o=r(Ne(this.rules,t,n,r).join(\"\"),\"\"),s=this.componentId+e;n.insertRules(s,s,o)},t.removeStyles=function(e,t){t.clearRules(this.componentId+e)},t.renderStyles=function(e,t,n,r){e>2&&Z.registerId(this.componentId+e),this.removeStyles(e,n),this.createStyles(e,t,n,r)},e}();function We(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),o=1;o meta tag to the stylesheet, or simply embedding it manually in your index.html section for a simpler app.\"),t.server&&h(l,e,t,o,n),d((function(){if(!t.server)return h(l,e,t,o,n),function(){return u.removeStyles(l,t)}}),[l,e,t,o,n]),null}function h(e,t,n,r,o){if(u.isStatic)u.renderStyles(e,O,n,o);else{var s=v({},t,{theme:Re(t,r,l.defaultProps)});u.renderStyles(e,s,n,o)}}return\"production\"!==process.env.NODE_ENV&&Oe(a),r.memo(l)}function Ue(e){\"production\"!==process.env.NODE_ENV&&\"undefined\"!=typeof navigator&&\"ReactNative\"===navigator.product&&console.warn(\"`keyframes` cannot be used on ReactNative, only on the web. To do animation in ReactNative please use Animated.\");for(var t=arguments.length,n=new Array(t>1?t-1:0),r=1;r\"+t+\"\"},this.getStyleTags=function(){return e.sealed?j(2):e._emitSheetCSS()},this.getStyleElement=function(){var t;if(e.sealed)return j(2);var n=((t={})[A]=\"\",t[\"data-styled-version\"]=\"5.3.3\",t.dangerouslySetInnerHTML={__html:e.instance.toString()},t),o=q();return o&&(n.nonce=o),[r.createElement(\"style\",v({},n,{key:\"sc-0-0\"}))]},this.seal=function(){e.sealed=!0},this.instance=new Z({isServer:!0}),this.sealed=!1}var t=e.prototype;return t.collectStyles=function(e){return this.sealed?j(2):r.createElement(ye,{sheet:this.instance},e)},t.interleaveWithNodeStream=function(e){return j(3)},e}(),Xe=function(e){var t=r.forwardRef((function(t,n){var o=s(Ge),i=e.defaultProps,a=Re(t,o,i);return\"production\"!==process.env.NODE_ENV&&void 0===a&&console.warn('[withTheme] You are not using a ThemeProvider nor passing a theme prop or a theme in defaultProps in component class \"'+_(e)+'\"'),r.createElement(e,v({},t,{theme:a,ref:n}))}));return y(t,e),t.displayName=\"WithTheme(\"+_(e)+\")\",t},Ze=function(){return s(Ge)},Ke={StyleSheet:Z,masterSheet:he};\"production\"!==process.env.NODE_ENV&&\"undefined\"!=typeof navigator&&\"ReactNative\"===navigator.product&&console.warn(\"It looks like you've imported 'styled-components' on React Native.\\nPerhaps you're looking to import 'styled-components/native'?\\nRead more about this at https://www.styled-components.com/docs/basics#react-native\"),\"production\"!==process.env.NODE_ENV&&\"test\"!==process.env.NODE_ENV&&\"undefined\"!=typeof window&&(window[\"__styled-components-init__\"]=window[\"__styled-components-init__\"]||0,1===window[\"__styled-components-init__\"]&&console.warn(\"It looks like there are several instances of 'styled-components' initialized in this application. This may cause dynamic styles to not render properly, errors during the rehydration process, a missing theme prop, and makes your application bigger without good reason.\\n\\nSee https://s-c.sh/2BAXzed for more info.\"),window[\"__styled-components-init__\"]+=1);export default He;export{Je as ServerStyleSheet,le as StyleSheetConsumer,ue as StyleSheetContext,ye as StyleSheetManager,Le as ThemeConsumer,Ge as ThemeContext,Fe as ThemeProvider,Ke as __PRIVATE__,We as createGlobalStyle,Ce as css,N as isStyledComponent,Ue as keyframes,Ze as useTheme,C as version,Xe as withTheme};\n//# sourceMappingURL=styled-components.browser.esm.js.map\n","function download(str: string, filename = 'contest.md'): void {\n const blob = new Blob([str], { type: 'text/plain' })\n const url = URL.createObjectURL(blob)\n\n const a = document.createElement('a')\n a.href = url\n a.download = filename\n document.body.appendChild(a)\n a.click()\n\n document.body.removeChild(a)\n}\n\nfunction getElement(\n query: string,\n fn: (e: NodeListOf) => boolean = e => e.length > 0,\n timeout = 10000\n): Promise> {\n const delay = 100\n return new Promise(function (resolve, reject) {\n const timer = setInterval(() => {\n const element = document.querySelectorAll(query)\n if (fn(element)) {\n clearInterval(timer)\n resolve(element)\n }\n if (timeout <= 0) {\n clearInterval(timer)\n reject('超时')\n }\n timeout -= delay\n }, delay)\n })\n}\n\ninterface RootNode {\n name: string\n node: any\n}\n\n/**\n * 使用 BFS 搜索对象下的所有属性和值\n * @param roots 需要搜索的根节点\n * @param complete 判断是否结束搜索,如果返回 true 则结束搜索\n * @returns\n */\nfunction searchProperty(\n roots: RootNode | RootNode[],\n complete: (\n paths: string[],\n key: string,\n node: PropertyDescriptor | undefined\n ) => boolean\n): void {\n if (!Array.isArray(roots)) roots = [roots]\n\n if (!complete) throw new Error('The lack of complete')\n const queue = roots.map(({ name, node }) => ({ path: [name], node }))\n let i = 0\n const cache = new Set()\n while (i < queue.length) {\n const { path, node } = queue[i]\n i++\n if (cache.has(node) || !node) continue\n cache.add(node)\n for (const key of Object.getOwnPropertyNames(node)) {\n const p = Object.getOwnPropertyDescriptor(node, key)\n\n if (complete(path, key, p)) return\n\n if (p?.value) queue.push({ path: path.concat(key), node: p.value })\n\n if (p?.get) queue.push({ path: path.concat(key, 'getter'), node: p.get })\n\n if (p?.set) queue.push({ path: path.concat(key, 'setter'), node: p.set })\n }\n }\n}\n\n/**\n * 获取对象中指定路径数组的值\n * @param root 指定的对象\n * @param paths 路径数组\n * @returns 获取到的值\n * @example\n * ```ts\n * getObjByPaths({a:{b:{c:{d:4}}}},['a','b','c','d']) // 4\n * ```\n */\nfunction getObjByPaths(root: { [key: string]: unknown }, paths: string[]): any {\n let i = 0\n while (root && i < paths.length) {\n root = root[paths[i]] as { [key: string]: unknown }\n i++\n }\n return root\n}\n\nfunction getFiber(el: Element): FiberRoot | null {\n for (const key in el) {\n if (Reflect.hasOwnProperty.call(el, key)) {\n if (/^__reactFiber\\$/.test(key)) {\n return Reflect.get(el, key)\n }\n }\n }\n return null\n}\n\nfunction submissionOnMarkChange(submissionId: string): void {\n const root = getFiber(\n document.querySelectorAll(`[data-row-key=\"${submissionId}\"]`)?.[0]\n )\n\n if (!root) {\n console.log(`leetcode-extend: 未找到提交记录容器的 root`)\n return\n }\n\n let onMarkChange: ((onMarkChange: string) => void) | undefined\n\n searchProperty({ name: 'root', node: root }, (paths, key, node) => {\n if (key === 'submissionId' && node?.value === submissionId) {\n const parent = getObjByPaths(root as any, paths.slice(1))\n if (Object.prototype.hasOwnProperty.call(parent, 'onMarkChange')) {\n onMarkChange = parent.onMarkChange\n return true\n }\n }\n return false\n })\n\n if (onMarkChange) {\n onMarkChange(submissionId)\n } else {\n console.log(`leetcode-extend: 未找到 onMarkChange`)\n }\n}\n\nexport { download, getElement, submissionOnMarkChange }\n","import React, { FC, useState } from 'react'\nimport styled, { css } from 'styled-components/macro'\n\nimport { LeetCodeApi } from '../../leetcode-api'\nimport { download } from '../../utils'\n\nconst Container = styled.div`\n display: flex;\n justify-content: center;\n align-items: center;\n font-size: 14px;\n`\n\nconst Button = styled.a<{ primary?: boolean }>`\n background: transparent;\n border-radius: 3px;\n border: 2px solid palevioletred;\n color: palevioletred;\n margin: 0.5em 1em;\n padding: 0.25em 1em;\n width: 150px;\n text-align: center;\n\n ${props =>\n props.primary &&\n css`\n background: palevioletred;\n color: white;\n `}\n`\n\nconst Download: FC = () => {\n const [option, setOption] = useState({ runtime: true, memory: false })\n const [isDownloading, setDownloading] = useState(false)\n const [progress, setProgress] = useState(0)\n\n const handleChange: React.ChangeEventHandler = e => {\n const key = e.target.id as 'runtime' | 'memory'\n setOption(option => ({ ...option, [key]: !option[key] }))\n }\n const handleClick = async function () {\n setDownloading(true)\n const pathnames = location.pathname.split('/').filter(Boolean)\n const leetCodeApi = new LeetCodeApi(location.origin)\n const data = await leetCodeApi.getSubmissionDetail(\n pathnames[pathnames.length - 1]\n )\n const allQuestions = await leetCodeApi.getAllQuestions()\n const { questionId, lang } = data\n const question = allQuestions.find(q => q.questionId === questionId)\n let res = `# ${question?.title} - ${lang}\\n\\n`\n const cache = new Set()\n\n const total =\n (option.runtime\n ? data.runtimeDistribution?.distribution.length ?? 0\n : 0) +\n (option.memory ? data.memoryDistribution?.distribution.length ?? 0 : 0)\n\n let progress = 0\n if (option.runtime) {\n const time = data.runtimeDistribution\n res += `## 用时分布代码\\n\\n`\n if (time) {\n const { lang, distribution } = time\n for (const [t] of distribution) {\n const code = await leetCodeApi.getCodeByTime(lang, questionId, t)\n\n res += `### ${t}ms\\n\\n`\n res += `\\`\\`\\`${lang}\\n${code}\\n\\`\\`\\`\\n\\n`\n cache.add(code)\n progress++\n setProgress(progress / total)\n }\n }\n }\n if (option.memory) {\n const memory = data.memoryDistribution\n res += `## 小号内存分布分布代码\\n\\n`\n if (memory) {\n const { lang, distribution } = memory\n for (const [m] of distribution) {\n const code = await leetCodeApi.getCodeByMemory(lang, questionId, m)\n if (cache.has(code)) continue\n\n res += `### ${m}kb\\n\\n`\n res += `\\`\\`\\`${lang}\\n${code}\\n\\`\\`\\`\\n\\n`\n\n progress++\n setProgress(progress / total)\n }\n }\n }\n download(res, `${question?.titleSlug}-${lang}.md`)\n setDownloading(false)\n setProgress(0)\n }\n\n return (\n \n
\n \n \n
\n
\n \n \n
\n \n
\n )\n}\n\nexport default Download\n","import { useEffect, useRef, useState } from 'react'\n\nfunction formatTime(time: number) {\n time = time / 1000\n const house = Math.floor(time / 3600)\n const minute = Math.floor((time / 60) % 60)\n const second = Math.floor(time % 60)\n return [house, minute, second]\n}\n\ntype UseTimeReturn = {\n time: number[]\n isDone: boolean\n done: (fn?: (time: number[]) => void) => void\n restart: () => void\n}\n\nconst useTimer = (): UseTimeReturn => {\n const [start, setStart] = useState(new Date())\n const [isDone, setIsDone] = useState(false)\n const [time, setTime] = useState(formatTime(0))\n const cacheTime = useRef(time)\n cacheTime.current = time\n useEffect(() => {\n let timer: ReturnType\n if (!isDone) {\n timer = setInterval(async () => {\n setTime(formatTime(new Date().valueOf() - start.valueOf()))\n }, 1000)\n }\n\n return () => {\n if (timer) {\n clearInterval(timer)\n }\n }\n }, [isDone])\n\n const restart = () => {\n setIsDone(false)\n setStart(new Date())\n setTime(formatTime(0))\n }\n\n const done = (fn?: (time: number[]) => void) => {\n setIsDone(true)\n\n if (fn) {\n fn(cacheTime.current)\n }\n }\n\n return { time, isDone, done, restart }\n}\n\nexport { useTimer }\n","import React, { FC, useEffect, useState } from 'react'\nimport styled from 'styled-components/macro'\n\nimport { LeetCodeApi, SuccessCheckReturnType } from '../../leetcode-api'\nimport { sleep } from '../../leetcode-api/utils'\nimport { getElement, submissionOnMarkChange } from '../../utils'\nimport { useTimer } from './useTimer'\n\nconst Container = styled.div`\n display: flex;\n justify-content: center;\n align-items: center;\n font-size: 14px;\n`\n\nconst Content = styled.div`\n border-radius: 3px 0 0 3px;\n border: 1px solid palevioletred;\n border-right-width: 0;\n margin-left: 15px;\n padding: 6px 15px;\n`\n\nconst Button = styled.button<{ primary?: boolean }>`\n background: transparent;\n border-radius: 0 3px 3px 0;\n border: 1px solid palevioletred;\n color: palevioletred;\n margin-right: 15px;\n padding: 6px 15px;\n width: 100px;\n text-align: center;\n cursor: pointer;\n`\n\nconst Clock: FC = () => {\n const pathnames = location.pathname.split('/').filter(Boolean)\n\n const slug = pathnames[1]\n const [leetCodeApi] = useState(new LeetCodeApi(location.origin))\n const [hidden, setHidden] = useState(false)\n\n const { time, isDone, done, restart } = useTimer()\n\n const handleHidden = () => {\n setHidden(hidden => !hidden)\n }\n\n async function getSubmissionId(\n retry = 1,\n time = new Date()\n ): Promise {\n if (retry > 10) throw new Error('获取 SubmissionId 失败')\n\n await sleep(500)\n const { submissions } = await leetCodeApi.getSubmissions(slug)\n const pendingSubmission = submissions.find(\n ({ timestamp, isPending }) =>\n isPending === 'Pending' ||\n new Date((Number(timestamp) + 2) * 1000) >= time\n )\n\n if (!pendingSubmission) {\n return getSubmissionId(retry + 1, time)\n } else {\n return pendingSubmission.id\n }\n }\n\n async function check(\n submissionId: string,\n retry = 1\n ): Promise {\n if (retry > 10) throw new Error('获取提交状态结果超时')\n\n await sleep(1000 + retry * 500)\n const state = await leetCodeApi.check(submissionId)\n\n if (state.state === 'SUCCESS') {\n return state\n } else {\n return await check(submissionId, retry + 1)\n }\n }\n\n useEffect(() => {\n let cancel: (() => void) | null = null\n\n void (async function () {\n const submitBtn = (await getElement('.submit__-6u9'))[0]\n const handleClick: EventListenerOrEventListenerObject = async () => {\n const submissionId = await getSubmissionId()\n const state = await check(submissionId)\n\n if (state.status_msg === 'Accepted') {\n // 提交成功\n done(async time => {\n // 对当前提交添加备注\n await leetCodeApi.submissionCreateOrUpdateSubmissionComment(\n submissionId,\n 'RED',\n time.map(t => t.toString().padStart(2, '0')).join(' : ')\n )\n\n await sleep(1000)\n submissionOnMarkChange(submissionId)\n })\n\n setHidden(false)\n }\n }\n\n submitBtn.addEventListener('click', handleClick)\n cancel = () => {\n submitBtn.removeEventListener('click', handleClick)\n }\n })()\n return () => {\n if (cancel) cancel()\n }\n }, [])\n\n return (\n \n {!hidden && (\n \n {`${isDone ? '本次耗时: ' : ''}${time\n .map(t => t.toString().padStart(2, '0'))\n .join(' : ')}`}\n \n )}\n {!isDone ? (\n \n )\n}\n\nexport default Clock\n","import { StrictMode } from 'react'\nimport { render } from 'react-dom'\nimport minimatch from 'minimatch'\n\nimport Download from './page/submissions-detail/Download'\nimport Clock from './page/problems/Clock'\nimport { getElement } from './utils'\n\nfunction loadDownload(parent: Element) {\n if (parent && parent instanceof HTMLElement) {\n parent.style.display = 'flex'\n parent.style.justifyContent = 'space-between'\n const root = document.createElement('div')\n parent.append(root)\n\n render(\n \n \n ,\n root\n )\n }\n}\n\nif (minimatch(location.href, 'https://leetcode-cn.com/submissions/detail/**')) {\n window.onload = async () => {\n const main = await getElement('.css-smuvek-Main')\n loadDownload(main[0]?.children?.[0])\n }\n}\n\nif (minimatch(location.href, 'https://leetcode.com/submissions/detail/**')) {\n window.onload = async () => {\n const parent = await getElement('#submission-app>.row>div:first-child')\n loadDownload(parent[0])\n }\n}\n\nif (minimatch(location.href, 'https://leetcode-cn.com/problems/**')) {\n window.onload = async () => {\n const parent = (await getElement('.container__Kjnx>.action__KaAP'))[0]\n if (parent && parent instanceof HTMLElement) {\n const root = document.createElement('div')\n parent.prepend(root)\n root.style.display = 'flex'\n root.style.alignItems = 'center'\n root.style.flexShrink = '0'\n\n render(\n \n \n ,\n root\n )\n }\n }\n}\n"],"names":["LeetCodeApi","REGION_URL","this","graphqlApi","baseApi","cache","localStorage","getItem","res","JSON","parse","console","log","body","operationName","variables","query","then","data","allQuestions","setItem","stringify","Error","questionSlug","limit","offset","lastKey","submissionList","submissionId","id","submissionDetail","runtimeApi","runtime_distribution_formatted","runtimeDistribution","memoryApi","memory_distribution_formatted","memoryDistribution","fetch","headers","accept","referrer","referrerPolicy","method","mode","credentials","text","dataText","match","eval","test","getSubmissionDetailByLocal","getDistributionLocal","questionId","question","lang","distribution","getSubmissionDetailByGlobal","code","submissionCode","runtime","memory","submissionData","rawMemory","statusDisplay","globalGetStatusText","status_code","getLangDisplay","passedTestCaseCnt","Number","total_correct","totalTestCaseCnt","total_testcases","sourceUrl","editCodeUrl","runtimeDistributionFormatted","memoryDistributionFormatted","time","api","flagType","comment","submissionCreateOrUpdateSubmissionComment","sleep","Promise","resolve","setTimeout","retry","RETRY_TIME","RETRY_COUNT","status","json","isObject","obj","url","bodyStr","toUpperCase","e","balanced","a","b","str","RegExp","maybeMatch","r","range","start","end","pre","slice","length","post","reg","m","begs","beg","left","right","result","ai","indexOf","bi","i","push","pop","module","exports","concatMap","substr","expand","split","join","escSlash","escOpen","escClose","escComma","escPeriod","escapeBraces","map","unescapeBraces","Math","random","numeric","parseInt","charCodeAt","parseCommaParts","parts","p","postParts","shift","apply","embrace","isPadded","el","lte","y","gte","isTop","expansions","n","isNumericSequence","isAlphaSequence","isSequence","isOptions","N","x","width","max","incr","abs","pad","some","c","String","fromCharCode","need","z","Array","j","k","expansion","xs","fn","isArray","Object","prototype","toString","call","reactIs","REACT_STATICS","childContextTypes","contextType","contextTypes","defaultProps","displayName","getDefaultProps","getDerivedStateFromError","getDerivedStateFromProps","mixins","propTypes","type","KNOWN_STATICS","name","caller","callee","arguments","arity","MEMO_STATICS","compare","TYPE_STATICS","getStatics","component","isMemo","ForwardRef","render","Memo","defineProperty","getOwnPropertyNames","getOwnPropertySymbols","getOwnPropertyDescriptor","getPrototypeOf","objectPrototype","hoistNonReactStatics","targetComponent","sourceComponent","blacklist","inheritedComponent","keys","concat","targetStatics","sourceStatics","key","descriptor","minimatch","Minimatch","path","sep","er","GLOBSTAR","plTypes","open","close","qmark","star","reSpecials","reduce","set","slashSplit","ext","t","forEach","pattern","options","TypeError","nocomment","charAt","trim","regexp","negate","empty","make","braceExpand","nobrace","filter","list","defaults","def","orig","debug","_made","parseNegate","globSet","error","globParts","s","si","negateOffset","nonegate","l","isSub","noglobstar","stateChar","re","hasMagic","nocase","escaping","patternListStack","negativeLists","inClass","reClassStart","classStart","patternStart","dot","self","clearStateChar","len","noext","reStart","pl","reEnd","cs","substring","sp","SUBPARSE","tail","replace","_","$1","$2","addPatternStart","nl","nlBefore","nlFirst","nlLast","nlAfter","openParensBefore","cleanAfter","dollar","flags","regExp","_glob","_src","makeRe","twoStar","ex","mm","f","nonull","partial","filename","file","matchBase","matchOne","flipNegate","fi","pi","fl","hit","fr","pr","swallowee","toLowerCase","hasOwnProperty","propIsEnumerable","propertyIsEnumerable","toObject","val","assign","test1","test2","test3","letter","err","shouldUseNative","target","source","from","symbols","to","Symbol","for","d","g","h","q","v","w","u","$$typeof","A","AsyncMode","ConcurrentMode","ContextConsumer","ContextProvider","Element","Fragment","Lazy","Portal","Profiler","StrictMode","Suspense","isAsyncMode","isConcurrentMode","isContextConsumer","isContextProvider","isElement","isForwardRef","isFragment","isLazy","isPortal","isProfiler","isStrictMode","isSuspense","isValidElementType","typeOf","__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED","ReactCurrentOwner","ref","__self","__source","props","_owner","current","jsx","jsxs","objA","objB","compareContext","ret","keysA","keysB","bHasOwnProperty","bind","idx","valueA","valueB","React","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","undefined","__webpack_modules__","getter","__esModule","definition","o","enumerable","get","prop","ReactDOM","W","M","C","K","I","B","J","F","G","ca","O","H","X","D","da","ea","fa","L","P","Y","E","ha","Q","ia","Z","ja","ka","aa","ba","la","ma","R","na","oa","S","U","prefix","use","T","animationIterationCount","borderImageOutset","borderImageSlice","borderImageWidth","boxFlex","boxFlexGroup","boxOrdinalGroup","columnCount","columns","flex","flexGrow","flexPositive","flexShrink","flexNegative","flexOrder","gridRow","gridRowEnd","gridRowSpan","gridRowStart","gridColumn","gridColumnEnd","gridColumnSpan","gridColumnStart","msGridRow","msGridRowSpan","msGridColumn","msGridColumnSpan","fontWeight","lineHeight","opacity","order","orphans","tabSize","widows","zIndex","zoom","WebkitLineClamp","fillOpacity","floodOpacity","stopOpacity","strokeDasharray","strokeDashoffset","strokeMiterlimit","strokeOpacity","strokeWidth","reactPropsRegex","arg","freeze","styledComponentId","process","env","REACT_APP_SC_ATTR","SC_ATTR","window","Boolean","SC_DISABLE_SPEEDY","REACT_APP_SC_DISABLE_SPEEDY","groupSizes","Uint32Array","tag","indexOfGroup","insertRules","insertRule","clearGroup","deleteRule","getGroup","getRule","Map","V","has","registerName","textContent","getTag","__webpack_nonce__","document","head","createElement","childNodes","nodeType","hasAttribute","nextSibling","setAttribute","insertBefore","$","element","appendChild","createTextNode","sheet","styleSheets","ownerNode","cssRules","cssText","nodes","removeChild","rules","splice","isServer","useCSSOMInjection","gs","names","server","querySelectorAll","getAttribute","parentNode","registerId","reconstructWithOptions","allocateGSInstance","hasNameForId","add","Set","clearNames","clear","clearRules","clearTag","size","ee","te","ne","oe","se","staticRulesId","isStatic","componentId","baseHash","baseStyle","generateAndInjectStyles","hash","Ne","ie","ae","ce","plugins","lastIndexOf","ue","de","Consumer","he","pe","fe","ye","stylisPlugins","disableCSSOMInjection","disableVendorPrefixes","Provider","value","children","ve","inject","getName","ge","Se","we","Ee","be","_e","isReactComponent","isCss","Ae","Ce","De","je","Te","ke","Ve","Be","ze","Me","Ge","Ye","qe","attrs","xe","parentComponentId","shouldForwardProp","componentStyle","foldedComponentIds","theme","Re","$as","as","style","className","withComponent","_foldedDefaultProps","He","withConfig","createStyles","removeStyles","renderStyles","_emitSheetCSS","instance","getStyleTags","sealed","getStyleElement","dangerouslySetInnerHTML","__html","nonce","seal","collectStyles","interleaveWithNodeStream","download","blob","Blob","URL","createObjectURL","href","click","getElement","timeout","delay","reject","timer","setInterval","clearInterval","submissionOnMarkChange","onMarkChange","root","Reflect","getFiber","roots","complete","queue","node","searchProperty","paths","parent","getObjByPaths","Container","styled","Button","primary","css","useState","option","setOption","isDownloading","setDownloading","progress","setProgress","handleChange","handleClick","pathnames","location","pathname","leetCodeApi","origin","getSubmissionDetail","getAllQuestions","find","title","total","getCodeByTime","getCodeByMemory","titleSlug","onChange","checked","htmlFor","onClick","formatTime","floor","Content","slug","hidden","setHidden","Date","setStart","isDone","setIsDone","setTime","cacheTime","useRef","useEffect","valueOf","done","restart","useTimer","getSubmissionId","getSubmissions","submissions","pendingSubmission","timestamp","isPending","check","state","cancel","submitBtn","status_msg","padStart","addEventListener","removeEventListener","borderTopLeftRadius","borderBottomLeftRadius","loadDownload","HTMLElement","display","justifyContent","append","onload","main","prepend","alignItems"],"sourceRoot":""} \ No newline at end of file diff --git a/docs/assets/block.gif b/docs/assets/block.gif new file mode 100644 index 0000000..c37b86f Binary files /dev/null and b/docs/assets/block.gif differ diff --git a/docs/assets/get_it_from_edge.png b/docs/assets/get_it_from_edge.png new file mode 100644 index 0000000..2a488b7 Binary files /dev/null and b/docs/assets/get_it_from_edge.png differ diff --git a/docs/assets/options.png b/docs/assets/options.png new file mode 100644 index 0000000..4193aeb Binary files /dev/null and b/docs/assets/options.png differ diff --git a/docs/assets/rating-predictor.png b/docs/assets/rating-predictor.png new file mode 100644 index 0000000..535f9b2 Binary files /dev/null and b/docs/assets/rating-predictor.png differ diff --git a/docs/assets/show-extension.png b/docs/assets/show-extension.png new file mode 100644 index 0000000..8e4eb2e Binary files /dev/null and b/docs/assets/show-extension.png differ diff --git a/docs/assets/show-file-icon.png b/docs/assets/show-file-icon.png new file mode 100644 index 0000000..2cddd45 Binary files /dev/null and b/docs/assets/show-file-icon.png differ diff --git a/docs/assets/slug.png b/docs/assets/slug.png new file mode 100644 index 0000000..563d701 Binary files /dev/null and b/docs/assets/slug.png differ diff --git a/docs/assets/trynow.png b/docs/assets/trynow.png new file mode 100644 index 0000000..a5f08bd Binary files /dev/null and b/docs/assets/trynow.png differ diff --git "a/docs/assets/\344\270\264\346\227\266\350\247\243\351\231\244\351\273\221\345\220\215\345\215\225.gif" "b/docs/assets/\344\270\264\346\227\266\350\247\243\351\231\244\351\273\221\345\220\215\345\215\225.gif" new file mode 100755 index 0000000..cfb3d72 Binary files /dev/null and "b/docs/assets/\344\270\264\346\227\266\350\247\243\351\231\244\351\273\221\345\220\215\345\215\225.gif" differ diff --git "a/docs/assets/\345\210\240\351\231\244\351\273\221\345\220\215\345\215\225.gif" "b/docs/assets/\345\210\240\351\231\244\351\273\221\345\220\215\345\215\225.gif" new file mode 100755 index 0000000..ff83391 Binary files /dev/null and "b/docs/assets/\345\210\240\351\231\244\351\273\221\345\220\215\345\215\225.gif" differ diff --git "a/docs/assets/\345\256\236\346\227\266\351\242\204\346\265\213.gif" "b/docs/assets/\345\256\236\346\227\266\351\242\204\346\265\213.gif" new file mode 100644 index 0000000..6d91ec4 Binary files /dev/null and "b/docs/assets/\345\256\236\346\227\266\351\242\204\346\265\213.gif" differ diff --git "a/docs/assets/\345\256\236\346\227\266\351\242\204\346\265\213\351\205\215\347\275\256.png" "b/docs/assets/\345\256\236\346\227\266\351\242\204\346\265\213\351\205\215\347\275\256.png" new file mode 100644 index 0000000..f8ad08c Binary files /dev/null and "b/docs/assets/\345\256\236\346\227\266\351\242\204\346\265\213\351\205\215\347\275\256.png" differ diff --git "a/docs/assets/\346\211\223\345\274\200\351\273\221\345\220\215\345\215\225\345\210\227\350\241\250.gif" "b/docs/assets/\346\211\223\345\274\200\351\273\221\345\220\215\345\215\225\345\210\227\350\241\250.gif" new file mode 100755 index 0000000..c6d1d9b Binary files /dev/null and "b/docs/assets/\346\211\223\345\274\200\351\273\221\345\220\215\345\215\225\345\210\227\350\241\250.gif" differ diff --git "a/docs/assets/\346\274\224\347\244\272\346\213\226\346\213\275\346\211\213\346\237\204.gif" "b/docs/assets/\346\274\224\347\244\272\346\213\226\346\213\275\346\211\213\346\237\204.gif" new file mode 100755 index 0000000..930529d Binary files /dev/null and "b/docs/assets/\346\274\224\347\244\272\346\213\226\346\213\275\346\211\213\346\237\204.gif" differ diff --git "a/docs/assets/\346\274\224\347\244\272\346\213\226\346\213\275\351\223\276\346\216\245.gif" "b/docs/assets/\346\274\224\347\244\272\346\213\226\346\213\275\351\223\276\346\216\245.gif" new file mode 100755 index 0000000..6d02b7a Binary files /dev/null and "b/docs/assets/\346\274\224\347\244\272\346\213\226\346\213\275\351\223\276\346\216\245.gif" differ diff --git "a/docs/assets/\347\253\236\350\265\233\347\255\224\351\242\230\351\241\265\350\207\252\345\256\232\344\271\211\345\270\203\345\261\200.png" "b/docs/assets/\347\253\236\350\265\233\347\255\224\351\242\230\351\241\265\350\207\252\345\256\232\344\271\211\345\270\203\345\261\200.png" new file mode 100644 index 0000000..8ed01d9 Binary files /dev/null and "b/docs/assets/\347\253\236\350\265\233\347\255\224\351\242\230\351\241\265\350\207\252\345\256\232\344\271\211\345\270\203\345\261\200.png" differ diff --git "a/docs/assets/\350\207\252\345\256\232\344\271\211\351\242\230\345\215\225\347\256\241\347\220\206.png" "b/docs/assets/\350\207\252\345\256\232\344\271\211\351\242\230\345\215\225\347\256\241\347\220\206.png" new file mode 100644 index 0000000..70f76d1 Binary files /dev/null and "b/docs/assets/\350\207\252\345\256\232\344\271\211\351\242\230\345\215\225\347\256\241\347\220\206.png" differ diff --git "a/docs/assets/\351\242\230\345\215\225\345\256\241\346\240\270.png" "b/docs/assets/\351\242\230\345\215\225\345\256\241\346\240\270.png" new file mode 100644 index 0000000..e8f630a Binary files /dev/null and "b/docs/assets/\351\242\230\345\215\225\345\256\241\346\240\270.png" differ diff --git "a/docs/assets/\351\242\230\345\215\225\351\241\265\344\276\247\350\276\271\346\240\217.png" "b/docs/assets/\351\242\230\345\215\225\351\241\265\344\276\247\350\276\271\346\240\217.png" new file mode 100644 index 0000000..f5f2db2 Binary files /dev/null and "b/docs/assets/\351\242\230\345\215\225\351\241\265\344\276\247\350\276\271\346\240\217.png" differ diff --git "a/docs/assets/\351\242\230\345\272\223\351\241\265\351\242\230\345\215\225\344\276\247\350\276\271\346\240\217.png" "b/docs/assets/\351\242\230\345\272\223\351\241\265\351\242\230\345\215\225\344\276\247\350\276\271\346\240\217.png" new file mode 100644 index 0000000..89dc8fd Binary files /dev/null and "b/docs/assets/\351\242\230\345\272\223\351\241\265\351\242\230\345\215\225\344\276\247\350\276\271\346\240\217.png" differ diff --git "a/docs/\345\274\200\345\217\221.md" "b/docs/\345\274\200\345\217\221.md" new file mode 100644 index 0000000..591f371 --- /dev/null +++ "b/docs/\345\274\200\345\217\221.md" @@ -0,0 +1,48 @@ +## 开发 + +首先需要安装运行环境 [Node.js](https://nodejs.org/en/download/)(>=v14),以及依赖管理工具 [pnpm](https://pnpm.io/) + +> 依赖管理工具可以使用 yarn 或者 npm 替代,下面使用 pnpm 演示 + +### 下载 + +```sh +git clone https://github.com/XYShaoKang/refined-leetcode.git +cd refined-leetcode +``` + +### 安装依赖 + +```sh +pnpm install +``` + +安装的时候,如果遇到 electron postinstall 安装失败的错误, 一般是因为网络问题,可以通过将 electron 的源设置为国内源解决。 + +通过修改 home 目录下的 `.npmrc` 或者直接在项目根目录下新建一个 `.npmrc` 文件,输入以下内容,保存后,在尝试安装 + +```sh +electron_mirror=https://npmmirror.com/mirrors/electron/ +``` + +### 运行 + +```sh +pnpm dev +``` + +### 加载扩展 + +运行之后会在项目中生成 dist 文件夹,之后进行如下操作 + +1. 打开 Chrome 浏览器 +2. 转到 chrome://extensions/ 页面 +3. 打开页面右上角的开发者模式 +4. 点击页面左上角的 `加载以解压的扩展程序` 按钮 +5. 选择到 dist 路径,再点击确定即可 + +### 热模块加载 + +对于 content 的页面开发,已经配置好了热模块加载([Hot Module Replacement](https://webpack.js.org/concepts/hot-module-replacement/))功能,React 组件内的大多数修改应该都能实时反应到页面中,可能有些特殊情况或者是修改 React 外部的代码时,页面会重新加载,不过这些都会自动完成. + +如果是需要修改 background 中的代码,保存之后,等待编译完成,需要到扩展页面,手动按刷新按钮才行. diff --git "a/docs/\347\253\236\350\265\233\346\216\222\345\220\215\351\241\265.md" "b/docs/\347\253\236\350\265\233\346\216\222\345\220\215\351\241\265.md" new file mode 100644 index 0000000..a237f18 --- /dev/null +++ "b/docs/\347\253\236\350\265\233\346\216\222\345\220\215\351\241\265.md" @@ -0,0 +1,63 @@ +# 竞赛排名页 + +## 显示预测 + +- 2022-02-24 完成初始版本 +- 2022-11-27 更新预测数据源 + +此功能源码 [src/content/pages/ranking](../src/content/pages/ranking) + +目前预测数据 API 已经切换至 https://lccn.lbao.site/,欢迎大家到作者的仓库中 https://github.com/baoliay2008/lccn_predictor 点点 Star + +> ~~效果如下,预测数据来自 https://lcpredictor.herokuapp.com/~~ +> +> https://lcpredictor.herokuapp.com/ 目前在[迁移](https://github.com/SysSn13/leetcode-rating-predictor/issues/48),旧的 API 已经失效,新的 API 未知,无法获取数据。 + +![rating-predictor](assets/rating-predictor.png) + +## 竞赛排名页面显示代码对应的语言图标 + +- 2022-03-09 完成初始版本 + +此功能源码 [src/content/pages/ranking/FileIcon.tsx](../src/content/pages/ranking/FileIcon.tsx) + +在排名页列表中的提交时间前面,将之前代码图标替换为提交所使用的语言对应的图标,这样可以很直观的看到选手提交所使用的语言 + +这样如果我只想看某种语言的提交,就不需要一个个点进去看,可以节省很多时间 + +> 由于世界服 API 返回的数据没有对应提交的语言标记,所以目前只支持国服的排名页 + +![show-file-icon](./assets/show-file-icon.png) + +演示 + +https://user-images.githubusercontent.com/38753204/212783934-2383f4a5-caf5-4997-b166-c13a6996ddd6.mp4 + +## 实时预测 + +- 2023-03-18 添加 + +在客户端根据选手的得分和完成时间实时计算预测分数,计算时会消耗一定的性能,所以最好是在有需要时在开启。可以在配置选项中控制功能的开关。 + +![实时预测配置](./assets/实时预测配置.png) + +另外实时预测会存在一定的误差,计算结果仅供参考。 + +为了跟榜单预测进行区分,实时预测外侧会添加一个虚线框。 + +演示 + +https://user-images.githubusercontent.com/38753204/226372446-6861c5e7-4a23-4a57-a1c6-3314229ed29c.mp4 + +### 预测算法说明 + +预测算法源码:[src/content/utils/predict.ts](../src/content/utils/predict.ts) + +- 因为无法区分 0 分选手属于未参赛,还是有提交但 WA 掉的,所以对于这部分选手进行特殊处理。目前采用的策略是直接过滤这部分选手。虽然这会造成一开始 AK 的选手预测结果误差较大,但随着比赛时间慢慢进行,这个误差也会慢慢缩小。 +- 对于相同分数并且相同完成时间的选手排名计算,首先会计算有多少选手是比这个分数和时间更快,然后在此基础上加 1,所以相同分数和相同完成时间的选手,会有一样的排名。 +- 为了提高性能,会先预处理 `[0,8000]` 范围内的 ERank,预测是只需要在这个范围内二分查找对应的 ERank 即可。 +- 但如果按照正常的算法去预处理 ERank 大概需要 5s 以上,虽然预处理后就可以重复使用,但第一次打开页面时的体验很不好。这个问题通过使用 FFT 来加速预处理 ERank 得到解决,使用 FFT 加速之后,预处理 ERank 就只需要 100ms~200ms 左右,速度非常快。 + +> FFT 加速的思路来自于 [Carrot](https://github.com/meooow25/carrot),但其实我一开始是看不懂的,好在经过 [@tiger2005](https://leetcode.cn/u/u/tiger2005/) 大佬的讲解并实现了代码,我了解了如何使用,并在项目中实际用上 FFT 加速,从而提升了预测算法的性能。同时非常感谢 [@tiger2005](https://leetcode.cn/u/u/tiger2005/) 大佬,在预测算法的优化过程中,提供的指导和反馈。 +> +> 以上测试的时间,均来自于我本地的测试结果。 diff --git "a/docs/\347\255\224\351\242\230\351\241\265.md" "b/docs/\347\255\224\351\242\230\351\241\265.md" new file mode 100644 index 0000000..d1989da --- /dev/null +++ "b/docs/\347\255\224\351\242\230\351\241\265.md" @@ -0,0 +1,63 @@ +# 答题页 + +- 2022-01-02 完成初始版本 +- 2022-01-03 自动添加标记的功能 +- 2022-10-22 适配力扣新版 UI +- 2022-11-1 添加随机一题按钮 +- 2022-11-1 阻止保存页面的弹窗 + +此功能源码 [src/content/pages/problems](../src/content/pages/problems/) + +## 计时器 + +> 此功能的最初创意由 https://leetcode-cn.com/u/s192516/ 提出 + +进入答题页时,自动开始计时,第一次提交成功之后会停止计时,并显示所用时间 + +计时器位于页面右下角,提交和执行代码按钮的左边. + +目前提供三种操作,分别是在计时阶段: + +提供隐藏时钟的操作 + +![](assets/hidden.png) + +重新显示时钟的操作 + +![](assets/show.png) + +以及在结束之后,重新开始的操作 + +![](assets/restart.png) + +计时器操作演示 + +https://user-images.githubusercontent.com/38753204/212781557-bcfbeb61-d7ff-413f-922a-da65db24bb85.mp4 + +## 自动添加标记的功能 + +当成功提交之后,会将当前所有时间自动添加到对应提交的标记中 + +![](assets/mark.png) + +新版答题页演示 + +https://user-images.githubusercontent.com/38753204/212781261-a6b6a367-8773-49ca-85a5-cef4738a0a73.mp4 + +## 随机一题按钮 + +`随机一题`按钮位于上方导航栏处,跟`上一题`、`下一题`等按钮放在一块,在随机刷题的计划中,不用每次都返回题库页去点击`随机一题`。 + +## 比赛答题页提供快捷键禁用选项 + +比赛的时候,直接在网页写题的时候,经常会发生按到某个快捷键的情况,比如像 Cmd+S 会触发页面保存,当然这个只要按下取消就好了,但如果是不小心按到提交的快捷键,则会造成罚时,导致比赛失利。 + +所以我添加了一个禁用快捷键的选项,启用后会禁止触发这些快捷键,防止意外发生。 + +## 比赛答题页自定义布局 + +来自 [https://github.com/acfinity](https://github.com/acfinity) 的贡献 + +将布局切换成横向布局,更加贴近平常刷题的界面,以及更加容易一遍看题目一遍写代码。另外还支持拖动改变题目和编辑框的宽度。 + +![](assets/%E7%AB%9E%E8%B5%9B%E7%AD%94%E9%A2%98%E9%A1%B5%E8%87%AA%E5%AE%9A%E4%B9%89%E5%B8%83%E5%B1%80.png) diff --git "a/docs/\351\205\215\347\275\256\351\200\211\351\241\271.md" "b/docs/\351\205\215\347\275\256\351\200\211\351\241\271.md" new file mode 100644 index 0000000..cb58076 --- /dev/null +++ "b/docs/\351\205\215\347\275\256\351\200\211\351\241\271.md" @@ -0,0 +1,11 @@ +# 配置选项 + +- 2022-01-31 完成初始版本 + +通过配置选项,去控制扩展各个功能的开关。安装后启用扩展,可以通过左键点击浏览器右上角的扩展图标,在弹出的窗口中进行配置。或者是右键点击扩展图标,在点击选项,会打开一个网页,可以在其中进行配置。 + +![options](assets/options.png) + +新版本的 Chrome 默认会隐藏扩展图标,可以通过点击拼图图标,在其中找到扩展图标进行操作。另外可以通过点击固定图标,将扩展图标固定显示出来。 + +![show-extension](assets/show-extension.png) diff --git "a/docs/\351\242\230\345\215\225\347\256\241\347\220\206.md" "b/docs/\351\242\230\345\215\225\347\256\241\347\220\206.md" new file mode 100644 index 0000000..aec94e0 --- /dev/null +++ "b/docs/\351\242\230\345\215\225\347\256\241\347\220\206.md" @@ -0,0 +1,44 @@ +# 题单管理 + +- 2023-01-03 在题库页和题单页新增侧边栏,通过鼠标点击展开,提供对题单的管理和浏览 +- 2023-01-17 引入题目评分数据 + +## 侧边栏 + +题库页位置 + +![题库页题单侧边栏](assets/%E9%A2%98%E5%BA%93%E9%A1%B5%E9%A2%98%E5%8D%95%E4%BE%A7%E8%BE%B9%E6%A0%8F.png) + +题单页位置 + +![题单页侧边栏](assets/%E9%A2%98%E5%8D%95%E9%A1%B5%E4%BE%A7%E8%BE%B9%E6%A0%8F.png) + +自定义题单提供增删改查等功能 + +![自定义题单管理](assets/%E8%87%AA%E5%AE%9A%E4%B9%89%E9%A2%98%E5%8D%95%E7%AE%A1%E7%90%86.png) + +目前题单的创建和修改名称都是需要经过审核的,为了更方便了解当前的状态,在处于审核状态的题单前面会有一个旋转的「审」字,如果检测到审核通过,则会自动取消。在审核中的题单无法修改名称和可见度,但可以被删除和添加题目 + +![题单审核](assets/%E9%A2%98%E5%8D%95%E5%AE%A1%E6%A0%B8.png) + +演示 + +https://user-images.githubusercontent.com/38753204/212785117-470c750b-30ae-4dc7-bc15-1e548eed46b1.mp4 + +## 题目评分 + +筛选出指定评分范围的题目 + +https://user-images.githubusercontent.com/38753204/212785264-85e030ed-844e-44f3-81c3-36da652692cf.mp4 + +按照评分进行排序 + +https://user-images.githubusercontent.com/38753204/212785300-37f93904-1550-44fe-a950-2ed375ea2cd4.mp4 + +将筛选出来的题目添加到题单中,注意题单最多只能添加 200 个题目,超出则不让添加 + +https://user-images.githubusercontent.com/38753204/212785367-0799f8c7-4465-49e4-b779-6de6c6981136.mp4 + +关闭和开启评分功能 + +https://user-images.githubusercontent.com/38753204/212886717-bbe4b613-ebcb-40c5-a515-24ba8053d6fb.mp4 diff --git "a/docs/\351\246\226\351\241\265\345\270\226\345\255\220\351\273\221\345\220\215\345\215\225.md" "b/docs/\351\246\226\351\241\265\345\270\226\345\255\220\351\273\221\345\220\215\345\215\225.md" new file mode 100644 index 0000000..38d31d0 --- /dev/null +++ "b/docs/\351\246\226\351\241\265\345\270\226\345\255\220\351\273\221\345\220\215\345\215\225.md" @@ -0,0 +1,38 @@ +# 首页帖子黑名单 + +- 2022-10-21 完成初始版本 +- 2022-11-14 更新添加黑名单的快捷方式 + +此功能源码 [src/content/pages/home](../src/content/pages/home) + +通过添加黑名单用户,可以阻止该用户的帖子在首页显示。黑名单数据只存储在本地,如果有多个地方使用的话,则需要在对应的浏览器上添加黑名单。目前只支持首页的帖子中过滤掉黑名单用户发的帖子。 + +安装扩展之后,会在首页右边栏最上方出现一栏黑名单管理的组件,点击可以对当前黑名单列表进行添加和删除等管理。 + +## 打开黑名单列表 + +![打开黑名单列表](assets/打开黑名单列表.gif) + +## 手动输入 slug 添加黑名单 + +![演示添加黑名单](assets/block.gif) + +如果要将某个用户添加到黑名单中,需要输入其 slug,可以从其个人主页获取,一般会出现在昵称的下面,或者是个人主页 url 的最后一段。 + +![slug 位置](assets/slug.png) + +## 通过添加拖拽手柄添加 + +![演示拖拽手柄](assets/演示拖拽手柄.gif) + +## 通过拖拽链接添加 + +![演示拖拽链接](assets/演示拖拽链接.gif) + +## 临时解除黑名单 + +![临时解除黑名单](assets/临时解除黑名单.gif) + +## 删除黑名单 + +![删除黑名单](assets/删除黑名单.gif) diff --git a/package.json b/package.json index a208fa0..f4c9113 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { - "name": "leetcode-extend", - "version": "0.0.19", + "name": "refined-leetcode", + "version": "0.14.4", "main": "index.js", "author": "XYShaoKang", "license": "MIT", @@ -10,62 +10,91 @@ "start": "webpack serve --node-env development", "dev": "webpack serve --node-env development", "build": "webpack --node-env production", - "lint": "yarn lint:prettier && yarn lint:eslint", + "build:debug": "webpack --node-env production --env LOG_LEVEL=debug", + "packcrx": "node packcrx.js", + "lint": "pnpm lint:prettier && pnpm lint:eslint", "lint:prettier": "prettier --check src", "lint:eslint": "eslint \"src/**/*.{ts,tsx}\"", - "test": "jest" + "test": "jest", + "reduxdev": "redux-devtools --open" }, "devDependencies": { - "@babel/cli": "^7.16.0", - "@babel/core": "^7.16.0", - "@babel/plugin-proposal-class-properties": "^7.16.0", - "@babel/preset-env": "^7.16.4", - "@babel/preset-react": "^7.16.0", - "@babel/preset-typescript": "^7.16.0", - "@pmmmwh/react-refresh-webpack-plugin": "^0.5.2", - "@testing-library/dom": "^8.11.1", - "@testing-library/jest-dom": "^5.15.0", + "@babel/cli": "^7.16.8", + "@babel/core": "^7.16.7", + "@babel/plugin-proposal-class-properties": "^7.16.7", + "@babel/preset-env": "^7.16.8", + "@babel/preset-react": "^7.16.7", + "@babel/preset-typescript": "^7.16.7", + "@pmmmwh/react-refresh-webpack-plugin": "^0.5.4", + "@redux-devtools/cli": "^1.0.4", + "@semantic-release/changelog": "^6.0.1", + "@semantic-release/error": "^3.0.0", + "@semantic-release/git": "^10.0.1", + "@testing-library/dom": "^8.11.2", + "@testing-library/jest-dom": "^5.16.1", "@testing-library/react": "^12.1.2", "@testing-library/user-event": "^13.5.0", - "@types/jest": "^27.0.3", - "@types/react": "^17.0.36", + "@types/chrome": "^0.0.176", + "@types/jest": "^27.4.0", + "@types/react": "^17.0.38", "@types/react-dom": "^17.0.11", - "@types/styled-components": "^5.1.15", - "@types/testing-library__jest-dom": "^5.14.1", - "@types/webpack-dev-server": "^4.5.0", - "@typescript-eslint/eslint-plugin": "^5.4.0", - "@typescript-eslint/parser": "^5.4.0", - "babel-jest": "^27.3.1", + "@types/react-redux": "^7.1.25", + "@types/redux-logger": "^3.0.9", + "@types/redux-state-sync": "^3.1.5", + "@types/remote-redux-devtools": "^0.5.5", + "@types/styled-components": "^5.1.20", + "@types/testing-library__jest-dom": "^5.14.2", + "@types/webpack-env": "^1.16.3", + "@typescript-eslint/eslint-plugin": "^5.9.1", + "@typescript-eslint/parser": "^5.9.1", + "archiver": "^5.3.0", + "babel-jest": "^27.4.6", "babel-loader": "^8.2.3", "babel-plugin-macros": "^3.1.0", "clean-webpack-plugin": "^4.0.0", - "css-loader": "^6.5.1", - "eslint": "^8.3.0", + "copy-webpack-plugin": "^10.2.0", + "crx": "^5.0.1", + "eslint": "^8.7.0", "eslint-config-prettier": "^8.3.0", - "eslint-plugin-import": "^2.25.3", + "eslint-import-resolver-typescript": "^3.5.2", + "eslint-plugin-import": "^2.25.4", "eslint-plugin-jsx-a11y": "^6.5.1", "eslint-plugin-prettier": "^4.0.0", - "eslint-plugin-react": "^7.27.1", + "eslint-plugin-react": "^7.28.0", "eslint-plugin-react-hooks": "^4.3.0", "file-loader": "^6.2.0", "html-webpack-plugin": "^5.5.0", - "jest": "^27.3.1", - "prettier": "^2.4.1", + "jest": "^27.4.7", + "prettier": "^2.5.1", + "react-devtools": "^4.22.1", "react-is": "^17.0.2", "react-refresh": "^0.11.0", + "remote-redux-devtools": "^0.5.16", + "semantic-release": "^19.0.2", "style-loader": "^3.3.1", - "type-fest": "^2.8.0", - "typescript": "^4.5.2", - "webpack": "^5.64.2", + "tapable": "^2.2.1", + "typescript": "^4.5.4", + "webpack": "^5.66.0", "webpack-cli": "^4.9.1", - "webpack-dev-server": "^4.5.0", + "webpack-dev-server": "^4.7.3", "webpack-merge": "^5.8.0", "whatwg-fetch": "^3.6.2" }, "dependencies": { - "minimatch": "^3.0.4", + "@reduxjs/toolkit": "^1.7.1", + "date-fns": "^2.28.0", + "json5": "^2.2.3", + "localforage": "^1.10.0", + "pino": "^7.11.0", "react": "^17.0.2", + "react-dnd": "^16.0.1", + "react-dnd-html5-backend": "^16.0.1", "react-dom": "^17.0.2", + "react-redux": "^7.2.6", + "redux": "^4.1.2", + "redux-logger": "^3.0.6", + "redux-persist": "^6.0.0", + "redux-state-sync": "^3.1.4", "styled-components": "^5.3.3" } -} +} \ No newline at end of file diff --git a/packcrx.js b/packcrx.js new file mode 100644 index 0000000..4cd8568 --- /dev/null +++ b/packcrx.js @@ -0,0 +1,27 @@ +const fs = require('fs') +const path = require('path') +const ChromeExtension = require('crx') + +const getKey = () => { + let { PRIVATE_KEY, PRIVATE_KEY_PATH } = process.env + if (PRIVATE_KEY) return Buffer.from(PRIVATE_KEY, 'utf-8') + + try { + const keyPath = PRIVATE_KEY_PATH || path.join(__dirname, './key.pem') + fs.accessSync(keyPath, fs.constants.W_OK) + return fs.readFileSync(keyPath) + } catch (error) { + throw new Error('请设置 PRIVATE_KEY 或 PRIVATE_KEY_PATH') + } +} + +const crx = new ChromeExtension({ + privateKey: getKey(), +}) + +crx + .load(path.join(__dirname, './dist/')) + .then(crx => crx.pack()) + .then(crxBuffer => { + fs.writeFileSync(path.join(__dirname, './refined-leetcode.crx'), crxBuffer) + }) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3007174..6d80af2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,119 +1,214 @@ -lockfileVersion: 5.3 +lockfileVersion: 5.4 specifiers: - '@babel/cli': ^7.16.0 - '@babel/core': ^7.16.0 - '@babel/plugin-proposal-class-properties': ^7.16.0 - '@babel/preset-env': ^7.16.4 - '@babel/preset-react': ^7.16.0 - '@babel/preset-typescript': ^7.16.0 - '@pmmmwh/react-refresh-webpack-plugin': ^0.5.2 - '@testing-library/dom': ^8.11.1 - '@testing-library/jest-dom': ^5.15.0 + '@babel/cli': ^7.16.8 + '@babel/core': ^7.16.7 + '@babel/plugin-proposal-class-properties': ^7.16.7 + '@babel/preset-env': ^7.16.8 + '@babel/preset-react': ^7.16.7 + '@babel/preset-typescript': ^7.16.7 + '@pmmmwh/react-refresh-webpack-plugin': ^0.5.4 + '@redux-devtools/cli': ^1.0.4 + '@reduxjs/toolkit': ^1.7.1 + '@semantic-release/changelog': ^6.0.1 + '@semantic-release/error': ^3.0.0 + '@semantic-release/git': ^10.0.1 + '@testing-library/dom': ^8.11.2 + '@testing-library/jest-dom': ^5.16.1 '@testing-library/react': ^12.1.2 '@testing-library/user-event': ^13.5.0 - '@types/jest': ^27.0.3 - '@types/react': ^17.0.36 + '@types/chrome': ^0.0.176 + '@types/jest': ^27.4.0 + '@types/react': ^17.0.38 '@types/react-dom': ^17.0.11 - '@types/styled-components': ^5.1.15 - '@types/testing-library__jest-dom': ^5.14.1 - '@types/webpack-dev-server': ^4.5.0 - '@typescript-eslint/eslint-plugin': ^5.4.0 - '@typescript-eslint/parser': ^5.4.0 - babel-jest: ^27.3.1 + '@types/react-redux': ^7.1.25 + '@types/redux-logger': ^3.0.9 + '@types/redux-state-sync': ^3.1.5 + '@types/remote-redux-devtools': ^0.5.5 + '@types/styled-components': ^5.1.20 + '@types/testing-library__jest-dom': ^5.14.2 + '@types/webpack-env': ^1.16.3 + '@typescript-eslint/eslint-plugin': ^5.9.1 + '@typescript-eslint/parser': ^5.9.1 + archiver: ^5.3.0 + babel-jest: ^27.4.6 babel-loader: ^8.2.3 babel-plugin-macros: ^3.1.0 clean-webpack-plugin: ^4.0.0 - css-loader: ^6.5.1 - eslint: ^8.3.0 + copy-webpack-plugin: ^10.2.0 + crx: ^5.0.1 + date-fns: ^2.28.0 + eslint: ^8.7.0 eslint-config-prettier: ^8.3.0 - eslint-plugin-import: ^2.25.3 + eslint-import-resolver-typescript: ^3.5.2 + eslint-plugin-import: ^2.25.4 eslint-plugin-jsx-a11y: ^6.5.1 eslint-plugin-prettier: ^4.0.0 - eslint-plugin-react: ^7.27.1 + eslint-plugin-react: ^7.28.0 eslint-plugin-react-hooks: ^4.3.0 file-loader: ^6.2.0 html-webpack-plugin: ^5.5.0 - jest: ^27.3.1 - minimatch: ^3.0.4 - prettier: ^2.4.1 + jest: ^27.4.7 + json5: ^2.2.3 + localforage: ^1.10.0 + pino: ^7.11.0 + prettier: ^2.5.1 react: ^17.0.2 + react-devtools: ^4.22.1 + react-dnd: ^16.0.1 + react-dnd-html5-backend: ^16.0.1 react-dom: ^17.0.2 react-is: ^17.0.2 + react-redux: ^7.2.6 react-refresh: ^0.11.0 + redux: ^4.1.2 + redux-logger: ^3.0.6 + redux-persist: ^6.0.0 + redux-state-sync: ^3.1.4 + remote-redux-devtools: ^0.5.16 + semantic-release: ^19.0.2 style-loader: ^3.3.1 styled-components: ^5.3.3 - type-fest: ^2.8.0 - typescript: ^4.5.2 - webpack: ^5.64.2 + tapable: ^2.2.1 + typescript: ^4.5.4 + webpack: ^5.66.0 webpack-cli: ^4.9.1 - webpack-dev-server: ^4.5.0 + webpack-dev-server: ^4.7.3 webpack-merge: ^5.8.0 whatwg-fetch: ^3.6.2 dependencies: - minimatch: 3.0.4 + '@reduxjs/toolkit': 1.7.2_g7iv2n2puphpvmcbz4lgg4le54 + date-fns: 2.28.0 + json5: 2.2.3 + localforage: 1.10.0 + pino: 7.11.0 react: 17.0.2 + react-dnd: 16.0.1_udcsdvdzjr5ns727jqoeu7kyda + react-dnd-html5-backend: 16.0.1 react-dom: 17.0.2_react@17.0.2 - styled-components: 5.3.3_281a4fa50a045c9112baf635f3bc27a7 + react-redux: 7.2.6_sfoxds7t5ydpegc3knd667wn6m + redux: 4.1.2 + redux-logger: 3.0.6 + redux-persist: 6.0.0_react@17.0.2+redux@4.1.2 + redux-state-sync: 3.1.4 + styled-components: 5.3.3_fane7jikarojcev26y27hpbhu4 devDependencies: - '@babel/cli': 7.16.0_@babel+core@7.16.0 - '@babel/core': 7.16.0 - '@babel/plugin-proposal-class-properties': 7.16.0_@babel+core@7.16.0 - '@babel/preset-env': 7.16.4_@babel+core@7.16.0 - '@babel/preset-react': 7.16.0_@babel+core@7.16.0 - '@babel/preset-typescript': 7.16.0_@babel+core@7.16.0 - '@pmmmwh/react-refresh-webpack-plugin': 0.5.2_a5fd73e8f007f6df7a56d6f8dc678958 - '@testing-library/dom': 8.11.1 - '@testing-library/jest-dom': 5.15.0 - '@testing-library/react': 12.1.2_react-dom@17.0.2+react@17.0.2 - '@testing-library/user-event': 13.5.0_@testing-library+dom@8.11.1 - '@types/jest': 27.0.3 - '@types/react': 17.0.36 + '@babel/cli': 7.17.3_@babel+core@7.17.4 + '@babel/core': 7.17.4 + '@babel/plugin-proposal-class-properties': 7.16.7_@babel+core@7.17.4 + '@babel/preset-env': 7.16.11_@babel+core@7.17.4 + '@babel/preset-react': 7.16.7_@babel+core@7.17.4 + '@babel/preset-typescript': 7.16.7_@babel+core@7.17.4 + '@pmmmwh/react-refresh-webpack-plugin': 0.5.4_tpiyiaculwakb4my4mlnuh4syi + '@redux-devtools/cli': 1.0.6_cz5jwzb6rw5xqianyejpzuh5ja + '@semantic-release/changelog': 6.0.1_semantic-release@19.0.2 + '@semantic-release/error': 3.0.0 + '@semantic-release/git': 10.0.1_semantic-release@19.0.2 + '@testing-library/dom': 8.11.3 + '@testing-library/jest-dom': 5.16.2 + '@testing-library/react': 12.1.2_sfoxds7t5ydpegc3knd667wn6m + '@testing-library/user-event': 13.5.0_gzufz4q333be4gqfrvipwvqt6a + '@types/chrome': 0.0.176 + '@types/jest': 27.4.0 + '@types/react': 17.0.39 '@types/react-dom': 17.0.11 - '@types/styled-components': 5.1.15 - '@types/testing-library__jest-dom': 5.14.1 - '@types/webpack-dev-server': 4.5.0_webpack-cli@4.9.1 - '@typescript-eslint/eslint-plugin': 5.4.0_5c8ff4cecd5a55e744866c0654edac32 - '@typescript-eslint/parser': 5.4.0_eslint@8.3.0+typescript@4.5.2 - babel-jest: 27.3.1_@babel+core@7.16.0 - babel-loader: 8.2.3_95e63ddb935ae8cb6c63cf95c1e0c16e + '@types/react-redux': 7.1.25 + '@types/redux-logger': 3.0.9 + '@types/redux-state-sync': 3.1.5 + '@types/remote-redux-devtools': 0.5.5 + '@types/styled-components': 5.1.22 + '@types/testing-library__jest-dom': 5.14.2 + '@types/webpack-env': 1.16.3 + '@typescript-eslint/eslint-plugin': 5.12.0_yrt47g5utmuvsqpihtshtjlyw4 + '@typescript-eslint/parser': 5.12.0_fhzmdq77bspfhxkfuzq4fbrdsy + archiver: 5.3.0 + babel-jest: 27.5.1_@babel+core@7.17.4 + babel-loader: 8.2.3_6w76b5w2swsmq5slbwizdwekbi babel-plugin-macros: 3.1.0 - clean-webpack-plugin: 4.0.0_webpack@5.64.2 - css-loader: 6.5.1_webpack@5.64.2 - eslint: 8.3.0 - eslint-config-prettier: 8.3.0_eslint@8.3.0 - eslint-plugin-import: 2.25.3_eslint@8.3.0 - eslint-plugin-jsx-a11y: 6.5.1_eslint@8.3.0 - eslint-plugin-prettier: 4.0.0_6c1acfc8d9d3a8dba99beef4e8bcebae - eslint-plugin-react: 7.27.1_eslint@8.3.0 - eslint-plugin-react-hooks: 4.3.0_eslint@8.3.0 - file-loader: 6.2.0_webpack@5.64.2 - html-webpack-plugin: 5.5.0_webpack@5.64.2 - jest: 27.3.1 - prettier: 2.4.1 + clean-webpack-plugin: 4.0.0_webpack@5.69.0 + copy-webpack-plugin: 10.2.4_webpack@5.69.0 + crx: 5.0.1 + eslint: 8.9.0 + eslint-config-prettier: 8.3.0_eslint@8.9.0 + eslint-import-resolver-typescript: 3.5.2_cmtdok55f7srt3k3ux6kqq5jcq + eslint-plugin-import: 2.25.4_oaka2ueiwurhrio2l3qatfl7wa + eslint-plugin-jsx-a11y: 6.5.1_eslint@8.9.0 + eslint-plugin-prettier: 4.0.0_a62cezdlw5ot3n4rmiou7w6jsi + eslint-plugin-react: 7.28.0_eslint@8.9.0 + eslint-plugin-react-hooks: 4.3.0_eslint@8.9.0 + file-loader: 6.2.0_webpack@5.69.0 + html-webpack-plugin: 5.5.0_webpack@5.69.0 + jest: 27.5.1 + prettier: 2.5.1 + react-devtools: 4.23.0 react-is: 17.0.2 react-refresh: 0.11.0 - style-loader: 3.3.1_webpack@5.64.2 - type-fest: 2.8.0 - typescript: 4.5.2 - webpack: 5.64.2_webpack-cli@4.9.1 - webpack-cli: 4.9.1_5bf98977c75b4da48bb2f18b6135c48d - webpack-dev-server: 4.5.0_webpack-cli@4.9.1+webpack@5.64.2 + remote-redux-devtools: 0.5.16_redux@4.1.2 + semantic-release: 19.0.2 + style-loader: 3.3.1_webpack@5.69.0 + tapable: 2.2.1 + typescript: 4.5.5 + webpack: 5.69.0_webpack-cli@4.9.1 + webpack-cli: 4.9.1_cpiwtwqgcyyvqiqogay7dd4uam + webpack-dev-server: 4.7.4_3awzrjtbpxvmpzpfa3syzgxzq4 webpack-merge: 5.8.0 whatwg-fetch: 3.6.2 packages: - /@babel/cli/7.16.0_@babel+core@7.16.0: - resolution: {integrity: sha512-WLrM42vKX/4atIoQB+eb0ovUof53UUvecb4qGjU2PDDWRiZr50ZpiV8NpcLo7iSxeGYrRG0Mqembsa+UrTAV6Q==} + /@ampproject/remapping/2.1.2: + resolution: {integrity: sha512-hoyByceqwKirw7w3Z7gnIIZC3Wx3J484Y3L/cMpXFbr7d9ZQj2mODrirNzcJa+SM3UlpWXYvKV4RlRpFXlWgXg==} + engines: {node: '>=6.0.0'} + dependencies: + '@jridgewell/trace-mapping': 0.3.4 + dev: true + + /@apollo/protobufjs/1.2.2: + resolution: {integrity: sha512-vF+zxhPiLtkwxONs6YanSt1EpwpGilThpneExUN5K3tCymuxNnVq2yojTvnpRjv2QfsEIt/n7ozPIIzBLwGIDQ==} + hasBin: true + requiresBuild: true + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/base64': 1.1.2 + '@protobufjs/codegen': 2.0.4 + '@protobufjs/eventemitter': 1.1.0 + '@protobufjs/fetch': 1.1.0 + '@protobufjs/float': 1.0.2 + '@protobufjs/inquire': 1.1.0 + '@protobufjs/path': 1.1.2 + '@protobufjs/pool': 1.1.0 + '@protobufjs/utf8': 1.1.0 + '@types/long': 4.0.1 + '@types/node': 10.17.60 + long: 4.0.0 + dev: true + + /@apollographql/apollo-tools/0.5.2_graphql@16.3.0: + resolution: {integrity: sha512-KxZiw0Us3k1d0YkJDhOpVH5rJ+mBfjXcgoRoCcslbgirjgLotKMzOcx4PZ7YTEvvEROmvG7X3Aon41GvMmyGsw==} + engines: {node: '>=8', npm: '>=6'} + peerDependencies: + graphql: ^14.2.1 || ^15.0.0 + dependencies: + graphql: 16.3.0 + dev: true + + /@apollographql/graphql-playground-html/1.6.29: + resolution: {integrity: sha512-xCcXpoz52rI4ksJSdOCxeOCn2DLocxwHf9dVT/Q90Pte1LX+LY+91SFtJF3KXVHH8kEin+g1KKCQPKBjZJfWNA==} + dependencies: + xss: 1.0.10 + dev: true + + /@babel/cli/7.17.3_@babel+core@7.17.4: + resolution: {integrity: sha512-1+WRlh1IqLocOp122CLx4if345RSHMspwIZNJTlqG/GA46HVZC6p49N1kolfdd2/GOdr+tu4nScbAR3ACJ2ZiA==} engines: {node: '>=6.9.0'} hasBin: true peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 + '@babel/core': 7.17.4 + '@jridgewell/trace-mapping': 0.3.4 commander: 4.1.1 convert-source-map: 1.8.0 fs-readdir-recursive: 1.1.0 @@ -123,39 +218,39 @@ packages: source-map: 0.5.7 optionalDependencies: '@nicolo-ribaudo/chokidar-2': 2.1.8-no-fsevents.3 - chokidar: 3.5.2 + chokidar: 3.5.3 dev: true - /@babel/code-frame/7.16.0: - resolution: {integrity: sha512-IF4EOMEV+bfYwOmNxGzSnjR2EmQod7f1UXOpZM3l4i4o4QNwzjtJAu/HxdjHq0aYBvdqMuQEY1eg0nqW9ZPORA==} + /@babel/code-frame/7.16.7: + resolution: {integrity: sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==} engines: {node: '>=6.9.0'} dependencies: - '@babel/highlight': 7.16.0 + '@babel/highlight': 7.16.10 - /@babel/compat-data/7.16.4: - resolution: {integrity: sha512-1o/jo7D+kC9ZjHX5v+EHrdjl3PhxMrLSOTGsOdHJ+KL8HCaEK6ehrVL2RS6oHDZp+L7xLirLrPmQtEng769J/Q==} + /@babel/compat-data/7.17.0: + resolution: {integrity: sha512-392byTlpGWXMv4FbyWw3sAZ/FrW/DrwqLGXpy0mbyNe9Taqv1mg9yON5/o0cnr8XYCkFTZbC1eV+c+LAROgrng==} engines: {node: '>=6.9.0'} dev: true - /@babel/core/7.16.0: - resolution: {integrity: sha512-mYZEvshBRHGsIAiyH5PzCFTCfbWfoYbO/jcSdXQSUQu1/pW0xDZAUP7KEc32heqWTAfAHhV9j1vH8Sav7l+JNQ==} + /@babel/core/7.17.4: + resolution: {integrity: sha512-R9x5r4t4+hBqZTmioSnkrW+I6NmbojwjGT8p4G2Gw1thWbXIHGDnmGdLdFw0/7ljucdIrNRp7Npgb4CyBYzzJg==} engines: {node: '>=6.9.0'} dependencies: - '@babel/code-frame': 7.16.0 - '@babel/generator': 7.16.0 - '@babel/helper-compilation-targets': 7.16.3_@babel+core@7.16.0 - '@babel/helper-module-transforms': 7.16.0 - '@babel/helpers': 7.16.3 - '@babel/parser': 7.16.4 - '@babel/template': 7.16.0 - '@babel/traverse': 7.16.3 - '@babel/types': 7.16.0 + '@ampproject/remapping': 2.1.2 + '@babel/code-frame': 7.16.7 + '@babel/generator': 7.17.3 + '@babel/helper-compilation-targets': 7.16.7_@babel+core@7.17.4 + '@babel/helper-module-transforms': 7.16.7 + '@babel/helpers': 7.17.2 + '@babel/parser': 7.17.3 + '@babel/template': 7.16.7 + '@babel/traverse': 7.17.3 + '@babel/types': 7.17.0 convert-source-map: 1.8.0 debug: 4.3.2 gensync: 1.0.0-beta.2 - json5: 2.2.0 + json5: 2.2.3 semver: 6.3.0 - source-map: 0.5.7 transitivePeerDependencies: - supports-color dev: true @@ -164,76 +259,111 @@ packages: resolution: {integrity: sha512-RR8hUCfRQn9j9RPKEVXo9LiwoxLPYn6hNZlvUOR8tSnaxlD0p0+la00ZP9/SnRt6HchKr+X0fO2r8vrETiJGew==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.16.0 + '@babel/types': 7.17.0 + jsesc: 2.5.2 + source-map: 0.5.7 + + /@babel/generator/7.17.3: + resolution: {integrity: sha512-+R6Dctil/MgUsZsZAkYgK+ADNSZzJRRy0TvY65T71z/CR854xHQ1EweBYXdfT+HNeN7w0cSJJEzgxZMv40pxsg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.17.0 jsesc: 2.5.2 source-map: 0.5.7 + dev: true /@babel/helper-annotate-as-pure/7.16.0: resolution: {integrity: sha512-ItmYF9vR4zA8cByDocY05o0LGUkp1zhbTQOH1NFyl5xXEqlTJQCEJjieriw+aFpxo16swMxUnUiKS7a/r4vtHg==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.16.0 + '@babel/types': 7.17.0 - /@babel/helper-builder-binary-assignment-operator-visitor/7.16.0: - resolution: {integrity: sha512-9KuleLT0e77wFUku6TUkqZzCEymBdtuQQ27MhEKzf9UOOJu3cYj98kyaDAzxpC7lV6DGiZFuC8XqDsq8/Kl6aQ==} + /@babel/helper-annotate-as-pure/7.16.7: + resolution: {integrity: sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw==} engines: {node: '>=6.9.0'} dependencies: - '@babel/helper-explode-assignable-expression': 7.16.0 - '@babel/types': 7.16.0 + '@babel/types': 7.17.0 + dev: true + + /@babel/helper-builder-binary-assignment-operator-visitor/7.16.7: + resolution: {integrity: sha512-C6FdbRaxYjwVu/geKW4ZeQ0Q31AftgRcdSnZ5/jsH6BzCJbtvXvhpfkbkThYSuutZA7nCXpPR6AD9zd1dprMkA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-explode-assignable-expression': 7.16.7 + '@babel/types': 7.17.0 dev: true - /@babel/helper-compilation-targets/7.16.3_@babel+core@7.16.0: - resolution: {integrity: sha512-vKsoSQAyBmxS35JUOOt+07cLc6Nk/2ljLIHwmq2/NM6hdioUaqEXq/S+nXvbvXbZkNDlWOymPanJGOc4CBjSJA==} + /@babel/helper-compilation-targets/7.16.7_@babel+core@7.17.4: + resolution: {integrity: sha512-mGojBwIWcwGD6rfqgRXVlVYmPAv7eOpIemUG3dGnDdCY4Pae70ROij3XmfrH6Fa1h1aiDylpglbZyktfzyo/hA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/compat-data': 7.16.4 - '@babel/core': 7.16.0 - '@babel/helper-validator-option': 7.14.5 + '@babel/compat-data': 7.17.0 + '@babel/core': 7.17.4 + '@babel/helper-validator-option': 7.16.7 browserslist: 4.18.1 semver: 6.3.0 dev: true - /@babel/helper-create-class-features-plugin/7.16.0_@babel+core@7.16.0: - resolution: {integrity: sha512-XLwWvqEaq19zFlF5PTgOod4bUA+XbkR4WLQBct1bkzmxJGB0ZEJaoKF4c8cgH9oBtCDuYJ8BP5NB9uFiEgO5QA==} + /@babel/helper-create-class-features-plugin/7.17.1_@babel+core@7.17.4: + resolution: {integrity: sha512-JBdSr/LtyYIno/pNnJ75lBcqc3Z1XXujzPanHqjvvrhOA+DTceTFuJi8XjmWTZh4r3fsdfqaCMN0iZemdkxZHQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-annotate-as-pure': 7.16.0 - '@babel/helper-function-name': 7.16.0 - '@babel/helper-member-expression-to-functions': 7.16.0 - '@babel/helper-optimise-call-expression': 7.16.0 - '@babel/helper-replace-supers': 7.16.0 - '@babel/helper-split-export-declaration': 7.16.0 + '@babel/core': 7.17.4 + '@babel/helper-annotate-as-pure': 7.16.7 + '@babel/helper-environment-visitor': 7.16.7 + '@babel/helper-function-name': 7.16.7 + '@babel/helper-member-expression-to-functions': 7.16.7 + '@babel/helper-optimise-call-expression': 7.16.7 + '@babel/helper-replace-supers': 7.16.7 + '@babel/helper-split-export-declaration': 7.16.7 transitivePeerDependencies: - supports-color dev: true - /@babel/helper-create-regexp-features-plugin/7.16.0_@babel+core@7.16.0: - resolution: {integrity: sha512-3DyG0zAFAZKcOp7aVr33ddwkxJ0Z0Jr5V99y3I690eYLpukJsJvAbzTy1ewoCqsML8SbIrjH14Jc/nSQ4TvNPA==} + /@babel/helper-create-regexp-features-plugin/7.17.0_@babel+core@7.17.4: + resolution: {integrity: sha512-awO2So99wG6KnlE+TPs6rn83gCz5WlEePJDTnLEqbchMVrBeAujURVphRdigsk094VhvZehFoNOihSlcBjwsXA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-annotate-as-pure': 7.16.0 - regexpu-core: 4.8.0 + '@babel/core': 7.17.4 + '@babel/helper-annotate-as-pure': 7.16.7 + regexpu-core: 5.0.1 dev: true - /@babel/helper-define-polyfill-provider/0.3.0_@babel+core@7.16.0: + /@babel/helper-define-polyfill-provider/0.3.0_@babel+core@7.17.4: resolution: {integrity: sha512-7hfT8lUljl/tM3h+izTX/pO3W3frz2ok6Pk+gzys8iJqDfZrZy2pXjRTZAvG2YmfHun1X4q8/UZRLatMfqc5Tg==} peerDependencies: '@babel/core': ^7.4.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-compilation-targets': 7.16.3_@babel+core@7.16.0 - '@babel/helper-module-imports': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 - '@babel/traverse': 7.16.3 - debug: 4.3.2 + '@babel/core': 7.17.4 + '@babel/helper-compilation-targets': 7.16.7_@babel+core@7.17.4 + '@babel/helper-module-imports': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/traverse': 7.17.3 + debug: 4.3.4 + lodash.debounce: 4.0.8 + resolve: 1.20.0 + semver: 6.3.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/helper-define-polyfill-provider/0.3.1_@babel+core@7.17.4: + resolution: {integrity: sha512-J9hGMpJQmtWmj46B3kBHmL38UhJGhYX7eqkcq+2gsstyYt341HmPeWspihX43yVRA0mS+8GGk2Gckc7bY/HCmA==} + peerDependencies: + '@babel/core': ^7.4.0-0 + dependencies: + '@babel/core': 7.17.4 + '@babel/helper-compilation-targets': 7.16.7_@babel+core@7.17.4 + '@babel/helper-module-imports': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/traverse': 7.17.3 + debug: 4.3.4 lodash.debounce: 4.0.8 resolve: 1.20.0 semver: 6.3.0 @@ -241,11 +371,18 @@ packages: - supports-color dev: true - /@babel/helper-explode-assignable-expression/7.16.0: - resolution: {integrity: sha512-Hk2SLxC9ZbcOhLpg/yMznzJ11W++lg5GMbxt1ev6TXUiJB0N42KPC+7w8a+eWGuqDnUYuwStJoZHM7RgmIOaGQ==} + /@babel/helper-environment-visitor/7.16.7: + resolution: {integrity: sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.16.0 + '@babel/types': 7.17.0 + dev: true + + /@babel/helper-explode-assignable-expression/7.16.7: + resolution: {integrity: sha512-KyUenhWMC8VrxzkGP0Jizjo4/Zx+1nNZhgocs+gLzyZyB8SHidhoq9KK/8Ato4anhwsivfkBLftky7gvzbZMtQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.17.0 dev: true /@babel/helper-function-name/7.16.0: @@ -253,26 +390,49 @@ packages: engines: {node: '>=6.9.0'} dependencies: '@babel/helper-get-function-arity': 7.16.0 - '@babel/template': 7.16.0 - '@babel/types': 7.16.0 + '@babel/template': 7.16.7 + '@babel/types': 7.17.0 + + /@babel/helper-function-name/7.16.7: + resolution: {integrity: sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-get-function-arity': 7.16.7 + '@babel/template': 7.16.7 + '@babel/types': 7.17.0 + dev: true /@babel/helper-get-function-arity/7.16.0: resolution: {integrity: sha512-ASCquNcywC1NkYh/z7Cgp3w31YW8aojjYIlNg4VeJiHkqyP4AzIvr4qx7pYDb4/s8YcsZWqqOSxgkvjUz1kpDQ==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.16.0 + '@babel/types': 7.17.0 + + /@babel/helper-get-function-arity/7.16.7: + resolution: {integrity: sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.17.0 + dev: true /@babel/helper-hoist-variables/7.16.0: resolution: {integrity: sha512-1AZlpazjUR0EQZQv3sgRNfM9mEVWPK3M6vlalczA+EECcPz3XPh6VplbErL5UoMpChhSck5wAJHthlj1bYpcmg==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.16.0 + '@babel/types': 7.17.0 - /@babel/helper-member-expression-to-functions/7.16.0: - resolution: {integrity: sha512-bsjlBFPuWT6IWhl28EdrQ+gTvSvj5tqVP5Xeftp07SEuz5pLnsXZuDkDD3Rfcxy0IsHmbZ+7B2/9SHzxO0T+sQ==} + /@babel/helper-hoist-variables/7.16.7: + resolution: {integrity: sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.16.0 + '@babel/types': 7.17.0 + dev: true + + /@babel/helper-member-expression-to-functions/7.16.7: + resolution: {integrity: sha512-VtJ/65tYiU/6AbMTDwyoXGPKHgTsfRarivm+YbB5uAzKUyuPjgZSgAFeG87FCigc7KNHu2Pegh1XIT3lXjvz3Q==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.17.0 dev: true /@babel/helper-module-imports/7.16.0: @@ -281,114 +441,133 @@ packages: dependencies: '@babel/types': 7.16.0 - /@babel/helper-module-transforms/7.16.0: - resolution: {integrity: sha512-My4cr9ATcaBbmaEa8M0dZNA74cfI6gitvUAskgDtAFmAqyFKDSHQo5YstxPbN+lzHl2D9l/YOEFqb2mtUh4gfA==} + /@babel/helper-module-imports/7.16.7: + resolution: {integrity: sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==} engines: {node: '>=6.9.0'} dependencies: - '@babel/helper-module-imports': 7.16.0 - '@babel/helper-replace-supers': 7.16.0 - '@babel/helper-simple-access': 7.16.0 - '@babel/helper-split-export-declaration': 7.16.0 - '@babel/helper-validator-identifier': 7.15.7 - '@babel/template': 7.16.0 - '@babel/traverse': 7.16.3 - '@babel/types': 7.16.0 + '@babel/types': 7.17.0 + dev: true + + /@babel/helper-module-transforms/7.16.7: + resolution: {integrity: sha512-gaqtLDxJEFCeQbYp9aLAefjhkKdjKcdh6DB7jniIGU3Pz52WAmP268zK0VgPz9hUNkMSYeH976K2/Y6yPadpng==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-environment-visitor': 7.16.7 + '@babel/helper-module-imports': 7.16.7 + '@babel/helper-simple-access': 7.16.7 + '@babel/helper-split-export-declaration': 7.16.7 + '@babel/helper-validator-identifier': 7.16.7 + '@babel/template': 7.16.7 + '@babel/traverse': 7.17.3 + '@babel/types': 7.17.0 transitivePeerDependencies: - supports-color dev: true - /@babel/helper-optimise-call-expression/7.16.0: - resolution: {integrity: sha512-SuI467Gi2V8fkofm2JPnZzB/SUuXoJA5zXe/xzyPP2M04686RzFKFHPK6HDVN6JvWBIEW8tt9hPR7fXdn2Lgpw==} + /@babel/helper-optimise-call-expression/7.16.7: + resolution: {integrity: sha512-EtgBhg7rd/JcnpZFXpBy0ze1YRfdm7BnBX4uKMBd3ixa3RGAE002JZB66FJyNH7g0F38U05pXmA5P8cBh7z+1w==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.16.0 + '@babel/types': 7.17.0 dev: true - /@babel/helper-plugin-utils/7.14.5: - resolution: {integrity: sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ==} + /@babel/helper-plugin-utils/7.16.7: + resolution: {integrity: sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA==} engines: {node: '>=6.9.0'} dev: true - /@babel/helper-remap-async-to-generator/7.16.4: - resolution: {integrity: sha512-vGERmmhR+s7eH5Y/cp8PCVzj4XEjerq8jooMfxFdA5xVtAk9Sh4AQsrWgiErUEBjtGrBtOFKDUcWQFW4/dFwMA==} + /@babel/helper-remap-async-to-generator/7.16.8: + resolution: {integrity: sha512-fm0gH7Flb8H51LqJHy3HJ3wnE1+qtYR2A99K06ahwrawLdOFsCEWjZOrYricXJHoPSudNKxrMBUPEIPxiIIvBw==} engines: {node: '>=6.9.0'} dependencies: - '@babel/helper-annotate-as-pure': 7.16.0 - '@babel/helper-wrap-function': 7.16.0 - '@babel/types': 7.16.0 + '@babel/helper-annotate-as-pure': 7.16.7 + '@babel/helper-wrap-function': 7.16.8 + '@babel/types': 7.17.0 transitivePeerDependencies: - supports-color dev: true - /@babel/helper-replace-supers/7.16.0: - resolution: {integrity: sha512-TQxuQfSCdoha7cpRNJvfaYxxxzmbxXw/+6cS7V02eeDYyhxderSoMVALvwupA54/pZcOTtVeJ0xccp1nGWladA==} + /@babel/helper-replace-supers/7.16.7: + resolution: {integrity: sha512-y9vsWilTNaVnVh6xiJfABzsNpgDPKev9HnAgz6Gb1p6UUwf9NepdlsV7VXGCftJM+jqD5f7JIEubcpLjZj5dBw==} engines: {node: '>=6.9.0'} dependencies: - '@babel/helper-member-expression-to-functions': 7.16.0 - '@babel/helper-optimise-call-expression': 7.16.0 - '@babel/traverse': 7.16.3 - '@babel/types': 7.16.0 + '@babel/helper-environment-visitor': 7.16.7 + '@babel/helper-member-expression-to-functions': 7.16.7 + '@babel/helper-optimise-call-expression': 7.16.7 + '@babel/traverse': 7.17.3 + '@babel/types': 7.17.0 transitivePeerDependencies: - supports-color dev: true - /@babel/helper-simple-access/7.16.0: - resolution: {integrity: sha512-o1rjBT/gppAqKsYfUdfHq5Rk03lMQrkPHG1OWzHWpLgVXRH4HnMM9Et9CVdIqwkCQlobnGHEJMsgWP/jE1zUiw==} + /@babel/helper-simple-access/7.16.7: + resolution: {integrity: sha512-ZIzHVyoeLMvXMN/vok/a4LWRy8G2v205mNP0XOuf9XRLyX5/u9CnVulUtDgUTama3lT+bf/UqucuZjqiGuTS1g==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.16.0 + '@babel/types': 7.17.0 dev: true /@babel/helper-skip-transparent-expression-wrappers/7.16.0: resolution: {integrity: sha512-+il1gTy0oHwUsBQZyJvukbB4vPMdcYBrFHa0Uc4AizLxbq6BOYC51Rv4tWocX9BLBDLZ4kc6qUFpQ6HRgL+3zw==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.16.0 + '@babel/types': 7.17.0 dev: true /@babel/helper-split-export-declaration/7.16.0: resolution: {integrity: sha512-0YMMRpuDFNGTHNRiiqJX19GjNXA4H0E8jZ2ibccfSxaCogbm3am5WN/2nQNj0YnQwGWM1J06GOcQ2qnh3+0paw==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.16.0 + '@babel/types': 7.17.0 + + /@babel/helper-split-export-declaration/7.16.7: + resolution: {integrity: sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.17.0 + dev: true /@babel/helper-validator-identifier/7.15.7: resolution: {integrity: sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w==} engines: {node: '>=6.9.0'} - /@babel/helper-validator-option/7.14.5: - resolution: {integrity: sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow==} + /@babel/helper-validator-identifier/7.16.7: + resolution: {integrity: sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==} + engines: {node: '>=6.9.0'} + + /@babel/helper-validator-option/7.16.7: + resolution: {integrity: sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==} engines: {node: '>=6.9.0'} dev: true - /@babel/helper-wrap-function/7.16.0: - resolution: {integrity: sha512-VVMGzYY3vkWgCJML+qVLvGIam902mJW0FvT7Avj1zEe0Gn7D93aWdLblYARTxEw+6DhZmtzhBM2zv0ekE5zg1g==} + /@babel/helper-wrap-function/7.16.8: + resolution: {integrity: sha512-8RpyRVIAW1RcDDGTA+GpPAwV22wXCfKOoM9bet6TLkGIFTkRQSkH1nMQ5Yet4MpoXe1ZwHPVtNasc2w0uZMqnw==} engines: {node: '>=6.9.0'} dependencies: - '@babel/helper-function-name': 7.16.0 - '@babel/template': 7.16.0 - '@babel/traverse': 7.16.3 - '@babel/types': 7.16.0 + '@babel/helper-function-name': 7.16.7 + '@babel/template': 7.16.7 + '@babel/traverse': 7.17.3 + '@babel/types': 7.17.0 transitivePeerDependencies: - supports-color dev: true - /@babel/helpers/7.16.3: - resolution: {integrity: sha512-Xn8IhDlBPhvYTvgewPKawhADichOsbkZuzN7qz2BusOM0brChsyXMDJvldWaYMMUNiCQdQzNEioXTp3sC8Nt8w==} + /@babel/helpers/7.17.2: + resolution: {integrity: sha512-0Qu7RLR1dILozr/6M0xgj+DFPmi6Bnulgm9M8BVa9ZCWxDqlSnqt3cf8IDPB5m45sVXUZ0kuQAgUrdSFFH79fQ==} engines: {node: '>=6.9.0'} dependencies: - '@babel/template': 7.16.0 - '@babel/traverse': 7.16.3 - '@babel/types': 7.16.0 + '@babel/template': 7.16.7 + '@babel/traverse': 7.17.3 + '@babel/types': 7.17.0 transitivePeerDependencies: - supports-color dev: true - /@babel/highlight/7.16.0: - resolution: {integrity: sha512-t8MH41kUQylBtu2+4IQA3atqevA2lRgqA2wyVB/YiWmsDSuylZZuXOUy9ric30hfzauEFfdsuk/eXTRrGrfd0g==} + /@babel/highlight/7.16.10: + resolution: {integrity: sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==} engines: {node: '>=6.9.0'} dependencies: - '@babel/helper-validator-identifier': 7.15.7 + '@babel/helper-validator-identifier': 7.16.7 chalk: 2.4.2 js-tokens: 4.0.0 @@ -396,919 +575,930 @@ packages: resolution: {integrity: sha512-6V0qdPUaiVHH3RtZeLIsc+6pDhbYzHR8ogA8w+f+Wc77DuXto19g2QUwveINoS34Uw+W8/hQDGJCx+i4n7xcng==} engines: {node: '>=6.0.0'} hasBin: true + dependencies: + '@babel/types': 7.17.0 + + /@babel/parser/7.17.3: + resolution: {integrity: sha512-7yJPvPV+ESz2IUTPbOL+YkIGyCqOyNIzdguKQuJGnH7bg1WTIifuM21YqokFt/THWh1AkCRn9IgoykTRCBVpzA==} + engines: {node: '>=6.0.0'} + hasBin: true + dependencies: + '@babel/types': 7.17.0 - /@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/7.16.2_@babel+core@7.16.0: - resolution: {integrity: sha512-h37CvpLSf8gb2lIJ2CgC3t+EjFbi0t8qS7LCS1xcJIlEXE4czlofwaW7W1HA8zpgOCzI9C1nmoqNR1zWkk0pQg==} + /@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/7.16.7_@babel+core@7.17.4: + resolution: {integrity: sha512-anv/DObl7waiGEnC24O9zqL0pSuI9hljihqiDuFHC8d7/bjr/4RLGPWuc8rYOff/QPzbEPSkzG8wGG9aDuhHRg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 + '@babel/core': 7.17.4 + '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/7.16.0_@babel+core@7.16.0: - resolution: {integrity: sha512-4tcFwwicpWTrpl9qjf7UsoosaArgImF85AxqCRZlgc3IQDvkUHjJpruXAL58Wmj+T6fypWTC/BakfEkwIL/pwA==} + /@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/7.16.7_@babel+core@7.17.4: + resolution: {integrity: sha512-di8vUHRdf+4aJ7ltXhaDbPoszdkh59AQtJM5soLsuHpQJdFQZOA4uGj0V2u/CZ8bJ/u8ULDL5yq6FO/bCXnKHw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.13.0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 + '@babel/core': 7.17.4 + '@babel/helper-plugin-utils': 7.16.7 '@babel/helper-skip-transparent-expression-wrappers': 7.16.0 - '@babel/plugin-proposal-optional-chaining': 7.16.0_@babel+core@7.16.0 + '@babel/plugin-proposal-optional-chaining': 7.16.7_@babel+core@7.17.4 dev: true - /@babel/plugin-proposal-async-generator-functions/7.16.4_@babel+core@7.16.0: - resolution: {integrity: sha512-/CUekqaAaZCQHleSK/9HajvcD/zdnJiKRiuUFq8ITE+0HsPzquf53cpFiqAwl/UfmJbR6n5uGPQSPdrmKOvHHg==} + /@babel/plugin-proposal-async-generator-functions/7.16.8_@babel+core@7.17.4: + resolution: {integrity: sha512-71YHIvMuiuqWJQkebWJtdhQTfd4Q4mF76q2IX37uZPkG9+olBxsX+rH1vkhFto4UeJZ9dPY2s+mDvhDm1u2BGQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 - '@babel/helper-remap-async-to-generator': 7.16.4 - '@babel/plugin-syntax-async-generators': 7.8.4_@babel+core@7.16.0 + '@babel/core': 7.17.4 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-remap-async-to-generator': 7.16.8 + '@babel/plugin-syntax-async-generators': 7.8.4_@babel+core@7.17.4 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-proposal-class-properties/7.16.0_@babel+core@7.16.0: - resolution: {integrity: sha512-mCF3HcuZSY9Fcx56Lbn+CGdT44ioBMMvjNVldpKtj8tpniETdLjnxdHI1+sDWXIM1nNt+EanJOZ3IG9lzVjs7A==} + /@babel/plugin-proposal-class-properties/7.16.7_@babel+core@7.17.4: + resolution: {integrity: sha512-IobU0Xme31ewjYOShSIqd/ZGM/r/cuOz2z0MDbNrhF5FW+ZVgi0f2lyeoj9KFPDOAqsYxmLWZte1WOwlvY9aww==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-create-class-features-plugin': 7.16.0_@babel+core@7.16.0 - '@babel/helper-plugin-utils': 7.14.5 + '@babel/core': 7.17.4 + '@babel/helper-create-class-features-plugin': 7.17.1_@babel+core@7.17.4 + '@babel/helper-plugin-utils': 7.16.7 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-proposal-class-static-block/7.16.0_@babel+core@7.16.0: - resolution: {integrity: sha512-mAy3sdcY9sKAkf3lQbDiv3olOfiLqI51c9DR9b19uMoR2Z6r5pmGl7dfNFqEvqOyqbf1ta4lknK4gc5PJn3mfA==} + /@babel/plugin-proposal-class-static-block/7.16.7_@babel+core@7.17.4: + resolution: {integrity: sha512-dgqJJrcZoG/4CkMopzhPJjGxsIe9A8RlkQLnL/Vhhx8AA9ZuaRwGSlscSh42hazc7WSrya/IK7mTeoF0DP9tEw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.12.0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-create-class-features-plugin': 7.16.0_@babel+core@7.16.0 - '@babel/helper-plugin-utils': 7.14.5 - '@babel/plugin-syntax-class-static-block': 7.14.5_@babel+core@7.16.0 + '@babel/core': 7.17.4 + '@babel/helper-create-class-features-plugin': 7.17.1_@babel+core@7.17.4 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/plugin-syntax-class-static-block': 7.14.5_@babel+core@7.17.4 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-proposal-dynamic-import/7.16.0_@babel+core@7.16.0: - resolution: {integrity: sha512-QGSA6ExWk95jFQgwz5GQ2Dr95cf7eI7TKutIXXTb7B1gCLTCz5hTjFTQGfLFBBiC5WSNi7udNwWsqbbMh1c4yQ==} + /@babel/plugin-proposal-dynamic-import/7.16.7_@babel+core@7.17.4: + resolution: {integrity: sha512-I8SW9Ho3/8DRSdmDdH3gORdyUuYnk1m4cMxUAdu5oy4n3OfN8flDEH+d60iG7dUfi0KkYwSvoalHzzdRzpWHTg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 - '@babel/plugin-syntax-dynamic-import': 7.8.3_@babel+core@7.16.0 + '@babel/core': 7.17.4 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/plugin-syntax-dynamic-import': 7.8.3_@babel+core@7.17.4 dev: true - /@babel/plugin-proposal-export-namespace-from/7.16.0_@babel+core@7.16.0: - resolution: {integrity: sha512-CjI4nxM/D+5wCnhD11MHB1AwRSAYeDT+h8gCdcVJZ/OK7+wRzFsf7PFPWVpVpNRkHMmMkQWAHpTq+15IXQ1diA==} + /@babel/plugin-proposal-export-namespace-from/7.16.7_@babel+core@7.17.4: + resolution: {integrity: sha512-ZxdtqDXLRGBL64ocZcs7ovt71L3jhC1RGSyR996svrCi3PYqHNkb3SwPJCs8RIzD86s+WPpt2S73+EHCGO+NUA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 - '@babel/plugin-syntax-export-namespace-from': 7.8.3_@babel+core@7.16.0 + '@babel/core': 7.17.4 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/plugin-syntax-export-namespace-from': 7.8.3_@babel+core@7.17.4 dev: true - /@babel/plugin-proposal-json-strings/7.16.0_@babel+core@7.16.0: - resolution: {integrity: sha512-kouIPuiv8mSi5JkEhzApg5Gn6hFyKPnlkO0a9YSzqRurH8wYzSlf6RJdzluAsbqecdW5pBvDJDfyDIUR/vLxvg==} + /@babel/plugin-proposal-json-strings/7.16.7_@babel+core@7.17.4: + resolution: {integrity: sha512-lNZ3EEggsGY78JavgbHsK9u5P3pQaW7k4axlgFLYkMd7UBsiNahCITShLjNQschPyjtO6dADrL24757IdhBrsQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 - '@babel/plugin-syntax-json-strings': 7.8.3_@babel+core@7.16.0 + '@babel/core': 7.17.4 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/plugin-syntax-json-strings': 7.8.3_@babel+core@7.17.4 dev: true - /@babel/plugin-proposal-logical-assignment-operators/7.16.0_@babel+core@7.16.0: - resolution: {integrity: sha512-pbW0fE30sVTYXXm9lpVQQ/Vc+iTeQKiXlaNRZPPN2A2VdlWyAtsUrsQ3xydSlDW00TFMK7a8m3cDTkBF5WnV3Q==} + /@babel/plugin-proposal-logical-assignment-operators/7.16.7_@babel+core@7.17.4: + resolution: {integrity: sha512-K3XzyZJGQCr00+EtYtrDjmwX7o7PLK6U9bi1nCwkQioRFVUv6dJoxbQjtWVtP+bCPy82bONBKG8NPyQ4+i6yjg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4_@babel+core@7.16.0 + '@babel/core': 7.17.4 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4_@babel+core@7.17.4 dev: true - /@babel/plugin-proposal-nullish-coalescing-operator/7.16.0_@babel+core@7.16.0: - resolution: {integrity: sha512-3bnHA8CAFm7cG93v8loghDYyQ8r97Qydf63BeYiGgYbjKKB/XP53W15wfRC7dvKfoiJ34f6Rbyyx2btExc8XsQ==} + /@babel/plugin-proposal-nullish-coalescing-operator/7.16.7_@babel+core@7.17.4: + resolution: {integrity: sha512-aUOrYU3EVtjf62jQrCj63pYZ7k6vns2h/DQvHPWGmsJRYzWXZ6/AsfgpiRy6XiuIDADhJzP2Q9MwSMKauBQ+UQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3_@babel+core@7.16.0 + '@babel/core': 7.17.4 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3_@babel+core@7.17.4 dev: true - /@babel/plugin-proposal-numeric-separator/7.16.0_@babel+core@7.16.0: - resolution: {integrity: sha512-FAhE2I6mjispy+vwwd6xWPyEx3NYFS13pikDBWUAFGZvq6POGs5eNchw8+1CYoEgBl9n11I3NkzD7ghn25PQ9Q==} + /@babel/plugin-proposal-numeric-separator/7.16.7_@babel+core@7.17.4: + resolution: {integrity: sha512-vQgPMknOIgiuVqbokToyXbkY/OmmjAzr/0lhSIbG/KmnzXPGwW/AdhdKpi+O4X/VkWiWjnkKOBiqJrTaC98VKw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 - '@babel/plugin-syntax-numeric-separator': 7.10.4_@babel+core@7.16.0 + '@babel/core': 7.17.4 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/plugin-syntax-numeric-separator': 7.10.4_@babel+core@7.17.4 dev: true - /@babel/plugin-proposal-object-rest-spread/7.16.0_@babel+core@7.16.0: - resolution: {integrity: sha512-LU/+jp89efe5HuWJLmMmFG0+xbz+I2rSI7iLc1AlaeSMDMOGzWlc5yJrMN1d04osXN4sSfpo4O+azkBNBes0jg==} + /@babel/plugin-proposal-object-rest-spread/7.17.3_@babel+core@7.17.4: + resolution: {integrity: sha512-yuL5iQA/TbZn+RGAfxQXfi7CNLmKi1f8zInn4IgobuCWcAb7i+zj4TYzQ9l8cEzVyJ89PDGuqxK1xZpUDISesw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/compat-data': 7.16.4 - '@babel/core': 7.16.0 - '@babel/helper-compilation-targets': 7.16.3_@babel+core@7.16.0 - '@babel/helper-plugin-utils': 7.14.5 - '@babel/plugin-syntax-object-rest-spread': 7.8.3_@babel+core@7.16.0 - '@babel/plugin-transform-parameters': 7.16.3_@babel+core@7.16.0 + '@babel/compat-data': 7.17.0 + '@babel/core': 7.17.4 + '@babel/helper-compilation-targets': 7.16.7_@babel+core@7.17.4 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/plugin-syntax-object-rest-spread': 7.8.3_@babel+core@7.17.4 + '@babel/plugin-transform-parameters': 7.16.7_@babel+core@7.17.4 dev: true - /@babel/plugin-proposal-optional-catch-binding/7.16.0_@babel+core@7.16.0: - resolution: {integrity: sha512-kicDo0A/5J0nrsCPbn89mTG3Bm4XgYi0CZtvex9Oyw7gGZE3HXGD0zpQNH+mo+tEfbo8wbmMvJftOwpmPy7aVw==} + /@babel/plugin-proposal-optional-catch-binding/7.16.7_@babel+core@7.17.4: + resolution: {integrity: sha512-eMOH/L4OvWSZAE1VkHbr1vckLG1WUcHGJSLqqQwl2GaUqG6QjddvrOaTUMNYiv77H5IKPMZ9U9P7EaHwvAShfA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 - '@babel/plugin-syntax-optional-catch-binding': 7.8.3_@babel+core@7.16.0 + '@babel/core': 7.17.4 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/plugin-syntax-optional-catch-binding': 7.8.3_@babel+core@7.17.4 dev: true - /@babel/plugin-proposal-optional-chaining/7.16.0_@babel+core@7.16.0: - resolution: {integrity: sha512-Y4rFpkZODfHrVo70Uaj6cC1JJOt3Pp0MdWSwIKtb8z1/lsjl9AmnB7ErRFV+QNGIfcY1Eruc2UMx5KaRnXjMyg==} + /@babel/plugin-proposal-optional-chaining/7.16.7_@babel+core@7.17.4: + resolution: {integrity: sha512-eC3xy+ZrUcBtP7x+sq62Q/HYd674pPTb/77XZMb5wbDPGWIdUbSr4Agr052+zaUPSb+gGRnjxXfKFvx5iMJ+DA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 + '@babel/core': 7.17.4 + '@babel/helper-plugin-utils': 7.16.7 '@babel/helper-skip-transparent-expression-wrappers': 7.16.0 - '@babel/plugin-syntax-optional-chaining': 7.8.3_@babel+core@7.16.0 + '@babel/plugin-syntax-optional-chaining': 7.8.3_@babel+core@7.17.4 dev: true - /@babel/plugin-proposal-private-methods/7.16.0_@babel+core@7.16.0: - resolution: {integrity: sha512-IvHmcTHDFztQGnn6aWq4t12QaBXTKr1whF/dgp9kz84X6GUcwq9utj7z2wFCUfeOup/QKnOlt2k0zxkGFx9ubg==} + /@babel/plugin-proposal-private-methods/7.16.11_@babel+core@7.17.4: + resolution: {integrity: sha512-F/2uAkPlXDr8+BHpZvo19w3hLFKge+k75XUprE6jaqKxjGkSYcK+4c+bup5PdW/7W/Rpjwql7FTVEDW+fRAQsw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-create-class-features-plugin': 7.16.0_@babel+core@7.16.0 - '@babel/helper-plugin-utils': 7.14.5 + '@babel/core': 7.17.4 + '@babel/helper-create-class-features-plugin': 7.17.1_@babel+core@7.17.4 + '@babel/helper-plugin-utils': 7.16.7 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-proposal-private-property-in-object/7.16.0_@babel+core@7.16.0: - resolution: {integrity: sha512-3jQUr/HBbMVZmi72LpjQwlZ55i1queL8KcDTQEkAHihttJnAPrcvG9ZNXIfsd2ugpizZo595egYV6xy+pv4Ofw==} + /@babel/plugin-proposal-private-property-in-object/7.16.7_@babel+core@7.17.4: + resolution: {integrity: sha512-rMQkjcOFbm+ufe3bTZLyOfsOUOxyvLXZJCTARhJr+8UMSoZmqTe1K1BgkFcrW37rAchWg57yI69ORxiWvUINuQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-annotate-as-pure': 7.16.0 - '@babel/helper-create-class-features-plugin': 7.16.0_@babel+core@7.16.0 - '@babel/helper-plugin-utils': 7.14.5 - '@babel/plugin-syntax-private-property-in-object': 7.14.5_@babel+core@7.16.0 + '@babel/core': 7.17.4 + '@babel/helper-annotate-as-pure': 7.16.7 + '@babel/helper-create-class-features-plugin': 7.17.1_@babel+core@7.17.4 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/plugin-syntax-private-property-in-object': 7.14.5_@babel+core@7.17.4 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-proposal-unicode-property-regex/7.16.0_@babel+core@7.16.0: - resolution: {integrity: sha512-ti7IdM54NXv29cA4+bNNKEMS4jLMCbJgl+Drv+FgYy0erJLAxNAIXcNjNjrRZEcWq0xJHsNVwQezskMFpF8N9g==} + /@babel/plugin-proposal-unicode-property-regex/7.16.7_@babel+core@7.17.4: + resolution: {integrity: sha512-QRK0YI/40VLhNVGIjRNAAQkEHws0cswSdFFjpFyt943YmJIU1da9uW63Iu6NFV6CxTZW5eTDCrwZUstBWgp/Rg==} engines: {node: '>=4'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-create-regexp-features-plugin': 7.16.0_@babel+core@7.16.0 - '@babel/helper-plugin-utils': 7.14.5 + '@babel/core': 7.17.4 + '@babel/helper-create-regexp-features-plugin': 7.17.0_@babel+core@7.17.4 + '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-syntax-async-generators/7.8.4_@babel+core@7.16.0: + /@babel/plugin-syntax-async-generators/7.8.4_@babel+core@7.17.4: resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 + '@babel/core': 7.17.4 + '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-syntax-bigint/7.8.3_@babel+core@7.16.0: + /@babel/plugin-syntax-bigint/7.8.3_@babel+core@7.17.4: resolution: {integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 + '@babel/core': 7.17.4 + '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-syntax-class-properties/7.12.13_@babel+core@7.16.0: + /@babel/plugin-syntax-class-properties/7.12.13_@babel+core@7.17.4: resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 + '@babel/core': 7.17.4 + '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-syntax-class-static-block/7.14.5_@babel+core@7.16.0: + /@babel/plugin-syntax-class-static-block/7.14.5_@babel+core@7.17.4: resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 + '@babel/core': 7.17.4 + '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-syntax-dynamic-import/7.8.3_@babel+core@7.16.0: + /@babel/plugin-syntax-dynamic-import/7.8.3_@babel+core@7.17.4: resolution: {integrity: sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 + '@babel/core': 7.17.4 + '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-syntax-export-namespace-from/7.8.3_@babel+core@7.16.0: + /@babel/plugin-syntax-export-namespace-from/7.8.3_@babel+core@7.17.4: resolution: {integrity: sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 + '@babel/core': 7.17.4 + '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-syntax-import-meta/7.10.4_@babel+core@7.16.0: + /@babel/plugin-syntax-import-meta/7.10.4_@babel+core@7.17.4: resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 + '@babel/core': 7.17.4 + '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-syntax-json-strings/7.8.3_@babel+core@7.16.0: + /@babel/plugin-syntax-json-strings/7.8.3_@babel+core@7.17.4: resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 + '@babel/core': 7.17.4 + '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-syntax-jsx/7.16.0_@babel+core@7.16.0: - resolution: {integrity: sha512-8zv2+xiPHwly31RK4RmnEYY5zziuF3O7W2kIDW+07ewWDh6Oi0dRq8kwvulRkFgt6DB97RlKs5c1y068iPlCUg==} + /@babel/plugin-syntax-jsx/7.16.7_@babel+core@7.17.4: + resolution: {integrity: sha512-Esxmk7YjA8QysKeT3VhTXvF6y77f/a91SIs4pWb4H2eWGQkCKFgQaG6hdoEVZtGsrAcb2K5BW66XsOErD4WU3Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 + '@babel/core': 7.17.4 + '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-syntax-logical-assignment-operators/7.10.4_@babel+core@7.16.0: + /@babel/plugin-syntax-logical-assignment-operators/7.10.4_@babel+core@7.17.4: resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 + '@babel/core': 7.17.4 + '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-syntax-nullish-coalescing-operator/7.8.3_@babel+core@7.16.0: + /@babel/plugin-syntax-nullish-coalescing-operator/7.8.3_@babel+core@7.17.4: resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 + '@babel/core': 7.17.4 + '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-syntax-numeric-separator/7.10.4_@babel+core@7.16.0: + /@babel/plugin-syntax-numeric-separator/7.10.4_@babel+core@7.17.4: resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 + '@babel/core': 7.17.4 + '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-syntax-object-rest-spread/7.8.3_@babel+core@7.16.0: + /@babel/plugin-syntax-object-rest-spread/7.8.3_@babel+core@7.17.4: resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 + '@babel/core': 7.17.4 + '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-syntax-optional-catch-binding/7.8.3_@babel+core@7.16.0: + /@babel/plugin-syntax-optional-catch-binding/7.8.3_@babel+core@7.17.4: resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 + '@babel/core': 7.17.4 + '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-syntax-optional-chaining/7.8.3_@babel+core@7.16.0: + /@babel/plugin-syntax-optional-chaining/7.8.3_@babel+core@7.17.4: resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 + '@babel/core': 7.17.4 + '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-syntax-private-property-in-object/7.14.5_@babel+core@7.16.0: + /@babel/plugin-syntax-private-property-in-object/7.14.5_@babel+core@7.17.4: resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 + '@babel/core': 7.17.4 + '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-syntax-top-level-await/7.14.5_@babel+core@7.16.0: + /@babel/plugin-syntax-top-level-await/7.14.5_@babel+core@7.17.4: resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 + '@babel/core': 7.17.4 + '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-syntax-typescript/7.16.0_@babel+core@7.16.0: - resolution: {integrity: sha512-Xv6mEXqVdaqCBfJFyeab0fH2DnUoMsDmhamxsSi4j8nLd4Vtw213WMJr55xxqipC/YVWyPY3K0blJncPYji+dQ==} + /@babel/plugin-syntax-typescript/7.16.7_@babel+core@7.17.4: + resolution: {integrity: sha512-YhUIJHHGkqPgEcMYkPCKTyGUdoGKWtopIycQyjJH8OjvRgOYsXsaKehLVPScKJWAULPxMa4N1vCe6szREFlZ7A==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 + '@babel/core': 7.17.4 + '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-transform-arrow-functions/7.16.0_@babel+core@7.16.0: - resolution: {integrity: sha512-vIFb5250Rbh7roWARvCLvIJ/PtAU5Lhv7BtZ1u24COwpI9Ypjsh+bZcKk6rlIyalK+r0jOc1XQ8I4ovNxNrWrA==} + /@babel/plugin-transform-arrow-functions/7.16.7_@babel+core@7.17.4: + resolution: {integrity: sha512-9ffkFFMbvzTvv+7dTp/66xvZAWASuPD5Tl9LK3Z9vhOmANo6j94rik+5YMBt4CwHVMWLWpMsriIc2zsa3WW3xQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 + '@babel/core': 7.17.4 + '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-transform-async-to-generator/7.16.0_@babel+core@7.16.0: - resolution: {integrity: sha512-PbIr7G9kR8tdH6g8Wouir5uVjklETk91GMVSUq+VaOgiinbCkBP6Q7NN/suM/QutZkMJMvcyAriogcYAdhg8Gw==} + /@babel/plugin-transform-async-to-generator/7.16.8_@babel+core@7.17.4: + resolution: {integrity: sha512-MtmUmTJQHCnyJVrScNzNlofQJ3dLFuobYn3mwOTKHnSCMtbNsqvF71GQmJfFjdrXSsAA7iysFmYWw4bXZ20hOg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-module-imports': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 - '@babel/helper-remap-async-to-generator': 7.16.4 + '@babel/core': 7.17.4 + '@babel/helper-module-imports': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-remap-async-to-generator': 7.16.8 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-transform-block-scoped-functions/7.16.0_@babel+core@7.16.0: - resolution: {integrity: sha512-V14As3haUOP4ZWrLJ3VVx5rCnrYhMSHN/jX7z6FAt5hjRkLsb0snPCmJwSOML5oxkKO4FNoNv7V5hw/y2bjuvg==} + /@babel/plugin-transform-block-scoped-functions/7.16.7_@babel+core@7.17.4: + resolution: {integrity: sha512-JUuzlzmF40Z9cXyytcbZEZKckgrQzChbQJw/5PuEHYeqzCsvebDx0K0jWnIIVcmmDOAVctCgnYs0pMcrYj2zJg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 + '@babel/core': 7.17.4 + '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-transform-block-scoping/7.16.0_@babel+core@7.16.0: - resolution: {integrity: sha512-27n3l67/R3UrXfizlvHGuTwsRIFyce3D/6a37GRxn28iyTPvNXaW4XvznexRh1zUNLPjbLL22Id0XQElV94ruw==} + /@babel/plugin-transform-block-scoping/7.16.7_@babel+core@7.17.4: + resolution: {integrity: sha512-ObZev2nxVAYA4bhyusELdo9hb3H+A56bxH3FZMbEImZFiEDYVHXQSJ1hQKFlDnlt8G9bBrCZ5ZpURZUrV4G5qQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 + '@babel/core': 7.17.4 + '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-transform-classes/7.16.0_@babel+core@7.16.0: - resolution: {integrity: sha512-HUxMvy6GtAdd+GKBNYDWCIA776byUQH8zjnfjxwT1P1ARv/wFu8eBDpmXQcLS/IwRtrxIReGiplOwMeyO7nsDQ==} + /@babel/plugin-transform-classes/7.16.7_@babel+core@7.17.4: + resolution: {integrity: sha512-WY7og38SFAGYRe64BrjKf8OrE6ulEHtr5jEYaZMwox9KebgqPi67Zqz8K53EKk1fFEJgm96r32rkKZ3qA2nCWQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-annotate-as-pure': 7.16.0 - '@babel/helper-function-name': 7.16.0 - '@babel/helper-optimise-call-expression': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 - '@babel/helper-replace-supers': 7.16.0 - '@babel/helper-split-export-declaration': 7.16.0 + '@babel/core': 7.17.4 + '@babel/helper-annotate-as-pure': 7.16.7 + '@babel/helper-environment-visitor': 7.16.7 + '@babel/helper-function-name': 7.16.7 + '@babel/helper-optimise-call-expression': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-replace-supers': 7.16.7 + '@babel/helper-split-export-declaration': 7.16.7 globals: 11.12.0 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-transform-computed-properties/7.16.0_@babel+core@7.16.0: - resolution: {integrity: sha512-63l1dRXday6S8V3WFY5mXJwcRAnPYxvFfTlt67bwV1rTyVTM5zrp0DBBb13Kl7+ehkCVwIZPumPpFP/4u70+Tw==} + /@babel/plugin-transform-computed-properties/7.16.7_@babel+core@7.17.4: + resolution: {integrity: sha512-gN72G9bcmenVILj//sv1zLNaPyYcOzUho2lIJBMh/iakJ9ygCo/hEF9cpGb61SCMEDxbbyBoVQxrt+bWKu5KGw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 + '@babel/core': 7.17.4 + '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-transform-destructuring/7.16.0_@babel+core@7.16.0: - resolution: {integrity: sha512-Q7tBUwjxLTsHEoqktemHBMtb3NYwyJPTJdM+wDwb0g8PZ3kQUIzNvwD5lPaqW/p54TXBc/MXZu9Jr7tbUEUM8Q==} + /@babel/plugin-transform-destructuring/7.17.3_@babel+core@7.17.4: + resolution: {integrity: sha512-dDFzegDYKlPqa72xIlbmSkly5MluLoaC1JswABGktyt6NTXSBcUuse/kWE/wvKFWJHPETpi158qJZFS3JmykJg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 + '@babel/core': 7.17.4 + '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-transform-dotall-regex/7.16.0_@babel+core@7.16.0: - resolution: {integrity: sha512-FXlDZfQeLILfJlC6I1qyEwcHK5UpRCFkaoVyA1nk9A1L1Yu583YO4un2KsLBsu3IJb4CUbctZks8tD9xPQubLw==} + /@babel/plugin-transform-dotall-regex/7.16.7_@babel+core@7.17.4: + resolution: {integrity: sha512-Lyttaao2SjZF6Pf4vk1dVKv8YypMpomAbygW+mU5cYP3S5cWTfCJjG8xV6CFdzGFlfWK81IjL9viiTvpb6G7gQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-create-regexp-features-plugin': 7.16.0_@babel+core@7.16.0 - '@babel/helper-plugin-utils': 7.14.5 + '@babel/core': 7.17.4 + '@babel/helper-create-regexp-features-plugin': 7.17.0_@babel+core@7.17.4 + '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-transform-duplicate-keys/7.16.0_@babel+core@7.16.0: - resolution: {integrity: sha512-LIe2kcHKAZOJDNxujvmp6z3mfN6V9lJxubU4fJIGoQCkKe3Ec2OcbdlYP+vW++4MpxwG0d1wSDOJtQW5kLnkZQ==} + /@babel/plugin-transform-duplicate-keys/7.16.7_@babel+core@7.17.4: + resolution: {integrity: sha512-03DvpbRfvWIXyK0/6QiR1KMTWeT6OcQ7tbhjrXyFS02kjuX/mu5Bvnh5SDSWHxyawit2g5aWhKwI86EE7GUnTw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 + '@babel/core': 7.17.4 + '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-transform-exponentiation-operator/7.16.0_@babel+core@7.16.0: - resolution: {integrity: sha512-OwYEvzFI38hXklsrbNivzpO3fh87skzx8Pnqi4LoSYeav0xHlueSoCJrSgTPfnbyzopo5b3YVAJkFIcUpK2wsw==} + /@babel/plugin-transform-exponentiation-operator/7.16.7_@babel+core@7.17.4: + resolution: {integrity: sha512-8UYLSlyLgRixQvlYH3J2ekXFHDFLQutdy7FfFAMm3CPZ6q9wHCwnUyiXpQCe3gVVnQlHc5nsuiEVziteRNTXEA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-builder-binary-assignment-operator-visitor': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 + '@babel/core': 7.17.4 + '@babel/helper-builder-binary-assignment-operator-visitor': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-transform-for-of/7.16.0_@babel+core@7.16.0: - resolution: {integrity: sha512-5QKUw2kO+GVmKr2wMYSATCTTnHyscl6sxFRAY+rvN7h7WB0lcG0o4NoV6ZQU32OZGVsYUsfLGgPQpDFdkfjlJQ==} + /@babel/plugin-transform-for-of/7.16.7_@babel+core@7.17.4: + resolution: {integrity: sha512-/QZm9W92Ptpw7sjI9Nx1mbcsWz33+l8kuMIQnDwgQBG5s3fAfQvkRjQ7NqXhtNcKOnPkdICmUHyCaWW06HCsqg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 + '@babel/core': 7.17.4 + '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-transform-function-name/7.16.0_@babel+core@7.16.0: - resolution: {integrity: sha512-lBzMle9jcOXtSOXUpc7tvvTpENu/NuekNJVova5lCCWCV9/U1ho2HH2y0p6mBg8fPm/syEAbfaaemYGOHCY3mg==} + /@babel/plugin-transform-function-name/7.16.7_@babel+core@7.17.4: + resolution: {integrity: sha512-SU/C68YVwTRxqWj5kgsbKINakGag0KTgq9f2iZEXdStoAbOzLHEBRYzImmA6yFo8YZhJVflvXmIHUO7GWHmxxA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-function-name': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 + '@babel/core': 7.17.4 + '@babel/helper-compilation-targets': 7.16.7_@babel+core@7.17.4 + '@babel/helper-function-name': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-transform-literals/7.16.0_@babel+core@7.16.0: - resolution: {integrity: sha512-gQDlsSF1iv9RU04clgXqRjrPyyoJMTclFt3K1cjLmTKikc0s/6vE3hlDeEVC71wLTRu72Fq7650kABrdTc2wMQ==} + /@babel/plugin-transform-literals/7.16.7_@babel+core@7.17.4: + resolution: {integrity: sha512-6tH8RTpTWI0s2sV6uq3e/C9wPo4PTqqZps4uF0kzQ9/xPLFQtipynvmT1g/dOfEJ+0EQsHhkQ/zyRId8J2b8zQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 + '@babel/core': 7.17.4 + '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-transform-member-expression-literals/7.16.0_@babel+core@7.16.0: - resolution: {integrity: sha512-WRpw5HL4Jhnxw8QARzRvwojp9MIE7Tdk3ez6vRyUk1MwgjJN0aNpRoXainLR5SgxmoXx/vsXGZ6OthP6t/RbUg==} + /@babel/plugin-transform-member-expression-literals/7.16.7_@babel+core@7.17.4: + resolution: {integrity: sha512-mBruRMbktKQwbxaJof32LT9KLy2f3gH+27a5XSuXo6h7R3vqltl0PgZ80C8ZMKw98Bf8bqt6BEVi3svOh2PzMw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 + '@babel/core': 7.17.4 + '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-transform-modules-amd/7.16.0_@babel+core@7.16.0: - resolution: {integrity: sha512-rWFhWbCJ9Wdmzln1NmSCqn7P0RAD+ogXG/bd9Kg5c7PKWkJtkiXmYsMBeXjDlzHpVTJ4I/hnjs45zX4dEv81xw==} + /@babel/plugin-transform-modules-amd/7.16.7_@babel+core@7.17.4: + resolution: {integrity: sha512-KaaEtgBL7FKYwjJ/teH63oAmE3lP34N3kshz8mm4VMAw7U3PxjVwwUmxEFksbgsNUaO3wId9R2AVQYSEGRa2+g==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-module-transforms': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 + '@babel/core': 7.17.4 + '@babel/helper-module-transforms': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 babel-plugin-dynamic-import-node: 2.3.3 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-transform-modules-commonjs/7.16.0_@babel+core@7.16.0: - resolution: {integrity: sha512-Dzi+NWqyEotgzk/sb7kgQPJQf7AJkQBWsVp1N6JWc1lBVo0vkElUnGdr1PzUBmfsCCN5OOFya3RtpeHk15oLKQ==} + /@babel/plugin-transform-modules-commonjs/7.16.8_@babel+core@7.17.4: + resolution: {integrity: sha512-oflKPvsLT2+uKQopesJt3ApiaIS2HW+hzHFcwRNtyDGieAeC/dIHZX8buJQ2J2X1rxGPy4eRcUijm3qcSPjYcA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-module-transforms': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 - '@babel/helper-simple-access': 7.16.0 + '@babel/core': 7.17.4 + '@babel/helper-module-transforms': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-simple-access': 7.16.7 babel-plugin-dynamic-import-node: 2.3.3 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-transform-modules-systemjs/7.16.0_@babel+core@7.16.0: - resolution: {integrity: sha512-yuGBaHS3lF1m/5R+6fjIke64ii5luRUg97N2wr+z1sF0V+sNSXPxXDdEEL/iYLszsN5VKxVB1IPfEqhzVpiqvg==} + /@babel/plugin-transform-modules-systemjs/7.16.7_@babel+core@7.17.4: + resolution: {integrity: sha512-DuK5E3k+QQmnOqBR9UkusByy5WZWGRxfzV529s9nPra1GE7olmxfqO2FHobEOYSPIjPBTr4p66YDcjQnt8cBmw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-hoist-variables': 7.16.0 - '@babel/helper-module-transforms': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 - '@babel/helper-validator-identifier': 7.15.7 + '@babel/core': 7.17.4 + '@babel/helper-hoist-variables': 7.16.7 + '@babel/helper-module-transforms': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-validator-identifier': 7.16.7 babel-plugin-dynamic-import-node: 2.3.3 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-transform-modules-umd/7.16.0_@babel+core@7.16.0: - resolution: {integrity: sha512-nx4f6no57himWiHhxDM5pjwhae5vLpTK2zCnDH8+wNLJy0TVER/LJRHl2bkt6w9Aad2sPD5iNNoUpY3X9sTGDg==} + /@babel/plugin-transform-modules-umd/7.16.7_@babel+core@7.17.4: + resolution: {integrity: sha512-EMh7uolsC8O4xhudF2F6wedbSHm1HHZ0C6aJ7K67zcDNidMzVcxWdGr+htW9n21klm+bOn+Rx4CBsAntZd3rEQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-module-transforms': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 + '@babel/core': 7.17.4 + '@babel/helper-module-transforms': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-transform-named-capturing-groups-regex/7.16.0_@babel+core@7.16.0: - resolution: {integrity: sha512-LogN88uO+7EhxWc8WZuQ8vxdSyVGxhkh8WTC3tzlT8LccMuQdA81e9SGV6zY7kY2LjDhhDOFdQVxdGwPyBCnvg==} + /@babel/plugin-transform-named-capturing-groups-regex/7.16.8_@babel+core@7.17.4: + resolution: {integrity: sha512-j3Jw+n5PvpmhRR+mrgIh04puSANCk/T/UA3m3P1MjJkhlK906+ApHhDIqBQDdOgL/r1UYpz4GNclTXxyZrYGSw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-create-regexp-features-plugin': 7.16.0_@babel+core@7.16.0 + '@babel/core': 7.17.4 + '@babel/helper-create-regexp-features-plugin': 7.17.0_@babel+core@7.17.4 dev: true - /@babel/plugin-transform-new-target/7.16.0_@babel+core@7.16.0: - resolution: {integrity: sha512-fhjrDEYv2DBsGN/P6rlqakwRwIp7rBGLPbrKxwh7oVt5NNkIhZVOY2GRV+ULLsQri1bDqwDWnU3vhlmx5B2aCw==} + /@babel/plugin-transform-new-target/7.16.7_@babel+core@7.17.4: + resolution: {integrity: sha512-xiLDzWNMfKoGOpc6t3U+etCE2yRnn3SM09BXqWPIZOBpL2gvVrBWUKnsJx0K/ADi5F5YC5f8APFfWrz25TdlGg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 + '@babel/core': 7.17.4 + '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-transform-object-super/7.16.0_@babel+core@7.16.0: - resolution: {integrity: sha512-fds+puedQHn4cPLshoHcR1DTMN0q1V9ou0mUjm8whx9pGcNvDrVVrgw+KJzzCaiTdaYhldtrUps8DWVMgrSEyg==} + /@babel/plugin-transform-object-super/7.16.7_@babel+core@7.17.4: + resolution: {integrity: sha512-14J1feiQVWaGvRxj2WjyMuXS2jsBkgB3MdSN5HuC2G5nRspa5RK9COcs82Pwy5BuGcjb+fYaUj94mYcOj7rCvw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 - '@babel/helper-replace-supers': 7.16.0 + '@babel/core': 7.17.4 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-replace-supers': 7.16.7 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-transform-parameters/7.16.3_@babel+core@7.16.0: - resolution: {integrity: sha512-3MaDpJrOXT1MZ/WCmkOFo7EtmVVC8H4EUZVrHvFOsmwkk4lOjQj8rzv8JKUZV4YoQKeoIgk07GO+acPU9IMu/w==} + /@babel/plugin-transform-parameters/7.16.7_@babel+core@7.17.4: + resolution: {integrity: sha512-AT3MufQ7zZEhU2hwOA11axBnExW0Lszu4RL/tAlUJBuNoRak+wehQW8h6KcXOcgjY42fHtDxswuMhMjFEuv/aw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 + '@babel/core': 7.17.4 + '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-transform-property-literals/7.16.0_@babel+core@7.16.0: - resolution: {integrity: sha512-XLldD4V8+pOqX2hwfWhgwXzGdnDOThxaNTgqagOcpBgIxbUvpgU2FMvo5E1RyHbk756WYgdbS0T8y0Cj9FKkWQ==} + /@babel/plugin-transform-property-literals/7.16.7_@babel+core@7.17.4: + resolution: {integrity: sha512-z4FGr9NMGdoIl1RqavCqGG+ZuYjfZ/hkCIeuH6Do7tXmSm0ls11nYVSJqFEUOSJbDab5wC6lRE/w6YjVcr6Hqw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 + '@babel/core': 7.17.4 + '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-transform-react-display-name/7.16.0_@babel+core@7.16.0: - resolution: {integrity: sha512-FJFdJAqaCpndL+pIf0aeD/qlQwT7QXOvR6Cc8JPvNhKJBi2zc/DPc4g05Y3fbD/0iWAMQFGij4+Xw+4L/BMpTg==} + /@babel/plugin-transform-react-display-name/7.16.7_@babel+core@7.17.4: + resolution: {integrity: sha512-qgIg8BcZgd0G/Cz916D5+9kqX0c7nPZyXaP8R2tLNN5tkyIZdG5fEwBrxwplzSnjC1jvQmyMNVwUCZPcbGY7Pg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 + '@babel/core': 7.17.4 + '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-transform-react-jsx-development/7.16.0_@babel+core@7.16.0: - resolution: {integrity: sha512-qq65iSqBRq0Hr3wq57YG2AmW0H6wgTnIzpffTphrUWUgLCOK+zf1f7G0vuOiXrp7dU1qq+fQBoqZ3wCDAkhFzw==} + /@babel/plugin-transform-react-jsx-development/7.16.7_@babel+core@7.17.4: + resolution: {integrity: sha512-RMvQWvpla+xy6MlBpPlrKZCMRs2AGiHOGHY3xRwl0pEeim348dDyxeH4xBsMPbIMhujeq7ihE702eM2Ew0Wo+A==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/plugin-transform-react-jsx': 7.16.0_@babel+core@7.16.0 + '@babel/core': 7.17.4 + '@babel/plugin-transform-react-jsx': 7.17.3_@babel+core@7.17.4 dev: true - /@babel/plugin-transform-react-jsx/7.16.0_@babel+core@7.16.0: - resolution: {integrity: sha512-rqDgIbukZ44pqq7NIRPGPGNklshPkvlmvqjdx3OZcGPk4zGIenYkxDTvl3LsSL8gqcc3ZzGmXPE6hR/u/voNOw==} + /@babel/plugin-transform-react-jsx/7.17.3_@babel+core@7.17.4: + resolution: {integrity: sha512-9tjBm4O07f7mzKSIlEmPdiE6ub7kfIe6Cd+w+oQebpATfTQMAgW+YOuWxogbKVTulA+MEO7byMeIUtQ1z+z+ZQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-annotate-as-pure': 7.16.0 - '@babel/helper-module-imports': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 - '@babel/plugin-syntax-jsx': 7.16.0_@babel+core@7.16.0 - '@babel/types': 7.16.0 + '@babel/core': 7.17.4 + '@babel/helper-annotate-as-pure': 7.16.7 + '@babel/helper-module-imports': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/plugin-syntax-jsx': 7.16.7_@babel+core@7.17.4 + '@babel/types': 7.17.0 dev: true - /@babel/plugin-transform-react-pure-annotations/7.16.0_@babel+core@7.16.0: - resolution: {integrity: sha512-NC/Bj2MG+t8Ef5Pdpo34Ay74X4Rt804h5y81PwOpfPtmAK3i6CizmQqwyBQzIepz1Yt8wNr2Z2L7Lu3qBMfZMA==} + /@babel/plugin-transform-react-pure-annotations/7.16.7_@babel+core@7.17.4: + resolution: {integrity: sha512-hs71ToC97k3QWxswh2ElzMFABXHvGiJ01IB1TbYQDGeWRKWz/MPUTh5jGExdHvosYKpnJW5Pm3S4+TA3FyX+GA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-annotate-as-pure': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 + '@babel/core': 7.17.4 + '@babel/helper-annotate-as-pure': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-transform-regenerator/7.16.0_@babel+core@7.16.0: - resolution: {integrity: sha512-JAvGxgKuwS2PihiSFaDrp94XOzzTUeDeOQlcKzVAyaPap7BnZXK/lvMDiubkPTdotPKOIZq9xWXWnggUMYiExg==} + /@babel/plugin-transform-regenerator/7.16.7_@babel+core@7.17.4: + resolution: {integrity: sha512-mF7jOgGYCkSJagJ6XCujSQg+6xC1M77/03K2oBmVJWoFGNUtnVJO4WHKJk3dnPC8HCcj4xBQP1Egm8DWh3Pb3Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 + '@babel/core': 7.17.4 regenerator-transform: 0.14.5 dev: true - /@babel/plugin-transform-reserved-words/7.16.0_@babel+core@7.16.0: - resolution: {integrity: sha512-Dgs8NNCehHSvXdhEhln8u/TtJxfVwGYCgP2OOr5Z3Ar+B+zXicEOKNTyc+eca2cuEOMtjW6m9P9ijOt8QdqWkg==} + /@babel/plugin-transform-reserved-words/7.16.7_@babel+core@7.17.4: + resolution: {integrity: sha512-KQzzDnZ9hWQBjwi5lpY5v9shmm6IVG0U9pB18zvMu2i4H90xpT4gmqwPYsn8rObiadYe2M0gmgsiOIF5A/2rtg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 + '@babel/core': 7.17.4 + '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-transform-shorthand-properties/7.16.0_@babel+core@7.16.0: - resolution: {integrity: sha512-iVb1mTcD8fuhSv3k99+5tlXu5N0v8/DPm2mO3WACLG6al1CGZH7v09HJyUb1TtYl/Z+KrM6pHSIJdZxP5A+xow==} + /@babel/plugin-transform-shorthand-properties/7.16.7_@babel+core@7.17.4: + resolution: {integrity: sha512-hah2+FEnoRoATdIb05IOXf+4GzXYTq75TVhIn1PewihbpyrNWUt2JbudKQOETWw6QpLe+AIUpJ5MVLYTQbeeUg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 + '@babel/core': 7.17.4 + '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-transform-spread/7.16.0_@babel+core@7.16.0: - resolution: {integrity: sha512-Ao4MSYRaLAQczZVp9/7E7QHsCuK92yHRrmVNRe/SlEJjhzivq0BSn8mEraimL8wizHZ3fuaHxKH0iwzI13GyGg==} + /@babel/plugin-transform-spread/7.16.7_@babel+core@7.17.4: + resolution: {integrity: sha512-+pjJpgAngb53L0iaA5gU/1MLXJIfXcYepLgXB3esVRf4fqmj8f2cxM3/FKaHsZms08hFQJkFccEWuIpm429TXg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 + '@babel/core': 7.17.4 + '@babel/helper-plugin-utils': 7.16.7 '@babel/helper-skip-transparent-expression-wrappers': 7.16.0 dev: true - /@babel/plugin-transform-sticky-regex/7.16.0_@babel+core@7.16.0: - resolution: {integrity: sha512-/ntT2NljR9foobKk4E/YyOSwcGUXtYWv5tinMK/3RkypyNBNdhHUaq6Orw5DWq9ZcNlS03BIlEALFeQgeVAo4Q==} + /@babel/plugin-transform-sticky-regex/7.16.7_@babel+core@7.17.4: + resolution: {integrity: sha512-NJa0Bd/87QV5NZZzTuZG5BPJjLYadeSZ9fO6oOUoL4iQx+9EEuw/eEM92SrsT19Yc2jgB1u1hsjqDtH02c3Drw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 + '@babel/core': 7.17.4 + '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-transform-template-literals/7.16.0_@babel+core@7.16.0: - resolution: {integrity: sha512-Rd4Ic89hA/f7xUSJQk5PnC+4so50vBoBfxjdQAdvngwidM8jYIBVxBZ/sARxD4e0yMXRbJVDrYf7dyRtIIKT6Q==} + /@babel/plugin-transform-template-literals/7.16.7_@babel+core@7.17.4: + resolution: {integrity: sha512-VwbkDDUeenlIjmfNeDX/V0aWrQH2QiVyJtwymVQSzItFDTpxfyJh3EVaQiS0rIN/CqbLGr0VcGmuwyTdZtdIsA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 + '@babel/core': 7.17.4 + '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-transform-typeof-symbol/7.16.0_@babel+core@7.16.0: - resolution: {integrity: sha512-++V2L8Bdf4vcaHi2raILnptTBjGEFxn5315YU+e8+EqXIucA+q349qWngCLpUYqqv233suJ6NOienIVUpS9cqg==} + /@babel/plugin-transform-typeof-symbol/7.16.7_@babel+core@7.17.4: + resolution: {integrity: sha512-p2rOixCKRJzpg9JB4gjnG4gjWkWa89ZoYUnl9snJ1cWIcTH/hvxZqfO+WjG6T8DRBpctEol5jw1O5rA8gkCokQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 + '@babel/core': 7.17.4 + '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-transform-typescript/7.16.1_@babel+core@7.16.0: - resolution: {integrity: sha512-NO4XoryBng06jjw/qWEU2LhcLJr1tWkhpMam/H4eas/CDKMX/b2/Ylb6EI256Y7+FVPCawwSM1rrJNOpDiz+Lg==} + /@babel/plugin-transform-typescript/7.16.8_@babel+core@7.17.4: + resolution: {integrity: sha512-bHdQ9k7YpBDO2d0NVfkj51DpQcvwIzIusJ7mEUaMlbZq3Kt/U47j24inXZHQ5MDiYpCs+oZiwnXyKedE8+q7AQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-create-class-features-plugin': 7.16.0_@babel+core@7.16.0 - '@babel/helper-plugin-utils': 7.14.5 - '@babel/plugin-syntax-typescript': 7.16.0_@babel+core@7.16.0 + '@babel/core': 7.17.4 + '@babel/helper-create-class-features-plugin': 7.17.1_@babel+core@7.17.4 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/plugin-syntax-typescript': 7.16.7_@babel+core@7.17.4 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-transform-unicode-escapes/7.16.0_@babel+core@7.16.0: - resolution: {integrity: sha512-VFi4dhgJM7Bpk8lRc5CMaRGlKZ29W9C3geZjt9beuzSUrlJxsNwX7ReLwaL6WEvsOf2EQkyIJEPtF8EXjB/g2A==} + /@babel/plugin-transform-unicode-escapes/7.16.7_@babel+core@7.17.4: + resolution: {integrity: sha512-TAV5IGahIz3yZ9/Hfv35TV2xEm+kaBDaZQCn2S/hG9/CZ0DktxJv9eKfPc7yYCvOYR4JGx1h8C+jcSOvgaaI/Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 + '@babel/core': 7.17.4 + '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-transform-unicode-regex/7.16.0_@babel+core@7.16.0: - resolution: {integrity: sha512-jHLK4LxhHjvCeZDWyA9c+P9XH1sOxRd1RO9xMtDVRAOND/PczPqizEtVdx4TQF/wyPaewqpT+tgQFYMnN/P94A==} + /@babel/plugin-transform-unicode-regex/7.16.7_@babel+core@7.17.4: + resolution: {integrity: sha512-oC5tYYKw56HO75KZVLQ+R/Nl3Hro9kf8iG0hXoaHP7tjAyCpvqBiSNe6vGrZni1Z6MggmUOC6A7VP7AVmw225Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-create-regexp-features-plugin': 7.16.0_@babel+core@7.16.0 - '@babel/helper-plugin-utils': 7.14.5 + '@babel/core': 7.17.4 + '@babel/helper-create-regexp-features-plugin': 7.17.0_@babel+core@7.17.4 + '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/preset-env/7.16.4_@babel+core@7.16.0: - resolution: {integrity: sha512-v0QtNd81v/xKj4gNKeuAerQ/azeNn/G1B1qMLeXOcV8+4TWlD2j3NV1u8q29SDFBXx/NBq5kyEAO+0mpRgacjA==} + /@babel/preset-env/7.16.11_@babel+core@7.17.4: + resolution: {integrity: sha512-qcmWG8R7ZW6WBRPZK//y+E3Cli151B20W1Rv7ln27vuPaXU/8TKms6jFdiJtF7UDTxcrb7mZd88tAeK9LjdT8g==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/compat-data': 7.16.4 - '@babel/core': 7.16.0 - '@babel/helper-compilation-targets': 7.16.3_@babel+core@7.16.0 - '@babel/helper-plugin-utils': 7.14.5 - '@babel/helper-validator-option': 7.14.5 - '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.16.2_@babel+core@7.16.0 - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.16.0_@babel+core@7.16.0 - '@babel/plugin-proposal-async-generator-functions': 7.16.4_@babel+core@7.16.0 - '@babel/plugin-proposal-class-properties': 7.16.0_@babel+core@7.16.0 - '@babel/plugin-proposal-class-static-block': 7.16.0_@babel+core@7.16.0 - '@babel/plugin-proposal-dynamic-import': 7.16.0_@babel+core@7.16.0 - '@babel/plugin-proposal-export-namespace-from': 7.16.0_@babel+core@7.16.0 - '@babel/plugin-proposal-json-strings': 7.16.0_@babel+core@7.16.0 - '@babel/plugin-proposal-logical-assignment-operators': 7.16.0_@babel+core@7.16.0 - '@babel/plugin-proposal-nullish-coalescing-operator': 7.16.0_@babel+core@7.16.0 - '@babel/plugin-proposal-numeric-separator': 7.16.0_@babel+core@7.16.0 - '@babel/plugin-proposal-object-rest-spread': 7.16.0_@babel+core@7.16.0 - '@babel/plugin-proposal-optional-catch-binding': 7.16.0_@babel+core@7.16.0 - '@babel/plugin-proposal-optional-chaining': 7.16.0_@babel+core@7.16.0 - '@babel/plugin-proposal-private-methods': 7.16.0_@babel+core@7.16.0 - '@babel/plugin-proposal-private-property-in-object': 7.16.0_@babel+core@7.16.0 - '@babel/plugin-proposal-unicode-property-regex': 7.16.0_@babel+core@7.16.0 - '@babel/plugin-syntax-async-generators': 7.8.4_@babel+core@7.16.0 - '@babel/plugin-syntax-class-properties': 7.12.13_@babel+core@7.16.0 - '@babel/plugin-syntax-class-static-block': 7.14.5_@babel+core@7.16.0 - '@babel/plugin-syntax-dynamic-import': 7.8.3_@babel+core@7.16.0 - '@babel/plugin-syntax-export-namespace-from': 7.8.3_@babel+core@7.16.0 - '@babel/plugin-syntax-json-strings': 7.8.3_@babel+core@7.16.0 - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4_@babel+core@7.16.0 - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3_@babel+core@7.16.0 - '@babel/plugin-syntax-numeric-separator': 7.10.4_@babel+core@7.16.0 - '@babel/plugin-syntax-object-rest-spread': 7.8.3_@babel+core@7.16.0 - '@babel/plugin-syntax-optional-catch-binding': 7.8.3_@babel+core@7.16.0 - '@babel/plugin-syntax-optional-chaining': 7.8.3_@babel+core@7.16.0 - '@babel/plugin-syntax-private-property-in-object': 7.14.5_@babel+core@7.16.0 - '@babel/plugin-syntax-top-level-await': 7.14.5_@babel+core@7.16.0 - '@babel/plugin-transform-arrow-functions': 7.16.0_@babel+core@7.16.0 - '@babel/plugin-transform-async-to-generator': 7.16.0_@babel+core@7.16.0 - '@babel/plugin-transform-block-scoped-functions': 7.16.0_@babel+core@7.16.0 - '@babel/plugin-transform-block-scoping': 7.16.0_@babel+core@7.16.0 - '@babel/plugin-transform-classes': 7.16.0_@babel+core@7.16.0 - '@babel/plugin-transform-computed-properties': 7.16.0_@babel+core@7.16.0 - '@babel/plugin-transform-destructuring': 7.16.0_@babel+core@7.16.0 - '@babel/plugin-transform-dotall-regex': 7.16.0_@babel+core@7.16.0 - '@babel/plugin-transform-duplicate-keys': 7.16.0_@babel+core@7.16.0 - '@babel/plugin-transform-exponentiation-operator': 7.16.0_@babel+core@7.16.0 - '@babel/plugin-transform-for-of': 7.16.0_@babel+core@7.16.0 - '@babel/plugin-transform-function-name': 7.16.0_@babel+core@7.16.0 - '@babel/plugin-transform-literals': 7.16.0_@babel+core@7.16.0 - '@babel/plugin-transform-member-expression-literals': 7.16.0_@babel+core@7.16.0 - '@babel/plugin-transform-modules-amd': 7.16.0_@babel+core@7.16.0 - '@babel/plugin-transform-modules-commonjs': 7.16.0_@babel+core@7.16.0 - '@babel/plugin-transform-modules-systemjs': 7.16.0_@babel+core@7.16.0 - '@babel/plugin-transform-modules-umd': 7.16.0_@babel+core@7.16.0 - '@babel/plugin-transform-named-capturing-groups-regex': 7.16.0_@babel+core@7.16.0 - '@babel/plugin-transform-new-target': 7.16.0_@babel+core@7.16.0 - '@babel/plugin-transform-object-super': 7.16.0_@babel+core@7.16.0 - '@babel/plugin-transform-parameters': 7.16.3_@babel+core@7.16.0 - '@babel/plugin-transform-property-literals': 7.16.0_@babel+core@7.16.0 - '@babel/plugin-transform-regenerator': 7.16.0_@babel+core@7.16.0 - '@babel/plugin-transform-reserved-words': 7.16.0_@babel+core@7.16.0 - '@babel/plugin-transform-shorthand-properties': 7.16.0_@babel+core@7.16.0 - '@babel/plugin-transform-spread': 7.16.0_@babel+core@7.16.0 - '@babel/plugin-transform-sticky-regex': 7.16.0_@babel+core@7.16.0 - '@babel/plugin-transform-template-literals': 7.16.0_@babel+core@7.16.0 - '@babel/plugin-transform-typeof-symbol': 7.16.0_@babel+core@7.16.0 - '@babel/plugin-transform-unicode-escapes': 7.16.0_@babel+core@7.16.0 - '@babel/plugin-transform-unicode-regex': 7.16.0_@babel+core@7.16.0 - '@babel/preset-modules': 0.1.5_@babel+core@7.16.0 - '@babel/types': 7.16.0 - babel-plugin-polyfill-corejs2: 0.3.0_@babel+core@7.16.0 - babel-plugin-polyfill-corejs3: 0.4.0_@babel+core@7.16.0 - babel-plugin-polyfill-regenerator: 0.3.0_@babel+core@7.16.0 - core-js-compat: 3.19.1 + '@babel/compat-data': 7.17.0 + '@babel/core': 7.17.4 + '@babel/helper-compilation-targets': 7.16.7_@babel+core@7.17.4 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-validator-option': 7.16.7 + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.16.7_@babel+core@7.17.4 + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.16.7_@babel+core@7.17.4 + '@babel/plugin-proposal-async-generator-functions': 7.16.8_@babel+core@7.17.4 + '@babel/plugin-proposal-class-properties': 7.16.7_@babel+core@7.17.4 + '@babel/plugin-proposal-class-static-block': 7.16.7_@babel+core@7.17.4 + '@babel/plugin-proposal-dynamic-import': 7.16.7_@babel+core@7.17.4 + '@babel/plugin-proposal-export-namespace-from': 7.16.7_@babel+core@7.17.4 + '@babel/plugin-proposal-json-strings': 7.16.7_@babel+core@7.17.4 + '@babel/plugin-proposal-logical-assignment-operators': 7.16.7_@babel+core@7.17.4 + '@babel/plugin-proposal-nullish-coalescing-operator': 7.16.7_@babel+core@7.17.4 + '@babel/plugin-proposal-numeric-separator': 7.16.7_@babel+core@7.17.4 + '@babel/plugin-proposal-object-rest-spread': 7.17.3_@babel+core@7.17.4 + '@babel/plugin-proposal-optional-catch-binding': 7.16.7_@babel+core@7.17.4 + '@babel/plugin-proposal-optional-chaining': 7.16.7_@babel+core@7.17.4 + '@babel/plugin-proposal-private-methods': 7.16.11_@babel+core@7.17.4 + '@babel/plugin-proposal-private-property-in-object': 7.16.7_@babel+core@7.17.4 + '@babel/plugin-proposal-unicode-property-regex': 7.16.7_@babel+core@7.17.4 + '@babel/plugin-syntax-async-generators': 7.8.4_@babel+core@7.17.4 + '@babel/plugin-syntax-class-properties': 7.12.13_@babel+core@7.17.4 + '@babel/plugin-syntax-class-static-block': 7.14.5_@babel+core@7.17.4 + '@babel/plugin-syntax-dynamic-import': 7.8.3_@babel+core@7.17.4 + '@babel/plugin-syntax-export-namespace-from': 7.8.3_@babel+core@7.17.4 + '@babel/plugin-syntax-json-strings': 7.8.3_@babel+core@7.17.4 + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4_@babel+core@7.17.4 + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3_@babel+core@7.17.4 + '@babel/plugin-syntax-numeric-separator': 7.10.4_@babel+core@7.17.4 + '@babel/plugin-syntax-object-rest-spread': 7.8.3_@babel+core@7.17.4 + '@babel/plugin-syntax-optional-catch-binding': 7.8.3_@babel+core@7.17.4 + '@babel/plugin-syntax-optional-chaining': 7.8.3_@babel+core@7.17.4 + '@babel/plugin-syntax-private-property-in-object': 7.14.5_@babel+core@7.17.4 + '@babel/plugin-syntax-top-level-await': 7.14.5_@babel+core@7.17.4 + '@babel/plugin-transform-arrow-functions': 7.16.7_@babel+core@7.17.4 + '@babel/plugin-transform-async-to-generator': 7.16.8_@babel+core@7.17.4 + '@babel/plugin-transform-block-scoped-functions': 7.16.7_@babel+core@7.17.4 + '@babel/plugin-transform-block-scoping': 7.16.7_@babel+core@7.17.4 + '@babel/plugin-transform-classes': 7.16.7_@babel+core@7.17.4 + '@babel/plugin-transform-computed-properties': 7.16.7_@babel+core@7.17.4 + '@babel/plugin-transform-destructuring': 7.17.3_@babel+core@7.17.4 + '@babel/plugin-transform-dotall-regex': 7.16.7_@babel+core@7.17.4 + '@babel/plugin-transform-duplicate-keys': 7.16.7_@babel+core@7.17.4 + '@babel/plugin-transform-exponentiation-operator': 7.16.7_@babel+core@7.17.4 + '@babel/plugin-transform-for-of': 7.16.7_@babel+core@7.17.4 + '@babel/plugin-transform-function-name': 7.16.7_@babel+core@7.17.4 + '@babel/plugin-transform-literals': 7.16.7_@babel+core@7.17.4 + '@babel/plugin-transform-member-expression-literals': 7.16.7_@babel+core@7.17.4 + '@babel/plugin-transform-modules-amd': 7.16.7_@babel+core@7.17.4 + '@babel/plugin-transform-modules-commonjs': 7.16.8_@babel+core@7.17.4 + '@babel/plugin-transform-modules-systemjs': 7.16.7_@babel+core@7.17.4 + '@babel/plugin-transform-modules-umd': 7.16.7_@babel+core@7.17.4 + '@babel/plugin-transform-named-capturing-groups-regex': 7.16.8_@babel+core@7.17.4 + '@babel/plugin-transform-new-target': 7.16.7_@babel+core@7.17.4 + '@babel/plugin-transform-object-super': 7.16.7_@babel+core@7.17.4 + '@babel/plugin-transform-parameters': 7.16.7_@babel+core@7.17.4 + '@babel/plugin-transform-property-literals': 7.16.7_@babel+core@7.17.4 + '@babel/plugin-transform-regenerator': 7.16.7_@babel+core@7.17.4 + '@babel/plugin-transform-reserved-words': 7.16.7_@babel+core@7.17.4 + '@babel/plugin-transform-shorthand-properties': 7.16.7_@babel+core@7.17.4 + '@babel/plugin-transform-spread': 7.16.7_@babel+core@7.17.4 + '@babel/plugin-transform-sticky-regex': 7.16.7_@babel+core@7.17.4 + '@babel/plugin-transform-template-literals': 7.16.7_@babel+core@7.17.4 + '@babel/plugin-transform-typeof-symbol': 7.16.7_@babel+core@7.17.4 + '@babel/plugin-transform-unicode-escapes': 7.16.7_@babel+core@7.17.4 + '@babel/plugin-transform-unicode-regex': 7.16.7_@babel+core@7.17.4 + '@babel/preset-modules': 0.1.5_@babel+core@7.17.4 + '@babel/types': 7.17.0 + babel-plugin-polyfill-corejs2: 0.3.0_@babel+core@7.17.4 + babel-plugin-polyfill-corejs3: 0.5.2_@babel+core@7.17.4 + babel-plugin-polyfill-regenerator: 0.3.0_@babel+core@7.17.4 + core-js-compat: 3.21.0 semver: 6.3.0 transitivePeerDependencies: - supports-color dev: true - /@babel/preset-modules/0.1.5_@babel+core@7.16.0: + /@babel/preset-modules/0.1.5_@babel+core@7.17.4: resolution: {integrity: sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 - '@babel/plugin-proposal-unicode-property-regex': 7.16.0_@babel+core@7.16.0 - '@babel/plugin-transform-dotall-regex': 7.16.0_@babel+core@7.16.0 - '@babel/types': 7.16.0 + '@babel/core': 7.17.4 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/plugin-proposal-unicode-property-regex': 7.16.7_@babel+core@7.17.4 + '@babel/plugin-transform-dotall-regex': 7.16.7_@babel+core@7.17.4 + '@babel/types': 7.17.0 esutils: 2.0.3 dev: true - /@babel/preset-react/7.16.0_@babel+core@7.16.0: - resolution: {integrity: sha512-d31IFW2bLRB28uL1WoElyro8RH5l6531XfxMtCeCmp6RVAF1uTfxxUA0LH1tXl+psZdwfmIbwoG4U5VwgbhtLw==} + /@babel/preset-react/7.16.7_@babel+core@7.17.4: + resolution: {integrity: sha512-fWpyI8UM/HE6DfPBzD8LnhQ/OcH8AgTaqcqP2nGOXEUV+VKBR5JRN9hCk9ai+zQQ57vtm9oWeXguBCPNUjytgA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 - '@babel/helper-validator-option': 7.14.5 - '@babel/plugin-transform-react-display-name': 7.16.0_@babel+core@7.16.0 - '@babel/plugin-transform-react-jsx': 7.16.0_@babel+core@7.16.0 - '@babel/plugin-transform-react-jsx-development': 7.16.0_@babel+core@7.16.0 - '@babel/plugin-transform-react-pure-annotations': 7.16.0_@babel+core@7.16.0 + '@babel/core': 7.17.4 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-validator-option': 7.16.7 + '@babel/plugin-transform-react-display-name': 7.16.7_@babel+core@7.17.4 + '@babel/plugin-transform-react-jsx': 7.17.3_@babel+core@7.17.4 + '@babel/plugin-transform-react-jsx-development': 7.16.7_@babel+core@7.17.4 + '@babel/plugin-transform-react-pure-annotations': 7.16.7_@babel+core@7.17.4 dev: true - /@babel/preset-typescript/7.16.0_@babel+core@7.16.0: - resolution: {integrity: sha512-txegdrZYgO9DlPbv+9QOVpMnKbOtezsLHWsnsRF4AjbSIsVaujrq1qg8HK0mxQpWv0jnejt0yEoW1uWpvbrDTg==} + /@babel/preset-typescript/7.16.7_@babel+core@7.17.4: + resolution: {integrity: sha512-WbVEmgXdIyvzB77AQjGBEyYPZx+8tTsO50XtfozQrkW8QB2rLJpH2lgx0TRw5EJrBxOZQ+wCcyPVQvS8tjEHpQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-plugin-utils': 7.14.5 - '@babel/helper-validator-option': 7.14.5 - '@babel/plugin-transform-typescript': 7.16.1_@babel+core@7.16.0 + '@babel/core': 7.17.4 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-validator-option': 7.16.7 + '@babel/plugin-transform-typescript': 7.16.8_@babel+core@7.17.4 transitivePeerDependencies: - supports-color dev: true @@ -1326,49 +1516,54 @@ packages: engines: {node: '>=6.9.0'} dependencies: regenerator-runtime: 0.13.9 - dev: true - /@babel/template/7.16.0: - resolution: {integrity: sha512-MnZdpFD/ZdYhXwiunMqqgyZyucaYsbL0IrjoGjaVhGilz+x8YB++kRfygSOIj1yOtWKPlx7NBp+9I1RQSgsd5A==} + /@babel/runtime/7.17.2: + resolution: {integrity: sha512-hzeyJyMA1YGdJTuWU0e/j4wKXrU4OMFvY2MSlaI9B7VQb0r5cxTE3EAIS2Q7Tn2RIcDkRvTA/v2JsAEhxe99uw==} engines: {node: '>=6.9.0'} dependencies: - '@babel/code-frame': 7.16.0 - '@babel/parser': 7.16.4 - '@babel/types': 7.16.0 + regenerator-runtime: 0.13.9 + + /@babel/template/7.16.7: + resolution: {integrity: sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.16.7 + '@babel/parser': 7.17.3 + '@babel/types': 7.17.0 - /@babel/traverse/7.16.3: + /@babel/traverse/7.16.3_supports-color@5.5.0: resolution: {integrity: sha512-eolumr1vVMjqevCpwVO99yN/LoGL0EyHiLO5I043aYQvwOJ9eR5UsZSClHVCzfhBduMAsSzgA/6AyqPjNayJag==} engines: {node: '>=6.9.0'} dependencies: - '@babel/code-frame': 7.16.0 + '@babel/code-frame': 7.16.7 '@babel/generator': 7.16.0 '@babel/helper-function-name': 7.16.0 '@babel/helper-hoist-variables': 7.16.0 '@babel/helper-split-export-declaration': 7.16.0 '@babel/parser': 7.16.4 '@babel/types': 7.16.0 - debug: 4.3.2 + debug: 4.3.4_supports-color@5.5.0 globals: 11.12.0 transitivePeerDependencies: - supports-color - dev: true - /@babel/traverse/7.16.3_supports-color@5.5.0: - resolution: {integrity: sha512-eolumr1vVMjqevCpwVO99yN/LoGL0EyHiLO5I043aYQvwOJ9eR5UsZSClHVCzfhBduMAsSzgA/6AyqPjNayJag==} + /@babel/traverse/7.17.3: + resolution: {integrity: sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw==} engines: {node: '>=6.9.0'} dependencies: - '@babel/code-frame': 7.16.0 - '@babel/generator': 7.16.0 - '@babel/helper-function-name': 7.16.0 - '@babel/helper-hoist-variables': 7.16.0 - '@babel/helper-split-export-declaration': 7.16.0 - '@babel/parser': 7.16.4 - '@babel/types': 7.16.0 - debug: 4.3.2_supports-color@5.5.0 + '@babel/code-frame': 7.16.7 + '@babel/generator': 7.17.3 + '@babel/helper-environment-visitor': 7.16.7 + '@babel/helper-function-name': 7.16.7 + '@babel/helper-hoist-variables': 7.16.7 + '@babel/helper-split-export-declaration': 7.16.7 + '@babel/parser': 7.17.3 + '@babel/types': 7.17.0 + debug: 4.3.2 globals: 11.12.0 transitivePeerDependencies: - supports-color - dev: false + dev: true /@babel/types/7.16.0: resolution: {integrity: sha512-PJgg/k3SdLsGb3hhisFvtLOw5ts113klrpLuIPtCJIU+BB24fqq6lf8RWqKJEjzqXR9AEH1rIb5XTqwBHB+kQg==} @@ -1377,6 +1572,13 @@ packages: '@babel/helper-validator-identifier': 7.15.7 to-fast-properties: 2.0.0 + /@babel/types/7.17.0: + resolution: {integrity: sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-validator-identifier': 7.16.7 + to-fast-properties: 2.0.0 + /@bcoe/v8-coverage/0.2.3: resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} dev: true @@ -1386,31 +1588,105 @@ packages: engines: {node: '>=10.0.0'} dev: true + /@electron/get/1.13.1: + resolution: {integrity: sha512-U5vkXDZ9DwXtkPqlB45tfYnnYBN8PePp1z/XDCupnSpdrxT8/ThCv9WCwPLf9oqiSGZTkH6dx2jDUPuoXpjkcA==} + engines: {node: '>=8.6'} + dependencies: + debug: 4.3.4 + env-paths: 2.2.1 + fs-extra: 8.1.0 + got: 9.6.0 + progress: 2.0.3 + semver: 6.3.0 + sumchecker: 3.0.1 + optionalDependencies: + global-agent: 3.0.0 + global-tunnel-ng: 2.7.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@emotion/cache/11.7.1: + resolution: {integrity: sha512-r65Zy4Iljb8oyjtLeCuBH8Qjiy107dOYC6SJq7g7GV5UCQWMObY4SJDPGFjiiVpPrOJ2hmJOoBiYTC7hwx9E2A==} + dependencies: + '@emotion/memoize': 0.7.4 + '@emotion/sheet': 1.1.0 + '@emotion/utils': 1.0.0 + '@emotion/weak-memoize': 0.2.5 + stylis: 4.0.13 + dev: true + + /@emotion/hash/0.8.0: + resolution: {integrity: sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==} + dev: true + /@emotion/is-prop-valid/0.8.8: resolution: {integrity: sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==} dependencies: '@emotion/memoize': 0.7.4 - dev: false /@emotion/memoize/0.7.4: resolution: {integrity: sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==} - dev: false + + /@emotion/react/11.7.1_oeypub6dug5xwmzqzpvzyakzzi: + resolution: {integrity: sha512-DV2Xe3yhkF1yT4uAUoJcYL1AmrnO5SVsdfvu+fBuS7IbByDeTVx9+wFmvx9Idzv7/78+9Mgx2Hcmr7Fex3tIyw==} + peerDependencies: + '@babel/core': ^7.0.0 + '@types/react': '*' + react: '>=16.8.0' + peerDependenciesMeta: + '@babel/core': + optional: true + '@types/react': + optional: true + dependencies: + '@babel/core': 7.17.4 + '@babel/runtime': 7.17.2 + '@emotion/cache': 11.7.1 + '@emotion/serialize': 1.0.2 + '@emotion/sheet': 1.1.0 + '@emotion/utils': 1.0.0 + '@emotion/weak-memoize': 0.2.5 + '@types/react': 17.0.39 + hoist-non-react-statics: 3.3.2 + react: 17.0.2 + dev: true + + /@emotion/serialize/1.0.2: + resolution: {integrity: sha512-95MgNJ9+/ajxU7QIAruiOAdYNjxZX7G2mhgrtDWswA21VviYIRP1R5QilZ/bDY42xiKsaktP4egJb3QdYQZi1A==} + dependencies: + '@emotion/hash': 0.8.0 + '@emotion/memoize': 0.7.4 + '@emotion/unitless': 0.7.5 + '@emotion/utils': 1.0.0 + csstype: 3.0.10 + dev: true + + /@emotion/sheet/1.1.0: + resolution: {integrity: sha512-u0AX4aSo25sMAygCuQTzS+HsImZFuS8llY8O7b9MDRzbJM0kVJlAz6KNDqcG7pOuQZJmj/8X/rAW+66kMnMW+g==} + dev: true /@emotion/stylis/0.8.5: resolution: {integrity: sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==} - dev: false /@emotion/unitless/0.7.5: resolution: {integrity: sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==} - dev: false - /@eslint/eslintrc/1.0.4: - resolution: {integrity: sha512-h8Vx6MdxwWI2WM8/zREHMoqdgLNXEL4QX3MWSVMdyNJGvXVOs+6lp+m2hc3FnuMHDc4poxFNI20vCk0OmI4G0Q==} + /@emotion/utils/1.0.0: + resolution: {integrity: sha512-mQC2b3XLDs6QCW+pDQDiyO/EdGZYOygE8s5N5rrzjSI4M3IejPE/JPndCBwRT9z982aqQNi6beWs1UeayrQxxA==} + dev: true + + /@emotion/weak-memoize/0.2.5: + resolution: {integrity: sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA==} + dev: true + + /@eslint/eslintrc/1.1.0: + resolution: {integrity: sha512-C1DfL7XX4nPqGd6jcP01W9pVM1HYCuUkFk1432D7F0v3JSlUIeOYn9oCoi3eoLZ+iwBSb29BMFxxny0YrrEZqg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: ajv: 6.12.6 debug: 4.3.2 - espree: 9.1.0 + espree: 9.3.1 globals: 13.12.0 ignore: 4.0.6 import-fresh: 3.3.0 @@ -1421,8 +1697,51 @@ packages: - supports-color dev: true - /@humanwhocodes/config-array/0.6.0: - resolution: {integrity: sha512-JQlEKbcgEUjBFhLIF4iqM7u/9lwgHRBcpHrmUNCALK0Q3amXN6lxdoXLnF0sm11E9VqTmBALR87IlUg1bZ8A9A==} + /@graphql-tools/merge/8.2.2_graphql@16.3.0: + resolution: {integrity: sha512-2DyqhIOMUMKbCPqo8p6xSdll2OBcBxGdOrxlJJlFQvinsSaYqp/ct3dhAxNtzaIcvSVgXvttQqfD7O2ziFtE7Q==} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + '@graphql-tools/utils': 8.6.1_graphql@16.3.0 + graphql: 16.3.0 + tslib: 2.3.1 + dev: true + + /@graphql-tools/mock/8.5.1_graphql@16.3.0: + resolution: {integrity: sha512-cwwqGs9Rofev1JdMheAseqM/rw1uw4CYb35vv3Kcv2bbyiPF+490xdlHqFeIazceotMFxC60LlQztwb64rsEnw==} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + '@graphql-tools/schema': 8.3.1_graphql@16.3.0 + '@graphql-tools/utils': 8.6.1_graphql@16.3.0 + fast-json-stable-stringify: 2.1.0 + graphql: 16.3.0 + tslib: 2.3.1 + dev: true + + /@graphql-tools/schema/8.3.1_graphql@16.3.0: + resolution: {integrity: sha512-3R0AJFe715p4GwF067G5i0KCr/XIdvSfDLvTLEiTDQ8V/hwbOHEKHKWlEBHGRQwkG5lwFQlW1aOn7VnlPERnWQ==} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + '@graphql-tools/merge': 8.2.2_graphql@16.3.0 + '@graphql-tools/utils': 8.6.1_graphql@16.3.0 + graphql: 16.3.0 + tslib: 2.3.1 + value-or-promise: 1.0.11 + dev: true + + /@graphql-tools/utils/8.6.1_graphql@16.3.0: + resolution: {integrity: sha512-uxcfHCocp4ENoIiovPxUWZEHOnbXqj3ekWc0rm7fUhW93a1xheARNHcNKhwMTR+UKXVJbTFQdGI1Rl5XdyvDBg==} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + graphql: 16.3.0 + tslib: 2.3.1 + dev: true + + /@humanwhocodes/config-array/0.9.3: + resolution: {integrity: sha512-3xSMlXHh03hCcCmFc0rbKp3Ivt2PFEJnQUJDDMTJQ2wkECZWdq4GePs2ctc5H8zV+cHPaq8k2vU8mrQjA6iHdQ==} engines: {node: '>=10.10.0'} dependencies: '@humanwhocodes/object-schema': 1.2.1 @@ -1452,20 +1771,20 @@ packages: engines: {node: '>=8'} dev: true - /@jest/console/27.3.1: - resolution: {integrity: sha512-RkFNWmv0iui+qsOr/29q9dyfKTTT5DCuP31kUwg7rmOKPT/ozLeGLKJKVIiOfbiKyleUZKIrHwhmiZWVe8IMdw==} + /@jest/console/27.5.1: + resolution: {integrity: sha512-kZ/tNpS3NXn0mlXXXPNuDZnb4c0oZ20r4K5eemM2k30ZC3G0T02nXUvyhf5YdbXWHPEJLc9qGLxEZ216MdL+Zg==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dependencies: - '@jest/types': 27.2.5 + '@jest/types': 27.5.1 '@types/node': 16.11.9 chalk: 4.1.2 - 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 dev: true - /@jest/core/27.3.1: - resolution: {integrity: sha512-DMNE90RR5QKx0EA+wqe3/TNEwiRpOkhshKNxtLxd4rt3IZpCt+RSL+FoJsGeblRZmqdK4upHA/mKKGPPRAifhg==} + /@jest/core/27.5.1: + resolution: {integrity: sha512-AK6/UTrvQD0Cd24NSqmIA6rKsu0tKIxfiCducZvqxYdmMisOYAsdItspT+fQDQYARPf8XgjAFZi0ogW2agH5nQ==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} peerDependencies: node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 @@ -1473,30 +1792,30 @@ packages: node-notifier: optional: 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': 16.11.9 ansi-escapes: 4.3.2 chalk: 4.1.2 emittery: 0.8.1 exit: 0.1.2 - graceful-fs: 4.2.8 - 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.2 slash: 3.0.0 @@ -1509,39 +1828,39 @@ packages: - utf-8-validate dev: true - /@jest/environment/27.3.1: - resolution: {integrity: sha512-BCKCj4mOVLme6Tanoyc9k0ultp3pnmuyHw73UHRPeeZxirsU/7E3HC4le/VDb/SMzE1JcPnto+XBKFOcoiJzVw==} + /@jest/environment/27.5.1: + resolution: {integrity: sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} 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': 16.11.9 - jest-mock: 27.3.0 + jest-mock: 27.5.1 dev: true - /@jest/fake-timers/27.3.1: - resolution: {integrity: sha512-M3ZFgwwlqJtWZ+QkBG5NmC23A9w+A6ZxNsO5nJxJsKYt4yguBd3i8TpjQz5NfCX91nEve1KqD9RA2Q+Q1uWqoA==} + /@jest/fake-timers/27.5.1: + resolution: {integrity: sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dependencies: - '@jest/types': 27.2.5 + '@jest/types': 27.5.1 '@sinonjs/fake-timers': 8.1.0 '@types/node': 16.11.9 - 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 dev: true - /@jest/globals/27.3.1: - resolution: {integrity: sha512-Q651FWiWQAIFiN+zS51xqhdZ8g9b88nGCobC87argAxA7nMfNQq0Q0i9zTfQYgLa6qFXk2cGANEqfK051CZ8Pg==} + /@jest/globals/27.5.1: + resolution: {integrity: sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} 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 dev: true - /@jest/reporters/27.3.1: - resolution: {integrity: sha512-m2YxPmL9Qn1emFVgZGEiMwDntDxRRQ2D58tiDQlwYTg5GvbFOKseYCcHtn0WsI8CG4vzPglo3nqbOiT8ySBT/w==} + /@jest/reporters/27.5.1: + resolution: {integrity: sha512-cPXh9hWIlVJMQkVk84aIvXuBB4uQQmFqZiacloFuGiP3ah1sbCxCosidXFDfqG8+6fO1oR2dTJTlsOy4VFmUfw==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} peerDependencies: node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 @@ -1550,25 +1869,25 @@ packages: optional: 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': 16.11.9 chalk: 4.1.2 collect-v8-coverage: 1.0.1 exit: 0.1.2 glob: 7.2.0 - graceful-fs: 4.2.8 + graceful-fs: 4.2.9 istanbul-lib-coverage: 3.2.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.1 - istanbul-reports: 3.0.5 - 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.4 + 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.1 string-length: 4.0.2 @@ -1578,53 +1897,53 @@ packages: - supports-color dev: true - /@jest/source-map/27.0.6: - resolution: {integrity: sha512-Fek4mi5KQrqmlY07T23JRi0e7Z9bXTOOD86V/uS0EIW4PClvPDqZOyFlLpNJheS6QI0FNX1CgmPjtJ4EA/2M+g==} + /@jest/source-map/27.5.1: + resolution: {integrity: sha512-y9NIHUYF3PJRlHk98NdC/N1gl88BL08aQQgu4k4ZopQkCw9t9cV8mtl3TV8b/YCB8XaVTFrmUTAJvjsntDireg==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dependencies: callsites: 3.1.0 - graceful-fs: 4.2.8 + graceful-fs: 4.2.9 source-map: 0.6.1 dev: true - /@jest/test-result/27.3.1: - resolution: {integrity: sha512-mLn6Thm+w2yl0opM8J/QnPTqrfS4FoXsXF2WIWJb2O/GBSyResL71BRuMYbYRsGt7ELwS5JGcEcGb52BNrumgg==} + /@jest/test-result/27.5.1: + resolution: {integrity: sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} 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.3 collect-v8-coverage: 1.0.1 dev: true - /@jest/test-sequencer/27.3.1: - resolution: {integrity: sha512-siySLo07IMEdSjA4fqEnxfIX8lB/lWYsBPwNFtkOvsFQvmBrL3yj3k3uFNZv/JDyApTakRpxbKLJ3CT8UGVCrA==} + /@jest/test-sequencer/27.5.1: + resolution: {integrity: sha512-LCheJF7WB2+9JuCS7VB/EmGIdQuhtqjRNI9A43idHv3E4KltCTsPsLxvdaubFHSYwY/fNjMWjl6vNRhDiN7vpQ==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dependencies: - '@jest/test-result': 27.3.1 - graceful-fs: 4.2.8 - 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 transitivePeerDependencies: - supports-color dev: true - /@jest/transform/27.3.1: - resolution: {integrity: sha512-3fSvQ02kuvjOI1C1ssqMVBKJpZf6nwoCiSu00zAKh5nrp3SptNtZy/8s5deayHnqxhjD9CWDJ+yqQwuQ0ZafXQ==} + /@jest/transform/27.5.1: + resolution: {integrity: sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dependencies: - '@babel/core': 7.16.0 - '@jest/types': 27.2.5 + '@babel/core': 7.17.4 + '@jest/types': 27.5.1 babel-plugin-istanbul: 6.1.1 chalk: 4.1.2 convert-source-map: 1.8.0 fast-json-stable-stringify: 2.1.0 - graceful-fs: 4.2.8 - 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.5 slash: 3.0.0 source-map: 0.6.1 write-file-atomic: 3.0.3 @@ -1632,8 +1951,8 @@ packages: - supports-color dev: true - /@jest/types/27.2.5: - resolution: {integrity: sha512-nmuM4VuDtCZcY+eTpw+0nvstwReMsjPoj7ZR80/BbixulhLaiX+fbv8oeLW8WZlJMcsGQsTmMKT/iTZu1Uy/lQ==} + /@jest/types/27.5.1: + resolution: {integrity: sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dependencies: '@types/istanbul-lib-coverage': 2.0.3 @@ -1643,6 +1962,26 @@ packages: chalk: 4.1.2 dev: true + /@josephg/resolvable/1.0.1: + resolution: {integrity: sha512-CtzORUwWTTOTqfVtHaKRJ0I1kNQd1bpn3sUh8I3nJDVY+5/M/Oe1DnEWzPQvqq/xPIIkzzzIP7mfCoAjFRvDhg==} + dev: true + + /@jridgewell/resolve-uri/3.0.5: + resolution: {integrity: sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew==} + engines: {node: '>=6.0.0'} + dev: true + + /@jridgewell/sourcemap-codec/1.4.11: + resolution: {integrity: sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg==} + dev: true + + /@jridgewell/trace-mapping/0.3.4: + resolution: {integrity: sha512-vFv9ttIedivx0ux3QSjhgtCVjPZd5l46ZOMDSCwnH1yUO2e964gO8LZGyv2QkqcgR6TnBU1v+1IFqmeoG+0UJQ==} + dependencies: + '@jridgewell/resolve-uri': 3.0.5 + '@jridgewell/sourcemap-codec': 1.4.11 + dev: true + /@nicolo-ribaudo/chokidar-2/2.1.8-no-fsevents.3: resolution: {integrity: sha512-s88O1aVtXftvp5bCPB7WnmXc5IwOZZ7YPuwNPt+GtOOXpPvad1LfbmjYv+qII7zP6RU2QGnqve27dnLycEnyEQ==} requiresBuild: true @@ -1670,66 +2009,756 @@ packages: fastq: 1.13.0 dev: true - /@pmmmwh/react-refresh-webpack-plugin/0.5.2_a5fd73e8f007f6df7a56d6f8dc678958: - resolution: {integrity: sha512-BWOG6opI9+L5HjQIj6znFLwVXkjDS98PKfRDlbPFvinTz4wQ7ZSXxV0lLOfRW12HXcqk4DEzrphjRMJFXuihNg==} - engines: {node: '>= 10.13'} - peerDependencies: - '@types/webpack': 4.x || 5.x - react-refresh: '>=0.10.0 <1.0.0' - sockjs-client: ^1.4.0 - type-fest: '>=0.17.0 <3.0.0' - webpack: '>=4.43.0 <6.0.0' - webpack-dev-server: 3.x || 4.x - webpack-hot-middleware: 2.x - webpack-plugin-serve: 0.x || 1.x - peerDependenciesMeta: - '@types/webpack': - optional: true - sockjs-client: - optional: true - type-fest: - optional: true - webpack-dev-server: - optional: true - webpack-hot-middleware: - optional: true - webpack-plugin-serve: - optional: true + /@octokit/auth-token/2.5.0: + resolution: {integrity: sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==} dependencies: - ansi-html-community: 0.0.8 - common-path-prefix: 3.0.0 - core-js-pure: 3.19.1 - error-stack-parser: 2.0.6 - find-up: 5.0.0 - html-entities: 2.3.2 - loader-utils: 2.0.2 - react-refresh: 0.11.0 - schema-utils: 3.1.1 - source-map: 0.7.3 - type-fest: 2.8.0 - webpack: 5.64.2_webpack-cli@4.9.1 - webpack-dev-server: 4.5.0_webpack-cli@4.9.1+webpack@5.64.2 + '@octokit/types': 6.34.0 dev: true - /@sinonjs/commons/1.8.3: - resolution: {integrity: sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==} + /@octokit/core/3.5.1: + resolution: {integrity: sha512-omncwpLVxMP+GLpLPgeGJBF6IWJFjXDS5flY5VbppePYX9XehevbDykRH9PdCdvqt9TS5AOTiDide7h0qrkHjw==} dependencies: - type-detect: 4.0.8 + '@octokit/auth-token': 2.5.0 + '@octokit/graphql': 4.8.0 + '@octokit/request': 5.6.3 + '@octokit/request-error': 2.1.0 + '@octokit/types': 6.34.0 + before-after-hook: 2.2.2 + universal-user-agent: 6.0.0 + transitivePeerDependencies: + - encoding dev: true - /@sinonjs/fake-timers/8.1.0: - resolution: {integrity: sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==} + /@octokit/endpoint/6.0.12: + resolution: {integrity: sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==} dependencies: - '@sinonjs/commons': 1.8.3 + '@octokit/types': 6.34.0 + is-plain-object: 5.0.0 + universal-user-agent: 6.0.0 dev: true - /@testing-library/dom/8.11.1: - resolution: {integrity: sha512-3KQDyx9r0RKYailW2MiYrSSKEfH0GTkI51UGEvJenvcoDoeRYs0PZpi2SXqtnMClQvCqdtTTpOfFETDTVADpAg==} - engines: {node: '>=12'} + /@octokit/graphql/4.8.0: + resolution: {integrity: sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==} dependencies: - '@babel/code-frame': 7.16.0 - '@babel/runtime': 7.16.3 - '@types/aria-query': 4.2.2 + '@octokit/request': 5.6.3 + '@octokit/types': 6.34.0 + universal-user-agent: 6.0.0 + transitivePeerDependencies: + - encoding + dev: true + + /@octokit/openapi-types/11.2.0: + resolution: {integrity: sha512-PBsVO+15KSlGmiI8QAzaqvsNlZlrDlyAJYcrXBCvVUxCp7VnXjkwPoFHgjEJXx3WF9BAwkA6nfCUA7i9sODzKA==} + dev: true + + /@octokit/plugin-paginate-rest/2.17.0_@octokit+core@3.5.1: + resolution: {integrity: sha512-tzMbrbnam2Mt4AhuyCHvpRkS0oZ5MvwwcQPYGtMv4tUa5kkzG58SVB0fcsLulOZQeRnOgdkZWkRUiyBlh0Bkyw==} + peerDependencies: + '@octokit/core': '>=2' + dependencies: + '@octokit/core': 3.5.1 + '@octokit/types': 6.34.0 + dev: true + + /@octokit/plugin-request-log/1.0.4_@octokit+core@3.5.1: + resolution: {integrity: sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==} + peerDependencies: + '@octokit/core': '>=3' + dependencies: + '@octokit/core': 3.5.1 + dev: true + + /@octokit/plugin-rest-endpoint-methods/5.13.0_@octokit+core@3.5.1: + resolution: {integrity: sha512-uJjMTkN1KaOIgNtUPMtIXDOjx6dGYysdIFhgA52x4xSadQCz3b/zJexvITDVpANnfKPW/+E0xkOvLntqMYpviA==} + peerDependencies: + '@octokit/core': '>=3' + dependencies: + '@octokit/core': 3.5.1 + '@octokit/types': 6.34.0 + deprecation: 2.3.1 + dev: true + + /@octokit/request-error/2.1.0: + resolution: {integrity: sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==} + dependencies: + '@octokit/types': 6.34.0 + deprecation: 2.3.1 + once: 1.4.0 + dev: true + + /@octokit/request/5.6.3: + resolution: {integrity: sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==} + dependencies: + '@octokit/endpoint': 6.0.12 + '@octokit/request-error': 2.1.0 + '@octokit/types': 6.34.0 + is-plain-object: 5.0.0 + node-fetch: 2.6.7 + universal-user-agent: 6.0.0 + transitivePeerDependencies: + - encoding + dev: true + + /@octokit/rest/18.12.0: + resolution: {integrity: sha512-gDPiOHlyGavxr72y0guQEhLsemgVjwRePayJ+FcKc2SJqKUbxbkvf5kAZEWA/MKvsfYlQAMVzNJE3ezQcxMJ2Q==} + dependencies: + '@octokit/core': 3.5.1 + '@octokit/plugin-paginate-rest': 2.17.0_@octokit+core@3.5.1 + '@octokit/plugin-request-log': 1.0.4_@octokit+core@3.5.1 + '@octokit/plugin-rest-endpoint-methods': 5.13.0_@octokit+core@3.5.1 + transitivePeerDependencies: + - encoding + dev: true + + /@octokit/types/6.34.0: + resolution: {integrity: sha512-s1zLBjWhdEI2zwaoSgyOFoKSl109CUcVBCc7biPJ3aAf6LGLU6szDvi31JPU7bxfla2lqfhjbbg/5DdFNxOwHw==} + dependencies: + '@octokit/openapi-types': 11.2.0 + dev: true + + /@pkgr/utils/2.3.1: + resolution: {integrity: sha512-wfzX8kc1PMyUILA+1Z/EqoE4UCXGy0iRGMhPwdfae1+f0OXlLqCk+By+aMzgJBzR9AzS4CDizioG6Ss1gvAFJw==} + engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + dependencies: + cross-spawn: 7.0.3 + is-glob: 4.0.3 + open: 8.4.0 + picocolors: 1.0.0 + tiny-glob: 0.2.9 + tslib: 2.4.1 + dev: true + + /@pmmmwh/react-refresh-webpack-plugin/0.5.4_tpiyiaculwakb4my4mlnuh4syi: + resolution: {integrity: sha512-zZbZeHQDnoTlt2AF+diQT0wsSXpvWiaIOZwBRdltNFhG1+I3ozyaw7U/nBiUwyJ0D+zwdXp0E3bWOl38Ag2BMw==} + engines: {node: '>= 10.13'} + peerDependencies: + '@types/webpack': 4.x || 5.x + react-refresh: '>=0.10.0 <1.0.0' + sockjs-client: ^1.4.0 + type-fest: '>=0.17.0 <3.0.0' + webpack: '>=4.43.0 <6.0.0' + webpack-dev-server: 3.x || 4.x + webpack-hot-middleware: 2.x + webpack-plugin-serve: 0.x || 1.x + peerDependenciesMeta: + '@types/webpack': + optional: true + sockjs-client: + optional: true + type-fest: + optional: true + webpack-dev-server: + optional: true + webpack-hot-middleware: + optional: true + webpack-plugin-serve: + optional: true + dependencies: + ansi-html-community: 0.0.8 + common-path-prefix: 3.0.0 + core-js-pure: 3.19.1 + error-stack-parser: 2.0.6 + find-up: 5.0.0 + html-entities: 2.3.2 + loader-utils: 2.0.2 + react-refresh: 0.11.0 + schema-utils: 3.1.1 + source-map: 0.7.3 + webpack: 5.69.0_webpack-cli@4.9.1 + webpack-dev-server: 4.7.4_3awzrjtbpxvmpzpfa3syzgxzq4 + dev: true + + /@protobufjs/aspromise/1.1.2: + resolution: {integrity: sha1-m4sMxmPWaafY9vXQiToU00jzD78=} + dev: true + + /@protobufjs/base64/1.1.2: + resolution: {integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==} + dev: true + + /@protobufjs/codegen/2.0.4: + resolution: {integrity: sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==} + dev: true + + /@protobufjs/eventemitter/1.1.0: + resolution: {integrity: sha1-NVy8mLr61ZePntCV85diHx0Ga3A=} + dev: true + + /@protobufjs/fetch/1.1.0: + resolution: {integrity: sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=} + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/inquire': 1.1.0 + dev: true + + /@protobufjs/float/1.0.2: + resolution: {integrity: sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E=} + dev: true + + /@protobufjs/inquire/1.1.0: + resolution: {integrity: sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik=} + dev: true + + /@protobufjs/path/1.1.2: + resolution: {integrity: sha1-bMKyDFya1q0NzP0hynZz2Nf79o0=} + dev: true + + /@protobufjs/pool/1.1.0: + resolution: {integrity: sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q=} + dev: true + + /@protobufjs/utf8/1.1.0: + resolution: {integrity: sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=} + dev: true + + /@react-dnd/asap/5.0.2: + resolution: {integrity: sha512-WLyfoHvxhs0V9U+GTsGilGgf2QsPl6ZZ44fnv0/b8T3nQyvzxidxsg/ZltbWssbsRDlYW8UKSQMTGotuTotZ6A==} + dev: false + + /@react-dnd/invariant/4.0.2: + resolution: {integrity: sha512-xKCTqAK/FFauOM9Ta2pswIyT3D8AQlfrYdOi/toTPEhqCuAs1v5tcJ3Y08Izh1cJ5Jchwy9SeAXmMg6zrKs2iw==} + dev: false + + /@react-dnd/shallowequal/4.0.2: + resolution: {integrity: sha512-/RVXdLvJxLg4QKvMoM5WlwNR9ViO9z8B/qPcc+C0Sa/teJY7QG7kJ441DwzOjMYEY7GmU4dj5EcGHIkKZiQZCA==} + dev: false + + /@redux-devtools/app/2.1.2_itrogk26nwqsr5d4gjfeisf5ty: + resolution: {integrity: sha512-jP/SyKZSb2+f2yOs5HLFrRXBuoMi59ag09hyAi5Q8bZ3WRHq568WERFRgQEyi951UgFkYgI1NhymXOPcGIQXqA==} + peerDependencies: + '@types/react': ^16.3.0 || ^17.0.0 + '@types/styled-components': ^5.1.22 + react: ^16.3.0 || ^17.0.0 + styled-components: ^5.3.3 + dependencies: + '@babel/runtime': 7.17.2 + '@redux-devtools/chart-monitor': 2.1.0_rvs3f2qpbecy7yxltqbwcn2yda + '@redux-devtools/core': 3.11.0_gq3cvwa2sgmjdee46ke36anzgq + '@redux-devtools/inspector-monitor': 2.1.1_rvs3f2qpbecy7yxltqbwcn2yda + '@redux-devtools/inspector-monitor-test-tab': 0.8.5_cgl6epj3dbv4ossnvgsy7gcojm + '@redux-devtools/inspector-monitor-trace-tab': 0.3.3_wdzficqly6zphfu3szjwvt752a + '@redux-devtools/log-monitor': 3.1.0_rvs3f2qpbecy7yxltqbwcn2yda + '@redux-devtools/rtk-query-monitor': 2.1.1_27itqj7mgvo5kwpj6vbyl23f4i + '@redux-devtools/slider-monitor': 3.1.1_ngaa4nfyq5xjej4dzouxj7avee + '@redux-devtools/ui': 1.2.2_itrogk26nwqsr5d4gjfeisf5ty + '@reduxjs/toolkit': 1.7.2_g7iv2n2puphpvmcbz4lgg4le54 + '@types/prop-types': 15.7.4 + '@types/react': 17.0.39 + '@types/styled-components': 5.1.22 + d3-state-visualizer: 1.6.0 + javascript-stringify: 2.1.0 + jsan: 3.1.14 + jsondiffpatch: 0.4.1 + localforage: 1.10.0 + lodash: 4.17.21 + prop-types: 15.8.1 + react: 17.0.2 + react-icons: 4.3.1_react@17.0.2 + react-is: 17.0.2 + react-redux: 7.2.6_sfoxds7t5ydpegc3knd667wn6m + redux: 4.1.2 + redux-persist: 6.0.0_react@17.0.2+redux@4.1.2 + socketcluster-client: 14.3.2 + styled-components: 5.3.3_fane7jikarojcev26y27hpbhu4 + transitivePeerDependencies: + - '@babel/core' + - bufferutil + - react-dom + - react-native + - utf-8-validate + dev: true + + /@redux-devtools/chart-monitor/2.1.0_rvs3f2qpbecy7yxltqbwcn2yda: + resolution: {integrity: sha512-y8YFSPivpRb58tb9hoRkXjmmnNN2nroNF2NSks7zGgcTV+RYWfAXe3rjQGriWLXcPxcOe8qTEdUQw6d23knlaQ==} + peerDependencies: + '@redux-devtools/core': ^3.7.0 + '@types/react': ^16.3.0 || ^17.0.0 + react: ^16.3.0 || ^17.0.0 + redux: ^3.4.0 || ^4.0.0 + dependencies: + '@babel/runtime': 7.17.2 + '@redux-devtools/core': 3.11.0_gq3cvwa2sgmjdee46ke36anzgq + '@types/prop-types': 15.7.4 + '@types/react': 17.0.39 + '@types/redux-devtools-themes': 1.0.0 + d3-state-visualizer: 1.6.0 + deepmerge: 4.2.2 + prop-types: 15.8.1 + react: 17.0.2 + redux: 4.1.2 + redux-devtools-themes: 1.0.0 + dev: true + + /@redux-devtools/cli/1.0.6_cz5jwzb6rw5xqianyejpzuh5ja: + resolution: {integrity: sha512-JvEX326pYrcrhTcejR4IbwBMMty5ic1DJkKVa3WVgxPdoUjYuxwXq9TB3vTVhNFnzkn1md0qsVYl5in+ioudIA==} + engines: {node: '>=14.15.0'} + hasBin: true + dependencies: + '@redux-devtools/app': 2.1.2_itrogk26nwqsr5d4gjfeisf5ty + '@types/react': 17.0.39 + apollo-server-express: 3.6.3_2stwdwnt4bpcabnirdp3k6z4ba + body-parser: 1.19.2 + chalk: 4.1.2 + cors: 2.8.5 + cross-spawn: 7.0.3 + electron: 16.0.9 + express: 4.17.2 + getport: 0.1.0 + graphql: 16.3.0 + knex: 0.95.15_sqlite3@5.0.2 + lodash: 4.17.21 + minimist: 1.2.5 + morgan: 1.10.0 + open: 8.4.0 + react: 17.0.2 + react-dom: 17.0.2_react@17.0.2 + react-is: 17.0.2 + semver: 7.3.5 + socketcluster: 14.4.2 + sqlite3: 5.0.2 + styled-components: 5.3.3_fane7jikarojcev26y27hpbhu4 + uuid: 8.3.2 + transitivePeerDependencies: + - '@babel/core' + - '@types/styled-components' + - bufferutil + - encoding + - mysql + - mysql2 + - pg + - pg-native + - react-native + - supports-color + - tedious + - utf-8-validate + dev: true + + /@redux-devtools/core/3.11.0_gq3cvwa2sgmjdee46ke36anzgq: + resolution: {integrity: sha512-LE8GF/9pttlIOYJWqOfwbAvYAokRNHCEtCu0DfA11tksYVwIX79CpB2jIJH/KH7n1LzwXPCCl4MOFnyZH4przg==} + peerDependencies: + react: ^0.14.9 || ^15.3.0 || ^16.0.0 || ^17.0.0 + react-redux: ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 + redux: ^3.5.2 || ^4.0.0 + dependencies: + '@babel/runtime': 7.17.2 + '@redux-devtools/instrument': 2.1.0_redux@4.1.2 + '@types/prop-types': 15.7.4 + lodash: 4.17.21 + prop-types: 15.8.1 + react: 17.0.2 + react-redux: 7.2.6_sfoxds7t5ydpegc3knd667wn6m + redux: 4.1.2 + dev: true + + /@redux-devtools/inspector-monitor-test-tab/0.8.5_cgl6epj3dbv4ossnvgsy7gcojm: + resolution: {integrity: sha512-2KlBIKmyhs4iwziJJUcYDqCVNPOzouhS1VQOP8gnRR4c8dpMfkHBq0BYfp3d0HxSQOXREx5bPLsltBusU3hs0A==} + peerDependencies: + '@redux-devtools/inspector-monitor': ^2.0.0 + '@types/react': ^16.3.0 || ^17.0.0 + '@types/styled-components': ^5.1.21 + react: ^16.3.0 || ^17.0.0 + redux: ^3.4.0 || ^4.0.0 + styled-components: ^5.3.3 + dependencies: + '@babel/runtime': 7.17.2 + '@redux-devtools/inspector-monitor': 2.1.1_rvs3f2qpbecy7yxltqbwcn2yda + '@redux-devtools/ui': 1.2.2_itrogk26nwqsr5d4gjfeisf5ty + '@types/prop-types': 15.7.4 + '@types/react': 17.0.39 + '@types/styled-components': 5.1.22 + es6template: 1.0.5 + javascript-stringify: 2.1.0 + jsan: 3.1.14 + object-path: 0.11.8 + prop-types: 15.8.1 + react: 17.0.2 + react-icons: 4.3.1_react@17.0.2 + redux: 4.1.2 + simple-diff: 1.6.0 + styled-components: 5.3.3_fane7jikarojcev26y27hpbhu4 + transitivePeerDependencies: + - '@babel/core' + - react-dom + dev: true + + /@redux-devtools/inspector-monitor-trace-tab/0.3.3_wdzficqly6zphfu3szjwvt752a: + resolution: {integrity: sha512-UqbIkRAXQYZ7TOgsiIM0faMP65NAxnEV+sVNAHq7aFtEiLCIp0PTU6ZceMYgQW2sVnxx5DF98j7uRjN6QVYKHg==} + peerDependencies: + '@redux-devtools/inspector-monitor': ^2.0.0 + '@types/react': ^16.3.0 || ^17.0.0 + react: ^16.3.0 || ^17.0.0 + redux: ^3.4.0 || ^4.0.0 + dependencies: + '@babel/code-frame': 7.16.7 + '@babel/runtime': 7.17.2 + '@redux-devtools/inspector-monitor': 2.1.1_rvs3f2qpbecy7yxltqbwcn2yda + '@types/chrome': 0.0.176 + '@types/react': 17.0.39 + anser: 2.1.1 + html-entities: 2.3.2 + path-browserify: 1.0.1 + react: 17.0.2 + redux: 4.1.2 + redux-devtools-themes: 1.0.0 + source-map: 0.5.7 + dev: true + + /@redux-devtools/inspector-monitor/2.1.1_rvs3f2qpbecy7yxltqbwcn2yda: + resolution: {integrity: sha512-UhINu7jlLSd/kVY0cU0GqD3yNwOpP99O+wEmbIOEGx91hAPf6G02aU8S7s81hoAOYbebN69wuFGBozgOp/FP1g==} + peerDependencies: + '@redux-devtools/core': ^3.7.0 + '@types/react': ^16.3.0 || ^17.0.0 + react: ^16.3.0 || ^17.0.0 + redux: ^3.4.0 || ^4.0.0 + dependencies: + '@babel/runtime': 7.17.2 + '@redux-devtools/core': 3.11.0_gq3cvwa2sgmjdee46ke36anzgq + '@types/dragula': 3.7.1 + '@types/lodash': 4.14.178 + '@types/prop-types': 15.7.4 + '@types/react': 17.0.39 + dateformat: 4.6.3 + hex-rgba: 1.0.2 + immutable: 4.0.0 + javascript-stringify: 2.1.0 + jsondiffpatch: 0.4.1 + jss: 10.9.0 + jss-preset-default: 10.9.0 + lodash.debounce: 4.0.8 + prop-types: 15.8.1 + react: 17.0.2 + react-base16-styling: 0.9.1 + react-dragula: 1.1.17 + react-json-tree: 0.16.1_udcsdvdzjr5ns727jqoeu7kyda + redux: 4.1.2 + redux-devtools-themes: 1.0.0 + dev: true + + /@redux-devtools/instrument/2.1.0_redux@4.1.2: + resolution: {integrity: sha512-e8fo88kuq/zWqfNf6S/GNfaQMjF4WSPpucmYfRhzZyyXHC3PCLd/xgz7zooPErDh9QwUXK6sTVYvrkq7hPbsFA==} + peerDependencies: + redux: ^3.4.0 || ^4.0.0 + dependencies: + '@babel/runtime': 7.17.2 + lodash: 4.17.21 + redux: 4.1.2 + dev: true + + /@redux-devtools/log-monitor/3.1.0_rvs3f2qpbecy7yxltqbwcn2yda: + resolution: {integrity: sha512-T5NXzasj7250tJmQPiXzFkxlY0Rg0W7feR1eZj8VrdePvVkeXTP5k9VjxkVqtba5EmZR8swGec+Z1eD71ZgUsA==} + peerDependencies: + '@redux-devtools/core': ^3.7.0 + '@types/react': ^16.3.0 || ^17.0.0 + react: ^16.3.0 || ^17.0.0 + redux: ^3.4.0 || ^4.0.0 + dependencies: + '@babel/runtime': 7.17.2 + '@redux-devtools/core': 3.11.0_gq3cvwa2sgmjdee46ke36anzgq + '@types/lodash.debounce': 4.0.6 + '@types/prop-types': 15.7.4 + '@types/react': 17.0.39 + '@types/redux-devtools-themes': 1.0.0 + lodash.debounce: 4.0.8 + prop-types: 15.8.1 + react: 17.0.2 + react-json-tree: 0.16.1_udcsdvdzjr5ns727jqoeu7kyda + redux: 4.1.2 + redux-devtools-themes: 1.0.0 + dev: true + + /@redux-devtools/rtk-query-monitor/2.1.1_27itqj7mgvo5kwpj6vbyl23f4i: + resolution: {integrity: sha512-OJVoSpg7DRIgVtRfNjgtF9cZF/z3dQ25cu/SdcJT1uEaXRSIoVoxXN2aPKxJrKpffXmnx8ma74aw0/ApyZ4SOw==} + peerDependencies: + '@redux-devtools/core': ^3.7.0 + '@reduxjs/toolkit': ^1.7.1 + '@types/react': ^16.3.0 || ^17.0.0 + '@types/styled-components': ^5.1.21 + react: ^16.3.0 || ^17.0.0 + redux: ^3.4.0 || ^4.0.0 + styled-components: ^5.3.3 + dependencies: + '@babel/runtime': 7.17.2 + '@redux-devtools/core': 3.11.0_gq3cvwa2sgmjdee46ke36anzgq + '@redux-devtools/ui': 1.2.2_itrogk26nwqsr5d4gjfeisf5ty + '@reduxjs/toolkit': 1.7.2_g7iv2n2puphpvmcbz4lgg4le54 + '@types/prop-types': 15.7.4 + '@types/react': 17.0.39 + '@types/redux-devtools-themes': 1.0.0 + '@types/styled-components': 5.1.22 + hex-rgba: 1.0.2 + immutable: 4.0.0 + jss: 10.9.0 + jss-preset-default: 10.9.0 + lodash.debounce: 4.0.8 + prop-types: 15.8.1 + react: 17.0.2 + react-base16-styling: 0.9.1 + react-json-tree: 0.16.1_udcsdvdzjr5ns727jqoeu7kyda + redux: 4.1.2 + redux-devtools-themes: 1.0.0 + styled-components: 5.3.3_fane7jikarojcev26y27hpbhu4 + transitivePeerDependencies: + - '@babel/core' + - react-dom + dev: true + + /@redux-devtools/slider-monitor/3.1.1_ngaa4nfyq5xjej4dzouxj7avee: + resolution: {integrity: sha512-f2rhMv+kpqd//euXo5vTPFCI11pMevXRL7aQYMh0SfacvgwkEVx3GaKbsEmjkdsqrG7xekRjqbZzschV/7OVgQ==} + peerDependencies: + '@redux-devtools/core': ^3.7.0 + '@types/react': ^16.3.0 || ^17.0.0 + '@types/styled-components': ^5.1.21 + react: ^16.3.0 || ^17.0.0 + redux: ^3.4.0 || ^4.0.0 + styled-components: ^5.3.3 + dependencies: + '@babel/runtime': 7.17.2 + '@redux-devtools/core': 3.11.0_gq3cvwa2sgmjdee46ke36anzgq + '@redux-devtools/ui': 1.2.2_itrogk26nwqsr5d4gjfeisf5ty + '@types/prop-types': 15.7.4 + '@types/react': 17.0.39 + '@types/redux-devtools-themes': 1.0.0 + '@types/styled-components': 5.1.22 + prop-types: 15.8.1 + react: 17.0.2 + redux: 4.1.2 + redux-devtools-themes: 1.0.0 + styled-components: 5.3.3_fane7jikarojcev26y27hpbhu4 + transitivePeerDependencies: + - '@babel/core' + - react-dom + dev: true + + /@redux-devtools/ui/1.2.2_itrogk26nwqsr5d4gjfeisf5ty: + resolution: {integrity: sha512-PxfUZSIsecltHenn/MOxetZwOR9AdgFWiWxiFxjt4bKF1tPT8WkJhgrHsp39Oyg48vgZYY2nRXO+REIqb7HyDw==} + peerDependencies: + '@types/react': ^16.3.0 || ^17.0.0 + '@types/styled-components': ^5.1.21 + react: ^16.3.0 || ^17.0.0 + styled-components: ^5.3.3 + dependencies: + '@babel/runtime': 7.17.2 + '@rjsf/core': 3.2.1_react@17.0.2 + '@types/base16': 1.0.2 + '@types/codemirror': 5.60.5 + '@types/json-schema': 7.0.9 + '@types/prop-types': 15.7.4 + '@types/react': 17.0.39 + '@types/redux-devtools-themes': 1.0.0 + '@types/simple-element-resize-detector': 1.3.0 + '@types/styled-components': 5.1.22 + base16: 1.0.0 + codemirror: 5.65.1 + color: 3.2.1 + prop-types: 15.8.1 + react: 17.0.2 + react-icons: 4.3.1_react@17.0.2 + react-select: 5.2.2_ivj6fu6x63tqzxiw3bovn75e4a + redux-devtools-themes: 1.0.0 + simple-element-resize-detector: 1.3.0 + styled-components: 5.3.3_fane7jikarojcev26y27hpbhu4 + transitivePeerDependencies: + - '@babel/core' + - react-dom + dev: true + + /@reduxjs/toolkit/1.7.2_g7iv2n2puphpvmcbz4lgg4le54: + resolution: {integrity: sha512-wwr3//Ar8ZhM9bS58O+HCIaMlR4Y6SNHfuszz9hKnQuFIKvwaL3Kmjo6fpDKUOjo4Lv54Yi299ed8rofCJ/Vjw==} + peerDependencies: + react: ^16.9.0 || ^17.0.0 || 18.0.0-beta + react-redux: ^7.2.1 || ^8.0.0-beta + peerDependenciesMeta: + react: + optional: true + react-redux: + optional: true + dependencies: + immer: 9.0.12 + react: 17.0.2 + react-redux: 7.2.6_sfoxds7t5ydpegc3knd667wn6m + redux: 4.1.2 + redux-thunk: 2.4.1_redux@4.1.2 + reselect: 4.1.5 + + /@rjsf/core/3.2.1_react@17.0.2: + resolution: {integrity: sha512-dk8ihvxFbcuIwU7G+HiJbFgwyIvaumPt5g5zfnuC26mwTUPlaDGFXKK2yITp8tJ3+hcwS5zEXtAN9wUkfuM4jA==} + engines: {node: '>=12'} + peerDependencies: + react: '>=16' + dependencies: + '@types/json-schema': 7.0.9 + ajv: 6.12.6 + core-js-pure: 3.19.1 + json-schema-merge-allof: 0.6.0 + jsonpointer: 5.0.0 + lodash: 4.17.21 + nanoid: 3.1.30 + prop-types: 15.8.1 + react: 17.0.2 + react-is: 16.13.1 + dev: true + + /@semantic-release/changelog/6.0.1_semantic-release@19.0.2: + resolution: {integrity: sha512-FT+tAGdWHr0RCM3EpWegWnvXJ05LQtBkQUaQRIExONoXjVjLuOILNm4DEKNaV+GAQyJjbLRVs57ti//GypH6PA==} + engines: {node: '>=14.17'} + peerDependencies: + semantic-release: '>=18.0.0' + dependencies: + '@semantic-release/error': 3.0.0 + aggregate-error: 3.1.0 + fs-extra: 9.1.0 + lodash: 4.17.21 + semantic-release: 19.0.2 + dev: true + + /@semantic-release/commit-analyzer/9.0.2_semantic-release@19.0.2: + resolution: {integrity: sha512-E+dr6L+xIHZkX4zNMe6Rnwg4YQrWNXK+rNsvwOPpdFppvZO1olE2fIgWhv89TkQErygevbjsZFSIxp+u6w2e5g==} + engines: {node: '>=14.17'} + peerDependencies: + semantic-release: '>=18.0.0-beta.1' + dependencies: + conventional-changelog-angular: 5.0.13 + conventional-commits-filter: 2.0.7 + conventional-commits-parser: 3.2.4 + debug: 4.3.2 + import-from: 4.0.0 + lodash: 4.17.21 + micromatch: 4.0.4 + semantic-release: 19.0.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@semantic-release/error/2.2.0: + resolution: {integrity: sha512-9Tj/qn+y2j+sjCI3Jd+qseGtHjOAeg7dU2/lVcqIQ9TV3QDaDXDYXcoOHU+7o2Hwh8L8ymL4gfuO7KxDs3q2zg==} + dev: true + + /@semantic-release/error/3.0.0: + resolution: {integrity: sha512-5hiM4Un+tpl4cKw3lV4UgzJj+SmfNIDCLLw0TepzQxz9ZGV5ixnqkzIVF+3tp0ZHgcMKE+VNGHJjEeyFG2dcSw==} + engines: {node: '>=14.17'} + dev: true + + /@semantic-release/git/10.0.1_semantic-release@19.0.2: + resolution: {integrity: sha512-eWrx5KguUcU2wUPaO6sfvZI0wPafUKAMNC18aXY4EnNcrZL86dEmpNVnC9uMpGZkmZJ9EfCVJBQx4pV4EMGT1w==} + engines: {node: '>=14.17'} + peerDependencies: + semantic-release: '>=18.0.0' + dependencies: + '@semantic-release/error': 3.0.0 + aggregate-error: 3.1.0 + debug: 4.3.2 + dir-glob: 3.0.1 + execa: 5.1.1 + lodash: 4.17.21 + micromatch: 4.0.4 + p-reduce: 2.1.0 + semantic-release: 19.0.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@semantic-release/github/8.0.2_semantic-release@19.0.2: + resolution: {integrity: sha512-wIbfhOeuxlYzMTjtSAa2xgr54n7ZuPAS2gadyTWBpUt2PNAPgla7A6XxCXJnaKPgfVF0iFfSk3B+KlVKk6ByVg==} + engines: {node: '>=14.17'} + peerDependencies: + semantic-release: '>=18.0.0-beta.1' + dependencies: + '@octokit/rest': 18.12.0 + '@semantic-release/error': 2.2.0 + aggregate-error: 3.1.0 + bottleneck: 2.19.5 + debug: 4.3.2 + dir-glob: 3.0.1 + fs-extra: 10.0.0 + globby: 11.0.4 + http-proxy-agent: 5.0.0 + https-proxy-agent: 5.0.0 + issue-parser: 6.0.0 + lodash: 4.17.21 + mime: 3.0.0 + p-filter: 2.1.0 + p-retry: 4.6.1 + semantic-release: 19.0.2 + url-join: 4.0.1 + transitivePeerDependencies: + - encoding + - supports-color + dev: true + + /@semantic-release/npm/9.0.0_semantic-release@19.0.2: + resolution: {integrity: sha512-hj2jqayS2SPUmFtCMCOQMX975uMDfRoymj1HvMSwYdaoI6hVZvhrTFPBgJeM85O0C+G3IFviAUar5gel/1VGDQ==} + engines: {node: '>=16 || ^14.17'} + peerDependencies: + semantic-release: '>=19.0.0' + dependencies: + '@semantic-release/error': 3.0.0 + aggregate-error: 3.1.0 + execa: 5.1.1 + fs-extra: 10.0.0 + lodash: 4.17.21 + nerf-dart: 1.0.0 + normalize-url: 6.1.0 + npm: 8.5.1 + rc: 1.2.8 + read-pkg: 5.2.0 + registry-auth-token: 4.2.1 + semantic-release: 19.0.2 + semver: 7.3.5 + tempy: 1.0.1 + dev: true + + /@semantic-release/release-notes-generator/10.0.3_semantic-release@19.0.2: + resolution: {integrity: sha512-k4x4VhIKneOWoBGHkx0qZogNjCldLPRiAjnIpMnlUh6PtaWXp/T+C9U7/TaNDDtgDa5HMbHl4WlREdxHio6/3w==} + engines: {node: '>=14.17'} + peerDependencies: + semantic-release: '>=18.0.0-beta.1' + dependencies: + conventional-changelog-angular: 5.0.13 + conventional-changelog-writer: 5.0.1 + conventional-commits-filter: 2.0.7 + conventional-commits-parser: 3.2.4 + debug: 4.3.2 + get-stream: 6.0.1 + import-from: 4.0.0 + into-stream: 6.0.0 + lodash: 4.17.21 + read-pkg-up: 7.0.1 + semantic-release: 19.0.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@sindresorhus/is/0.14.0: + resolution: {integrity: sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==} + engines: {node: '>=6'} + dev: true + + /@sinonjs/commons/1.8.3: + resolution: {integrity: sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==} + dependencies: + type-detect: 4.0.8 + dev: true + + /@sinonjs/fake-timers/8.1.0: + resolution: {integrity: sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==} + dependencies: + '@sinonjs/commons': 1.8.3 + dev: true + + /@szmarczak/http-timer/1.1.2: + resolution: {integrity: sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==} + engines: {node: '>=6'} + dependencies: + defer-to-connect: 1.1.3 + dev: true + + /@testing-library/dom/8.11.3: + resolution: {integrity: sha512-9LId28I+lx70wUiZjLvi1DB/WT2zGOxUh46glrSNMaWVx849kKAluezVzZrXJfTKKoQTmEOutLes/bHg4Bj3aA==} + engines: {node: '>=12'} + dependencies: + '@babel/code-frame': 7.16.7 + '@babel/runtime': 7.16.3 + '@types/aria-query': 4.2.2 aria-query: 5.0.0 chalk: 4.1.2 dom-accessibility-api: 0.5.10 @@ -1737,13 +2766,13 @@ packages: pretty-format: 27.3.1 dev: true - /@testing-library/jest-dom/5.15.0: - resolution: {integrity: sha512-lOMuQidnL1tWHLEWIhL6UvSZC1Qt3OkNe1khvi2h6xFiqpe5O8arYs46OU0qyUGq0cSTbroQyMktYNXu3a7sAA==} + /@testing-library/jest-dom/5.16.2: + resolution: {integrity: sha512-6ewxs1MXWwsBFZXIk4nKKskWANelkdUehchEOokHsN8X7c2eKXGw+77aRV63UU8f/DTSVUPLaGxdrj4lN7D/ug==} engines: {node: '>=8', npm: '>=6', yarn: '>=1'} dependencies: '@babel/runtime': 7.16.3 - '@types/testing-library__jest-dom': 5.14.1 - aria-query: 4.2.2 + '@types/testing-library__jest-dom': 5.14.2 + aria-query: 5.0.0 chalk: 3.0.0 css: 3.0.0 css.escape: 1.5.1 @@ -1752,7 +2781,7 @@ packages: redent: 3.0.0 dev: true - /@testing-library/react/12.1.2_react-dom@17.0.2+react@17.0.2: + /@testing-library/react/12.1.2_sfoxds7t5ydpegc3knd667wn6m: resolution: {integrity: sha512-ihQiEOklNyHIpo2Y8FREkyD1QAea054U0MVbwH1m8N9TxeFz+KoJ9LkqoKqJlzx2JDm56DVwaJ1r36JYxZM05g==} engines: {node: '>=12'} peerDependencies: @@ -1760,19 +2789,19 @@ packages: react-dom: '*' dependencies: '@babel/runtime': 7.16.3 - '@testing-library/dom': 8.11.1 + '@testing-library/dom': 8.11.3 react: 17.0.2 react-dom: 17.0.2_react@17.0.2 dev: true - /@testing-library/user-event/13.5.0_@testing-library+dom@8.11.1: + /@testing-library/user-event/13.5.0_gzufz4q333be4gqfrvipwvqt6a: resolution: {integrity: sha512-5Kwtbo3Y/NowpkbRuSepbyMFkZmHgD+vPzYB/RJ4oxt5Gj/avFFBYjhw27cqSVPVw/3a67NK1PbiIr9k4Gwmdg==} engines: {node: '>=10', npm: '>=6'} peerDependencies: '@testing-library/dom': '>=7.21.4' dependencies: '@babel/runtime': 7.16.3 - '@testing-library/dom': 8.11.1 + '@testing-library/dom': 8.11.3 dev: true /@tootallnate/once/1.1.2: @@ -1780,6 +2809,17 @@ packages: engines: {node: '>= 6'} dev: true + /@tootallnate/once/2.0.0: + resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==} + engines: {node: '>= 10'} + dev: true + + /@types/accepts/1.3.5: + resolution: {integrity: sha512-jOdnI/3qTpHABjM5cx1Hc0sKsPoYCp+DP/GJRGtDlPd7fiV9oXGGIcjW/ZOxLIvjGz8MA+uMZI9metHlgqbgwQ==} + dependencies: + '@types/node': 16.11.9 + dev: true + /@types/aria-query/4.2.2: resolution: {integrity: sha512-HnYpAE1Y6kRyKM/XkEuiRQhTHvkzMBurTHnpFLYLBGPIylZNPs9jJcuOOYWxPLJCSEtmZT0Y8rHDokKN7rRTig==} dev: true @@ -1787,8 +2827,8 @@ packages: /@types/babel__core/7.1.16: resolution: {integrity: sha512-EAEHtisTMM+KaKwfWdC3oyllIqswlznXCIVCt7/oRNrh+DhgT4UEBNC/jlADNjvw7UnfbcdkGQcPVZ1xYiLcrQ==} dependencies: - '@babel/parser': 7.16.4 - '@babel/types': 7.16.0 + '@babel/parser': 7.17.3 + '@babel/types': 7.17.0 '@types/babel__generator': 7.6.3 '@types/babel__template': 7.4.1 '@types/babel__traverse': 7.14.2 @@ -1797,20 +2837,24 @@ packages: /@types/babel__generator/7.6.3: resolution: {integrity: sha512-/GWCmzJWqV7diQW54smJZzWbSFf4QYtF71WCKhcx6Ru/tFyQIY2eiiITcCAeuPbNSvT9YCGkVMqqvSk2Z0mXiA==} dependencies: - '@babel/types': 7.16.0 + '@babel/types': 7.17.0 dev: true /@types/babel__template/7.4.1: resolution: {integrity: sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==} dependencies: - '@babel/parser': 7.16.4 - '@babel/types': 7.16.0 + '@babel/parser': 7.17.3 + '@babel/types': 7.17.0 dev: true /@types/babel__traverse/7.14.2: resolution: {integrity: sha512-K2waXdXBi2302XUdcHcR1jCeU0LL4TD9HRs/gk0N2Xvrht+G/BfJa4QObBQZfhMdxiCpV3COl5Nfq4uKTeTnJA==} dependencies: - '@babel/types': 7.16.0 + '@babel/types': 7.17.0 + dev: true + + /@types/base16/1.0.2: + resolution: {integrity: sha512-oYO/U4VD1DavwrKuCSQWdLG+5K22SLPem2OQaHmFcQuwHoVeGC+JGVRji2MUqZUAIQZHEonOeVfAX09hYiLsdg==} dev: true /@types/body-parser/1.19.2: @@ -1826,6 +2870,19 @@ packages: '@types/node': 16.11.9 dev: true + /@types/chrome/0.0.176: + resolution: {integrity: sha512-LOveFOMIUhMJjvRzZv5whGBpncP/gdJ4hcxeAqg94wGi6CyKaCmLgFSofgItf85GuLTl/0BQ6J/Y1e8BqZWfEg==} + dependencies: + '@types/filesystem': 0.0.32 + '@types/har-format': 1.2.8 + dev: true + + /@types/codemirror/5.60.5: + resolution: {integrity: sha512-TiECZmm8St5YxjFUp64LK0c8WU5bxMDt9YaAek1UqUb9swrSCoJhh92fWu1p3mTEqlHjhB5sY7OFBhWroJXZVg==} + dependencies: + '@types/tern': 0.23.4 + dev: true + /@types/connect-history-api-fallback/1.3.5: resolution: {integrity: sha512-h8QJa8xSb1WD4fpKBDcATDNGXghFj6/3GRWG6dhmRcu0RX1Ubasur2Uvx5aeEwlf0MwblEC2bMzzMQntxnw/Cw==} dependencies: @@ -1839,22 +2896,34 @@ packages: '@types/node': 16.11.9 dev: true - /@types/eslint-scope/3.7.1: - resolution: {integrity: sha512-SCFeogqiptms4Fg29WpOTk5nHIzfpKCemSN63ksBQYKTcXoJEmJagV+DhVmbapZzY4/5YaOV1nZwrsU79fFm1g==} + /@types/cors/2.8.12: + resolution: {integrity: sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==} + dev: true + + /@types/d3/3.5.46: + resolution: {integrity: sha512-jNHfiGd41+JUV43LTMzQNidyp4Hn0XfhoSmy8baE0d/N5pGYpD+yX03JacY/MH+smFxYOQGXlz4HxkRZOuRNOQ==} + dev: true + + /@types/dragula/3.7.1: + resolution: {integrity: sha512-hbMEG5+wZEwV6NK4cbexldLWEvYNox8PywM9ICIeCTM99g8nJxccE3C8vvl66TCfnN+R8ioNdOrHWJT+5X0pvw==} + dev: true + + /@types/eslint-scope/3.7.3: + resolution: {integrity: sha512-PB3ldyrcnAicT35TWPs5IcwKD8S333HMaa2VVv4+wdvebJkjWuW/xESoB8IwRcog8HYVYamb1g/R31Qv5Bx03g==} dependencies: '@types/eslint': 8.2.0 - '@types/estree': 0.0.50 + '@types/estree': 0.0.51 dev: true /@types/eslint/8.2.0: resolution: {integrity: sha512-74hbvsnc+7TEDa1z5YLSe4/q8hGYB3USNvCuzHUJrjPV6hXaq8IXcngCrHkuvFt0+8rFz7xYXrHgNayIX0UZvQ==} dependencies: - '@types/estree': 0.0.50 + '@types/estree': 0.0.51 '@types/json-schema': 7.0.9 dev: true - /@types/estree/0.0.50: - resolution: {integrity: sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw==} + /@types/estree/0.0.51: + resolution: {integrity: sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==} dev: true /@types/express-serve-static-core/4.17.25: @@ -1865,6 +2934,14 @@ packages: '@types/range-parser': 1.2.4 dev: true + /@types/express-serve-static-core/4.17.28: + resolution: {integrity: sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig==} + dependencies: + '@types/node': 16.11.9 + '@types/qs': 6.9.7 + '@types/range-parser': 1.2.4 + dev: true + /@types/express/4.17.13: resolution: {integrity: sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==} dependencies: @@ -1874,6 +2951,16 @@ packages: '@types/serve-static': 1.13.10 dev: true + /@types/filesystem/0.0.32: + resolution: {integrity: sha512-Yuf4jR5YYMR2DVgwuCiP11s0xuVRyPKmz8vo6HBY3CGdeMj8af93CFZX+T82+VD1+UqHOxTq31lO7MI7lepBtQ==} + dependencies: + '@types/filewriter': 0.0.29 + dev: true + + /@types/filewriter/0.0.29: + resolution: {integrity: sha512-BsPXH/irW0ht0Ji6iw/jJaK8Lj3FJemon2gvEqHKpCdDCeemHa+rI3WBGq5z7cDMZgoLjY40oninGxqk+8NzNQ==} + dev: true + /@types/glob/7.2.0: resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==} dependencies: @@ -1887,12 +2974,15 @@ packages: '@types/node': 16.11.9 dev: true + /@types/har-format/1.2.8: + resolution: {integrity: sha512-OP6L9VuZNdskgNN3zFQQ54ceYD8OLq5IbqO4VK91ORLfOm7WdT/CiT/pHEBSQEqCInJ2y3O6iCm/zGtPElpgJQ==} + dev: true + /@types/hoist-non-react-statics/3.3.1: resolution: {integrity: sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==} dependencies: - '@types/react': 17.0.36 + '@types/react': 17.0.39 hoist-non-react-statics: 3.3.2 - dev: true /@types/html-minifier-terser/6.0.0: resolution: {integrity: sha512-NZwaaynfs1oIoLAV1vg18e7QMVDvw+6SQrdJc8w3BwUaoroVSf6EBj/Sk4PBWGxsq0dzhA2drbsuMC1/6C6KgQ==} @@ -1920,8 +3010,8 @@ packages: '@types/istanbul-lib-report': 3.0.0 dev: true - /@types/jest/27.0.3: - resolution: {integrity: sha512-cmmwv9t7gBYt7hNKH5Spu7Kuu/DotGa+Ff+JGRKZ4db5eh8PnKS4LuebJ3YLUoyOyIHraTGyULn23YtEAm0VSg==} + /@types/jest/27.4.0: + resolution: {integrity: sha512-gHl8XuC1RZ8H2j5sHv/JqsaxXkDDM9iDOgu0Wp8sjs4u/snb2PVehyWXJPr+ORA0RPpgw231mnutWI1+0hgjIQ==} dependencies: jest-diff: 27.3.1 pretty-format: 27.3.1 @@ -1935,6 +3025,26 @@ packages: resolution: {integrity: sha1-7ihweulOEdK4J7y+UnC86n8+ce4=} dev: true + /@types/keyv/3.1.4: + resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==} + dependencies: + '@types/node': 16.11.9 + dev: true + + /@types/lodash.debounce/4.0.6: + resolution: {integrity: sha512-4WTmnnhCfDvvuLMaF3KV4Qfki93KebocUF45msxhYyjMttZDQYzHkO639ohhk8+oco2cluAFL3t5+Jn4mleylQ==} + dependencies: + '@types/lodash': 4.14.178 + dev: true + + /@types/lodash/4.14.178: + resolution: {integrity: sha512-0d5Wd09ItQWH1qFbEyQ7oTQ3GZrMfth5JkbN3EvTKLXcHLRDSXeLnlvlOn0wvxVIwK5o2M8JzP/OWz7T3NRsbw==} + dev: true + + /@types/long/4.0.1: + resolution: {integrity: sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w==} + dev: true + /@types/mime/1.3.2: resolution: {integrity: sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==} dev: true @@ -1943,10 +3053,30 @@ packages: resolution: {integrity: sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==} dev: true + /@types/minimist/1.2.2: + resolution: {integrity: sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==} + dev: true + + /@types/node/10.17.60: + resolution: {integrity: sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==} + dev: true + + /@types/node/12.20.46: + resolution: {integrity: sha512-cPjLXj8d6anFPzFvOPxS3fvly3Shm5nTfl6g8X5smexixbuGUf7hfr21J5tX9JW+UPStp/5P5R8qrKL5IyVJ+A==} + dev: true + + /@types/node/14.18.12: + resolution: {integrity: sha512-q4jlIR71hUpWTnGhXWcakgkZeHa3CCjcQcnuzU8M891BAWA2jHiziiWEPEkdS5pFsz7H9HJiy8BrK7tBRNrY7A==} + dev: true + /@types/node/16.11.9: resolution: {integrity: sha512-MKmdASMf3LtPzwLyRrFjtFFZ48cMf8jmX5VRYrDQiJa8Ybu5VAmkqBWqKU8fdCwD8ysw4mQ9nrEHvzg6gunR7A==} dev: true + /@types/normalize-package-data/2.4.1: + resolution: {integrity: sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==} + dev: true + /@types/parse-json/4.0.0: resolution: {integrity: sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==} dev: true @@ -1957,7 +3087,6 @@ packages: /@types/prop-types/15.7.4: resolution: {integrity: sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ==} - dev: true /@types/qs/6.9.7: resolution: {integrity: sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==} @@ -1970,15 +3099,59 @@ packages: /@types/react-dom/17.0.11: resolution: {integrity: sha512-f96K3k+24RaLGVu/Y2Ng3e1EbZ8/cVJvypZWd7cy0ofCBaf2lcM46xNhycMZ2xGwbBjRql7hOlZ+e2WlJ5MH3Q==} dependencies: - '@types/react': 17.0.36 + '@types/react': 17.0.39 + dev: true + + /@types/react-redux/7.1.25: + resolution: {integrity: sha512-bAGh4e+w5D8dajd6InASVIyCo4pZLJ66oLb80F9OBLO1gKESbZcRCJpTT6uLXX+HAB57zw1WTdwJdAsewuTweg==} + dependencies: + '@types/hoist-non-react-statics': 3.3.1 + '@types/react': 17.0.39 + hoist-non-react-statics: 3.3.2 + redux: 4.2.0 + + /@types/react-transition-group/4.4.4: + resolution: {integrity: sha512-7gAPz7anVK5xzbeQW9wFBDg7G++aPLAFY0QaSMOou9rJZpbuI58WAuJrgu+qR92l61grlnCUe7AFX8KGahAgug==} + dependencies: + '@types/react': 17.0.39 dev: true - /@types/react/17.0.36: - resolution: {integrity: sha512-CUFUp01OdfbpN/76v4koqgcpcRGT3sYOq3U3N6q0ZVGcyeP40NUdVU+EWe3hs34RNaTefiYyBzOpxBBidCc5zw==} + /@types/react/17.0.39: + resolution: {integrity: sha512-UVavlfAxDd/AgAacMa60Azl7ygyQNRwC/DsHZmKgNvPmRR5p70AJ5Q9EAmL2NWOJmeV+vVUI4IAP7GZrN8h8Ug==} dependencies: '@types/prop-types': 15.7.4 '@types/scheduler': 0.16.2 csstype: 3.0.10 + + /@types/redux-devtools-themes/1.0.0: + resolution: {integrity: sha512-ul3x0MYM5Nzj57Fh9wINyHFne8vZL04RC4nWAUWLYcL105vHoa/oJyopuKOrQmqVmhqmDiL4c9FfLbUmIB7TWQ==} + dependencies: + '@types/base16': 1.0.2 + dev: true + + /@types/redux-logger/3.0.9: + resolution: {integrity: sha512-cwYhVbYNgH01aepeMwhd0ABX6fhVB2rcQ9m80u8Fl50ZODhsZ8RhQArnLTkE7/Zrfq4Sz/taNoF7DQy9pCZSKg==} + dependencies: + redux: 4.2.0 + dev: true + + /@types/redux-state-sync/3.1.5: + resolution: {integrity: sha512-NtcV94bmZNFMmcjgYzjK9WHN/0NVHyH4OO/a4sAd4WG1ywcVZA5vdczjPQZLC1IVMRBi693b3FWsWB7wELL+tg==} + dependencies: + broadcast-channel: 2.3.4 + redux: 4.2.0 + dev: true + + /@types/remote-redux-devtools/0.5.5: + resolution: {integrity: sha512-Xuya1TegRPAe92+nnEeYpfufE/mtfN99+GH272edaoWohbMA+yP6r+wYqK4sq/fvmoUPtPHtwZR2Mkk+6uHeBQ==} + dependencies: + redux: 4.1.2 + dev: true + + /@types/responselike/1.0.0: + resolution: {integrity: sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==} + dependencies: + '@types/node': 16.11.9 dev: true /@types/retry/0.12.1: @@ -1987,7 +3160,6 @@ packages: /@types/scheduler/0.16.2: resolution: {integrity: sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==} - dev: true /@types/serve-index/1.9.1: resolution: {integrity: sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg==} @@ -2002,55 +3174,48 @@ packages: '@types/node': 16.11.9 dev: true + /@types/simple-element-resize-detector/1.3.0: + resolution: {integrity: sha512-z89ForrCNg+4uwTHjwBCM9LjcsXYC/4O8u3tSi+82v2LCbfiYFpkjH/qQVkDewFBK6FUG7RRV7jw78EGs2maoQ==} + dev: true + + /@types/sockjs/0.3.33: + resolution: {integrity: sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw==} + dependencies: + '@types/node': 16.11.9 + dev: true + /@types/stack-utils/2.0.1: resolution: {integrity: sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==} dev: true - /@types/styled-components/5.1.15: - resolution: {integrity: sha512-4evch8BRI3AKgb0GAZ/sn+mSeB+Dq7meYtMi7J/0Mg98Dt1+r8fySOek7Sjw1W+Wskyjc93565o5xWAT/FdY0Q==} + /@types/styled-components/5.1.22: + resolution: {integrity: sha512-zQzf/0aGtgFDjB942f8IaKA6UilFziDza9wXkAX5mpiSWA/FBZBU6yUavvczulTvoR6759h6CH8HuuIcJDBgZA==} dependencies: '@types/hoist-non-react-statics': 3.3.1 - '@types/react': 17.0.36 + '@types/react': 17.0.39 csstype: 3.0.10 dev: true - /@types/testing-library__jest-dom/5.14.1: - resolution: {integrity: sha512-Gk9vaXfbzc5zCXI9eYE9BI5BNHEp4D3FWjgqBE/ePGYElLAP+KvxBcsdkwfIVvezs605oiyd/VrpiHe3Oeg+Aw==} + /@types/tern/0.23.4: + resolution: {integrity: sha512-JAUw1iXGO1qaWwEOzxTKJZ/5JxVeON9kvGZ/osgZaJImBnyjyn0cjovPsf6FNLmyGY8Vw9DoXZCMlfMkMwHRWg==} dependencies: - '@types/jest': 27.0.3 + '@types/estree': 0.0.51 dev: true - /@types/webpack-dev-middleware/5.0.2_webpack-cli@4.9.1: - resolution: {integrity: sha512-S3WUtef//Vx6WETyWZkM45WqgRxWSaqbpWtPcKySNRhiQNyhCqM9EueggaMX3L9N2IbG4dJIK5PgYcAWUifUbA==} + /@types/testing-library__jest-dom/5.14.2: + resolution: {integrity: sha512-vehbtyHUShPxIa9SioxDwCvgxukDMH//icJG90sXQBUm5lJOHLT5kNeU9tnivhnA/TkOFMzGIXN2cTc4hY8/kg==} dependencies: - '@types/connect': 3.4.35 - tapable: 2.2.1 - webpack: 5.64.2_webpack-cli@4.9.1 - transitivePeerDependencies: - - '@swc/core' - - esbuild - - uglify-js - - webpack-cli + '@types/jest': 27.4.0 + dev: true + + /@types/webpack-env/1.16.3: + resolution: {integrity: sha512-9gtOPPkfyNoEqCQgx4qJKkuNm/x0R2hKR7fdl7zvTJyHnIisuE/LfvXOsYWL0o3qq6uiBnKZNNNzi3l0y/X+xw==} dev: true - /@types/webpack-dev-server/4.5.0_webpack-cli@4.9.1: - resolution: {integrity: sha512-HMb6pZPANObue3LwbdpQLWzQyF9O0wntiPyXj4vGutlAbNKTXH4hDCHaZyfvfZDmFn+5HprrWHm1TGt3awNr/A==} + /@types/ws/8.2.2: + resolution: {integrity: sha512-NOn5eIcgWLOo6qW8AcuLZ7G8PycXu0xTxxkS6Q18VWFxgPUSOwV0pBj2a/4viNZVu25i7RIB7GttdkAIUUXOOg==} dependencies: - '@types/bonjour': 3.5.9 - '@types/connect-history-api-fallback': 1.3.5 - '@types/express': 4.17.13 - '@types/serve-index': 1.9.1 - '@types/serve-static': 1.13.10 - '@types/webpack-dev-middleware': 5.0.2_webpack-cli@4.9.1 - chokidar: 3.5.2 - http-proxy-middleware: 2.0.1 - webpack: 5.64.2_webpack-cli@4.9.1 - transitivePeerDependencies: - - '@swc/core' - - debug - - esbuild - - uglify-js - - webpack-cli + '@types/node': 16.11.9 dev: true /@types/yargs-parser/20.2.1: @@ -2063,8 +3228,8 @@ packages: '@types/yargs-parser': 20.2.1 dev: true - /@typescript-eslint/eslint-plugin/5.4.0_5c8ff4cecd5a55e744866c0654edac32: - resolution: {integrity: sha512-9/yPSBlwzsetCsGEn9j24D8vGQgJkOTr4oMLas/w886ZtzKIs1iyoqFrwsX2fqYEeUwsdBpC21gcjRGo57u0eg==} + /@typescript-eslint/eslint-plugin/5.12.0_yrt47g5utmuvsqpihtshtjlyw4: + resolution: {integrity: sha512-fwCMkDimwHVeIOKeBHiZhRUfJXU8n6xW1FL9diDxAyGAFvKcH4csy0v7twivOQdQdA0KC8TDr7GGRd3L4Lv0rQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: '@typescript-eslint/parser': ^5.0.0 @@ -2074,74 +3239,76 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/experimental-utils': 5.4.0_eslint@8.3.0+typescript@4.5.2 - '@typescript-eslint/parser': 5.4.0_eslint@8.3.0+typescript@4.5.2 - '@typescript-eslint/scope-manager': 5.4.0 + '@typescript-eslint/parser': 5.12.0_fhzmdq77bspfhxkfuzq4fbrdsy + '@typescript-eslint/scope-manager': 5.12.0 + '@typescript-eslint/type-utils': 5.12.0_fhzmdq77bspfhxkfuzq4fbrdsy + '@typescript-eslint/utils': 5.12.0_fhzmdq77bspfhxkfuzq4fbrdsy debug: 4.3.2 - eslint: 8.3.0 + eslint: 8.9.0 functional-red-black-tree: 1.0.1 - ignore: 5.1.9 + ignore: 5.2.0 regexpp: 3.2.0 semver: 7.3.5 - tsutils: 3.21.0_typescript@4.5.2 - typescript: 4.5.2 + tsutils: 3.21.0_typescript@4.5.5 + typescript: 4.5.5 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/experimental-utils/5.4.0_eslint@8.3.0+typescript@4.5.2: - resolution: {integrity: sha512-Nz2JDIQUdmIGd6p33A+naQmwfkU5KVTLb/5lTk+tLVTDacZKoGQisj8UCxk7onJcrgjIvr8xWqkYI+DbI3TfXg==} + /@typescript-eslint/parser/5.12.0_fhzmdq77bspfhxkfuzq4fbrdsy: + resolution: {integrity: sha512-MfSwg9JMBojMUoGjUmX+D2stoQj1CBYTCP0qnnVtu9A+YQXVKNtLjasYh+jozOcrb/wau8TCfWOkQTiOAruBog==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: - eslint: '*' + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true dependencies: - '@types/json-schema': 7.0.9 - '@typescript-eslint/scope-manager': 5.4.0 - '@typescript-eslint/types': 5.4.0 - '@typescript-eslint/typescript-estree': 5.4.0_typescript@4.5.2 - eslint: 8.3.0 - eslint-scope: 5.1.1 - eslint-utils: 3.0.0_eslint@8.3.0 + '@typescript-eslint/scope-manager': 5.12.0 + '@typescript-eslint/types': 5.12.0 + '@typescript-eslint/typescript-estree': 5.12.0_typescript@4.5.5 + debug: 4.3.2 + eslint: 8.9.0 + typescript: 4.5.5 transitivePeerDependencies: - supports-color - - typescript dev: true - /@typescript-eslint/parser/5.4.0_eslint@8.3.0+typescript@4.5.2: - resolution: {integrity: sha512-JoB41EmxiYpaEsRwpZEYAJ9XQURPFer8hpkIW9GiaspVLX8oqbqNM8P4EP8HOZg96yaALiLEVWllA2E8vwsIKw==} + /@typescript-eslint/scope-manager/5.12.0: + resolution: {integrity: sha512-GAMobtIJI8FGf1sLlUWNUm2IOkIjvn7laFWyRx7CLrv6nLBI7su+B7lbStqVlK5NdLvHRFiJo2HhiDF7Ki01WQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + '@typescript-eslint/types': 5.12.0 + '@typescript-eslint/visitor-keys': 5.12.0 + dev: true + + /@typescript-eslint/type-utils/5.12.0_fhzmdq77bspfhxkfuzq4fbrdsy: + resolution: {integrity: sha512-9j9rli3zEBV+ae7rlbBOotJcI6zfc6SHFMdKI9M3Nc0sy458LJ79Os+TPWeBBL96J9/e36rdJOfCuyRSgFAA0Q==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + eslint: '*' typescript: '*' peerDependenciesMeta: typescript: optional: true dependencies: - '@typescript-eslint/scope-manager': 5.4.0 - '@typescript-eslint/types': 5.4.0 - '@typescript-eslint/typescript-estree': 5.4.0_typescript@4.5.2 + '@typescript-eslint/utils': 5.12.0_fhzmdq77bspfhxkfuzq4fbrdsy debug: 4.3.2 - eslint: 8.3.0 - typescript: 4.5.2 + eslint: 8.9.0 + tsutils: 3.21.0_typescript@4.5.5 + typescript: 4.5.5 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/scope-manager/5.4.0: - resolution: {integrity: sha512-pRxFjYwoi8R+n+sibjgF9iUiAELU9ihPBtHzocyW8v8D8G8KeQvXTsW7+CBYIyTYsmhtNk50QPGLE3vrvhM5KA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - '@typescript-eslint/types': 5.4.0 - '@typescript-eslint/visitor-keys': 5.4.0 - dev: true - - /@typescript-eslint/types/5.4.0: - resolution: {integrity: sha512-GjXNpmn+n1LvnttarX+sPD6+S7giO+9LxDIGlRl4wK3a7qMWALOHYuVSZpPTfEIklYjaWuMtfKdeByx0AcaThA==} + /@typescript-eslint/types/5.12.0: + resolution: {integrity: sha512-JowqbwPf93nvf8fZn5XrPGFBdIK8+yx5UEGs2QFAYFI8IWYfrzz+6zqlurGr2ctShMaJxqwsqmra3WXWjH1nRQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true - /@typescript-eslint/typescript-estree/5.4.0_typescript@4.5.2: - resolution: {integrity: sha512-nhlNoBdhKuwiLMx6GrybPT3SFILm5Gij2YBdPEPFlYNFAXUJWX6QRgvi/lwVoadaQEFsizohs6aFRMqsXI2ewA==} + /@typescript-eslint/typescript-estree/5.12.0_typescript@4.5.5: + resolution: {integrity: sha512-Dd9gVeOqt38QHR0BEA8oRaT65WYqPYbIc5tRFQPkfLquVEFPD1HAtbZT98TLBkEcCkvwDYOAvuSvAD9DnQhMfQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: typescript: '*' @@ -2149,24 +3316,42 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/types': 5.4.0 - '@typescript-eslint/visitor-keys': 5.4.0 + '@typescript-eslint/types': 5.12.0 + '@typescript-eslint/visitor-keys': 5.12.0 debug: 4.3.2 globby: 11.0.4 is-glob: 4.0.3 semver: 7.3.5 - tsutils: 3.21.0_typescript@4.5.2 - typescript: 4.5.2 + tsutils: 3.21.0_typescript@4.5.5 + typescript: 4.5.5 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/utils/5.12.0_fhzmdq77bspfhxkfuzq4fbrdsy: + resolution: {integrity: sha512-k4J2WovnMPGI4PzKgDtQdNrCnmBHpMUFy21qjX2CoPdoBcSBIMvVBr9P2YDP8jOqZOeK3ThOL6VO/sy6jtnvzw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + '@types/json-schema': 7.0.9 + '@typescript-eslint/scope-manager': 5.12.0 + '@typescript-eslint/types': 5.12.0 + '@typescript-eslint/typescript-estree': 5.12.0_typescript@4.5.5 + eslint: 8.9.0 + eslint-scope: 5.1.1 + eslint-utils: 3.0.0_eslint@8.9.0 transitivePeerDependencies: - supports-color + - typescript dev: true - /@typescript-eslint/visitor-keys/5.4.0: - resolution: {integrity: sha512-PVbax7MeE7tdLfW5SA0fs8NGVVr+buMPrcj+CWYWPXsZCH8qZ1THufDzbXm1xrZ2b2PA1iENJ0sRq5fuUtvsJg==} + /@typescript-eslint/visitor-keys/5.12.0: + resolution: {integrity: sha512-cFwTlgnMV6TgezQynx2c/4/tx9Tufbuo9LPzmWqyRC3QC4qTGkAG1C6pBr0/4I10PAI/FlYunI3vJjIcu+ZHMg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: - '@typescript-eslint/types': 5.4.0 - eslint-visitor-keys: 3.1.0 + '@typescript-eslint/types': 5.12.0 + eslint-visitor-keys: 3.3.0 dev: true /@webassemblyjs/ast/1.11.1: @@ -2275,14 +3460,14 @@ packages: '@xtuc/long': 4.2.2 dev: true - /@webpack-cli/configtest/1.1.0_webpack-cli@4.9.1+webpack@5.64.2: + /@webpack-cli/configtest/1.1.0_3awzrjtbpxvmpzpfa3syzgxzq4: resolution: {integrity: sha512-ttOkEkoalEHa7RaFYpM0ErK1xc4twg3Am9hfHhL7MVqlHebnkYd2wuI/ZqTDj0cVzZho6PdinY0phFZV3O0Mzg==} peerDependencies: webpack: 4.x.x || 5.x.x webpack-cli: 4.x.x dependencies: - webpack: 5.64.2_webpack-cli@4.9.1 - webpack-cli: 4.9.1_5bf98977c75b4da48bb2f18b6135c48d + webpack: 5.69.0_webpack-cli@4.9.1 + webpack-cli: 4.9.1_cpiwtwqgcyyvqiqogay7dd4uam dev: true /@webpack-cli/info/1.4.0_webpack-cli@4.9.1: @@ -2291,10 +3476,10 @@ packages: webpack-cli: 4.x.x dependencies: envinfo: 7.8.1 - webpack-cli: 4.9.1_5bf98977c75b4da48bb2f18b6135c48d + webpack-cli: 4.9.1_cpiwtwqgcyyvqiqogay7dd4uam dev: true - /@webpack-cli/serve/1.6.0_6273684a7d018c802013d37c995d983d: + /@webpack-cli/serve/1.6.0_5ylu5qs2nejtialjducb2qdkma: resolution: {integrity: sha512-ZkVeqEmRpBV2GHvjjUZqEai2PpUbuq8Bqd//vEYsp63J8WyexI8ppCqVS3Zs0QADf6aWuPdU+0XsPI647PVlQA==} peerDependencies: webpack-cli: 4.x.x @@ -2303,8 +3488,8 @@ packages: webpack-dev-server: optional: true dependencies: - webpack-cli: 4.9.1_5bf98977c75b4da48bb2f18b6135c48d - webpack-dev-server: 4.5.0_webpack-cli@4.9.1+webpack@5.64.2 + webpack-cli: 4.9.1_cpiwtwqgcyyvqiqogay7dd4uam + webpack-dev-server: 4.7.4_3awzrjtbpxvmpzpfa3syzgxzq4 dev: true /@xtuc/ieee754/1.2.0: @@ -2315,10 +3500,22 @@ packages: resolution: {integrity: sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==} dev: true + /JSONStream/1.3.5: + resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==} + hasBin: true + dependencies: + jsonparse: 1.3.1 + through: 2.3.8 + dev: true + /abab/2.0.5: resolution: {integrity: sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==} dev: true + /abbrev/1.1.1: + resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} + dev: true + /accepts/1.3.7: resolution: {integrity: sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==} engines: {node: '>= 0.6'} @@ -2342,12 +3539,12 @@ packages: acorn: 8.6.0 dev: true - /acorn-jsx/5.3.2_acorn@8.6.0: + /acorn-jsx/5.3.2_acorn@8.7.0: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 dependencies: - acorn: 8.6.0 + acorn: 8.7.0 dev: true /acorn-walk/7.2.0: @@ -2367,11 +3564,17 @@ packages: hasBin: true dev: true + /acorn/8.7.0: + resolution: {integrity: sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==} + engines: {node: '>=0.4.0'} + hasBin: true + dev: true + /agent-base/6.0.2: resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} engines: {node: '>= 6.0.0'} dependencies: - debug: 4.3.2 + debug: 4.3.4 transitivePeerDependencies: - supports-color dev: true @@ -2428,9 +3631,19 @@ packages: uri-js: 4.4.1 dev: true - /ansi-colors/4.1.1: - resolution: {integrity: sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==} - engines: {node: '>=6'} + /anser/2.1.1: + resolution: {integrity: sha512-nqLm4HxOTpeLOxcmB3QWmV5TcDFhW9y/fyQ+hivtDFcK4OQ+pQ5fzPnXHM1Mfcm0VkLtvVi1TCPr++Qy0Q/3EQ==} + dev: true + + /ansi-align/2.0.0: + resolution: {integrity: sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=} + dependencies: + string-width: 2.1.1 + dev: true + + /ansi-escapes/3.2.0: + resolution: {integrity: sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==} + engines: {node: '>=4'} dev: true /ansi-escapes/4.3.2: @@ -2440,12 +3653,29 @@ packages: type-fest: 0.21.3 dev: true + /ansi-escapes/5.0.0: + resolution: {integrity: sha512-5GFMVX8HqE/TB+FuBJGuO5XG0WrsA6ptUqoODaT/n9mmUaZFkqnBueB4leqGBCmrUHnCnC4PCZTCd0E7QQ83bA==} + engines: {node: '>=12'} + dependencies: + type-fest: 1.4.0 + dev: true + /ansi-html-community/0.0.8: resolution: {integrity: sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==} engines: {'0': node >= 0.8.0} hasBin: true dev: true + /ansi-regex/2.1.1: + resolution: {integrity: sha1-w7M6te42DYbg5ijwRorn7yfWVN8=} + engines: {node: '>=0.10.0'} + dev: true + + /ansi-regex/3.0.0: + resolution: {integrity: sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=} + engines: {node: '>=4'} + dev: true + /ansi-regex/5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} @@ -2474,6 +3704,10 @@ packages: engines: {node: '>=10'} dev: true + /ansicolors/0.3.2: + resolution: {integrity: sha1-ZlWX3oap/+Oqm/vmyuXG6kJrSXk=} + dev: true + /anymatch/3.1.2: resolution: {integrity: sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==} engines: {node: '>= 8'} @@ -2482,6 +3716,182 @@ packages: picomatch: 2.3.0 dev: true + /apollo-datasource/3.3.1: + resolution: {integrity: sha512-Z3a8rEUXVPIZ1p8xrFL8bcNhWmhOmovgDArvwIwmJOBnh093ZpRfO+ESJEDAN4KswmyzCLDAwjsW4zQOONdRUw==} + engines: {node: '>=12.0'} + dependencies: + apollo-server-caching: 3.3.0 + apollo-server-env: 4.2.1 + transitivePeerDependencies: + - encoding + dev: true + + /apollo-reporting-protobuf/3.3.0: + resolution: {integrity: sha512-51Jwrg0NvHJfKz7TIGU8+Os3rUAqWtXeKRsRtKYtTeMSBPNhzz8UoGjAB3XyVmUXRE3IRmLtDPDRFL7qbxMI/w==} + dependencies: + '@apollo/protobufjs': 1.2.2 + dev: true + + /apollo-server-caching/3.3.0: + resolution: {integrity: sha512-Wgcb0ArjZ5DjQ7ID+tvxUcZ7Yxdbk5l1MxZL8D8gkyjooOkhPNzjRVQ7ubPoXqO54PrOMOTm1ejVhsF+AfIirQ==} + engines: {node: '>=12.0'} + dependencies: + lru-cache: 6.0.0 + dev: true + + /apollo-server-core/3.6.3_graphql@16.3.0: + resolution: {integrity: sha512-TFJmAlI6vPp1MHOSXqYkE6leAyMekWv/D/3ma11uETkcd3EPjERGmxtTXPJElMVEkOK9BEElYKthCrH7bjYLuw==} + engines: {node: '>=12.0'} + peerDependencies: + graphql: ^15.3.0 || ^16.0.0 + dependencies: + '@apollographql/apollo-tools': 0.5.2_graphql@16.3.0 + '@apollographql/graphql-playground-html': 1.6.29 + '@graphql-tools/mock': 8.5.1_graphql@16.3.0 + '@graphql-tools/schema': 8.3.1_graphql@16.3.0 + '@josephg/resolvable': 1.0.1 + apollo-datasource: 3.3.1 + apollo-reporting-protobuf: 3.3.0 + apollo-server-caching: 3.3.0 + apollo-server-env: 4.2.1 + apollo-server-errors: 3.3.1_graphql@16.3.0 + apollo-server-plugin-base: 3.5.1_graphql@16.3.0 + apollo-server-types: 3.5.1_graphql@16.3.0 + async-retry: 1.3.3 + fast-json-stable-stringify: 2.1.0 + graphql: 16.3.0 + graphql-tag: 2.12.6_graphql@16.3.0 + lodash.sortby: 4.7.0 + loglevel: 1.8.0 + lru-cache: 6.0.0 + sha.js: 2.4.11 + uuid: 8.3.2 + transitivePeerDependencies: + - encoding + dev: true + + /apollo-server-env/4.2.1: + resolution: {integrity: sha512-vm/7c7ld+zFMxibzqZ7SSa5tBENc4B0uye9LTfjJwGoQFY5xsUPH5FpO5j0bMUDZ8YYNbrF9SNtzc5Cngcr90g==} + engines: {node: '>=12.0'} + dependencies: + node-fetch: 2.6.7 + transitivePeerDependencies: + - encoding + dev: true + + /apollo-server-errors/3.3.1_graphql@16.3.0: + resolution: {integrity: sha512-xnZJ5QWs6FixHICXHxUfm+ZWqqxrNuPlQ+kj5m6RtEgIpekOPssH/SD9gf2B4HuWV0QozorrygwZnux8POvyPA==} + engines: {node: '>=12.0'} + peerDependencies: + graphql: ^15.3.0 || ^16.0.0 + dependencies: + graphql: 16.3.0 + dev: true + + /apollo-server-express/3.6.3_2stwdwnt4bpcabnirdp3k6z4ba: + resolution: {integrity: sha512-3CjahZ+n+1T7pHH1qW1B6Ns0BzwOMeupAp2u0+M8ruOmE/e7VKn0OSOQQckZ8Z2AcWxWeno9K89fIv3PoSYgYA==} + engines: {node: '>=12.0'} + peerDependencies: + express: ^4.17.1 + graphql: ^15.3.0 || ^16.0.0 + dependencies: + '@types/accepts': 1.3.5 + '@types/body-parser': 1.19.2 + '@types/cors': 2.8.12 + '@types/express': 4.17.13 + '@types/express-serve-static-core': 4.17.28 + accepts: 1.3.7 + apollo-server-core: 3.6.3_graphql@16.3.0 + apollo-server-types: 3.5.1_graphql@16.3.0 + body-parser: 1.19.2 + cors: 2.8.5 + express: 4.17.2 + graphql: 16.3.0 + parseurl: 1.3.3 + transitivePeerDependencies: + - encoding + - supports-color + dev: true + + /apollo-server-plugin-base/3.5.1_graphql@16.3.0: + resolution: {integrity: sha512-wgDHz3lLrCqpecDky3z6AOQ0vik0qs0Cya/Ti6n3ESYXJ9MdK3jE/QunATIrOYYJaa+NKl9V7YwU+/bojNfFuQ==} + engines: {node: '>=12.0'} + peerDependencies: + graphql: ^15.3.0 || ^16.0.0 + dependencies: + apollo-server-types: 3.5.1_graphql@16.3.0 + graphql: 16.3.0 + transitivePeerDependencies: + - encoding + dev: true + + /apollo-server-types/3.5.1_graphql@16.3.0: + resolution: {integrity: sha512-zG7xLl4mmHuZMAYOfjWKHY/IC/GgIkJ3HnYuR7FRrnPpRA9Yt5Kf1M1rjm1Esuqzpb/dt8pM7cX40QaIQObCYQ==} + engines: {node: '>=12.0'} + peerDependencies: + graphql: ^15.3.0 || ^16.0.0 + dependencies: + apollo-reporting-protobuf: 3.3.0 + apollo-server-caching: 3.3.0 + apollo-server-env: 4.2.1 + graphql: 16.3.0 + transitivePeerDependencies: + - encoding + dev: true + + /aproba/1.2.0: + resolution: {integrity: sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==} + dev: true + + /archiver-utils/2.1.0: + resolution: {integrity: sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==} + engines: {node: '>= 6'} + dependencies: + glob: 7.2.0 + graceful-fs: 4.2.9 + lazystream: 1.0.1 + lodash.defaults: 4.2.0 + lodash.difference: 4.5.0 + lodash.flatten: 4.4.0 + lodash.isplainobject: 4.0.6 + lodash.union: 4.6.0 + normalize-path: 3.0.0 + readable-stream: 2.3.7 + dev: true + + /archiver/3.1.1: + resolution: {integrity: sha512-5Hxxcig7gw5Jod/8Gq0OneVgLYET+oNHcxgWItq4TbhOzRLKNAFUb9edAftiMKXvXfCB0vbGrJdZDNq0dWMsxg==} + engines: {node: '>= 6'} + dependencies: + archiver-utils: 2.1.0 + async: 2.6.3 + buffer-crc32: 0.2.13 + glob: 7.2.0 + readable-stream: 3.6.0 + tar-stream: 2.2.0 + zip-stream: 2.1.3 + dev: true + + /archiver/5.3.0: + resolution: {integrity: sha512-iUw+oDwK0fgNpvveEsdQ0Ase6IIKztBJU2U0E9MzszMfmVVUyv1QJhS2ITW9ZCqx8dktAxVAjWWkKehuZE8OPg==} + engines: {node: '>= 10'} + dependencies: + archiver-utils: 2.1.0 + async: 3.2.3 + buffer-crc32: 0.2.13 + readable-stream: 3.6.0 + readdir-glob: 1.1.1 + tar-stream: 2.2.0 + zip-stream: 4.1.0 + dev: true + + /are-we-there-yet/1.1.7: + resolution: {integrity: sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==} + dependencies: + delegates: 1.0.0 + readable-stream: 2.3.7 + dev: true + /argparse/1.0.10: resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} dependencies: @@ -2492,11 +3902,15 @@ packages: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} dev: true + /argv-formatter/1.0.0: + resolution: {integrity: sha1-oMoMvCmltz6Dbuvhy/bF4OTrgvk=} + dev: true + /aria-query/4.2.2: resolution: {integrity: sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==} engines: {node: '>=6.0'} dependencies: - '@babel/runtime': 7.16.3 + '@babel/runtime': 7.17.2 '@babel/runtime-corejs3': 7.16.3 dev: true @@ -2513,6 +3927,10 @@ packages: resolution: {integrity: sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==} dev: true + /array-ify/1.0.0: + resolution: {integrity: sha1-nlKHYrSpBmrRY6aWKjZEGOlibs4=} + dev: true + /array-includes/3.1.4: resolution: {integrity: sha512-ZTNSQkmWumEbiHO2GF4GmWxYVTiQyJy2XOTa15sdQSrvKn7l+180egQMqlrMOUMCyLMD7pmyQe4mMDUT6Behrw==} engines: {node: '>= 0.4'} @@ -2536,6 +3954,11 @@ packages: engines: {node: '>=8'} dev: true + /array-union/3.0.1: + resolution: {integrity: sha512-1OvF9IbWwaeiM9VhzYXVQacMibxpXOMYVNIvMtKRyX9SImBXpKcFr8XvFDeEslCyuH/t6KRt7HEO94AlP8Iatw==} + engines: {node: '>=12'} + dev: true + /array-uniq/1.0.3: resolution: {integrity: sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=} engines: {node: '>=0.10.0'} @@ -2559,26 +3982,89 @@ packages: es-abstract: 1.19.1 dev: true + /arrify/1.0.1: + resolution: {integrity: sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=} + engines: {node: '>=0.10.0'} + dev: true + + /asn1/0.2.6: + resolution: {integrity: sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==} + dependencies: + safer-buffer: 2.1.2 + dev: true + + /assert-plus/1.0.0: + resolution: {integrity: sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=} + engines: {node: '>=0.8'} + dev: true + optional: true + /ast-types-flow/0.0.7: resolution: {integrity: sha1-9wtzXGvKGlycItmCw+Oef+ujva0=} dev: true + /async-retry/1.3.3: + resolution: {integrity: sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==} + dependencies: + retry: 0.13.1 + dev: true + + /async/2.0.0: + resolution: {integrity: sha1-0JAK04WvE4BFQKEJxCFm4657K50=} + dependencies: + lodash: 4.17.21 + dev: true + + /async/2.3.0: + resolution: {integrity: sha1-EBPRBRBH3TIP4k5JTVxm7K9hR9k=} + dependencies: + lodash: 4.17.21 + dev: true + /async/2.6.3: resolution: {integrity: sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==} dependencies: lodash: 4.17.21 dev: true + /async/3.2.3: + resolution: {integrity: sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==} + dev: true + /asynckit/0.4.0: resolution: {integrity: sha1-x57Zf380y48robyXkLzDZkdLS3k=} dev: true + /at-least-node/1.0.0: + resolution: {integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==} + engines: {node: '>= 4.0.0'} + dev: true + + /atoa/1.0.0: + resolution: {integrity: sha1-DMDpGkgOc4+SPrwQNnZHF3mzSkk=} + dev: true + /atob/2.1.2: resolution: {integrity: sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==} engines: {node: '>= 4.5.0'} hasBin: true dev: true + /atomic-sleep/1.0.0: + resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==} + engines: {node: '>=8.0.0'} + dev: false + + /aws-sign2/0.7.0: + resolution: {integrity: sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=} + dev: true + optional: true + + /aws4/1.11.0: + resolution: {integrity: sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==} + dev: true + optional: true + /axe-core/4.3.5: resolution: {integrity: sha512-WKTW1+xAzhMS5dJsxWkliixlO/PqC4VhmO9T4juNYcaTg9jzWiJsou6m5pxWYGfigWbwzJWeFY6z47a+4neRXA==} engines: {node: '>=4'} @@ -2588,38 +4074,38 @@ packages: resolution: {integrity: sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA==} dev: true - /babel-jest/27.3.1_@babel+core@7.16.0: - resolution: {integrity: sha512-SjIF8hh/ir0peae2D6S6ZKRhUy7q/DnpH7k/V6fT4Bgs/LXXUztOpX4G2tCgq8mLo5HA9mN6NmlFMeYtKmIsTQ==} + /babel-jest/27.5.1_@babel+core@7.17.4: + resolution: {integrity: sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} peerDependencies: '@babel/core': ^7.8.0 dependencies: - '@babel/core': 7.16.0 - '@jest/transform': 27.3.1 - '@jest/types': 27.2.5 + '@babel/core': 7.17.4 + '@jest/transform': 27.5.1 + '@jest/types': 27.5.1 '@types/babel__core': 7.1.16 babel-plugin-istanbul: 6.1.1 - babel-preset-jest: 27.2.0_@babel+core@7.16.0 + babel-preset-jest: 27.5.1_@babel+core@7.17.4 chalk: 4.1.2 - graceful-fs: 4.2.8 + graceful-fs: 4.2.9 slash: 3.0.0 transitivePeerDependencies: - supports-color dev: true - /babel-loader/8.2.3_95e63ddb935ae8cb6c63cf95c1e0c16e: + /babel-loader/8.2.3_6w76b5w2swsmq5slbwizdwekbi: resolution: {integrity: sha512-n4Zeta8NC3QAsuyiizu0GkmRcQ6clkV9WFUnUf1iXP//IeSKbWjofW3UHyZVwlOB4y039YQKefawyTn64Zwbuw==} engines: {node: '>= 8.9'} peerDependencies: '@babel/core': ^7.0.0 webpack: '>=2' dependencies: - '@babel/core': 7.16.0 + '@babel/core': 7.17.4 find-cache-dir: 3.3.2 loader-utils: 1.4.0 make-dir: 3.1.0 schema-utils: 2.7.1 - webpack: 5.64.2_webpack-cli@4.9.1 + webpack: 5.69.0_webpack-cli@4.9.1 dev: true /babel-plugin-dynamic-import-node/2.3.3: @@ -2632,7 +4118,7 @@ packages: resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==} engines: {node: '>=8'} dependencies: - '@babel/helper-plugin-utils': 7.14.5 + '@babel/helper-plugin-utils': 7.16.7 '@istanbuljs/load-nyc-config': 1.1.0 '@istanbuljs/schema': 0.1.3 istanbul-lib-instrument: 5.1.0 @@ -2641,12 +4127,12 @@ packages: - supports-color dev: true - /babel-plugin-jest-hoist/27.2.0: - resolution: {integrity: sha512-TOux9khNKdi64mW+0OIhcmbAn75tTlzKhxmiNXevQaPbrBYK7YKjP1jl6NHTJ6XR5UgUrJbCnWlKVnJn29dfjw==} + /babel-plugin-jest-hoist/27.5.1: + resolution: {integrity: sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dependencies: - '@babel/template': 7.16.0 - '@babel/types': 7.16.0 + '@babel/template': 7.16.7 + '@babel/types': 7.17.0 '@types/babel__core': 7.1.16 '@types/babel__traverse': 7.14.2 dev: true @@ -2660,38 +4146,38 @@ packages: resolve: 1.20.0 dev: true - /babel-plugin-polyfill-corejs2/0.3.0_@babel+core@7.16.0: + /babel-plugin-polyfill-corejs2/0.3.0_@babel+core@7.17.4: resolution: {integrity: sha512-wMDoBJ6uG4u4PNFh72Ty6t3EgfA91puCuAwKIazbQlci+ENb/UU9A3xG5lutjUIiXCIn1CY5L15r9LimiJyrSA==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/compat-data': 7.16.4 - '@babel/core': 7.16.0 - '@babel/helper-define-polyfill-provider': 0.3.0_@babel+core@7.16.0 + '@babel/compat-data': 7.17.0 + '@babel/core': 7.17.4 + '@babel/helper-define-polyfill-provider': 0.3.0_@babel+core@7.17.4 semver: 6.3.0 transitivePeerDependencies: - supports-color dev: true - /babel-plugin-polyfill-corejs3/0.4.0_@babel+core@7.16.0: - resolution: {integrity: sha512-YxFreYwUfglYKdLUGvIF2nJEsGwj+RhWSX/ije3D2vQPOXuyMLMtg/cCGMDpOA7Nd+MwlNdnGODbd2EwUZPlsw==} + /babel-plugin-polyfill-corejs3/0.5.2_@babel+core@7.17.4: + resolution: {integrity: sha512-G3uJih0XWiID451fpeFaYGVuxHEjzKTHtc9uGFEjR6hHrvNzeS/PX+LLLcetJcytsB5m4j+K3o/EpXJNb/5IEQ==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-define-polyfill-provider': 0.3.0_@babel+core@7.16.0 - core-js-compat: 3.19.1 + '@babel/core': 7.17.4 + '@babel/helper-define-polyfill-provider': 0.3.1_@babel+core@7.17.4 + core-js-compat: 3.21.0 transitivePeerDependencies: - supports-color dev: true - /babel-plugin-polyfill-regenerator/0.3.0_@babel+core@7.16.0: + /babel-plugin-polyfill-regenerator/0.3.0_@babel+core@7.17.4: resolution: {integrity: sha512-dhAPTDLGoMW5/84wkgwiLRwMnio2i1fUe53EuvtKMv0pn2p3S8OCoV1xAzfJPl0KOX7IB89s2ib85vbYiea3jg==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 - '@babel/helper-define-polyfill-provider': 0.3.0_@babel+core@7.16.0 + '@babel/core': 7.17.4 + '@babel/helper-define-polyfill-provider': 0.3.0_@babel+core@7.17.4 transitivePeerDependencies: - supports-color dev: true @@ -2705,51 +4191,84 @@ packages: '@babel/helper-module-imports': 7.16.0 babel-plugin-syntax-jsx: 6.18.0 lodash: 4.17.21 - styled-components: 5.3.3_281a4fa50a045c9112baf635f3bc27a7 - dev: false + styled-components: 5.3.3_fane7jikarojcev26y27hpbhu4 /babel-plugin-syntax-jsx/6.18.0: resolution: {integrity: sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=} - dev: false - /babel-preset-current-node-syntax/1.0.1_@babel+core@7.16.0: + /babel-preset-current-node-syntax/1.0.1_@babel+core@7.17.4: resolution: {integrity: sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==} peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/core': 7.16.0 - '@babel/plugin-syntax-async-generators': 7.8.4_@babel+core@7.16.0 - '@babel/plugin-syntax-bigint': 7.8.3_@babel+core@7.16.0 - '@babel/plugin-syntax-class-properties': 7.12.13_@babel+core@7.16.0 - '@babel/plugin-syntax-import-meta': 7.10.4_@babel+core@7.16.0 - '@babel/plugin-syntax-json-strings': 7.8.3_@babel+core@7.16.0 - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4_@babel+core@7.16.0 - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3_@babel+core@7.16.0 - '@babel/plugin-syntax-numeric-separator': 7.10.4_@babel+core@7.16.0 - '@babel/plugin-syntax-object-rest-spread': 7.8.3_@babel+core@7.16.0 - '@babel/plugin-syntax-optional-catch-binding': 7.8.3_@babel+core@7.16.0 - '@babel/plugin-syntax-optional-chaining': 7.8.3_@babel+core@7.16.0 - '@babel/plugin-syntax-top-level-await': 7.14.5_@babel+core@7.16.0 - dev: true - - /babel-preset-jest/27.2.0_@babel+core@7.16.0: - resolution: {integrity: sha512-z7MgQ3peBwN5L5aCqBKnF6iqdlvZvFUQynEhu0J+X9nHLU72jO3iY331lcYrg+AssJ8q7xsv5/3AICzVmJ/wvg==} + '@babel/core': 7.17.4 + '@babel/plugin-syntax-async-generators': 7.8.4_@babel+core@7.17.4 + '@babel/plugin-syntax-bigint': 7.8.3_@babel+core@7.17.4 + '@babel/plugin-syntax-class-properties': 7.12.13_@babel+core@7.17.4 + '@babel/plugin-syntax-import-meta': 7.10.4_@babel+core@7.17.4 + '@babel/plugin-syntax-json-strings': 7.8.3_@babel+core@7.17.4 + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4_@babel+core@7.17.4 + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3_@babel+core@7.17.4 + '@babel/plugin-syntax-numeric-separator': 7.10.4_@babel+core@7.17.4 + '@babel/plugin-syntax-object-rest-spread': 7.8.3_@babel+core@7.17.4 + '@babel/plugin-syntax-optional-catch-binding': 7.8.3_@babel+core@7.17.4 + '@babel/plugin-syntax-optional-chaining': 7.8.3_@babel+core@7.17.4 + '@babel/plugin-syntax-top-level-await': 7.14.5_@babel+core@7.17.4 + dev: true + + /babel-preset-jest/27.5.1_@babel+core@7.17.4: + resolution: {integrity: sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/core': 7.16.0 - babel-plugin-jest-hoist: 27.2.0 - babel-preset-current-node-syntax: 1.0.1_@babel+core@7.16.0 + '@babel/core': 7.17.4 + babel-plugin-jest-hoist: 27.5.1 + babel-preset-current-node-syntax: 1.0.1_@babel+core@7.17.4 dev: true /balanced-match/1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + /base16/1.0.0: + resolution: {integrity: sha1-4pf2DX7BAUp6lxo568ipjAtoHnA=} + dev: true + + /base64-js/1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + dev: true + + /base64id/1.0.0: + resolution: {integrity: sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=} + engines: {node: '>= 0.4.0'} + dev: true + + /basic-auth/2.0.1: + resolution: {integrity: sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==} + engines: {node: '>= 0.8'} + dependencies: + safe-buffer: 5.1.2 + dev: true + /batch/0.6.1: resolution: {integrity: sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=} dev: true + /bcrypt-pbkdf/1.0.2: + resolution: {integrity: sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=} + dependencies: + tweetnacl: 0.14.5 + dev: true + optional: true + + /before-after-hook/2.2.2: + resolution: {integrity: sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ==} + dev: true + + /big-integer/1.6.51: + resolution: {integrity: sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==} + engines: {node: '>=0.6'} + /big.js/5.2.2: resolution: {integrity: sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==} dev: true @@ -2759,20 +4278,74 @@ packages: engines: {node: '>=8'} dev: true - /body-parser/1.19.0: - resolution: {integrity: sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==} + /bl/4.1.0: + resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} + dependencies: + buffer: 5.7.1 + inherits: 2.0.4 + readable-stream: 3.6.0 + dev: true + + /block-stream/0.0.9: + resolution: {integrity: sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=} + engines: {node: 0.4 || >=0.5.8} + dependencies: + inherits: 2.0.4 + dev: true + optional: true + + /body-parser/1.19.0: + resolution: {integrity: sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==} + engines: {node: '>= 0.8'} + dependencies: + bytes: 3.1.0 + content-type: 1.0.4 + debug: 2.6.9 + depd: 1.1.2 + http-errors: 1.7.2 + iconv-lite: 0.4.24 + on-finished: 2.3.0 + qs: 6.7.0 + raw-body: 2.4.0 + type-is: 1.6.18 + transitivePeerDependencies: + - supports-color + dev: true + + /body-parser/1.19.1: + resolution: {integrity: sha512-8ljfQi5eBk8EJfECMrgqNGWPEY5jWP+1IzkzkGdFFEwFQZZyaZ21UqdaHktgiMlH0xLHqIFtE/u2OYE5dOtViA==} + engines: {node: '>= 0.8'} + dependencies: + bytes: 3.1.1 + content-type: 1.0.4 + debug: 2.6.9 + depd: 1.1.2 + http-errors: 1.8.1 + iconv-lite: 0.4.24 + on-finished: 2.3.0 + qs: 6.9.6 + raw-body: 2.4.2 + type-is: 1.6.18 + transitivePeerDependencies: + - supports-color + dev: true + + /body-parser/1.19.2: + resolution: {integrity: sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw==} engines: {node: '>= 0.8'} dependencies: - bytes: 3.1.0 + bytes: 3.1.2 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 + qs: 6.9.7 + raw-body: 2.4.3 type-is: 1.6.18 + transitivePeerDependencies: + - supports-color dev: true /bonjour/3.5.0: @@ -2790,6 +4363,28 @@ packages: resolution: {integrity: sha1-aN/1++YMUes3cl6p4+0xDcwed24=} dev: true + /boolean/3.2.0: + resolution: {integrity: sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==} + dev: true + optional: true + + /bottleneck/2.19.5: + resolution: {integrity: sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==} + dev: true + + /boxen/1.3.0: + resolution: {integrity: sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw==} + engines: {node: '>=4'} + dependencies: + ansi-align: 2.0.0 + camelcase: 4.1.0 + chalk: 2.4.2 + cli-boxes: 1.0.0 + string-width: 2.1.1 + term-size: 1.2.0 + widest-line: 2.0.1 + dev: true + /brace-expansion/1.1.11: resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} dependencies: @@ -2803,6 +4398,31 @@ packages: fill-range: 7.0.1 dev: true + /broadcast-channel/2.3.4: + resolution: {integrity: sha512-cx1/dSb6KZ9HW1VtlqM/HLPjrdyzkKoteVmUpLXEpra00mDQW/F9ieDkoavuZMoh9/hC/6OplGzCERsZBfz/Wg==} + dependencies: + '@babel/runtime': 7.17.2 + detect-node: 2.1.0 + js-sha3: 0.8.0 + microseconds: 0.1.0 + nano-time: 1.0.0 + rimraf: 2.6.3 + unload: 2.2.0 + dev: true + + /broadcast-channel/3.7.0: + resolution: {integrity: sha512-cIAKJXAxGJceNZGTZSBzMxzyOn72cVgPnKx4dc6LRjQgbaJUQqhy5rzL3zbMxkMWsGKkv2hSFkPRMEXfoMZ2Mg==} + dependencies: + '@babel/runtime': 7.17.2 + detect-node: 2.1.0 + js-sha3: 0.8.0 + microseconds: 0.2.0 + nano-time: 1.0.0 + oblivious-set: 1.0.0 + rimraf: 3.0.2 + unload: 2.2.0 + dev: false + /browser-process-hrtime/1.0.0: resolution: {integrity: sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==} dev: true @@ -2819,12 +4439,32 @@ packages: picocolors: 1.0.0 dev: true + /browserslist/4.19.1: + resolution: {integrity: sha512-u2tbbG5PdKRTUoctO3NBD8FQ5HdPh1ZXPHzp1rwaa5jTc+RV9/+RlWiAIKmjRPQF+xbGM9Kklj5bZQFa2s/38A==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + dependencies: + caniuse-lite: 1.0.30001312 + electron-to-chromium: 1.4.71 + escalade: 3.1.1 + node-releases: 2.0.1 + picocolors: 1.0.0 + dev: true + /bser/2.1.1: resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} dependencies: node-int64: 0.4.0 dev: true + /buffer-crc32/0.2.13: + resolution: {integrity: sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=} + dev: true + + /buffer-equal-constant-time/1.0.1: + resolution: {integrity: sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=} + dev: true + /buffer-from/1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} dev: true @@ -2833,6 +4473,13 @@ packages: resolution: {integrity: sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==} dev: true + /buffer/5.7.1: + resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + dev: true + /bytes/3.0.0: resolution: {integrity: sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=} engines: {node: '>= 0.8'} @@ -2843,6 +4490,29 @@ packages: engines: {node: '>= 0.8'} dev: true + /bytes/3.1.1: + resolution: {integrity: sha512-dWe4nWO/ruEOY7HkUJ5gFt1DCFV9zPRoJr8pV0/ASQermOZjtq8jMjOprC0Kd10GLN+l7xaUPvxzJFWtxGu8Fg==} + engines: {node: '>= 0.8'} + dev: true + + /bytes/3.1.2: + resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} + engines: {node: '>= 0.8'} + dev: true + + /cacheable-request/6.1.0: + resolution: {integrity: sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==} + engines: {node: '>=8'} + dependencies: + clone-response: 1.0.2 + get-stream: 5.2.0 + http-cache-semantics: 4.1.0 + keyv: 3.1.0 + lowercase-keys: 2.0.0 + normalize-url: 4.5.1 + responselike: 1.0.2 + dev: true + /call-bind/1.0.2: resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==} dependencies: @@ -2859,7 +4529,21 @@ packages: resolution: {integrity: sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==} dependencies: pascal-case: 3.1.2 - tslib: 2.3.1 + tslib: 2.4.1 + dev: true + + /camelcase-keys/6.2.2: + resolution: {integrity: sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==} + engines: {node: '>=8'} + dependencies: + camelcase: 5.3.1 + map-obj: 4.3.0 + quick-lru: 4.0.1 + dev: true + + /camelcase/4.1.0: + resolution: {integrity: sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=} + engines: {node: '>=4'} dev: true /camelcase/5.3.1: @@ -2874,12 +4558,33 @@ packages: /camelize/1.0.0: resolution: {integrity: sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs=} - dev: false /caniuse-lite/1.0.30001282: resolution: {integrity: sha512-YhF/hG6nqBEllymSIjLtR2iWDDnChvhnVJqp+vloyt2tEHFG1yBR+ac2B/rOw0qOK0m0lEXU2dv4E/sMk5P9Kg==} dev: true + /caniuse-lite/1.0.30001312: + resolution: {integrity: sha512-Wiz1Psk2MEK0pX3rUzWaunLTZzqS2JYZFzNKqAiJGiuxIjRPLgV6+VDPOg6lQOUxmDwhTlh198JsTTi8Hzw6aQ==} + dev: true + + /capture-stack-trace/1.0.1: + resolution: {integrity: sha512-mYQLZnx5Qt1JgB1WEiMCf2647plpGeQ2NMR/5L0HNZzGQo4fuSPnK+wjfPnKZV0aiJDgzmWqqkV/g7JD+DW0qw==} + engines: {node: '>=0.10.0'} + dev: true + + /cardinal/2.1.1: + resolution: {integrity: sha1-fMEFXYItISlU0HsIXeolHMe8VQU=} + hasBin: true + dependencies: + ansicolors: 0.3.2 + redeyed: 2.1.1 + dev: true + + /caseless/0.12.0: + resolution: {integrity: sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=} + dev: true + optional: true + /chalk/2.4.2: resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} engines: {node: '>=4'} @@ -2904,13 +4609,22 @@ packages: supports-color: 7.2.0 dev: true + /chalk/5.0.0: + resolution: {integrity: sha512-/duVOqst+luxCQRKEo4bNxinsOQtMP80ZYm7mMqzuh5PociNL0PvmHFvREJ9ueYL2TxlHjBcmLCdmocx9Vg+IQ==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + dev: true + /char-regex/1.0.2: resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==} engines: {node: '>=10'} dev: true - /chokidar/3.5.2: - resolution: {integrity: sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==} + /chardet/0.4.2: + resolution: {integrity: sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=} + dev: true + + /chokidar/3.5.3: + resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} engines: {node: '>= 8.10.0'} dependencies: anymatch: 3.1.2 @@ -2924,11 +4638,19 @@ packages: fsevents: 2.3.2 dev: true + /chownr/1.1.4: + resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} + dev: true + /chrome-trace-event/1.0.3: resolution: {integrity: sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==} engines: {node: '>=6.0'} dev: true + /ci-info/1.6.0: + resolution: {integrity: sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==} + dev: true + /ci-info/3.2.0: resolution: {integrity: sha512-dVqRX7fLUm8J6FgHJ418XuIgDLZDkYcDFTeL6TA2gt5WlIZUQrrH6EZrNClwT/H0FateUsZkGIOPRrLbP+PR9A==} dev: true @@ -2949,14 +4671,39 @@ packages: engines: {node: '>=6'} dev: true - /clean-webpack-plugin/4.0.0_webpack@5.64.2: + /clean-webpack-plugin/4.0.0_webpack@5.69.0: resolution: {integrity: sha512-WuWE1nyTNAyW5T7oNyys2EN0cfP2fdRxhxnIQWiAp0bMabPdHhoGxM8A6YL2GhqwgrPnnaemVE7nv5XJ2Fhh2w==} engines: {node: '>=10.0.0'} peerDependencies: webpack: '>=4.0.0 <6.0.0' dependencies: del: 4.1.1 - webpack: 5.64.2_webpack-cli@4.9.1 + webpack: 5.69.0_webpack-cli@4.9.1 + dev: true + + /cli-boxes/1.0.0: + resolution: {integrity: sha1-T6kXw+WclKAEzWH47lCdplFocUM=} + engines: {node: '>=0.10.0'} + dev: true + + /cli-cursor/2.1.0: + resolution: {integrity: sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=} + engines: {node: '>=4'} + dependencies: + restore-cursor: 2.0.0 + dev: true + + /cli-table3/0.6.1: + resolution: {integrity: sha512-w0q/enDHhPLq44ovMGdQeeDLvwxwavsJX7oQGYt/LrBlYsyaxyDnp6z3QzFut/6kLLKnlcUVJLrpB7KBfgG/RA==} + engines: {node: 10.* || >= 12.*} + dependencies: + string-width: 4.2.3 + optionalDependencies: + colors: 1.4.0 + dev: true + + /cli-width/2.2.1: + resolution: {integrity: sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==} dev: true /cliui/7.0.4: @@ -2976,11 +4723,31 @@ packages: shallow-clone: 3.0.1 dev: true + /clone-response/1.0.2: + resolution: {integrity: sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=} + dependencies: + mimic-response: 1.0.1 + dev: true + + /clone/2.1.1: + resolution: {integrity: sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=} + engines: {node: '>=0.8'} + dev: true + /co/4.6.0: resolution: {integrity: sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=} engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} dev: true + /code-point-at/1.1.0: + resolution: {integrity: sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=} + engines: {node: '>=0.10.0'} + dev: true + + /codemirror/5.65.1: + resolution: {integrity: sha512-s6aac+DD+4O2u1aBmdxhB7yz2XU7tG3snOyQ05Kxifahz7hoxnfxIRHxiCSEv3TUC38dIVH8G+lZH9UWSfGQxA==} + dev: true + /collect-v8-coverage/1.0.1: resolution: {integrity: sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==} dev: true @@ -3004,10 +4771,31 @@ packages: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} dev: true + /color-string/1.9.0: + resolution: {integrity: sha512-9Mrz2AQLefkH1UvASKj6v6hj/7eWgjnT/cVsR8CumieLoT+g900exWeNogqtweI8dxloXN9BDQTYro1oWu/5CQ==} + dependencies: + color-name: 1.1.4 + simple-swizzle: 0.2.2 + dev: true + + /color/3.2.1: + resolution: {integrity: sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==} + dependencies: + color-convert: 1.9.3 + color-string: 1.9.0 + dev: true + /colorette/2.0.16: resolution: {integrity: sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g==} dev: true + /colors/1.4.0: + resolution: {integrity: sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==} + engines: {node: '>=0.1.90'} + requiresBuild: true + dev: true + optional: true + /combined-stream/1.0.8: resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} engines: {node: '>= 0.8'} @@ -3042,6 +4830,37 @@ packages: resolution: {integrity: sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=} dev: true + /compare-func/2.0.0: + resolution: {integrity: sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==} + dependencies: + array-ify: 1.0.0 + dot-prop: 5.3.0 + dev: true + + /component-emitter/1.2.1: + resolution: {integrity: sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=} + dev: true + + /compress-commons/2.1.1: + resolution: {integrity: sha512-eVw6n7CnEMFzc3duyFVrQEuY1BlHR3rYsSztyG32ibGMW722i3C6IizEGMFmfMU+A+fALvBIwxN3czffTcdA+Q==} + engines: {node: '>= 6'} + dependencies: + buffer-crc32: 0.2.13 + crc32-stream: 3.0.1 + normalize-path: 3.0.0 + readable-stream: 2.3.7 + dev: true + + /compress-commons/4.1.1: + resolution: {integrity: sha512-QLdDLCKNV2dtoTorqgxngQCMA+gWXkM/Nwu7FpeBhk/RdkzimqC3jueb/FDmaZeXh+uby1jkBqE3xArsLBE5wQ==} + engines: {node: '>= 10'} + dependencies: + buffer-crc32: 0.2.13 + crc32-stream: 4.0.2 + normalize-path: 3.0.0 + readable-stream: 3.6.0 + dev: true + /compressible/2.0.18: resolution: {integrity: sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==} engines: {node: '>= 0.6'} @@ -3060,16 +4879,69 @@ packages: on-headers: 1.0.2 safe-buffer: 5.1.2 vary: 1.1.2 + transitivePeerDependencies: + - supports-color + dev: true + + /compute-gcd/1.2.1: + resolution: {integrity: sha512-TwMbxBNz0l71+8Sc4czv13h4kEqnchV9igQZBi6QUaz09dnz13juGnnaWWJTRsP3brxOoxeB4SA2WELLw1hCtg==} + dependencies: + validate.io-array: 1.0.6 + validate.io-function: 1.0.2 + validate.io-integer-array: 1.0.0 + dev: true + + /compute-lcm/1.1.2: + resolution: {integrity: sha512-OFNPdQAXnQhDSKioX8/XYT6sdUlXwpeMjfd6ApxMJfyZ4GxmLR1xvMERctlYhlHwIiz6CSpBc2+qYKjHGZw4TQ==} + dependencies: + compute-gcd: 1.2.1 + validate.io-array: 1.0.6 + validate.io-function: 1.0.2 + validate.io-integer-array: 1.0.0 dev: true /concat-map/0.0.1: resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=} + /concat-stream/1.6.2: + resolution: {integrity: sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==} + engines: {'0': node >= 0.8} + dependencies: + buffer-from: 1.1.2 + inherits: 2.0.4 + readable-stream: 2.3.7 + typedarray: 0.0.6 + dev: true + + /config-chain/1.1.13: + resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==} + dependencies: + ini: 1.3.8 + proto-list: 1.2.4 + dev: true + optional: true + + /configstore/3.1.5: + resolution: {integrity: sha512-nlOhI4+fdzoK5xmJ+NY+1gZK56bwEaWZr8fYuXohZ9Vkc1o3a4T/R3M+yE/w7x/ZVJ1zF8c+oaOvF0dztdUgmA==} + engines: {node: '>=4'} + dependencies: + dot-prop: 4.2.1 + graceful-fs: 4.2.9 + make-dir: 1.3.0 + unique-string: 1.0.0 + write-file-atomic: 2.4.3 + xdg-basedir: 3.0.0 + dev: true + /connect-history-api-fallback/1.6.0: resolution: {integrity: sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==} engines: {node: '>=0.8'} dev: true + /console-control-strings/1.1.0: + resolution: {integrity: sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=} + dev: true + /content-disposition/0.5.3: resolution: {integrity: sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==} engines: {node: '>= 0.6'} @@ -3077,11 +4949,70 @@ packages: safe-buffer: 5.1.2 dev: true + /content-disposition/0.5.4: + resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} + engines: {node: '>= 0.6'} + dependencies: + safe-buffer: 5.2.1 + dev: true + /content-type/1.0.4: resolution: {integrity: sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==} engines: {node: '>= 0.6'} dev: true + /contra/1.9.4: + resolution: {integrity: sha1-9TveQtfltZhcrk2ZqNYQUm3o8o0=} + dependencies: + atoa: 1.0.0 + ticky: 1.0.1 + dev: true + + /conventional-changelog-angular/5.0.13: + resolution: {integrity: sha512-i/gipMxs7s8L/QeuavPF2hLnJgH6pEZAttySB6aiQLWcX3puWDL3ACVmvBhJGxnAy52Qc15ua26BufY6KpmrVA==} + engines: {node: '>=10'} + dependencies: + compare-func: 2.0.0 + q: 1.5.1 + dev: true + + /conventional-changelog-writer/5.0.1: + resolution: {integrity: sha512-5WsuKUfxW7suLblAbFnxAcrvf6r+0b7GvNaWUwUIk0bXMnENP/PEieGKVUQrjPqwPT4o3EPAASBXiY6iHooLOQ==} + engines: {node: '>=10'} + hasBin: true + dependencies: + conventional-commits-filter: 2.0.7 + dateformat: 3.0.3 + handlebars: 4.7.7 + json-stringify-safe: 5.0.1 + lodash: 4.17.21 + meow: 8.1.2 + semver: 6.3.0 + split: 1.0.1 + through2: 4.0.2 + dev: true + + /conventional-commits-filter/2.0.7: + resolution: {integrity: sha512-ASS9SamOP4TbCClsRHxIHXRfcGCnIoQqkvAzCSbZzTFLfcTqJVugB0agRgsEELsqaeWgsXv513eS116wnlSSPA==} + engines: {node: '>=10'} + dependencies: + lodash.ismatch: 4.4.0 + modify-values: 1.0.1 + dev: true + + /conventional-commits-parser/3.2.4: + resolution: {integrity: sha512-nK7sAtfi+QXbxHCYfhpZsfRtaitZLIA6889kFIouLvz6repszQDgxBu7wf2WbU+Dco7sAnNCJYERCwt54WPC2Q==} + engines: {node: '>=10'} + hasBin: true + dependencies: + JSONStream: 1.3.5 + is-text-path: 1.0.1 + lodash: 4.17.21 + meow: 8.1.2 + split2: 3.2.2 + through2: 4.0.2 + dev: true + /convert-source-map/1.8.0: resolution: {integrity: sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==} dependencies: @@ -3097,10 +5028,30 @@ packages: engines: {node: '>= 0.6'} dev: true - /core-js-compat/3.19.1: - resolution: {integrity: sha512-Q/VJ7jAF/y68+aUsQJ/afPOewdsGkDtcMb40J8MbuWKlK3Y+wtHq8bTHKPj2WKWLIqmS5JhHs4CzHtz6pT2W6g==} + /cookie/0.4.1: + resolution: {integrity: sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==} + engines: {node: '>= 0.6'} + dev: true + + /copy-webpack-plugin/10.2.4_webpack@5.69.0: + resolution: {integrity: sha512-xFVltahqlsRcyyJqQbDY6EYTtyQZF9rf+JPjwHObLdPFMEISqkFkr7mFoVOC6BfYS/dNThyoQKvziugm+OnwBg==} + engines: {node: '>= 12.20.0'} + peerDependencies: + webpack: ^5.1.0 dependencies: - browserslist: 4.18.1 + fast-glob: 3.2.7 + glob-parent: 6.0.2 + globby: 12.2.0 + normalize-path: 3.0.0 + schema-utils: 4.0.0 + serialize-javascript: 6.0.0 + webpack: 5.69.0_webpack-cli@4.9.1 + dev: true + + /core-js-compat/3.21.0: + resolution: {integrity: sha512-OSXseNPSK2OPJa6GdtkMz/XxeXx8/CJvfhQWTqd6neuUraujcL4jVsjkLQz1OWnax8xVQJnRPe0V2jqNWORA+A==} + dependencies: + browserslist: 4.19.1 semver: 7.0.0 dev: true @@ -3109,10 +5060,23 @@ packages: requiresBuild: true dev: true + /core-util-is/1.0.2: + resolution: {integrity: sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=} + dev: true + optional: true + /core-util-is/1.0.3: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} dev: true + /cors/2.8.5: + resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==} + engines: {node: '>= 0.10'} + dependencies: + object-assign: 4.1.1 + vary: 1.1.2 + dev: true + /cosmiconfig/7.0.1: resolution: {integrity: sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==} engines: {node: '>=10'} @@ -3124,36 +5088,91 @@ packages: yaml: 1.10.2 dev: true - /cross-spawn/7.0.3: - resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} - engines: {node: '>= 8'} - dependencies: - path-key: 3.1.1 - shebang-command: 2.0.0 - which: 2.0.2 + /crc-32/1.2.1: + resolution: {integrity: sha512-Dn/xm/1vFFgs3nfrpEVScHoIslO9NZRITWGz/1E/St6u4xw99vfZzVkW0OSnzx2h9egej9xwMCEut6sqwokM/w==} + engines: {node: '>=0.8'} + hasBin: true + dependencies: + exit-on-epipe: 1.0.1 + printj: 1.3.1 + dev: true + + /crc/3.8.0: + resolution: {integrity: sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==} + dependencies: + buffer: 5.7.1 + dev: true + + /crc32-stream/3.0.1: + resolution: {integrity: sha512-mctvpXlbzsvK+6z8kJwSJ5crm7yBwrQMTybJzMw1O4lLGJqjlDCXY2Zw7KheiA6XBEcBmfLx1D88mjRGVJtY9w==} + engines: {node: '>= 6.9.0'} + dependencies: + crc: 3.8.0 + readable-stream: 3.6.0 + dev: true + + /crc32-stream/4.0.2: + resolution: {integrity: sha512-DxFZ/Hk473b/muq1VJ///PMNLj0ZMnzye9thBpmjpJKCc5eMgB95aK8zCGrGfQ90cWo561Te6HK9D+j4KPdM6w==} + engines: {node: '>= 10'} + dependencies: + crc-32: 1.2.1 + readable-stream: 3.6.0 + dev: true + + /create-error-class/3.0.2: + resolution: {integrity: sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=} + engines: {node: '>=0.10.0'} + dependencies: + capture-stack-trace: 1.0.1 + dev: true + + /cross-spawn/5.1.0: + resolution: {integrity: sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=} + dependencies: + lru-cache: 4.1.5 + shebang-command: 1.2.0 + which: 1.3.1 + dev: true + + /cross-spawn/7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + dev: true + + /crossvent/1.5.4: + resolution: {integrity: sha1-2ixPj0DJR4JRe/K+7BBEFIGUq5I=} + dependencies: + custom-event: 1.0.0 + dev: true + + /crx/5.0.1: + resolution: {integrity: sha512-n/PzBx/fR1+xZCiJBats9y5zw/a+YBcoJ0ABnUaY56xb1RpXuFhsiCMpNY6WjVtylLzhUUXSWsbitesVg7v2vg==} + engines: {node: '>=10'} + hasBin: true + dependencies: + archiver: 3.1.1 + commander: 2.20.3 + node-rsa: 1.1.1 + pbf: 3.2.1 + dev: true + + /crypto-random-string/1.0.0: + resolution: {integrity: sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=} + engines: {node: '>=4'} + dev: true + + /crypto-random-string/2.0.0: + resolution: {integrity: sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==} + engines: {node: '>=8'} dev: true /css-color-keywords/1.0.0: resolution: {integrity: sha1-/qJhbcZ2spYmhrOvjb2+GAskTgU=} engines: {node: '>=4'} - dev: false - - /css-loader/6.5.1_webpack@5.64.2: - resolution: {integrity: sha512-gEy2w9AnJNnD9Kuo4XAP9VflW/ujKoS9c/syO+uWMlm5igc7LysKzPXaDoR2vroROkSwsTS2tGr1yGGEbZOYZQ==} - engines: {node: '>= 12.13.0'} - peerDependencies: - webpack: ^5.0.0 - dependencies: - icss-utils: 5.1.0_postcss@8.3.11 - postcss: 8.3.11 - postcss-modules-extract-imports: 3.0.0_postcss@8.3.11 - postcss-modules-local-by-default: 4.0.0_postcss@8.3.11 - postcss-modules-scope: 3.0.0_postcss@8.3.11 - postcss-modules-values: 4.0.0_postcss@8.3.11 - postcss-value-parser: 4.1.0 - semver: 7.3.5 - webpack: 5.64.2_webpack-cli@4.9.1 - dev: true /css-select/4.1.3: resolution: {integrity: sha512-gT3wBNd9Nj49rAbmtFHj1cljIAOLYSX1nZ8CB7TBO3INYckygm5B7LISU/szY//YmdiSLbJvDLOx9VnMVpMBxA==} @@ -3171,7 +5190,13 @@ packages: camelize: 1.0.0 css-color-keywords: 1.0.0 postcss-value-parser: 4.1.0 - dev: false + + /css-vendor/2.0.8: + resolution: {integrity: sha512-x9Aq0XTInxrkuFeHKbYC7zWY8ai7qJ04Kxd9MnvbC1uO5DagxoHQjm4JvG+vCdXOoFtCjbL2XSZfxmoYa9uQVQ==} + dependencies: + '@babel/runtime': 7.17.2 + is-in-browser: 1.1.3 + dev: true /css-what/5.1.0: resolution: {integrity: sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw==} @@ -3190,10 +5215,8 @@ packages: source-map-resolve: 0.6.0 dev: true - /cssesc/3.0.0: - resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} - engines: {node: '>=4'} - hasBin: true + /cssfilter/0.0.10: + resolution: {integrity: sha1-xtJnJjKi5cg+AT5oZKQs6N79IK4=} dev: true /cssom/0.3.8: @@ -3213,12 +5236,51 @@ packages: /csstype/3.0.10: resolution: {integrity: sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA==} + + /custom-event/1.0.0: + resolution: {integrity: sha1-LkYovhncSyFLXAJjDFlx6BFhgGI=} + dev: true + + /d3-state-visualizer/1.6.0: + resolution: {integrity: sha512-zlzh/BllmvMXkpIIV/OTF2Opb74MOW9ViMaDRFeMqDZ9WrwlWTgQiFpxpD3T6gDze3fJFbxbNZfbCTE7uTiUFA==} + dependencies: + '@babel/runtime': 7.17.2 + '@types/d3': 3.5.46 + d3: 3.5.17 + d3tooltip: 2.1.0_@types+d3@3.5.46+d3@3.5.17 + deepmerge: 4.2.2 + map2tree: 2.1.0 + ramda: 0.28.0 + dev: true + + /d3/3.5.17: + resolution: {integrity: sha1-vEZ0gAQ3iyGjYMn8fPUjF5B2L7g=} + dev: true + + /d3tooltip/2.1.0_@types+d3@3.5.46+d3@3.5.17: + resolution: {integrity: sha512-McomFzJ39RVyGTCKolazdmNG25AdykpdSbaEwyzFHEi4GZH7eZv8FxKwCpsN5/BaywvdsUtRa7eXCScISrJv9A==} + peerDependencies: + '@types/d3': ^3.5.46 + d3: ^3.5.17 + dependencies: + '@babel/runtime': 7.17.2 + '@types/d3': 3.5.46 + d3: 3.5.17 + ramda: 0.28.0 dev: true /damerau-levenshtein/1.0.7: resolution: {integrity: sha512-VvdQIPGdWP0SqFXghj79Wf/5LArmreyMsGLa6FG6iC4t3j7j5s71TrwWmT/4akbDQIqjfACkLZmjXhA7g2oUZw==} dev: true + /dashdash/1.14.1: + resolution: {integrity: sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=} + engines: {node: '>=0.10'} + dependencies: + assert-plus: 1.0.0 + dev: true + optional: true + /data-urls/2.0.0: resolution: {integrity: sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==} engines: {node: '>=10'} @@ -3228,14 +5290,37 @@ packages: whatwg-url: 8.7.0 dev: true + /date-fns/2.28.0: + resolution: {integrity: sha512-8d35hViGYx/QH0icHYCeLmsLmMUheMmTyV9Fcm6gvNwdw31yXXH+O85sOBJ+OLnLQMKZowvpKb6FgMIQjcpvQw==} + engines: {node: '>=0.11'} + dev: false + + /dateformat/3.0.3: + resolution: {integrity: sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==} + dev: true + + /dateformat/4.6.3: + resolution: {integrity: sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==} + dev: true + /debug/2.6.9: resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true dependencies: ms: 2.0.0 dev: true /debug/3.2.7: resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true dependencies: ms: 2.1.3 dev: true @@ -3252,8 +5337,20 @@ packages: ms: 2.1.2 dev: true - /debug/4.3.2_supports-color@5.5.0: - resolution: {integrity: sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==} + /debug/4.3.4: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.2 + dev: true + + /debug/4.3.4_supports-color@5.5.0: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} engines: {node: '>=6.0'} peerDependencies: supports-color: '*' @@ -3263,7 +5360,19 @@ packages: dependencies: ms: 2.1.2 supports-color: 5.5.0 - dev: false + + /decamelize-keys/1.1.0: + resolution: {integrity: sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=} + engines: {node: '>=0.10.0'} + dependencies: + decamelize: 1.2.0 + map-obj: 1.0.1 + dev: true + + /decamelize/1.2.0: + resolution: {integrity: sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=} + engines: {node: '>=0.10.0'} + dev: true /decimal.js/10.3.1: resolution: {integrity: sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==} @@ -3274,10 +5383,21 @@ packages: engines: {node: '>=0.10'} dev: true + /decompress-response/3.3.0: + resolution: {integrity: sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=} + engines: {node: '>=4'} + dependencies: + mimic-response: 1.0.1 + dev: true + /dedent/0.7.0: resolution: {integrity: sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=} dev: true + /deep-diff/0.3.8: + resolution: {integrity: sha512-yVn6RZmHiGnxRKR9sJb3iVV2XTF1Ghh2DiWRZ3dMnGc43yUdWWF/kX6lQyk3+P84iprfWKU/8zFTrlkvtFm1ug==} + dev: false + /deep-equal/1.1.1: resolution: {integrity: sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==} dependencies: @@ -3289,6 +5409,11 @@ packages: regexp.prototype.flags: 1.3.1 dev: true + /deep-extend/0.6.0: + resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} + engines: {node: '>=4.0.0'} + dev: true + /deep-is/0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} dev: true @@ -3305,6 +5430,10 @@ packages: execa: 5.1.1 dev: true + /defer-to-connect/1.1.3: + resolution: {integrity: sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==} + dev: true + /define-lazy-prop/2.0.0: resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==} engines: {node: '>=8'} @@ -3335,7 +5464,7 @@ packages: engines: {node: '>=10'} dependencies: globby: 11.0.4 - graceful-fs: 4.2.8 + graceful-fs: 4.2.9 is-glob: 4.0.3 is-path-cwd: 2.2.0 is-path-inside: 3.0.3 @@ -3349,15 +5478,34 @@ packages: engines: {node: '>=0.4.0'} dev: true + /delegates/1.0.0: + resolution: {integrity: sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=} + dev: true + /depd/1.1.2: resolution: {integrity: sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=} engines: {node: '>= 0.6'} dev: true + /depd/2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + dev: true + + /deprecation/2.3.1: + resolution: {integrity: sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==} + dev: true + /destroy/1.0.4: resolution: {integrity: sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=} dev: true + /detect-libc/1.0.3: + resolution: {integrity: sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=} + engines: {node: '>=0.10'} + hasBin: true + dev: true + /detect-newline/3.1.0: resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} engines: {node: '>=8'} @@ -3365,6 +5513,9 @@ packages: /detect-node/2.1.0: resolution: {integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==} + + /diff-match-patch/1.0.5: + resolution: {integrity: sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw==} dev: true /diff-sequences/27.0.6: @@ -3372,6 +5523,11 @@ packages: engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dev: true + /diff-sequences/27.5.1: + resolution: {integrity: sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + dev: true + /dir-glob/3.0.1: resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} engines: {node: '>=8'} @@ -3379,6 +5535,14 @@ packages: path-type: 4.0.0 dev: true + /dnd-core/16.0.1: + resolution: {integrity: sha512-HK294sl7tbw6F6IeuK16YSBUoorvHpY8RHO+9yFfaJyCDVb6n7PRcezrOEOa2SBCqiYpemh5Jx20ZcjKdFAVng==} + dependencies: + '@react-dnd/asap': 5.0.2 + '@react-dnd/invariant': 4.0.2 + redux: 4.2.0 + dev: false + /dns-equal/1.0.0: resolution: {integrity: sha1-s55/HabrCnW6nBcySzR1PEfgZU0=} dev: true @@ -3420,6 +5584,13 @@ packages: utila: 0.4.0 dev: true + /dom-helpers/5.2.1: + resolution: {integrity: sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==} + dependencies: + '@babel/runtime': 7.17.2 + csstype: 3.0.10 + dev: true + /dom-serializer/1.3.2: resolution: {integrity: sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==} dependencies: @@ -3458,7 +5629,61 @@ packages: resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==} dependencies: no-case: 3.0.4 - tslib: 2.3.1 + tslib: 2.4.1 + dev: true + + /dot-prop/4.2.1: + resolution: {integrity: sha512-l0p4+mIuJIua0mhxGoh4a+iNL9bmeK5DvnSVQa6T0OhrVmaEa1XScX5Etc673FePCJOArq/4Pa2cLGODUWTPOQ==} + engines: {node: '>=4'} + dependencies: + is-obj: 1.0.1 + dev: true + + /dot-prop/5.3.0: + resolution: {integrity: sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==} + engines: {node: '>=8'} + dependencies: + is-obj: 2.0.0 + dev: true + + /dragula/3.7.2: + resolution: {integrity: sha1-SjXJ05gf+sGpScKcpyhQWOhzk84=} + dependencies: + contra: 1.9.4 + crossvent: 1.5.4 + dev: true + + /duplexer2/0.1.4: + resolution: {integrity: sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=} + dependencies: + readable-stream: 2.3.7 + dev: true + + /duplexer3/0.1.4: + resolution: {integrity: sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=} + dev: true + + /duplexify/4.1.2: + resolution: {integrity: sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==} + dependencies: + end-of-stream: 1.4.4 + inherits: 2.0.4 + readable-stream: 3.6.0 + stream-shift: 1.0.1 + dev: false + + /ecc-jsbn/0.1.2: + resolution: {integrity: sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=} + dependencies: + jsbn: 0.1.1 + safer-buffer: 2.1.2 + dev: true + optional: true + + /ecdsa-sig-formatter/1.0.11: + resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==} + dependencies: + safe-buffer: 5.2.1 dev: true /ee-first/1.1.1: @@ -3469,6 +5694,36 @@ packages: resolution: {integrity: sha512-x5uZWXcVNYkTh4JubD7KSC1VMKz0vZwJUqVwY3ihsW0bst1BXDe494Uqbg3Y0fDGVjJqA8vEeGuvO5foyH2+qw==} dev: true + /electron-to-chromium/1.4.71: + resolution: {integrity: sha512-Hk61vXXKRb2cd3znPE9F+2pLWdIOmP7GjiTj45y6L3W/lO+hSnUSUhq+6lEaERWBdZOHbk2s3YV5c9xVl3boVw==} + dev: true + + /electron/11.5.0: + resolution: {integrity: sha512-WjNDd6lGpxyiNjE3LhnFCAk/D9GIj1rU3GSDealVShhkkkPR3Vh4q8ErXGDl1OAO/faomVa10KoFPUN/pLbNxg==} + engines: {node: '>= 8.6'} + hasBin: true + requiresBuild: true + dependencies: + '@electron/get': 1.13.1 + '@types/node': 12.20.46 + extract-zip: 1.7.0 + transitivePeerDependencies: + - supports-color + dev: true + + /electron/16.0.9: + resolution: {integrity: sha512-Kh2fc2g5Me0g8B1X2LMEDDtSNWsGGAmngh7adZpuJ8uI5TlR5GHDTcz37zwJid53S0BQ5d+Nz/NQ8s1DlKAAMA==} + engines: {node: '>= 8.6'} + hasBin: true + requiresBuild: true + dependencies: + '@electron/get': 1.13.1 + '@types/node': 14.18.12 + extract-zip: 1.7.0 + transitivePeerDependencies: + - supports-color + dev: true + /emittery/0.8.1: resolution: {integrity: sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg==} engines: {node: '>=10'} @@ -3492,25 +5747,45 @@ packages: engines: {node: '>= 0.8'} dev: true - /enhanced-resolve/5.8.3: - resolution: {integrity: sha512-EGAbGvH7j7Xt2nc0E7D99La1OiEs8LnyimkRgwExpUMScN6O+3x9tIWs7PLQZVNx4YD+00skHXPXi1yQHpAmZA==} + /end-of-stream/1.4.4: + resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} + dependencies: + once: 1.4.0 + + /enhanced-resolve/5.12.0: + resolution: {integrity: sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==} engines: {node: '>=10.13.0'} dependencies: - graceful-fs: 4.2.8 + graceful-fs: 4.2.9 tapable: 2.2.1 dev: true - /enquirer/2.3.6: - resolution: {integrity: sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==} - engines: {node: '>=8.6'} + /enhanced-resolve/5.9.0: + resolution: {integrity: sha512-weDYmzbBygL7HzGGS26M3hGQx68vehdEg6VUmqSOaFzXExFqlnKuSvsEJCVGQHScS8CQMbrAqftT+AzzHNt/YA==} + engines: {node: '>=10.13.0'} dependencies: - ansi-colors: 4.1.1 + graceful-fs: 4.2.9 + tapable: 2.2.1 dev: true /entities/2.2.0: resolution: {integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==} dev: true + /env-ci/5.5.0: + resolution: {integrity: sha512-o0JdWIbOLP+WJKIUt36hz1ImQQFuN92nhsfTkHHap+J8CiI8WgGpH/a9jEGHh4/TU5BUUGjlnKXNoDb57+ne+A==} + engines: {node: '>=10.17'} + dependencies: + execa: 5.1.1 + fromentries: 1.3.2 + java-properties: 1.0.2 + dev: true + + /env-paths/2.2.1: + resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} + engines: {node: '>=6'} + dev: true + /envinfo/7.8.1: resolution: {integrity: sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==} engines: {node: '>=4'} @@ -3568,6 +5843,25 @@ packages: is-symbol: 1.0.4 dev: true + /es6-error/4.1.1: + resolution: {integrity: sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==} + dev: true + optional: true + + /es6-template-regex/0.1.1: + resolution: {integrity: sha1-5Re54PdCvuuNMECDRUT9oORlFGc=} + engines: {node: '>=0.10.0'} + dev: true + + /es6template/1.0.5: + resolution: {integrity: sha1-O7u5efpriudlsMmGMQ9yAHJWKp8=} + dependencies: + es6-template-regex: 0.1.1 + extend-shallow: 2.0.1 + get-value: 2.0.6 + sliced: 1.0.1 + dev: true + /escalade/3.1.1: resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} engines: {node: '>=6'} @@ -3604,13 +5898,13 @@ packages: source-map: 0.6.1 dev: true - /eslint-config-prettier/8.3.0_eslint@8.3.0: + /eslint-config-prettier/8.3.0_eslint@8.9.0: resolution: {integrity: sha512-BgZuLUSeKzvlL/VUjx/Yb787VQ26RU3gGjA3iiFvdsp/2bMfVIWUVP7tjxtjS0e+HP409cPlPvNkQloz8C91ew==} hasBin: true peerDependencies: eslint: '>=7.0.0' dependencies: - eslint: 8.3.0 + eslint: 8.9.0 dev: true /eslint-import-resolver-node/0.3.6: @@ -3618,30 +5912,75 @@ packages: dependencies: debug: 3.2.7 resolve: 1.20.0 + transitivePeerDependencies: + - supports-color + dev: true + + /eslint-import-resolver-typescript/3.5.2_cmtdok55f7srt3k3ux6kqq5jcq: + resolution: {integrity: sha512-zX4ebnnyXiykjhcBvKIf5TNvt8K7yX6bllTRZ14MiurKPjDpCAZujlszTdB8pcNXhZcOf+god4s9SjQa5GnytQ==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + eslint: '*' + eslint-plugin-import: '*' + dependencies: + debug: 4.3.4 + enhanced-resolve: 5.12.0 + eslint: 8.9.0 + eslint-plugin-import: 2.25.4_oaka2ueiwurhrio2l3qatfl7wa + get-tsconfig: 4.2.0 + globby: 13.1.3 + is-core-module: 2.11.0 + is-glob: 4.0.3 + synckit: 0.8.4 + transitivePeerDependencies: + - supports-color dev: true - /eslint-module-utils/2.7.1: - resolution: {integrity: sha512-fjoetBXQZq2tSTWZ9yWVl2KuFrTZZH3V+9iD1V1RfpDgxzJR+mPd/KZmMiA8gbPqdBzpNiEHOuT7IYEWxrH0zQ==} + /eslint-module-utils/2.7.3_kju3ludv5s7iso6v32pghgvefq: + resolution: {integrity: sha512-088JEC7O3lDZM9xGe0RerkOMd0EjFl+Yvd1jPWIkMT5u3H9+HC34mWWPnqPrN13gieT9pBOO+Qt07Nb/6TresQ==} engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint-import-resolver-node: '*' + eslint-import-resolver-typescript: '*' + eslint-import-resolver-webpack: '*' + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + eslint-import-resolver-node: + optional: true + eslint-import-resolver-typescript: + optional: true + eslint-import-resolver-webpack: + optional: true dependencies: + '@typescript-eslint/parser': 5.12.0_fhzmdq77bspfhxkfuzq4fbrdsy debug: 3.2.7 + eslint-import-resolver-node: 0.3.6 + eslint-import-resolver-typescript: 3.5.2_cmtdok55f7srt3k3ux6kqq5jcq find-up: 2.1.0 - pkg-dir: 2.0.0 + transitivePeerDependencies: + - supports-color dev: true - /eslint-plugin-import/2.25.3_eslint@8.3.0: - resolution: {integrity: sha512-RzAVbby+72IB3iOEL8clzPLzL3wpDrlwjsTBAQXgyp5SeTqqY+0bFubwuo+y/HLhNZcXV4XqTBO4LGsfyHIDXg==} + /eslint-plugin-import/2.25.4_oaka2ueiwurhrio2l3qatfl7wa: + resolution: {integrity: sha512-/KJBASVFxpu0xg1kIBn9AUa8hQVnszpwgE7Ld0lKAlx7Ie87yzEzCgSkekt+le/YVhiaosO4Y14GDAOc41nfxA==} engines: {node: '>=4'} peerDependencies: + '@typescript-eslint/parser': '*' eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true dependencies: + '@typescript-eslint/parser': 5.12.0_fhzmdq77bspfhxkfuzq4fbrdsy array-includes: 3.1.4 array.prototype.flat: 1.2.5 debug: 2.6.9 doctrine: 2.1.0 - eslint: 8.3.0 + eslint: 8.9.0 eslint-import-resolver-node: 0.3.6 - eslint-module-utils: 2.7.1 + eslint-module-utils: 2.7.3_kju3ludv5s7iso6v32pghgvefq has: 1.0.3 is-core-module: 2.8.0 is-glob: 4.0.3 @@ -3649,9 +5988,13 @@ packages: object.values: 1.1.5 resolve: 1.20.0 tsconfig-paths: 3.12.0 + transitivePeerDependencies: + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color dev: true - /eslint-plugin-jsx-a11y/6.5.1_eslint@8.3.0: + /eslint-plugin-jsx-a11y/6.5.1_eslint@8.9.0: resolution: {integrity: sha512-sVCFKX9fllURnXT2JwLN5Qgo24Ug5NF6dxhkmxsMEUZhXRcGg+X3e1JbJ84YePQKBl5E0ZjAH5Q4rkdcGY99+g==} engines: {node: '>=4.0'} peerDependencies: @@ -3665,14 +6008,14 @@ packages: axobject-query: 2.2.0 damerau-levenshtein: 1.0.7 emoji-regex: 9.2.2 - eslint: 8.3.0 + eslint: 8.9.0 has: 1.0.3 jsx-ast-utils: 3.2.1 language-tags: 1.0.5 minimatch: 3.0.4 dev: true - /eslint-plugin-prettier/4.0.0_6c1acfc8d9d3a8dba99beef4e8bcebae: + /eslint-plugin-prettier/4.0.0_a62cezdlw5ot3n4rmiou7w6jsi: resolution: {integrity: sha512-98MqmCJ7vJodoQK359bqQWaxOE0CS8paAz/GgjaZLyex4TTk3g9HugoO89EqWCrFiOqn9EVvcoo7gZzONCWVwQ==} engines: {node: '>=6.0.0'} peerDependencies: @@ -3683,23 +6026,23 @@ packages: eslint-config-prettier: optional: true dependencies: - eslint: 8.3.0 - eslint-config-prettier: 8.3.0_eslint@8.3.0 - prettier: 2.4.1 + eslint: 8.9.0 + eslint-config-prettier: 8.3.0_eslint@8.9.0 + prettier: 2.5.1 prettier-linter-helpers: 1.0.0 dev: true - /eslint-plugin-react-hooks/4.3.0_eslint@8.3.0: + /eslint-plugin-react-hooks/4.3.0_eslint@8.9.0: resolution: {integrity: sha512-XslZy0LnMn+84NEG9jSGR6eGqaZB3133L8xewQo3fQagbQuGt7a63gf+P1NGKZavEYEC3UXaWEAA/AqDkuN6xA==} engines: {node: '>=10'} peerDependencies: eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 dependencies: - eslint: 8.3.0 + eslint: 8.9.0 dev: true - /eslint-plugin-react/7.27.1_eslint@8.3.0: - resolution: {integrity: sha512-meyunDjMMYeWr/4EBLTV1op3iSG3mjT/pz5gti38UzfM4OPpNc2m0t2xvKCOMU5D6FSdd34BIMFOvQbW+i8GAA==} + /eslint-plugin-react/7.28.0_eslint@8.9.0: + resolution: {integrity: sha512-IOlFIRHzWfEQQKcAD4iyYDndHwTQiCMcJVJjxempf203jnNLUnW34AXLrV33+nEXoifJE2ZEGmcjKPL8957eSw==} engines: {node: '>=4'} peerDependencies: eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 @@ -3707,7 +6050,7 @@ packages: array-includes: 3.1.4 array.prototype.flatmap: 1.2.5 doctrine: 2.1.0 - eslint: 8.3.0 + eslint: 8.9.0 estraverse: 5.3.0 jsx-ast-utils: 3.2.1 minimatch: 3.0.4 @@ -3729,21 +6072,21 @@ packages: estraverse: 4.3.0 dev: true - /eslint-scope/7.1.0: - resolution: {integrity: sha512-aWwkhnS0qAXqNOgKOK0dJ2nvzEbhEvpy8OlJ9kZ0FeZnA6zpjv1/Vei+puGFFX7zkPCkHHXb7IDX3A+7yPrRWg==} + /eslint-scope/7.1.1: + resolution: {integrity: sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: esrecurse: 4.3.0 estraverse: 5.3.0 dev: true - /eslint-utils/3.0.0_eslint@8.3.0: + /eslint-utils/3.0.0_eslint@8.9.0: resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==} engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0} peerDependencies: eslint: '>=5' dependencies: - eslint: 8.3.0 + eslint: 8.9.0 eslint-visitor-keys: 2.1.0 dev: true @@ -3752,29 +6095,28 @@ packages: engines: {node: '>=10'} dev: true - /eslint-visitor-keys/3.1.0: - resolution: {integrity: sha512-yWJFpu4DtjsWKkt5GeNBBuZMlNcYVs6vRCLoCVEJrTjaSB6LC98gFipNK/erM2Heg/E8mIK+hXG/pJMLK+eRZA==} + /eslint-visitor-keys/3.3.0: + resolution: {integrity: sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true - /eslint/8.3.0: - resolution: {integrity: sha512-aIay56Ph6RxOTC7xyr59Kt3ewX185SaGnAr8eWukoPLeriCrvGjvAubxuvaXOfsxhtwV5g0uBOsyhAom4qJdww==} + /eslint/8.9.0: + resolution: {integrity: sha512-PB09IGwv4F4b0/atrbcMFboF/giawbBLVC7fyDamk5Wtey4Jh2K+rYaBhCAbUyEI4QzB1ly09Uglc9iCtFaG2Q==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} hasBin: true dependencies: - '@eslint/eslintrc': 1.0.4 - '@humanwhocodes/config-array': 0.6.0 + '@eslint/eslintrc': 1.1.0 + '@humanwhocodes/config-array': 0.9.3 ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.3 debug: 4.3.2 doctrine: 3.0.0 - enquirer: 2.3.6 escape-string-regexp: 4.0.0 - eslint-scope: 7.1.0 - eslint-utils: 3.0.0_eslint@8.3.0 - eslint-visitor-keys: 3.1.0 - espree: 9.1.0 + eslint-scope: 7.1.1 + eslint-utils: 3.0.0_eslint@8.9.0 + eslint-visitor-keys: 3.3.0 + espree: 9.3.1 esquery: 1.4.0 esutils: 2.0.3 fast-deep-equal: 3.1.3 @@ -3782,7 +6124,7 @@ packages: functional-red-black-tree: 1.0.1 glob-parent: 6.0.2 globals: 13.12.0 - ignore: 4.0.6 + ignore: 5.2.0 import-fresh: 3.3.0 imurmurhash: 0.1.4 is-glob: 4.0.3 @@ -3793,9 +6135,7 @@ packages: minimatch: 3.0.4 natural-compare: 1.4.0 optionator: 0.9.1 - progress: 2.0.3 regexpp: 3.2.0 - semver: 7.3.5 strip-ansi: 6.0.1 strip-json-comments: 3.1.1 text-table: 0.2.0 @@ -3804,13 +6144,18 @@ packages: - supports-color dev: true - /espree/9.1.0: - resolution: {integrity: sha512-ZgYLvCS1wxOczBYGcQT9DDWgicXwJ4dbocr9uYN+/eresBAUuBu+O4WzB21ufQ/JqQT8gyp7hJ3z8SHii32mTQ==} + /esm/3.2.25: + resolution: {integrity: sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==} + engines: {node: '>=6'} + dev: true + + /espree/9.3.1: + resolution: {integrity: sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: - acorn: 8.6.0 - acorn-jsx: 5.3.2_acorn@8.6.0 - eslint-visitor-keys: 3.1.0 + acorn: 8.7.0 + acorn-jsx: 5.3.2_acorn@8.7.0 + eslint-visitor-keys: 3.3.0 dev: true /esprima/4.0.1: @@ -3862,6 +6207,19 @@ packages: engines: {node: '>=0.8.x'} dev: true + /execa/0.7.0: + resolution: {integrity: sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=} + engines: {node: '>=4'} + dependencies: + cross-spawn: 5.1.0 + get-stream: 3.0.0 + is-stream: 1.1.0 + npm-run-path: 2.0.2 + p-finally: 1.0.0 + signal-exit: 3.0.6 + strip-eof: 1.0.0 + dev: true + /execa/5.1.1: resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} engines: {node: '>=10'} @@ -3877,21 +6235,29 @@ packages: strip-final-newline: 2.0.0 dev: true + /exit-on-epipe/1.0.1: + resolution: {integrity: sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw==} + engines: {node: '>=0.8'} + dev: true + /exit/0.1.2: resolution: {integrity: sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=} engines: {node: '>= 0.8.0'} dev: true - /expect/27.3.1: - resolution: {integrity: sha512-MrNXV2sL9iDRebWPGOGFdPQRl2eDQNu/uhxIMShjjx74T6kC6jFIkmQ6OqXDtevjGUkyB2IT56RzDBqXf/QPCg==} + /expect/27.5.1: + resolution: {integrity: sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dependencies: - '@jest/types': 27.2.5 - ansi-styles: 5.2.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 + dev: true + + /expirymanager/0.9.4: + resolution: {integrity: sha512-bKcLuZPTs9mFxQ2VJPYJCMuGVAM9Ah6KfezbDA3IegbGeqR39WdPi+T7GgDGVuBPjYDFsSP/va5csiNVCGT1Mw==} + engines: {node: '>= 0.8.0'} dev: true /express/4.17.1: @@ -3928,16 +6294,105 @@ packages: type-is: 1.6.18 utils-merge: 1.0.1 vary: 1.1.2 + transitivePeerDependencies: + - supports-color + dev: true + + /express/4.17.2: + resolution: {integrity: sha512-oxlxJxcQlYwqPWKVJJtvQiwHgosH/LrLSPA+H4UxpyvSS6jC5aH+5MoHFM+KABgTOt0APue4w66Ha8jCUo9QGg==} + engines: {node: '>= 0.10.0'} + dependencies: + accepts: 1.3.7 + array-flatten: 1.1.1 + body-parser: 1.19.1 + content-disposition: 0.5.4 + content-type: 1.0.4 + cookie: 0.4.1 + cookie-signature: 1.0.6 + debug: 2.6.9 + depd: 1.1.2 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 1.1.2 + fresh: 0.5.2 + merge-descriptors: 1.0.1 + methods: 1.1.2 + on-finished: 2.3.0 + parseurl: 1.3.3 + path-to-regexp: 0.1.7 + proxy-addr: 2.0.7 + qs: 6.9.6 + range-parser: 1.2.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 + transitivePeerDependencies: + - supports-color + dev: true + + /extend-shallow/2.0.1: + resolution: {integrity: sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=} + engines: {node: '>=0.10.0'} + dependencies: + is-extendable: 0.1.1 + dev: true + + /extend/3.0.2: + resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} + dev: true + optional: true + + /external-editor/2.2.0: + resolution: {integrity: sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==} + engines: {node: '>=0.12'} + dependencies: + chardet: 0.4.2 + iconv-lite: 0.4.24 + tmp: 0.0.33 + dev: true + + /extract-zip/1.7.0: + resolution: {integrity: sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA==} + hasBin: true + dependencies: + concat-stream: 1.6.2 + debug: 2.6.9 + mkdirp: 0.5.5 + yauzl: 2.10.0 + transitivePeerDependencies: + - supports-color dev: true + /extsprintf/1.3.0: + resolution: {integrity: sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=} + engines: {'0': node >=0.6.0} + dev: true + optional: true + /fast-deep-equal/3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - dev: true /fast-diff/1.2.0: resolution: {integrity: sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==} dev: true + /fast-glob/3.2.12: + resolution: {integrity: sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==} + engines: {node: '>=8.6.0'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.4 + dev: true + /fast-glob/3.2.7: resolution: {integrity: sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==} engines: {node: '>=8'} @@ -3957,6 +6412,11 @@ packages: resolution: {integrity: sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=} dev: true + /fast-redact/3.1.1: + resolution: {integrity: sha512-odVmjC8x8jNeMZ3C+rPMESzXVSEU8tSWSHv9HFxP2mm89G/1WwqhrerJDQm9Zus8X6aoRgQDThKqptdNA6bt+A==} + engines: {node: '>=6'} + dev: false + /fastest-levenshtein/1.0.12: resolution: {integrity: sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==} dev: true @@ -3980,6 +6440,26 @@ packages: bser: 2.1.1 dev: true + /fd-slicer/1.1.0: + resolution: {integrity: sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=} + dependencies: + pend: 1.2.0 + dev: true + + /figures/2.0.0: + resolution: {integrity: sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=} + engines: {node: '>=4'} + dependencies: + escape-string-regexp: 1.0.5 + dev: true + + /figures/3.2.0: + resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==} + engines: {node: '>=8'} + dependencies: + escape-string-regexp: 1.0.5 + dev: true + /file-entry-cache/6.0.1: resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} engines: {node: ^10.12.0 || >=12.0.0} @@ -3987,7 +6467,7 @@ packages: flat-cache: 3.0.4 dev: true - /file-loader/6.2.0_webpack@5.64.2: + /file-loader/6.2.0_webpack@5.69.0: resolution: {integrity: sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==} engines: {node: '>= 10.13.0'} peerDependencies: @@ -3995,7 +6475,7 @@ packages: dependencies: loader-utils: 2.0.2 schema-utils: 3.1.1 - webpack: 5.64.2_webpack-cli@4.9.1 + webpack: 5.69.0_webpack-cli@4.9.1 dev: true /fill-range/7.0.1: @@ -4016,6 +6496,8 @@ packages: parseurl: 1.3.3 statuses: 1.5.0 unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color dev: true /find-cache-dir/3.3.2: @@ -4050,6 +6532,13 @@ packages: path-exists: 4.0.0 dev: true + /find-versions/4.0.0: + resolution: {integrity: sha512-wgpWy002tA+wgmO27buH/9KzyEOQnKsG/R0yrcjPT9BOFm0zRBVQbZ95nRGXWMywS8YR5knRbpohio0bcJABxQ==} + engines: {node: '>=10'} + dependencies: + semver-regex: 3.1.3 + dev: true + /flat-cache/3.0.4: resolution: {integrity: sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==} engines: {node: ^10.12.0 || >=12.0.0} @@ -4062,6 +6551,11 @@ packages: resolution: {integrity: sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw==} dev: true + /fleximap/1.0.0: + resolution: {integrity: sha512-zg/PthjBzESYKomTw/wivo8Id6B+obVkWriIzDuRfuw4wxEIV2/0D/NIGf+LKcGTTifHRfw73+oAAQozZ9MAhA==} + engines: {node: '>= 0.8.0'} + dev: true + /follow-redirects/1.14.5: resolution: {integrity: sha512-wtphSXy7d4/OR+MvIFbCVBDzZ5520qV8XfPklSN5QtxuMUJZ+b0Wnst1e1lCDocfzuCkHqj8k0FpZqO+UIaKNA==} engines: {node: '>=4.0'} @@ -4072,6 +6566,21 @@ packages: optional: true dev: true + /forever-agent/0.6.1: + resolution: {integrity: sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=} + dev: true + optional: true + + /form-data/2.3.3: + resolution: {integrity: sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==} + engines: {node: '>= 0.12'} + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.34 + dev: true + optional: true + /form-data/3.0.1: resolution: {integrity: sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==} engines: {node: '>= 6'} @@ -4091,6 +6600,63 @@ packages: engines: {node: '>= 0.6'} dev: true + /from2/2.3.0: + resolution: {integrity: sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=} + dependencies: + inherits: 2.0.4 + readable-stream: 2.3.7 + dev: true + + /fromentries/1.3.2: + resolution: {integrity: sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==} + dev: true + + /fs-constants/1.0.0: + resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} + dev: true + + /fs-extra/10.0.0: + resolution: {integrity: sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==} + engines: {node: '>=12'} + dependencies: + graceful-fs: 4.2.9 + jsonfile: 6.1.0 + universalify: 2.0.0 + dev: true + + /fs-extra/6.0.1: + resolution: {integrity: sha512-GnyIkKhhzXZUWFCaJzvyDLEEgDkPfb4/TPvJCJVuS8MWZgoSsErf++QpiAlDnKFcqhRlm+tIOcencCjyJE6ZCA==} + dependencies: + graceful-fs: 4.2.9 + jsonfile: 4.0.0 + universalify: 0.1.2 + dev: true + + /fs-extra/8.1.0: + resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} + engines: {node: '>=6 <7 || >=8'} + dependencies: + graceful-fs: 4.2.9 + jsonfile: 4.0.0 + universalify: 0.1.2 + dev: true + + /fs-extra/9.1.0: + resolution: {integrity: sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==} + engines: {node: '>=10'} + dependencies: + at-least-node: 1.0.0 + graceful-fs: 4.2.9 + jsonfile: 6.1.0 + universalify: 2.0.0 + dev: true + + /fs-minipass/1.2.7: + resolution: {integrity: sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==} + dependencies: + minipass: 2.9.0 + dev: true + /fs-monkey/1.0.3: resolution: {integrity: sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q==} dev: true @@ -4101,7 +6667,6 @@ packages: /fs.realpath/1.0.0: resolution: {integrity: sha1-FQStJSMVjKpA20onh8sBQRmU6k8=} - dev: true /fsevents/2.3.2: resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} @@ -4111,6 +6676,17 @@ packages: dev: true optional: true + /fstream/1.0.12: + resolution: {integrity: sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==} + engines: {node: '>=0.6'} + dependencies: + graceful-fs: 4.2.9 + inherits: 2.0.4 + mkdirp: 0.5.5 + rimraf: 2.7.1 + dev: true + optional: true + /function-bind/1.1.1: resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} dev: true @@ -4119,6 +6695,19 @@ packages: resolution: {integrity: sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=} dev: true + /gauge/2.7.4: + resolution: {integrity: sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=} + dependencies: + aproba: 1.2.0 + console-control-strings: 1.1.0 + has-unicode: 2.0.1 + object-assign: 4.1.1 + signal-exit: 3.0.6 + string-width: 1.0.2 + strip-ansi: 3.0.1 + wide-align: 1.1.5 + dev: true + /gensync/1.0.0-beta.2: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} @@ -4142,6 +6731,29 @@ packages: engines: {node: '>=8.0.0'} dev: true + /get-params/0.1.2: + resolution: {integrity: sha1-uuDfq6WIoMYNeDTA2Nwv9g7u8v4=} + dev: true + + /get-stream/3.0.0: + resolution: {integrity: sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=} + engines: {node: '>=4'} + dev: true + + /get-stream/4.1.0: + resolution: {integrity: sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==} + engines: {node: '>=6'} + dependencies: + pump: 3.0.0 + dev: true + + /get-stream/5.2.0: + resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} + engines: {node: '>=8'} + dependencies: + pump: 3.0.0 + dev: true + /get-stream/6.0.1: resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} engines: {node: '>=10'} @@ -4155,6 +6767,41 @@ packages: get-intrinsic: 1.1.1 dev: true + /get-tsconfig/4.2.0: + resolution: {integrity: sha512-X8u8fREiYOE6S8hLbq99PeykTDoLVnxvF4DjWKJmz9xy2nNRdUcV8ZN9tniJFeKyTU3qnC9lL8n4Chd6LmVKHg==} + dev: true + + /get-value/2.0.6: + resolution: {integrity: sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=} + engines: {node: '>=0.10.0'} + dev: true + + /getopts/2.2.5: + resolution: {integrity: sha512-9jb7AW5p3in+IiJWhQiZmmwkpLaR/ccTWdWQCtZM66HJcHHLegowh4q4tSD7gouUyeNvFWRavfK9GXosQHDpFA==} + dev: true + + /getpass/0.1.7: + resolution: {integrity: sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=} + dependencies: + assert-plus: 1.0.0 + dev: true + optional: true + + /getport/0.1.0: + resolution: {integrity: sha1-q93z1dHnfdlnzPorA2oKH7Jv1/c=} + dev: true + + /git-log-parser/1.2.0: + resolution: {integrity: sha1-LmpMGxP8AAKCB7p5WnrDFme5/Uo=} + dependencies: + argv-formatter: 1.0.0 + spawn-error-forwarder: 1.0.0 + split2: 1.0.0 + stream-combiner2: 1.1.1 + through2: 2.0.5 + traverse: 0.6.6 + dev: true + /glob-parent/5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} @@ -4182,7 +6829,39 @@ packages: minimatch: 3.0.4 once: 1.4.0 path-is-absolute: 1.0.1 + + /global-agent/3.0.0: + resolution: {integrity: sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==} + engines: {node: '>=10.0'} + requiresBuild: true + dependencies: + boolean: 3.2.0 + es6-error: 4.1.1 + matcher: 3.0.0 + roarr: 2.15.4 + semver: 7.3.5 + serialize-error: 7.0.1 + dev: true + optional: true + + /global-dirs/0.1.1: + resolution: {integrity: sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=} + engines: {node: '>=4'} + dependencies: + ini: 1.3.8 + dev: true + + /global-tunnel-ng/2.7.1: + resolution: {integrity: sha512-4s+DyciWBV0eK148wqXxcmVAbFVPqtc3sEtUE/GTQfuU80rySLcMhUmHKSHI7/LDj8q0gDYI1lIhRRB7ieRAqg==} + engines: {node: '>=0.10'} + requiresBuild: true + dependencies: + encodeurl: 1.0.2 + lodash: 4.17.21 + npm-conf: 1.1.3 + tunnel: 0.0.6 dev: true + optional: true /globals/11.12.0: resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} @@ -4195,6 +6874,18 @@ packages: type-fest: 0.20.2 dev: true + /globalthis/1.0.2: + resolution: {integrity: sha512-ZQnSFO1la8P7auIOQECnm0sSuoMeaSq0EEdXMBFF2QJO4uNcwbyhSgG3MruWNbFTqCLmxVwGOl7LZ9kASvHdeQ==} + engines: {node: '>= 0.4'} + dependencies: + define-properties: 1.1.3 + dev: true + optional: true + + /globalyzer/0.1.0: + resolution: {integrity: sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==} + dev: true + /globby/11.0.4: resolution: {integrity: sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==} engines: {node: '>=10'} @@ -4202,11 +6893,34 @@ packages: array-union: 2.1.0 dir-glob: 3.0.1 fast-glob: 3.2.7 - ignore: 5.1.9 + ignore: 5.2.0 merge2: 1.4.1 slash: 3.0.0 dev: true + /globby/12.2.0: + resolution: {integrity: sha512-wiSuFQLZ+urS9x2gGPl1H5drc5twabmm4m2gTR27XDFyjUHJUNsS8o/2aKyIF6IoBaR630atdher0XJ5g6OMmA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + array-union: 3.0.1 + dir-glob: 3.0.1 + fast-glob: 3.2.7 + ignore: 5.2.0 + merge2: 1.4.1 + slash: 4.0.0 + dev: true + + /globby/13.1.3: + resolution: {integrity: sha512-8krCNHXvlCgHDpegPzleMq07yMYTO2sXKASmZmquEYWEmCx6J5UTRbp5RwMJkTJGtcQ44YpiUYUiN0b9mzy8Bw==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + dir-glob: 3.0.1 + fast-glob: 3.2.12 + ignore: 5.2.0 + merge2: 1.4.1 + slash: 4.0.0 + dev: true + /globby/6.1.0: resolution: {integrity: sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=} engines: {node: '>=0.10.0'} @@ -4218,14 +6932,105 @@ packages: pinkie-promise: 2.0.1 dev: true - /graceful-fs/4.2.8: - resolution: {integrity: sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==} + /globrex/0.1.2: + resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==} + dev: true + + /got/6.7.1: + resolution: {integrity: sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=} + engines: {node: '>=4'} + dependencies: + '@types/keyv': 3.1.4 + '@types/responselike': 1.0.0 + create-error-class: 3.0.2 + duplexer3: 0.1.4 + get-stream: 3.0.0 + is-redirect: 1.0.0 + is-retry-allowed: 1.2.0 + is-stream: 1.1.0 + lowercase-keys: 1.0.1 + safe-buffer: 5.2.1 + timed-out: 4.0.1 + unzip-response: 2.0.1 + url-parse-lax: 1.0.0 + dev: true + + /got/9.6.0: + resolution: {integrity: sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==} + engines: {node: '>=8.6'} + dependencies: + '@sindresorhus/is': 0.14.0 + '@szmarczak/http-timer': 1.1.2 + '@types/keyv': 3.1.4 + '@types/responselike': 1.0.0 + cacheable-request: 6.1.0 + decompress-response: 3.3.0 + duplexer3: 0.1.4 + get-stream: 4.1.0 + lowercase-keys: 1.0.1 + mimic-response: 1.0.1 + p-cancelable: 1.1.0 + to-readable-stream: 1.0.0 + url-parse-lax: 3.0.0 + dev: true + + /graceful-fs/4.2.9: + resolution: {integrity: sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==} + dev: true + + /graphql-tag/2.12.6_graphql@16.3.0: + resolution: {integrity: sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg==} + engines: {node: '>=10'} + peerDependencies: + graphql: ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + graphql: 16.3.0 + tslib: 2.4.1 + dev: true + + /graphql/16.3.0: + resolution: {integrity: sha512-xm+ANmA16BzCT5pLjuXySbQVFwH3oJctUVdy81w1sV0vBU0KgDdBGtxQOUd5zqOBk/JayAFeG8Dlmeq74rjm/A==} + engines: {node: ^12.22.0 || ^14.16.0 || >=16.0.0} dev: true /handle-thing/2.0.1: resolution: {integrity: sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==} dev: true + /handlebars/4.7.7: + resolution: {integrity: sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==} + engines: {node: '>=0.4.7'} + hasBin: true + dependencies: + minimist: 1.2.5 + neo-async: 2.6.2 + source-map: 0.6.1 + wordwrap: 1.0.0 + optionalDependencies: + uglify-js: 3.15.1 + dev: true + + /har-schema/2.0.0: + resolution: {integrity: sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=} + engines: {node: '>=4'} + dev: true + optional: true + + /har-validator/5.1.5: + resolution: {integrity: sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==} + engines: {node: '>=6'} + deprecated: this library is no longer supported + dependencies: + ajv: 6.12.6 + har-schema: 2.0.0 + dev: true + optional: true + + /hard-rejection/2.1.0: + resolution: {integrity: sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==} + engines: {node: '>=6'} + dev: true + /has-bigints/1.0.1: resolution: {integrity: sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==} dev: true @@ -4251,6 +7056,10 @@ packages: has-symbols: 1.0.2 dev: true + /has-unicode/2.0.1: + resolution: {integrity: sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=} + dev: true + /has/1.0.3: resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} engines: {node: '>= 0.4.0'} @@ -4263,11 +7072,31 @@ packages: hasBin: true dev: true + /hex-rgba/1.0.2: + resolution: {integrity: sha512-MKla68wFGv+i7zU3Q4giWN74f+zWdkuf2Tk21fISV7aw55r8dH/noBbH5JsVlM4Z2WRTYCEmSxsoZ1QR/o68jg==} + dev: true + /hoist-non-react-statics/3.3.2: resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} dependencies: react-is: 16.13.1 + /hook-std/2.0.0: + resolution: {integrity: sha512-zZ6T5WcuBMIUVh49iPQS9t977t7C0l7OtHrpeMb5uk48JdflRX0NSFvCekfYNmGQETnLq9W/isMyHl69kxGi8g==} + engines: {node: '>=8'} + dev: true + + /hosted-git-info/2.8.9: + resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} + dev: true + + /hosted-git-info/4.1.0: + resolution: {integrity: sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==} + engines: {node: '>=10'} + dependencies: + lru-cache: 6.0.0 + dev: true + /hpack.js/2.1.6: resolution: {integrity: sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=} dependencies: @@ -4304,11 +7133,9 @@ packages: param-case: 3.0.4 relateurl: 0.2.7 terser: 5.10.0 - transitivePeerDependencies: - - acorn dev: true - /html-webpack-plugin/5.5.0_webpack@5.64.2: + /html-webpack-plugin/5.5.0_webpack@5.69.0: resolution: {integrity: sha512-sy88PC2cRTVxvETRgUHFrL4No3UxvcH8G1NepGhqaTT+GXN2kTamqasot0inS5hXeg1cMbFDt27zzo9p35lZVw==} engines: {node: '>=10.13.0'} peerDependencies: @@ -4319,9 +7146,7 @@ packages: lodash: 4.17.21 pretty-error: 4.0.0 tapable: 2.2.1 - webpack: 5.64.2_webpack-cli@4.9.1 - transitivePeerDependencies: - - acorn + webpack: 5.69.0_webpack-cli@4.9.1 dev: true /htmlparser2/6.1.0: @@ -4333,6 +7158,10 @@ packages: entities: 2.2.0 dev: true + /http-cache-semantics/4.1.0: + resolution: {integrity: sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==} + dev: true + /http-deceiver/1.2.7: resolution: {integrity: sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=} dev: true @@ -4369,6 +7198,17 @@ packages: toidentifier: 1.0.0 dev: true + /http-errors/1.8.1: + resolution: {integrity: sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==} + engines: {node: '>= 0.6'} + dependencies: + depd: 1.1.2 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 1.5.0 + toidentifier: 1.0.1 + dev: true + /http-parser-js/0.5.3: resolution: {integrity: sha512-t7hjvef/5HEK7RWTdUzVUhl8zkEu+LlaE0IYzdMuvbSDipxBRpOn4Uhw8ZyECEa808iVT8XCjzo6xmYt4CiLZg==} dev: true @@ -4379,7 +7219,18 @@ packages: dependencies: '@tootallnate/once': 1.1.2 agent-base: 6.0.2 - debug: 4.3.2 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: true + + /http-proxy-agent/5.0.0: + resolution: {integrity: sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==} + engines: {node: '>= 6'} + dependencies: + '@tootallnate/once': 2.0.0 + agent-base: 6.0.2 + debug: 4.3.4 transitivePeerDependencies: - supports-color dev: true @@ -4408,12 +7259,22 @@ packages: - debug dev: true + /http-signature/1.2.0: + resolution: {integrity: sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=} + engines: {node: '>=0.8', npm: '>=1.3.7'} + dependencies: + assert-plus: 1.0.0 + jsprim: 1.4.2 + sshpk: 1.17.0 + dev: true + optional: true + /https-proxy-agent/5.0.0: resolution: {integrity: sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==} engines: {node: '>= 6'} dependencies: agent-base: 6.0.2 - debug: 4.3.2 + debug: 4.3.4 transitivePeerDependencies: - supports-color dev: true @@ -4423,6 +7284,10 @@ packages: engines: {node: '>=10.17.0'} dev: true + /hyphenate-style-name/1.0.4: + resolution: {integrity: sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ==} + dev: true + /iconv-lite/0.4.24: resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} engines: {node: '>=0.10.0'} @@ -4430,13 +7295,14 @@ packages: safer-buffer: 2.1.2 dev: true - /icss-utils/5.1.0_postcss@8.3.11: - resolution: {integrity: sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==} - engines: {node: ^10 || ^12 || >= 14} - peerDependencies: - postcss: ^8.1.0 + /ieee754/1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + dev: true + + /ignore-walk/3.0.4: + resolution: {integrity: sha512-PY6Ii8o1jMRA1z4F2hRkH/xN59ox43DavKvD3oDpfurRlOJyAHpifIwpbdv1n4jt4ov0jSpw3kQ4GhJnpBL6WQ==} dependencies: - postcss: 8.3.11 + minimatch: 3.0.4 dev: true /ignore/4.0.6: @@ -4444,11 +7310,21 @@ packages: engines: {node: '>= 4'} dev: true - /ignore/5.1.9: - resolution: {integrity: sha512-2zeMQpbKz5dhZ9IwL0gbxSW5w0NK/MSAMtNuhgIHEPmaU3vPdKPL0UdvUCXs5SS4JAwsBxysK5sFMW8ocFiVjQ==} + /ignore/5.2.0: + resolution: {integrity: sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==} engines: {node: '>= 4'} dev: true + /immediate/3.0.6: + resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==} + + /immer/9.0.12: + resolution: {integrity: sha512-lk7UNmSbAukB5B6dh9fnh5D0bJTOFKxVg2cyJWTYrWRfhLrLMBquONcUs3aFq507hNoIZEDDh8lb8UtOizSMhA==} + + /immutable/4.0.0: + resolution: {integrity: sha512-zIE9hX70qew5qTUjSS7wi1iwj/l7+m54KWU247nhM3v806UdGj1yDndXj+IOYxxtW9zyLI+xqFNZjTuDaLUqFw==} + dev: true + /import-fresh/3.3.0: resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} engines: {node: '>=6'} @@ -4457,6 +7333,16 @@ packages: resolve-from: 4.0.0 dev: true + /import-from/4.0.0: + resolution: {integrity: sha512-P9J71vT5nLlDeV8FHs5nNxaLbrpfAV5cF5srvbZfpwpcJoM/xZR3hiv+q+SAnuSmuGbXMWud063iIMx/V/EWZQ==} + engines: {node: '>=12.2'} + dev: true + + /import-lazy/2.1.0: + resolution: {integrity: sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=} + engines: {node: '>=4'} + dev: true + /import-local/3.0.3: resolution: {integrity: sha512-bE9iaUY3CXH8Cwfan/abDKAxe1KGT9kyGsBPqf6DMK/z0a2OzAsrukeYNgIH6cH5Xr452jb1TUL8rSfCLjZ9uA==} engines: {node: '>=8'} @@ -4481,7 +7367,6 @@ packages: dependencies: once: 1.4.0 wrappy: 1.0.2 - dev: true /inherits/2.0.3: resolution: {integrity: sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=} @@ -4489,16 +7374,28 @@ packages: /inherits/2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + /ini/1.3.8: + resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} dev: true - /internal-ip/6.2.0: - resolution: {integrity: sha512-D8WGsR6yDt8uq7vDMu7mjcR+yRMm3dW8yufyChmszWRjcSHuxLBkR3GdS2HZAjodsaGuCvXeEJpueisXJULghg==} - engines: {node: '>=10'} + /inquirer/5.2.0: + resolution: {integrity: sha512-E9BmnJbAKLPGonz0HeWHtbKf+EeSP93paWO3ZYoUpq/aowXvYGjjCSuashhXPpzbArIjBbji39THkxTz9ZeEUQ==} + engines: {node: '>=6.0.0'} dependencies: - default-gateway: 6.0.3 - ipaddr.js: 1.9.1 - is-ip: 3.1.0 - p-event: 4.2.0 + ansi-escapes: 3.2.0 + chalk: 2.4.2 + cli-cursor: 2.1.0 + cli-width: 2.2.1 + external-editor: 2.2.0 + figures: 2.0.0 + lodash: 4.17.21 + mute-stream: 0.0.7 + run-async: 2.4.1 + rxjs: 5.5.12 + string-width: 2.1.1 + strip-ansi: 4.0.0 + through: 2.3.8 dev: true /internal-slot/1.0.3: @@ -4515,9 +7412,12 @@ packages: engines: {node: '>= 0.10'} dev: true - /ip-regex/4.3.0: - resolution: {integrity: sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q==} - engines: {node: '>=8'} + /into-stream/6.0.0: + resolution: {integrity: sha512-XHbaOAvP+uFKUFsOgoNPRjLkwB+I22JFPFe5OjTkQ0nwgj6+pSjb4NmB6VMxaPshLiOf+zcpOCBQuLwC1KHhZA==} + engines: {node: '>=10'} + dependencies: + from2: 2.3.0 + p-is-promise: 3.0.0 dev: true /ip/1.1.5: @@ -4546,6 +7446,10 @@ packages: resolution: {integrity: sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=} dev: true + /is-arrayish/0.3.2: + resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} + dev: true + /is-bigint/1.0.4: resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} dependencies: @@ -4572,6 +7476,19 @@ packages: engines: {node: '>= 0.4'} dev: true + /is-ci/1.2.1: + resolution: {integrity: sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==} + hasBin: true + dependencies: + ci-info: 1.6.0 + dev: true + + /is-core-module/2.11.0: + resolution: {integrity: sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==} + dependencies: + has: 1.0.3 + dev: true + /is-core-module/2.8.0: resolution: {integrity: sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw==} dependencies: @@ -4591,9 +7508,26 @@ packages: hasBin: true dev: true + /is-extendable/0.1.1: + resolution: {integrity: sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=} + engines: {node: '>=0.10.0'} + dev: true + /is-extglob/2.1.1: - resolution: {integrity: sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=} + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + dev: true + + /is-fullwidth-code-point/1.0.0: + resolution: {integrity: sha1-754xOG8DGn8NZDr4L95QxFfvAMs=} engines: {node: '>=0.10.0'} + dependencies: + number-is-nan: 1.0.1 + dev: true + + /is-fullwidth-code-point/2.0.0: + resolution: {integrity: sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=} + engines: {node: '>=4'} dev: true /is-fullwidth-code-point/3.0.0: @@ -4613,11 +7547,16 @@ packages: is-extglob: 2.1.1 dev: true - /is-ip/3.1.0: - resolution: {integrity: sha512-35vd5necO7IitFPjd/YBeqwWnyDWbuLH9ZXQdMfDA8TEo7pv5X8yfrvVO3xbJbLUlERCMvf6X0hTUamQxCYJ9Q==} - engines: {node: '>=8'} + /is-in-browser/1.1.3: + resolution: {integrity: sha1-Vv9NtoOgeMYILrldrX3GLh0E+DU=} + dev: true + + /is-installed-globally/0.1.0: + resolution: {integrity: sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA=} + engines: {node: '>=4'} dependencies: - ip-regex: 4.3.0 + global-dirs: 0.1.1 + is-path-inside: 1.0.1 dev: true /is-negative-zero/2.0.1: @@ -4625,6 +7564,11 @@ packages: engines: {node: '>= 0.4'} dev: true + /is-npm/1.0.0: + resolution: {integrity: sha1-8vtjpl5JBbQGyGBydloaTceTufQ=} + engines: {node: '>=0.10.0'} + dev: true + /is-number-object/1.0.6: resolution: {integrity: sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==} engines: {node: '>= 0.4'} @@ -4637,6 +7581,16 @@ packages: engines: {node: '>=0.12.0'} dev: true + /is-obj/1.0.1: + resolution: {integrity: sha1-PkcprB9f3gJc19g6iW2rn09n2w8=} + engines: {node: '>=0.10.0'} + dev: true + + /is-obj/2.0.0: + resolution: {integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==} + engines: {node: '>=8'} + dev: true + /is-path-cwd/2.2.0: resolution: {integrity: sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==} engines: {node: '>=6'} @@ -4649,6 +7603,13 @@ packages: is-path-inside: 2.1.0 dev: true + /is-path-inside/1.0.1: + resolution: {integrity: sha1-jvW33lBDej/cprToZe96pVy0gDY=} + engines: {node: '>=0.10.0'} + dependencies: + path-is-inside: 1.0.2 + dev: true + /is-path-inside/2.1.0: resolution: {integrity: sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==} engines: {node: '>=6'} @@ -4661,6 +7622,11 @@ packages: engines: {node: '>=8'} dev: true + /is-plain-obj/1.1.0: + resolution: {integrity: sha1-caUMhCnfync8kqOQpKA7OfzVHT4=} + engines: {node: '>=0.10.0'} + dev: true + /is-plain-obj/3.0.0: resolution: {integrity: sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==} engines: {node: '>=10'} @@ -4673,10 +7639,20 @@ packages: isobject: 3.0.1 dev: true + /is-plain-object/5.0.0: + resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==} + engines: {node: '>=0.10.0'} + dev: true + /is-potential-custom-element-name/1.0.1: resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} dev: true + /is-redirect/1.0.0: + resolution: {integrity: sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=} + engines: {node: '>=0.10.0'} + dev: true + /is-regex/1.1.4: resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} engines: {node: '>= 0.4'} @@ -4685,10 +7661,20 @@ packages: has-tostringtag: 1.0.0 dev: true + /is-retry-allowed/1.2.0: + resolution: {integrity: sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==} + engines: {node: '>=0.10.0'} + dev: true + /is-shared-array-buffer/1.0.1: resolution: {integrity: sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA==} dev: true + /is-stream/1.1.0: + resolution: {integrity: sha1-EtSj3U5o4Lec6428hBc66A2RykQ=} + engines: {node: '>=0.10.0'} + dev: true + /is-stream/2.0.1: resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} engines: {node: '>=8'} @@ -4708,6 +7694,13 @@ packages: has-symbols: 1.0.2 dev: true + /is-text-path/1.0.1: + resolution: {integrity: sha1-Thqg+1G/vLPpJogAE5cgLBd1tm4=} + engines: {node: '>=0.10.0'} + dependencies: + text-extensions: 1.9.0 + dev: true + /is-typedarray/1.0.0: resolution: {integrity: sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=} dev: true @@ -4738,29 +7731,33 @@ packages: engines: {node: '>=0.10.0'} dev: true - /istanbul-lib-coverage/3.2.0: - resolution: {integrity: sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==} - engines: {node: '>=8'} + /isstream/0.1.2: + resolution: {integrity: sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=} dev: true + optional: true - /istanbul-lib-instrument/4.0.3: - resolution: {integrity: sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==} - engines: {node: '>=8'} + /issue-parser/6.0.0: + resolution: {integrity: sha512-zKa/Dxq2lGsBIXQ7CUZWTHfvxPC2ej0KfO7fIPqLlHB9J2hJ7rGhZ5rilhuufylr4RXYPzJUeFjKxz305OsNlA==} + engines: {node: '>=10.13'} dependencies: - '@babel/core': 7.16.0 - '@istanbuljs/schema': 0.1.3 - istanbul-lib-coverage: 3.2.0 - semver: 6.3.0 - transitivePeerDependencies: - - supports-color + lodash.capitalize: 4.2.1 + lodash.escaperegexp: 4.1.2 + lodash.isplainobject: 4.0.6 + lodash.isstring: 4.0.1 + lodash.uniqby: 4.7.0 + dev: true + + /istanbul-lib-coverage/3.2.0: + resolution: {integrity: sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==} + engines: {node: '>=8'} dev: true /istanbul-lib-instrument/5.1.0: resolution: {integrity: sha512-czwUz525rkOFDJxfKK6mYfIs9zBKILyrZQxjz3ABhjQXhbhFsSbo1HW/BFcsDnfJYJWA6thRR5/TUY2qs5W99Q==} engines: {node: '>=8'} dependencies: - '@babel/core': 7.16.0 - '@babel/parser': 7.16.4 + '@babel/core': 7.17.4 + '@babel/parser': 7.17.3 '@istanbuljs/schema': 0.1.3 istanbul-lib-coverage: 3.2.0 semver: 6.3.0 @@ -4781,50 +7778,59 @@ packages: resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==} engines: {node: '>=10'} dependencies: - debug: 4.3.2 + debug: 4.3.4 istanbul-lib-coverage: 3.2.0 source-map: 0.6.1 transitivePeerDependencies: - supports-color dev: true - /istanbul-reports/3.0.5: - resolution: {integrity: sha512-5+19PlhnGabNWB7kOFnuxT8H3T/iIyQzIbQMxXsURmmvKg86P2sbkrGOT77VnHw0Qr0gc2XzRaRfMZYYbSQCJQ==} + /istanbul-reports/3.1.4: + resolution: {integrity: sha512-r1/DshN4KSE7xWEknZLLLLDn5CJybV3nw01VTkp6D5jzLuELlcbudfj/eSQFvrKsJuTVCGnePO7ho82Nw9zzfw==} engines: {node: '>=8'} dependencies: html-escaper: 2.0.2 istanbul-lib-report: 3.0.0 dev: true - /jest-changed-files/27.3.0: - resolution: {integrity: sha512-9DJs9garMHv4RhylUMZgbdCJ3+jHSkpL9aaVKp13xtXAD80qLTLrqcDZL1PHA9dYA0bCI86Nv2BhkLpLhrBcPg==} + /java-properties/1.0.2: + resolution: {integrity: sha512-qjdpeo2yKlYTH7nFdK0vbZWuTCesk4o63v5iVOlhMQPfuIZQfW/HI35SjfhA+4qpg36rnFSvUK5b1m+ckIblQQ==} + engines: {node: '>= 0.6.0'} + dev: true + + /javascript-stringify/2.1.0: + resolution: {integrity: sha512-JVAfqNPTvNq3sB/VHQJAFxN/sPgKnsKrCwyRt15zwNCdrMMJDdcEOdubuy+DuJYYdm0ox1J4uzEuYKkN+9yhVg==} + dev: true + + /jest-changed-files/27.5.1: + resolution: {integrity: sha512-buBLMiByfWGCoMsLLzGUUSpAmIAGnbR2KJoMN10ziLhOLvP4e0SlypHnAel8iqQXTrcbmfEY9sSqae5sgUsTvw==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dependencies: - '@jest/types': 27.2.5 + '@jest/types': 27.5.1 execa: 5.1.1 throat: 6.0.1 dev: true - /jest-circus/27.3.1: - resolution: {integrity: sha512-v1dsM9II6gvXokgqq6Yh2jHCpfg7ZqV4jWY66u7npz24JnhP3NHxI0sKT7+ZMQ7IrOWHYAaeEllOySbDbWsiXw==} + /jest-circus/27.5.1: + resolution: {integrity: sha512-D95R7x5UtlMA5iBYsOHFFbMD/GVA4R/Kdq15f7xYWUfWHBto9NYRsOvnSauTgdF+ogCpJ4tyKOXhUifxS65gdw==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} 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': 16.11.9 chalk: 4.1.2 co: 4.6.0 dedent: 0.7.0 - expect: 27.3.1 + expect: 27.5.1 is-generator-fn: 2.1.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.5 throat: 6.0.1 @@ -4832,8 +7838,8 @@ packages: - supports-color dev: true - /jest-cli/27.3.1: - resolution: {integrity: sha512-WHnCqpfK+6EvT62me6WVs8NhtbjAS4/6vZJnk7/2+oOr50cwAzG4Wxt6RXX0hu6m1169ZGMlhYYUNeKBXCph/Q==} + /jest-cli/27.5.1: + resolution: {integrity: sha512-Hc6HOOwYq4/74/c62dEE3r5elx8wjYqxY0r0G/nFrLDPMFRu6RA/u8qINOIkvhxG7mMQ5EJsOGfRpI8L6eFUVw==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} hasBin: true peerDependencies: @@ -4842,16 +7848,16 @@ packages: node-notifier: optional: 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.1.2 exit: 0.1.2 - graceful-fs: 4.2.8 + graceful-fs: 4.2.9 import-local: 3.0.3 - 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.4.2 yargs: 16.2.0 transitivePeerDependencies: @@ -4862,8 +7868,8 @@ packages: - utf-8-validate dev: true - /jest-config/27.3.1: - resolution: {integrity: sha512-KY8xOIbIACZ/vdYCKSopL44I0xboxC751IX+DXL2+Wx6DKNycyEfV3rryC3BPm5Uq/BBqDoMrKuqLEUNJmMKKg==} + /jest-config/27.5.1: + resolution: {integrity: sha512-5sAsjm6tGdsVbW9ahcChPAFCk4IlkQUknH5AvKjuLTSlcO/wCZKyFdn7Rg0EkC+OGgWODEy2hDpWB1PgzH0JNA==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} peerDependencies: ts-node: '>=9.0.0' @@ -4871,27 +7877,30 @@ packages: ts-node: optional: true dependencies: - '@babel/core': 7.16.0 - '@jest/test-sequencer': 27.3.1 - '@jest/types': 27.2.5 - babel-jest: 27.3.1_@babel+core@7.16.0 + '@babel/core': 7.17.4 + '@jest/test-sequencer': 27.5.1 + '@jest/types': 27.5.1 + babel-jest: 27.5.1_@babel+core@7.17.4 chalk: 4.1.2 ci-info: 3.2.0 deepmerge: 4.2.2 glob: 7.2.0 - graceful-fs: 4.2.8 - 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 transitivePeerDependencies: - bufferutil - canvas @@ -4909,34 +7918,44 @@ packages: pretty-format: 27.3.1 dev: true - /jest-docblock/27.0.6: - resolution: {integrity: sha512-Fid6dPcjwepTFraz0YxIMCi7dejjJ/KL9FBjPYhBp4Sv1Y9PdhImlKZqYU555BlN4TQKaTc+F2Av1z+anVyGkA==} + /jest-diff/27.5.1: + resolution: {integrity: sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + dependencies: + chalk: 4.1.2 + diff-sequences: 27.5.1 + jest-get-type: 27.5.1 + pretty-format: 27.5.1 + dev: true + + /jest-docblock/27.5.1: + resolution: {integrity: sha512-rl7hlABeTsRYxKiUfpHrQrG4e2obOiTQWfMEH3PxPjOtdsfLQO4ReWSZaQ7DETm4xu07rl4q/h4zcKXyU0/OzQ==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dependencies: detect-newline: 3.1.0 dev: true - /jest-each/27.3.1: - resolution: {integrity: sha512-E4SwfzKJWYcvOYCjOxhZcxwL+AY0uFMvdCOwvzgutJiaiodFjkxQQDxHm8FQBeTqDnSmKsQWn7ldMRzTn2zJaQ==} + /jest-each/27.5.1: + resolution: {integrity: sha512-1Ff6p+FbhT/bXQnEouYy00bkNSY7OUpfIcmdl8vZ31A1UUaurOLPA8a8BbJOF2RDUElwJhmeaV7LnagI+5UwNQ==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dependencies: - '@jest/types': 27.2.5 + '@jest/types': 27.5.1 chalk: 4.1.2 - 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 dev: true - /jest-environment-jsdom/27.3.1: - resolution: {integrity: sha512-3MOy8qMzIkQlfb3W1TfrD7uZHj+xx8Olix5vMENkj5djPmRqndMaXtpnaZkxmxM+Qc3lo+yVzJjzuXbCcZjAlg==} + /jest-environment-jsdom/27.5.1: + resolution: {integrity: sha512-TFBvkTC1Hnnnrka/fUb56atfDtJ9VMZ94JkjTbggl1PEpwrYtUBKMezB3inLmWqQsXYLcMwNoDQwoBTAvFfsfw==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} 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': 16.11.9 - jest-mock: 27.3.0 - jest-util: 27.3.1 + jest-mock: 27.5.1 + jest-util: 27.5.1 jsdom: 16.7.0 transitivePeerDependencies: - bufferutil @@ -4945,16 +7964,16 @@ packages: - utf-8-validate dev: true - /jest-environment-node/27.3.1: - resolution: {integrity: sha512-T89F/FgkE8waqrTSA7/ydMkcc52uYPgZZ6q8OaZgyiZkJb5QNNCF6oPZjH9IfPFfcc9uBWh1574N0kY0pSvTXw==} + /jest-environment-node/27.5.1: + resolution: {integrity: sha512-Jt4ZUnxdOsTGwSRAfKEnE6BcwsSPNOijjwifq5sDFSA2kesnXTvNqKHYgM0hDq3549Uf/KzdXNYn4wMZJPlFLw==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} 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': 16.11.9 - jest-mock: 27.3.0 - jest-util: 27.3.1 + jest-mock: 27.5.1 + jest-util: 27.5.1 dev: true /jest-get-type/27.3.1: @@ -4962,94 +7981,98 @@ packages: engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dev: true - /jest-haste-map/27.3.1: - resolution: {integrity: sha512-lYfNZIzwPccDJZIyk9Iz5iQMM/MH56NIIcGj7AFU1YyA4ewWFBl8z+YPJuSCRML/ee2cCt2y3W4K3VXPT6Nhzg==} + /jest-get-type/27.5.1: + resolution: {integrity: sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + dev: true + + /jest-haste-map/27.5.1: + resolution: {integrity: sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dependencies: - '@jest/types': 27.2.5 + '@jest/types': 27.5.1 '@types/graceful-fs': 4.1.5 '@types/node': 16.11.9 anymatch: 3.1.2 fb-watchman: 2.0.1 - graceful-fs: 4.2.8 - 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.8 optionalDependencies: fsevents: 2.3.2 dev: true - /jest-jasmine2/27.3.1: - resolution: {integrity: sha512-WK11ZUetDQaC09w4/j7o4FZDUIp+4iYWH/Lik34Pv7ukL+DuXFGdnmmi7dT58J2ZYKFB5r13GyE0z3NPeyJmsg==} + /jest-jasmine2/27.5.1: + resolution: {integrity: sha512-jtq7VVyG8SqAorDpApwiJJImd0V2wv1xzdheGHRGyuT7gZm6gG47QEskOlzsN1PG/6WNaCo5pmwMHDf3AkG2pQ==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dependencies: - '@babel/traverse': 7.16.3 - '@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': 16.11.9 chalk: 4.1.2 co: 4.6.0 - expect: 27.3.1 + expect: 27.5.1 is-generator-fn: 2.1.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 transitivePeerDependencies: - supports-color dev: true - /jest-leak-detector/27.3.1: - resolution: {integrity: sha512-78QstU9tXbaHzwlRlKmTpjP9k4Pvre5l0r8Spo4SbFFVy/4Abg9I6ZjHwjg2QyKEAMg020XcjP+UgLZIY50yEg==} + /jest-leak-detector/27.5.1: + resolution: {integrity: sha512-POXfWAMvfU6WMUXftV4HolnJfnPOGEu10fscNCA76KBpRRhcMN2c8d3iT2pxQS3HLbA+5X4sOUPzYO2NUyIlHQ==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dependencies: - jest-get-type: 27.3.1 - pretty-format: 27.3.1 + jest-get-type: 27.5.1 + pretty-format: 27.5.1 dev: true - /jest-matcher-utils/27.3.1: - resolution: {integrity: sha512-hX8N7zXS4k+8bC1Aj0OWpGb7D3gIXxYvPNK1inP5xvE4ztbz3rc4AkI6jGVaerepBnfWB17FL5lWFJT3s7qo8w==} + /jest-matcher-utils/27.5.1: + resolution: {integrity: sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dependencies: chalk: 4.1.2 - 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 dev: true - /jest-message-util/27.3.1: - resolution: {integrity: sha512-bh3JEmxsTZ/9rTm0jQrPElbY2+y48Rw2t47uMfByNyUVR+OfPh4anuyKsGqsNkXk/TI4JbLRZx+7p7Hdt6q1yg==} + /jest-message-util/27.5.1: + resolution: {integrity: sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dependencies: - '@babel/code-frame': 7.16.0 - '@jest/types': 27.2.5 + '@babel/code-frame': 7.16.7 + '@jest/types': 27.5.1 '@types/stack-utils': 2.0.1 chalk: 4.1.2 - graceful-fs: 4.2.8 + 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.5 dev: true - /jest-mock/27.3.0: - resolution: {integrity: sha512-ziZiLk0elZOQjD08bLkegBzv5hCABu/c8Ytx45nJKkysQwGaonvmTxwjLqEA4qGdasq9o2I8/HtdGMNnVsMTGw==} + /jest-mock/27.5.1: + resolution: {integrity: sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dependencies: - '@jest/types': 27.2.5 + '@jest/types': 27.5.1 '@types/node': 16.11.9 dev: true - /jest-pnp-resolver/1.2.2_jest-resolve@27.3.1: + /jest-pnp-resolver/1.2.2_jest-resolve@27.5.1: resolution: {integrity: sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==} engines: {node: '>=6'} peerDependencies: @@ -5058,65 +8081,64 @@ packages: jest-resolve: optional: true dependencies: - jest-resolve: 27.3.1 + jest-resolve: 27.5.1 dev: true - /jest-regex-util/27.0.6: - resolution: {integrity: sha512-SUhPzBsGa1IKm8hx2F4NfTGGp+r7BXJ4CulsZ1k2kI+mGLG+lxGrs76veN2LF/aUdGosJBzKgXmNCw+BzFqBDQ==} + /jest-regex-util/27.5.1: + resolution: {integrity: sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dev: true - /jest-resolve-dependencies/27.3.1: - resolution: {integrity: sha512-X7iLzY8pCiYOnvYo2YrK3P9oSE8/3N2f4pUZMJ8IUcZnT81vlSonya1KTO9ZfKGuC+svE6FHK/XOb8SsoRUV1A==} + /jest-resolve-dependencies/27.5.1: + resolution: {integrity: sha512-QQOOdY4PE39iawDn5rzbIePNigfe5B9Z91GDD1ae/xNDlu9kaat8QQ5EKnNmVWPV54hUdxCVwwj6YMgR2O7IOg==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} 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 transitivePeerDependencies: - supports-color dev: true - /jest-resolve/27.3.1: - resolution: {integrity: sha512-Dfzt25CFSPo3Y3GCbxynRBZzxq9AdyNN+x/v2IqYx6KVT5Z6me2Z/PsSGFSv3cOSUZqJ9pHxilao/I/m9FouLw==} + /jest-resolve/27.5.1: + resolution: {integrity: sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dependencies: - '@jest/types': 27.2.5 + '@jest/types': 27.5.1 chalk: 4.1.2 - graceful-fs: 4.2.8 - jest-haste-map: 27.3.1 - jest-pnp-resolver: 1.2.2_jest-resolve@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-pnp-resolver: 1.2.2_jest-resolve@27.5.1 + jest-util: 27.5.1 + jest-validate: 27.5.1 resolve: 1.20.0 resolve.exports: 1.1.0 slash: 3.0.0 dev: true - /jest-runner/27.3.1: - resolution: {integrity: sha512-r4W6kBn6sPr3TBwQNmqE94mPlYVn7fLBseeJfo4E2uCTmAyDFm2O5DYAQAFP7Q3YfiA/bMwg8TVsciP7k0xOww==} + /jest-runner/27.5.1: + resolution: {integrity: sha512-g4NPsM4mFCOwFKXO4p/H/kWGdJp9V8kURY2lX8Me2drgXqG7rrZAx5kv+5H7wtt/cdFIjhqYx1HrlqWHaOvDaQ==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} 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': 16.11.9 chalk: 4.1.2 emittery: 0.8.1 - exit: 0.1.2 - graceful-fs: 4.2.8 - 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.21 throat: 6.0.1 transitivePeerDependencies: @@ -5126,114 +8148,108 @@ packages: - utf-8-validate dev: true - /jest-runtime/27.3.1: - resolution: {integrity: sha512-qtO6VxPbS8umqhEDpjA4pqTkKQ1Hy4ZSi9mDVeE9Za7LKBo2LdW2jmT+Iod3XFaJqINikZQsn2wEi0j9wPRbLg==} + /jest-runtime/27.5.1: + resolution: {integrity: sha512-o7gxw3Gf+H2IGt8fv0RiyE1+r83FJBRruoA+FXrlHw6xEyBsU8ugA6IPfTdVyA0w8HClpbK+DGJxH59UrNMx8A==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} 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.4 + '@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.1.2 cjs-module-lexer: 1.2.2 collect-v8-coverage: 1.0.1 execa: 5.1.1 - exit: 0.1.2 glob: 7.2.0 - graceful-fs: 4.2.8 - 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 transitivePeerDependencies: - supports-color dev: true - /jest-serializer/27.0.6: - resolution: {integrity: sha512-PtGdVK9EGC7dsaziskfqaAPib6wTViY3G8E5wz9tLVPhHyiDNTZn/xjZ4khAw+09QkoOVpn7vF5nPSN6dtBexA==} + /jest-serializer/27.5.1: + resolution: {integrity: sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dependencies: '@types/node': 16.11.9 - graceful-fs: 4.2.8 + graceful-fs: 4.2.9 dev: true - /jest-snapshot/27.3.1: - resolution: {integrity: sha512-APZyBvSgQgOT0XumwfFu7X3G5elj6TGhCBLbBdn3R1IzYustPGPE38F51dBWMQ8hRXa9je0vAdeVDtqHLvB6lg==} + /jest-snapshot/27.5.1: + resolution: {integrity: sha512-yYykXI5a0I31xX67mgeLw1DZ0bJB+gpq5IpSuCAoyDi0+BhgU/RIrL+RTzDmkNTchvDFWKP8lp+w/42Z3us5sA==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dependencies: - '@babel/core': 7.16.0 - '@babel/generator': 7.16.0 - '@babel/parser': 7.16.4 - '@babel/plugin-syntax-typescript': 7.16.0_@babel+core@7.16.0 - '@babel/traverse': 7.16.3 - '@babel/types': 7.16.0 - '@jest/transform': 27.3.1 - '@jest/types': 27.2.5 + '@babel/core': 7.17.4 + '@babel/generator': 7.17.3 + '@babel/plugin-syntax-typescript': 7.16.7_@babel+core@7.17.4 + '@babel/traverse': 7.17.3 + '@babel/types': 7.17.0 + '@jest/transform': 27.5.1 + '@jest/types': 27.5.1 '@types/babel__traverse': 7.14.2 '@types/prettier': 2.4.2 - babel-preset-current-node-syntax: 1.0.1_@babel+core@7.16.0 + babel-preset-current-node-syntax: 1.0.1_@babel+core@7.17.4 chalk: 4.1.2 - expect: 27.3.1 - graceful-fs: 4.2.8 - 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.5 transitivePeerDependencies: - supports-color dev: true - /jest-util/27.3.1: - resolution: {integrity: sha512-8fg+ifEH3GDryLQf/eKZck1DEs2YuVPBCMOaHQxVVLmQwl/CDhWzrvChTX4efLZxGrw+AA0mSXv78cyytBt/uw==} + /jest-util/27.5.1: + resolution: {integrity: sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dependencies: - '@jest/types': 27.2.5 + '@jest/types': 27.5.1 '@types/node': 16.11.9 chalk: 4.1.2 ci-info: 3.2.0 - graceful-fs: 4.2.8 + graceful-fs: 4.2.9 picomatch: 2.3.0 dev: true - /jest-validate/27.3.1: - resolution: {integrity: sha512-3H0XCHDFLA9uDII67Bwi1Vy7AqwA5HqEEjyy934lgVhtJ3eisw6ShOF1MDmRPspyikef5MyExvIm0/TuLzZ86Q==} + /jest-validate/27.5.1: + resolution: {integrity: sha512-thkNli0LYTmOI1tDB3FI1S1RTp/Bqyd9pTarJwL87OIBFuqEb5Apv5EaApEudYg4g86e3CT6kM0RowkhtEnCBQ==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dependencies: - '@jest/types': 27.2.5 + '@jest/types': 27.5.1 camelcase: 6.2.1 chalk: 4.1.2 - 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 dev: true - /jest-watcher/27.3.1: - resolution: {integrity: sha512-9/xbV6chABsGHWh9yPaAGYVVKurWoP3ZMCv6h+O1v9/+pkOroigs6WzZ0e9gLP/njokUwM7yQhr01LKJVMkaZA==} + /jest-watcher/27.5.1: + resolution: {integrity: sha512-z676SuD6Z8o8qbmEGhoEUFOM1+jfEiL3DXHK/xgEiG2EyNYfFG60jluWcupY6dATjfEsKQuibReS1djInQnoVw==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} 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': 16.11.9 ansi-escapes: 4.3.2 chalk: 4.1.2 - jest-util: 27.3.1 + jest-util: 27.5.1 string-length: 4.0.2 dev: true @@ -5246,8 +8262,17 @@ packages: supports-color: 8.1.1 dev: true - /jest/27.3.1: - resolution: {integrity: sha512-U2AX0AgQGd5EzMsiZpYt8HyZ+nSVIh5ujQ9CPp9EQZJMjXIiSZpJNweZl0swatKRoqHWgGKM3zaSwm4Zaz87ng==} + /jest-worker/27.5.1: + resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} + engines: {node: '>= 10.13.0'} + dependencies: + '@types/node': 16.11.9 + merge-stream: 2.0.0 + supports-color: 8.1.1 + dev: true + + /jest/27.5.1: + resolution: {integrity: sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} hasBin: true peerDependencies: @@ -5256,9 +8281,9 @@ packages: node-notifier: optional: true dependencies: - '@jest/core': 27.3.1 + '@jest/core': 27.5.1 import-local: 3.0.3 - jest-cli: 27.3.1 + jest-cli: 27.5.1 transitivePeerDependencies: - bufferutil - canvas @@ -5267,6 +8292,9 @@ packages: - utf-8-validate dev: true + /js-sha3/0.8.0: + resolution: {integrity: sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==} + /js-tokens/4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -5285,6 +8313,15 @@ packages: argparse: 2.0.1 dev: true + /jsan/3.1.14: + resolution: {integrity: sha512-wStfgOJqMv4QKktuH273f5fyi3D3vy2pHOiSDGPvpcS/q+wb/M7AK3vkCcaHbkZxDOlDU/lDJgccygKSG2OhtA==} + dev: true + + /jsbn/0.1.1: + resolution: {integrity: sha1-peZUwuWi3rXyAdls77yoDA7y9RM=} + dev: true + optional: true + /jsdom/16.7.0: resolution: {integrity: sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==} engines: {node: '>=10'} @@ -5295,7 +8332,7 @@ packages: optional: true dependencies: abab: 2.0.5 - acorn: 8.6.0 + acorn: 8.7.0 acorn-globals: 6.0.0 cssom: 0.4.4 cssstyle: 2.3.0 @@ -5337,6 +8374,10 @@ packages: engines: {node: '>=4'} hasBin: true + /json-buffer/3.0.0: + resolution: {integrity: sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=} + dev: true + /json-parse-better-errors/1.0.2: resolution: {integrity: sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==} dev: true @@ -5345,6 +8386,20 @@ packages: resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} dev: true + /json-schema-compare/0.2.2: + resolution: {integrity: sha512-c4WYmDKyJXhs7WWvAWm3uIYnfyWFoIp+JEoX34rctVvEkMYCPGhXtvmFFXiffBbxfZsvQ0RNnV5H7GvDF5HCqQ==} + dependencies: + lodash: 4.17.21 + dev: true + + /json-schema-merge-allof/0.6.0: + resolution: {integrity: sha512-LEw4VMQVRceOPLuGRWcxW5orTTiR9ZAtqTAe4rQUjNADTeR81bezBVFa0MqIwp0YmHIM1KkhSjZM7o+IQhaPbQ==} + dependencies: + compute-lcm: 1.1.2 + json-schema-compare: 0.2.2 + lodash: 4.17.21 + dev: true + /json-schema-traverse/0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} dev: true @@ -5353,10 +8408,19 @@ packages: resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} dev: true + /json-schema/0.4.0: + resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==} + dev: true + optional: true + /json-stable-stringify-without-jsonify/1.0.1: resolution: {integrity: sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=} dev: true + /json-stringify-safe/5.0.1: + resolution: {integrity: sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=} + dev: true + /json5/1.0.1: resolution: {integrity: sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==} hasBin: true @@ -5364,12 +8428,190 @@ packages: minimist: 1.2.5 dev: true - /json5/2.2.0: - resolution: {integrity: sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==} + /json5/2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} engines: {node: '>=6'} hasBin: true + + /jsondiffpatch/0.4.1: + resolution: {integrity: sha512-t0etAxTUk1w5MYdNOkZBZ8rvYYN5iL+2dHCCx/DpkFm/bW28M6y5nUS83D4XdZiHy35Fpaw6LBb+F88fHZnVCw==} + engines: {node: '>=8.17.0'} + hasBin: true dependencies: - minimist: 1.2.5 + chalk: 2.4.2 + diff-match-patch: 1.0.5 + dev: true + bundledDependencies: [] + + /jsonfile/4.0.0: + resolution: {integrity: sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=} + optionalDependencies: + graceful-fs: 4.2.9 + dev: true + + /jsonfile/6.1.0: + resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + dependencies: + universalify: 2.0.0 + optionalDependencies: + graceful-fs: 4.2.9 + dev: true + + /jsonparse/1.3.1: + resolution: {integrity: sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=} + engines: {'0': node >= 0.2.0} + dev: true + + /jsonpointer/5.0.0: + resolution: {integrity: sha512-PNYZIdMjVIvVgDSYKTT63Y+KZ6IZvGRNNWcxwD+GNnUz1MKPfv30J8ueCjdwcN0nDx2SlshgyB7Oy0epAzVRRg==} + engines: {node: '>=0.10.0'} + dev: true + + /jsonwebtoken/8.5.1: + resolution: {integrity: sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==} + engines: {node: '>=4', npm: '>=1.4.28'} + dependencies: + jws: 3.2.2 + lodash.includes: 4.3.0 + lodash.isboolean: 3.0.3 + lodash.isinteger: 4.0.4 + lodash.isnumber: 3.0.3 + lodash.isplainobject: 4.0.6 + lodash.isstring: 4.0.1 + lodash.once: 4.1.1 + ms: 2.1.3 + semver: 5.7.1 + dev: true + + /jsprim/1.4.2: + resolution: {integrity: sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==} + engines: {node: '>=0.6.0'} + dependencies: + assert-plus: 1.0.0 + extsprintf: 1.3.0 + json-schema: 0.4.0 + verror: 1.10.0 + dev: true + optional: true + + /jss-plugin-camel-case/10.9.0: + resolution: {integrity: sha512-UH6uPpnDk413/r/2Olmw4+y54yEF2lRIV8XIZyuYpgPYTITLlPOsq6XB9qeqv+75SQSg3KLocq5jUBXW8qWWww==} + dependencies: + '@babel/runtime': 7.17.2 + hyphenate-style-name: 1.0.4 + jss: 10.9.0 + dev: true + + /jss-plugin-compose/10.9.0: + resolution: {integrity: sha512-Q/0FEZhDwGUpf3/b7+PspmMi6MVSlN3YlTDmvrft7I6N346jUpd8MYkYP/6qM1ZMuVj4v8ky/XYqr1v2ganLLg==} + dependencies: + '@babel/runtime': 7.17.2 + jss: 10.9.0 + tiny-warning: 1.0.3 + dev: true + + /jss-plugin-default-unit/10.9.0: + resolution: {integrity: sha512-7Ju4Q9wJ/MZPsxfu4T84mzdn7pLHWeqoGd/D8O3eDNNJ93Xc8PxnLmV8s8ZPNRYkLdxZqKtm1nPQ0BM4JRlq2w==} + dependencies: + '@babel/runtime': 7.17.2 + jss: 10.9.0 + dev: true + + /jss-plugin-expand/10.9.0: + resolution: {integrity: sha512-QfZ9jld0HpF1OiYU7cGWQ4q+f6+Wu93mV4X+cA1iVRssiUbSbygwdfZkUwX23UOhS1WWRJeQlLK1aJC94K8/0A==} + dependencies: + '@babel/runtime': 7.17.2 + jss: 10.9.0 + dev: true + + /jss-plugin-extend/10.9.0: + resolution: {integrity: sha512-xvmosUh3RsKVsm9L14ml6PL3i0Ejj5gB6eo/jTMkGW1kIy42gNXV1EthR8cD5xiowWstnvugQ3JF0pI5+QkPMg==} + dependencies: + '@babel/runtime': 7.17.2 + jss: 10.9.0 + tiny-warning: 1.0.3 + dev: true + + /jss-plugin-global/10.9.0: + resolution: {integrity: sha512-4G8PHNJ0x6nwAFsEzcuVDiBlyMsj2y3VjmFAx/uHk/R/gzJV+yRHICjT4MKGGu1cJq2hfowFWCyrr/Gg37FbgQ==} + dependencies: + '@babel/runtime': 7.17.2 + jss: 10.9.0 + dev: true + + /jss-plugin-nested/10.9.0: + resolution: {integrity: sha512-2UJnDrfCZpMYcpPYR16oZB7VAC6b/1QLsRiAutOt7wJaaqwCBvNsosLEu/fUyKNQNGdvg2PPJFDO5AX7dwxtoA==} + dependencies: + '@babel/runtime': 7.17.2 + jss: 10.9.0 + tiny-warning: 1.0.3 + dev: true + + /jss-plugin-props-sort/10.9.0: + resolution: {integrity: sha512-7A76HI8bzwqrsMOJTWKx/uD5v+U8piLnp5bvru7g/3ZEQOu1+PjHvv7bFdNO3DwNPC9oM0a//KwIJsIcDCjDzw==} + dependencies: + '@babel/runtime': 7.17.2 + jss: 10.9.0 + dev: true + + /jss-plugin-rule-value-function/10.9.0: + resolution: {integrity: sha512-IHJv6YrEf8pRzkY207cPmdbBstBaE+z8pazhPShfz0tZSDtRdQua5jjg6NMz3IbTasVx9FdnmptxPqSWL5tyJg==} + dependencies: + '@babel/runtime': 7.17.2 + jss: 10.9.0 + tiny-warning: 1.0.3 + dev: true + + /jss-plugin-rule-value-observable/10.9.0: + resolution: {integrity: sha512-/MWVPJVEn41+ofzQdsvH1GR4wusDqFqNnchh/98HVc580MxPy4NVkmUa2SAEpbHhnJ93sCoETZccW3HJKuvH4A==} + dependencies: + '@babel/runtime': 7.17.2 + jss: 10.9.0 + symbol-observable: 1.2.0 + dev: true + + /jss-plugin-template/10.9.0: + resolution: {integrity: sha512-lxThUvdt0drCi7xhuJWxADWTgLLy1IWCeFO5k+dtba900xJsNg0IGZplpP9w9UpaJsYS3WUwWMXw8Sxn1dobfQ==} + dependencies: + '@babel/runtime': 7.17.2 + jss: 10.9.0 + tiny-warning: 1.0.3 + dev: true + + /jss-plugin-vendor-prefixer/10.9.0: + resolution: {integrity: sha512-MbvsaXP7iiVdYVSEoi+blrW+AYnTDvHTW6I6zqi7JcwXdc6I9Kbm234nEblayhF38EftoenbM+5218pidmC5gA==} + dependencies: + '@babel/runtime': 7.17.2 + css-vendor: 2.0.8 + jss: 10.9.0 + dev: true + + /jss-preset-default/10.9.0: + resolution: {integrity: sha512-Zdsj+R+UTn7OOJ1TFQi+l8PfEL7APSAM6vRPaU8mJywT8OrMjgslMKckFLrgq1k+qk1hJR1ePAMesvZ5aAXGOQ==} + dependencies: + '@babel/runtime': 7.17.2 + jss: 10.9.0 + jss-plugin-camel-case: 10.9.0 + jss-plugin-compose: 10.9.0 + jss-plugin-default-unit: 10.9.0 + jss-plugin-expand: 10.9.0 + jss-plugin-extend: 10.9.0 + jss-plugin-global: 10.9.0 + jss-plugin-nested: 10.9.0 + jss-plugin-props-sort: 10.9.0 + jss-plugin-rule-value-function: 10.9.0 + jss-plugin-rule-value-observable: 10.9.0 + jss-plugin-template: 10.9.0 + jss-plugin-vendor-prefixer: 10.9.0 + dev: true + + /jss/10.9.0: + resolution: {integrity: sha512-YpzpreB6kUunQBbrlArlsMpXYyndt9JATbt95tajx0t4MTJJcCJdd4hdNpHmOIDiUJrF/oX5wtVFrS3uofWfGw==} + dependencies: + '@babel/runtime': 7.17.2 + csstype: 3.0.10 + is-in-browser: 1.1.3 + tiny-warning: 1.0.3 dev: true /jsx-ast-utils/3.2.1: @@ -5380,6 +8622,27 @@ packages: object.assign: 4.1.2 dev: true + /jwa/1.4.1: + resolution: {integrity: sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==} + dependencies: + buffer-equal-constant-time: 1.0.1 + ecdsa-sig-formatter: 1.0.11 + safe-buffer: 5.2.1 + dev: true + + /jws/3.2.2: + resolution: {integrity: sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==} + dependencies: + jwa: 1.4.1 + safe-buffer: 5.2.1 + dev: true + + /keyv/3.1.0: + resolution: {integrity: sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==} + dependencies: + json-buffer: 3.0.0 + dev: true + /kind-of/6.0.3: resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} engines: {node: '>=0.10.0'} @@ -5390,6 +8653,49 @@ packages: engines: {node: '>=6'} dev: true + /knex/0.95.15_sqlite3@5.0.2: + resolution: {integrity: sha512-Loq6WgHaWlmL2bfZGWPsy4l8xw4pOE+tmLGkPG0auBppxpI0UcK+GYCycJcqz9W54f2LiGewkCVLBm3Wq4ur/w==} + engines: {node: '>=10'} + hasBin: true + peerDependencies: + mysql: '*' + mysql2: '*' + pg: '*' + pg-native: '*' + sqlite3: '*' + tedious: '*' + peerDependenciesMeta: + mysql: + optional: true + mysql2: + optional: true + pg: + optional: true + pg-native: + optional: true + sqlite3: + optional: true + tedious: + optional: true + dependencies: + colorette: 2.0.16 + commander: 7.2.0 + debug: 4.3.2 + escalade: 3.1.1 + esm: 3.2.25 + getopts: 2.2.5 + interpret: 2.2.0 + lodash: 4.17.21 + pg-connection-string: 2.5.0 + rechoir: 0.7.0 + resolve-from: 5.0.0 + sqlite3: 5.0.2 + tarn: 3.0.2 + tildify: 2.0.0 + transitivePeerDependencies: + - supports-color + dev: true + /language-subtag-registry/0.3.21: resolution: {integrity: sha512-L0IqwlIXjilBVVYKFT37X9Ih11Um5NEl9cbJIuU/SwP/zEEAbBPOnEeeuxVMf45ydWQRDQN3Nqc96OgbH1K+Pg==} dev: true @@ -5400,6 +8706,20 @@ packages: language-subtag-registry: 0.3.21 dev: true + /latest-version/3.1.0: + resolution: {integrity: sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU=} + engines: {node: '>=4'} + dependencies: + package-json: 4.0.1 + dev: true + + /lazystream/1.0.1: + resolution: {integrity: sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==} + engines: {node: '>= 0.6.3'} + dependencies: + readable-stream: 2.3.7 + dev: true + /leven/3.1.0: resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} engines: {node: '>=6'} @@ -5421,10 +8741,29 @@ packages: type-check: 0.4.0 dev: true + /lie/3.1.1: + resolution: {integrity: sha1-mkNrLMd0bKWd56QfpGmz77dr2H4=} + dependencies: + immediate: 3.0.6 + /lines-and-columns/1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} dev: true + /linked-list/0.1.0: + resolution: {integrity: sha1-eYsP+X0bkqT9CEgPVa6k6dSdN78=} + dev: true + + /load-json-file/4.0.0: + resolution: {integrity: sha1-L19Fq5HjMhYjT9U62rZo607AmTs=} + engines: {node: '>=4'} + dependencies: + graceful-fs: 4.2.9 + parse-json: 4.0.0 + pify: 3.0.0 + strip-bom: 3.0.0 + dev: true + /loader-runner/4.2.0: resolution: {integrity: sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==} engines: {node: '>=6.11.5'} @@ -5445,9 +8784,14 @@ packages: dependencies: big.js: 5.2.2 emojis-list: 3.0.0 - json5: 2.2.0 + json5: 2.2.3 dev: true + /localforage/1.10.0: + resolution: {integrity: sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==} + dependencies: + lie: 3.1.1 + /locate-path/2.0.0: resolution: {integrity: sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=} engines: {node: '>=4'} @@ -5470,17 +8814,98 @@ packages: p-locate: 5.0.0 dev: true + /lodash.capitalize/4.2.1: + resolution: {integrity: sha1-+CbJtOKoUR2E46yinbBeGk87cqk=} + dev: true + + /lodash.clonedeep/4.5.0: + resolution: {integrity: sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=} + dev: true + + /lodash.curry/4.1.1: + resolution: {integrity: sha1-JI42By7ekGUB11lmIAqG2riyMXA=} + dev: true + /lodash.debounce/4.0.8: resolution: {integrity: sha1-gteb/zCmfEAF/9XiUVMArZyk168=} dev: true + /lodash.defaults/4.2.0: + resolution: {integrity: sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=} + dev: true + + /lodash.difference/4.5.0: + resolution: {integrity: sha1-nMtOUF1Ia5FlE0V3KIWi3yf9AXw=} + dev: true + + /lodash.escaperegexp/4.1.2: + resolution: {integrity: sha1-ZHYsSGGAglGKw99Mz11YhtriA0c=} + dev: true + + /lodash.flatten/4.4.0: + resolution: {integrity: sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=} + dev: true + + /lodash.includes/4.3.0: + resolution: {integrity: sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=} + dev: true + + /lodash.isboolean/3.0.3: + resolution: {integrity: sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=} + dev: true + + /lodash.isinteger/4.0.4: + resolution: {integrity: sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=} + dev: true + + /lodash.ismatch/4.4.0: + resolution: {integrity: sha1-dWy1FQyjum8RCFp4hJZF8Yj4Xzc=} + dev: true + + /lodash.isnumber/3.0.3: + resolution: {integrity: sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=} + dev: true + + /lodash.isplainobject/4.0.6: + resolution: {integrity: sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=} + dev: true + + /lodash.isstring/4.0.1: + resolution: {integrity: sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=} + dev: true + /lodash.merge/4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} dev: true + /lodash.once/4.1.1: + resolution: {integrity: sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=} + dev: true + + /lodash.sortby/4.7.0: + resolution: {integrity: sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=} + dev: true + + /lodash.union/4.6.0: + resolution: {integrity: sha1-SLtQiECfFvGCFmZkHETdGqrjzYg=} + dev: true + + /lodash.uniqby/4.7.0: + resolution: {integrity: sha1-2ZwHpmnp5tJOE2Lf4mbGdhavEwI=} + dev: true + /lodash/4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + /loglevel/1.8.0: + resolution: {integrity: sha512-G6A/nJLRgWOuuwdNuA6koovfEV1YpqqAG4pRUlFaz3jj2QNZ8M4vBqnVA+HBTmU/AMNUtlOsMmSpF6NyOjztbA==} + engines: {node: '>= 0.6.0'} + dev: true + + /long/4.0.0: + resolution: {integrity: sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==} + dev: true + /loose-envify/1.4.0: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true @@ -5490,7 +8915,24 @@ packages: /lower-case/2.0.2: resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==} dependencies: - tslib: 2.3.1 + tslib: 2.4.1 + dev: true + + /lowercase-keys/1.0.1: + resolution: {integrity: sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==} + engines: {node: '>=0.10.0'} + dev: true + + /lowercase-keys/2.0.0: + resolution: {integrity: sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==} + engines: {node: '>=8'} + dev: true + + /lru-cache/4.1.5: + resolution: {integrity: sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==} + dependencies: + pseudomap: 1.0.2 + yallist: 2.1.2 dev: true /lru-cache/6.0.0: @@ -5505,6 +8947,13 @@ packages: hasBin: true dev: true + /make-dir/1.3.0: + resolution: {integrity: sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==} + engines: {node: '>=4'} + dependencies: + pify: 3.0.0 + dev: true + /make-dir/2.1.0: resolution: {integrity: sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==} engines: {node: '>=6'} @@ -5526,18 +8975,85 @@ packages: tmpl: 1.0.5 dev: true + /map-obj/1.0.1: + resolution: {integrity: sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=} + engines: {node: '>=0.10.0'} + dev: true + + /map-obj/4.3.0: + resolution: {integrity: sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==} + engines: {node: '>=8'} + dev: true + + /map2tree/2.1.0: + resolution: {integrity: sha512-mRhb7q7TyO/uxtPURYmmwUKlnmcC9S4y18ZnLr6Ufkhyf2CpWHFh77fuM0US8owqjBDOhalo3vk8jzL+8vyNGQ==} + dependencies: + '@babel/runtime': 7.17.2 + lodash: 4.17.21 + dev: true + + /marked-terminal/5.1.1_marked@4.0.12: + resolution: {integrity: sha512-+cKTOx9P4l7HwINYhzbrBSyzgxO2HaHKGZGuB1orZsMIgXYaJyfidT81VXRdpelW/PcHEWxywscePVgI/oUF6g==} + engines: {node: '>=14.13.1 || >=16.0.0'} + peerDependencies: + marked: ^1.0.0 || ^2.0.0 || ^3.0.0 || ^4.0.0 + dependencies: + ansi-escapes: 5.0.0 + cardinal: 2.1.1 + chalk: 5.0.0 + cli-table3: 0.6.1 + marked: 4.0.12 + node-emoji: 1.11.0 + supports-hyperlinks: 2.2.0 + dev: true + + /marked/4.0.12: + resolution: {integrity: sha512-hgibXWrEDNBWgGiK18j/4lkS6ihTe9sxtV4Q1OQppb/0zzyPSzoFANBa5MfsG/zgsWklmNnhm0XACZOH/0HBiQ==} + engines: {node: '>= 12'} + hasBin: true + dev: true + + /matcher/3.0.0: + resolution: {integrity: sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==} + engines: {node: '>=10'} + dependencies: + escape-string-regexp: 4.0.0 + dev: true + optional: true + /media-typer/0.3.0: resolution: {integrity: sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=} engines: {node: '>= 0.6'} dev: true - /memfs/3.3.0: - resolution: {integrity: sha512-BEE62uMfKOavX3iG7GYX43QJ+hAeeWnwIAuJ/R6q96jaMtiLzhsxHJC8B1L7fK7Pt/vXDRwb3SG/yBpNGDPqzg==} + /memfs/3.4.1: + resolution: {integrity: sha512-1c9VPVvW5P7I85c35zAdEr1TD5+F11IToIHIlrVIcflfnzPkJa0ZoYEoEdYDP8KgPFoSZ/opDrUsAoZWym3mtw==} engines: {node: '>= 4.0.0'} dependencies: fs-monkey: 1.0.3 dev: true + /memoize-one/5.2.1: + resolution: {integrity: sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==} + dev: true + + /meow/8.1.2: + resolution: {integrity: sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==} + engines: {node: '>=10'} + dependencies: + '@types/minimist': 1.2.2 + camelcase-keys: 6.2.2 + decamelize-keys: 1.1.0 + hard-rejection: 2.1.0 + minimist-options: 4.1.0 + normalize-package-data: 3.0.3 + read-pkg-up: 7.0.1 + redent: 3.0.0 + trim-newlines: 3.0.1 + type-fest: 0.18.1 + yargs-parser: 20.2.9 + dev: true + /merge-descriptors/1.0.1: resolution: {integrity: sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=} dev: true @@ -5564,6 +9080,14 @@ packages: picomatch: 2.3.0 dev: true + /microseconds/0.1.0: + resolution: {integrity: sha512-yF2K4aHXKxO4OGhW7Ek2KLgKEAFbSblBLKlF6KzwQUhjK7+uAzatRr6fZ82bftdnuDQrkBHAJp5s8quj1ME3wA==} + dev: true + + /microseconds/0.2.0: + resolution: {integrity: sha512-n7DHHMjR1avBbSpsTBj6fmMGh2AGrifVV4e+WYc3Q9lO+xnSZ3NyhcBND3vzzatt05LFhoKFRxrIyklmLlUtyA==} + dev: false + /mime-db/1.51.0: resolution: {integrity: sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==} engines: {node: '>= 0.6'} @@ -5582,11 +9106,27 @@ packages: hasBin: true dev: true + /mime/3.0.0: + resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==} + engines: {node: '>=10.0.0'} + hasBin: true + dev: true + + /mimic-fn/1.2.0: + resolution: {integrity: sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==} + engines: {node: '>=4'} + dev: true + /mimic-fn/2.1.0: resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} engines: {node: '>=6'} dev: true + /mimic-response/1.0.1: + resolution: {integrity: sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==} + engines: {node: '>=4'} + dev: true + /min-indent/1.0.1: resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} engines: {node: '>=4'} @@ -5601,10 +9141,36 @@ packages: dependencies: brace-expansion: 1.1.11 + /minimist-options/4.1.0: + resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==} + engines: {node: '>= 6'} + dependencies: + arrify: 1.0.1 + is-plain-obj: 1.1.0 + kind-of: 6.0.3 + dev: true + + /minimist/1.2.0: + resolution: {integrity: sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=} + dev: true + /minimist/1.2.5: resolution: {integrity: sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==} dev: true + /minipass/2.9.0: + resolution: {integrity: sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==} + dependencies: + safe-buffer: 5.2.1 + yallist: 3.1.1 + dev: true + + /minizlib/1.3.3: + resolution: {integrity: sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==} + dependencies: + minipass: 2.9.0 + dev: true + /mkdirp/0.5.5: resolution: {integrity: sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==} hasBin: true @@ -5612,6 +9178,24 @@ packages: minimist: 1.2.5 dev: true + /modify-values/1.0.1: + resolution: {integrity: sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==} + engines: {node: '>=0.10.0'} + dev: true + + /morgan/1.10.0: + resolution: {integrity: sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==} + engines: {node: '>= 0.8.0'} + dependencies: + basic-auth: 2.0.1 + debug: 2.6.9 + depd: 2.0.0 + on-finished: 2.3.0 + on-headers: 1.0.2 + transitivePeerDependencies: + - supports-color + dev: true + /ms/2.0.0: resolution: {integrity: sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=} dev: true @@ -5639,53 +9223,231 @@ packages: thunky: 1.1.0 dev: true + /mute-stream/0.0.7: + resolution: {integrity: sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=} + dev: true + + /nano-time/1.0.0: + resolution: {integrity: sha512-flnngywOoQ0lLQOTRNexn2gGSNuM9bKj9RZAWSzhQ+UJYaAFG9bac4DW9VHjUAzrOaIcajHybCTHe/bkvozQqA==} + dependencies: + big-integer: 1.6.51 + + /nanoid/2.1.11: + resolution: {integrity: sha512-s/snB+WGm6uwi0WjsZdaVcuf3KJXlfGl2LcxgwkEwJF0D/BWzVWAZW/XY4bFaiR7s0Jk3FPvlnepg1H1b1UwlA==} + dev: true + /nanoid/3.1.30: resolution: {integrity: sha512-zJpuPDwOv8D2zq2WRoMe1HsfZthVewpel9CAvTfc/2mBD1uUT/agc5f7GHGWXlYkFvi1mVxe4IjvP2HNrop7nQ==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true dev: true - /natural-compare/1.4.0: - resolution: {integrity: sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=} + /natural-compare/1.4.0: + resolution: {integrity: sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=} + dev: true + + /ncom/1.0.3: + resolution: {integrity: sha512-PfA7rjxxMAItsGo2qXrGn2GvKJIwN0bUTa3GehsblrKRVdCCEwB0QG2ymM6/DppQGUt7YqbfxQB7LaMWMiHHWQ==} + engines: {node: '>= 0.8.0'} + dependencies: + sc-formatter: 3.0.2 + dev: true + + /needle/2.9.1: + resolution: {integrity: sha512-6R9fqJ5Zcmf+uYaFgdIHmLwNldn5HbK8L5ybn7Uz+ylX/rnOsSp1AHcvQSrCaFN+qNM1wpymHqD7mVasEOlHGQ==} + engines: {node: '>= 4.4.x'} + hasBin: true + dependencies: + debug: 3.2.7 + iconv-lite: 0.4.24 + sax: 1.2.4 + transitivePeerDependencies: + - supports-color + dev: true + + /negotiator/0.6.2: + resolution: {integrity: sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==} + engines: {node: '>= 0.6'} + dev: true + + /neo-async/2.6.2: + resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} + dev: true + + /nerf-dart/1.0.0: + resolution: {integrity: sha1-5tq3/r9a2Bbqgc9cYpxaDr3nLBo=} + dev: true + + /no-case/3.0.4: + resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} + dependencies: + lower-case: 2.0.2 + tslib: 2.4.1 + dev: true + + /node-addon-api/3.2.1: + resolution: {integrity: sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==} + dev: true + + /node-emoji/1.11.0: + resolution: {integrity: sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==} + dependencies: + lodash: 4.17.21 + dev: true + + /node-fetch/2.6.7: + resolution: {integrity: sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + dependencies: + whatwg-url: 5.0.0 + dev: true + + /node-forge/1.2.1: + resolution: {integrity: sha512-Fcvtbb+zBcZXbTTVwqGA5W+MKBj56UjVRevvchv5XrcyXbmNdesfZL37nlcWOfpgHhgmxApw3tQbTr4CqNmX4w==} + engines: {node: '>= 6.13.0'} + dev: true + + /node-gyp/3.8.0: + resolution: {integrity: sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA==} + engines: {node: '>= 0.8.0'} + hasBin: true + requiresBuild: true + dependencies: + fstream: 1.0.12 + glob: 7.2.0 + graceful-fs: 4.2.9 + mkdirp: 0.5.5 + nopt: 3.0.6 + npmlog: 4.1.2 + osenv: 0.1.5 + request: 2.88.2 + rimraf: 2.7.1 + semver: 5.3.0 + tar: 2.2.2 + which: 1.3.1 + dev: true + optional: true + + /node-int64/0.4.0: + resolution: {integrity: sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=} + dev: true + + /node-pre-gyp/0.11.0: + resolution: {integrity: sha512-TwWAOZb0j7e9eGaf9esRx3ZcLaE5tQ2lvYy1pb5IAaG1a2e2Kv5Lms1Y4hpj+ciXJRofIxxlt5haeQ/2ANeE0Q==} + deprecated: 'Please upgrade to @mapbox/node-pre-gyp: the non-scoped node-pre-gyp package is deprecated and only the @mapbox scoped package will recieve updates in the future' + hasBin: true + dependencies: + detect-libc: 1.0.3 + mkdirp: 0.5.5 + needle: 2.9.1 + nopt: 4.0.3 + npm-packlist: 1.4.8 + npmlog: 4.1.2 + rc: 1.2.8 + rimraf: 2.7.1 + semver: 5.7.1 + tar: 4.4.19 + transitivePeerDependencies: + - supports-color + dev: true + + /node-releases/2.0.1: + resolution: {integrity: sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA==} + dev: true + + /node-rsa/1.1.1: + resolution: {integrity: sha512-Jd4cvbJMryN21r5HgxQOpMEqv+ooke/korixNNK3mGqfGJmy0M77WDDzo/05969+OkMy3XW1UuZsSmW9KQm7Fw==} + dependencies: + asn1: 0.2.6 + dev: true + + /nopt/3.0.6: + resolution: {integrity: sha1-xkZdvwirzU2zWTF/eaxopkayj/k=} + hasBin: true + dependencies: + abbrev: 1.1.1 + dev: true + optional: true + + /nopt/4.0.3: + resolution: {integrity: sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==} + hasBin: true + dependencies: + abbrev: 1.1.1 + osenv: 0.1.5 + dev: true + + /normalize-package-data/2.5.0: + resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} + dependencies: + hosted-git-info: 2.8.9 + resolve: 1.20.0 + semver: 5.7.1 + validate-npm-package-license: 3.0.4 + dev: true + + /normalize-package-data/3.0.3: + resolution: {integrity: sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==} + engines: {node: '>=10'} + dependencies: + hosted-git-info: 4.1.0 + is-core-module: 2.11.0 + semver: 7.3.5 + validate-npm-package-license: 3.0.4 + dev: true + + /normalize-path/3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} dev: true - /negotiator/0.6.2: - resolution: {integrity: sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==} - engines: {node: '>= 0.6'} + /normalize-url/4.5.1: + resolution: {integrity: sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==} + engines: {node: '>=8'} dev: true - /neo-async/2.6.2: - resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} + /normalize-url/6.1.0: + resolution: {integrity: sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==} + engines: {node: '>=10'} dev: true - /no-case/3.0.4: - resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} + /npm-bundled/1.1.2: + resolution: {integrity: sha512-x5DHup0SuyQcmL3s7Rx/YQ8sbw/Hzg0rj48eN0dV7hf5cmQq5PXIeioroH3raV1QC1yh3uTYuMThvEQF3iKgGQ==} dependencies: - lower-case: 2.0.2 - tslib: 2.3.1 - dev: true - - /node-forge/0.10.0: - resolution: {integrity: sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==} - engines: {node: '>= 6.0.0'} + npm-normalize-package-bin: 1.0.1 dev: true - /node-int64/0.4.0: - resolution: {integrity: sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=} + /npm-conf/1.1.3: + resolution: {integrity: sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw==} + engines: {node: '>=4'} + dependencies: + config-chain: 1.1.13 + pify: 3.0.0 dev: true + optional: true - /node-modules-regexp/1.0.0: - resolution: {integrity: sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=} - engines: {node: '>=0.10.0'} + /npm-normalize-package-bin/1.0.1: + resolution: {integrity: sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==} dev: true - /node-releases/2.0.1: - resolution: {integrity: sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA==} + /npm-packlist/1.4.8: + resolution: {integrity: sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==} + dependencies: + ignore-walk: 3.0.4 + npm-bundled: 1.1.2 + npm-normalize-package-bin: 1.0.1 dev: true - /normalize-path/3.0.0: - resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} - engines: {node: '>=0.10.0'} + /npm-run-path/2.0.2: + resolution: {integrity: sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=} + engines: {node: '>=4'} + dependencies: + path-key: 2.0.1 dev: true /npm-run-path/4.0.1: @@ -5695,16 +9457,113 @@ packages: path-key: 3.1.1 dev: true + /npm/8.5.1: + resolution: {integrity: sha512-zHrOHAatEPJ59o2JIPlhgc9LX9mb8xFrqu4kiiul4w1IGMTtKn2lqRiGIRKU0or69NSLXNmqbCP9bNJIr/wB6Q==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16} + hasBin: true + dev: true + bundledDependencies: + - '@isaacs/string-locale-compare' + - '@npmcli/arborist' + - '@npmcli/ci-detect' + - '@npmcli/config' + - '@npmcli/map-workspaces' + - '@npmcli/package-json' + - '@npmcli/run-script' + - abbrev + - ansicolors + - ansistyles + - archy + - cacache + - chalk + - chownr + - cli-columns + - cli-table3 + - columnify + - fastest-levenshtein + - glob + - graceful-fs + - hosted-git-info + - ini + - init-package-json + - is-cidr + - json-parse-even-better-errors + - libnpmaccess + - libnpmdiff + - libnpmexec + - libnpmfund + - libnpmhook + - libnpmorg + - libnpmpack + - libnpmpublish + - libnpmsearch + - libnpmteam + - libnpmversion + - make-fetch-happen + - minipass + - minipass-pipeline + - mkdirp + - mkdirp-infer-owner + - ms + - node-gyp + - nopt + - npm-audit-report + - npm-install-checks + - npm-package-arg + - npm-pick-manifest + - npm-profile + - npm-registry-fetch + - npm-user-validate + - npmlog + - opener + - pacote + - parse-conflict-json + - proc-log + - qrcode-terminal + - read + - read-package-json + - read-package-json-fast + - readdir-scoped-modules + - rimraf + - semver + - ssri + - tar + - text-table + - tiny-relative-date + - treeverse + - validate-npm-package-name + - which + - write-file-atomic + + /npmlog/4.1.2: + resolution: {integrity: sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==} + dependencies: + are-we-there-yet: 1.1.7 + console-control-strings: 1.1.0 + gauge: 2.7.4 + set-blocking: 2.0.0 + dev: true + /nth-check/2.0.1: resolution: {integrity: sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==} dependencies: boolbase: 1.0.0 dev: true + /number-is-nan/1.0.1: + resolution: {integrity: sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=} + engines: {node: '>=0.10.0'} + dev: true + /nwsapi/2.2.0: resolution: {integrity: sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==} dev: true + /oauth-sign/0.9.0: + resolution: {integrity: sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==} + dev: true + optional: true + /object-assign/4.1.1: resolution: {integrity: sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=} engines: {node: '>=0.10.0'} @@ -5726,6 +9585,11 @@ packages: engines: {node: '>= 0.4'} dev: true + /object-path/0.11.8: + resolution: {integrity: sha512-YJjNZrlXJFM42wTBn6zgOJVar9KFJvzx6sTWDte8sWZF//cnjl0BxHNpfZx+ZffXX63A9q0b1zsFiBX4g4X5KA==} + engines: {node: '>= 10.12.0'} + dev: true + /object.assign/4.1.2: resolution: {integrity: sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==} engines: {node: '>= 0.4'} @@ -5770,10 +9634,18 @@ packages: es-abstract: 1.19.1 dev: true + /oblivious-set/1.0.0: + resolution: {integrity: sha512-z+pI07qxo4c2CulUHCDf9lcqDlMSo72N/4rLUpRXf6fu+q8vjt8y0xS+Tlf8NTJDdTXHbdeO1n3MlbctwEoXZw==} + dev: false + /obuf/1.1.2: resolution: {integrity: sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==} dev: true + /on-exit-leak-free/0.2.0: + resolution: {integrity: sha512-dqaz3u44QbRXQooZLTUKU41ZrzYrcvLISVgbrzbyCMxpmSLJvZ3ZamIJIZ29P6OhZIkNIQKosdeM6t1LYbA9hg==} + dev: false + /on-finished/2.3.0: resolution: {integrity: sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=} engines: {node: '>= 0.8'} @@ -5790,6 +9662,12 @@ packages: resolution: {integrity: sha1-WDsap3WWHUsROsF9nFC6753Xa9E=} dependencies: wrappy: 1.0.2 + + /onetime/2.0.1: + resolution: {integrity: sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=} + engines: {node: '>=4'} + dependencies: + mimic-fn: 1.2.0 dev: true /onetime/5.1.2: @@ -5832,11 +9710,38 @@ packages: word-wrap: 1.2.3 dev: true - /p-event/4.2.0: - resolution: {integrity: sha512-KXatOjCRXXkSePPb1Nbi0p0m+gQAwdlbhi4wQKJPI1HsMQS9g+Sqp2o+QHziPr7eYJyOZet836KoHEVM1mwOrQ==} + /os-homedir/1.0.2: + resolution: {integrity: sha1-/7xJiDNuDoM94MFox+8VISGqf7M=} + engines: {node: '>=0.10.0'} + dev: true + + /os-tmpdir/1.0.2: + resolution: {integrity: sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=} + engines: {node: '>=0.10.0'} + dev: true + + /osenv/0.1.5: + resolution: {integrity: sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==} + dependencies: + os-homedir: 1.0.2 + os-tmpdir: 1.0.2 + dev: true + + /p-cancelable/1.1.0: + resolution: {integrity: sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==} + engines: {node: '>=6'} + dev: true + + /p-each-series/2.2.0: + resolution: {integrity: sha512-ycIL2+1V32th+8scbpTvyHNaHe02z0sjgh91XXjAk+ZeXoPN4Z46DVUnzdso0aX4KckKw0FNNFHdjZ2UsZvxiA==} + engines: {node: '>=8'} + dev: true + + /p-filter/2.1.0: + resolution: {integrity: sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==} engines: {node: '>=8'} dependencies: - p-timeout: 3.2.0 + p-map: 2.1.0 dev: true /p-finally/1.0.0: @@ -5844,6 +9749,11 @@ packages: engines: {node: '>=4'} dev: true + /p-is-promise/3.0.0: + resolution: {integrity: sha512-Wo8VsW4IRQSKVXsJCn7TomUaVtyfjVDn3nUP7kE967BQk0CwFpdbZs0X0uk5sW9mkBa9eNM7hCMaG93WUAwxYQ==} + engines: {node: '>=8'} + dev: true + /p-limit/1.3.0: resolution: {integrity: sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==} engines: {node: '>=4'} @@ -5898,6 +9808,11 @@ packages: aggregate-error: 3.1.0 dev: true + /p-reduce/2.1.0: + resolution: {integrity: sha512-2USApvnsutq8uoxZBGbbWM0JIYLiEMJ9RlaN7fAzVNb9OZN0SHjjTTfIcb667XynS5Y1VhwDJVDa72TnPzAYWw==} + engines: {node: '>=8'} + dev: true + /p-retry/4.6.1: resolution: {integrity: sha512-e2xXGNhZOZ0lfgR9kL34iGlU8N/KO0xZnQxVEwdeOvpqNDQfdnxIYizvWtK8RglUa3bGqI8g0R/BdfzLMxRkiA==} engines: {node: '>=8'} @@ -5906,13 +9821,6 @@ packages: retry: 0.13.1 dev: true - /p-timeout/3.2.0: - resolution: {integrity: sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==} - engines: {node: '>=8'} - dependencies: - p-finally: 1.0.0 - dev: true - /p-try/1.0.0: resolution: {integrity: sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=} engines: {node: '>=4'} @@ -5923,11 +9831,21 @@ packages: engines: {node: '>=6'} dev: true + /package-json/4.0.1: + resolution: {integrity: sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0=} + engines: {node: '>=4'} + dependencies: + got: 6.7.1 + registry-auth-token: 3.4.0 + registry-url: 3.1.0 + semver: 5.7.1 + dev: true + /param-case/3.0.4: resolution: {integrity: sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==} dependencies: dot-case: 3.0.4 - tslib: 2.3.1 + tslib: 2.4.1 dev: true /parent-module/1.0.1: @@ -5937,11 +9855,19 @@ packages: callsites: 3.1.0 dev: true + /parse-json/4.0.0: + resolution: {integrity: sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=} + engines: {node: '>=4'} + dependencies: + error-ex: 1.3.2 + json-parse-better-errors: 1.0.2 + dev: true + /parse-json/5.2.0: resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} engines: {node: '>=8'} dependencies: - '@babel/code-frame': 7.16.0 + '@babel/code-frame': 7.16.7 error-ex: 1.3.2 json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 @@ -5960,7 +9886,11 @@ packages: resolution: {integrity: sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==} dependencies: no-case: 3.0.4 - tslib: 2.3.1 + tslib: 2.4.1 + dev: true + + /path-browserify/1.0.1: + resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} dev: true /path-exists/3.0.0: @@ -5976,12 +9906,16 @@ packages: /path-is-absolute/1.0.1: resolution: {integrity: sha1-F0uSaHNVNP+8es5r9TpanhtcX18=} engines: {node: '>=0.10.0'} - dev: true /path-is-inside/1.0.2: resolution: {integrity: sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=} dev: true + /path-key/2.0.1: + resolution: {integrity: sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=} + engines: {node: '>=4'} + dev: true + /path-key/3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} @@ -6000,6 +9934,27 @@ packages: engines: {node: '>=8'} dev: true + /pbf/3.2.1: + resolution: {integrity: sha512-ClrV7pNOn7rtmoQVF4TS1vyU0WhYRnP92fzbfF75jAIwpnzdJXf8iTd4CMEqO4yUenH6NDqLiwjqlh6QgZzgLQ==} + hasBin: true + dependencies: + ieee754: 1.2.1 + resolve-protobuf-schema: 2.1.0 + dev: true + + /pend/1.2.0: + resolution: {integrity: sha1-elfrVQpng/kRUzH89GY9XI4AelA=} + dev: true + + /performance-now/2.1.0: + resolution: {integrity: sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=} + dev: true + optional: true + + /pg-connection-string/2.5.0: + resolution: {integrity: sha512-r5o/V/ORTA6TmUnyWZR9nCj1klXCO2CEKNRlVuJptZe85QuhFayC7WeMic7ndayT5IRIR0S0xFxFi2ousartlQ==} + dev: true + /picocolors/1.0.0: resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} dev: true @@ -6014,6 +9969,11 @@ packages: engines: {node: '>=0.10.0'} dev: true + /pify/3.0.0: + resolution: {integrity: sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=} + engines: {node: '>=4'} + dev: true + /pify/4.0.1: resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} engines: {node: '>=6'} @@ -6031,18 +9991,45 @@ packages: engines: {node: '>=0.10.0'} dev: true - /pirates/4.0.1: - resolution: {integrity: sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA==} - engines: {node: '>= 6'} + /pino-abstract-transport/0.5.0: + resolution: {integrity: sha512-+KAgmVeqXYbTtU2FScx1XS3kNyfZ5TrXY07V96QnUSFqo2gAqlvmaxH67Lj7SWazqsMabf+58ctdTcBgnOLUOQ==} + dependencies: + duplexify: 4.1.2 + split2: 4.1.0 + dev: false + + /pino-std-serializers/4.0.0: + resolution: {integrity: sha512-cK0pekc1Kjy5w9V2/n+8MkZwusa6EyyxfeQCB799CQRhRt/CqYKiWs5adeu8Shve2ZNffvfC/7J64A2PJo1W/Q==} + dev: false + + /pino/7.11.0: + resolution: {integrity: sha512-dMACeu63HtRLmCG8VKdy4cShCPKaYDR4youZqoSWLxl5Gu99HUw8bw75thbPv9Nip+H+QYX8o3ZJbTdVZZ2TVg==} + hasBin: true dependencies: - node-modules-regexp: 1.0.0 + atomic-sleep: 1.0.0 + fast-redact: 3.1.1 + on-exit-leak-free: 0.2.0 + pino-abstract-transport: 0.5.0 + pino-std-serializers: 4.0.0 + process-warning: 1.0.0 + quick-format-unescaped: 4.0.4 + real-require: 0.1.0 + safe-stable-stringify: 2.3.1 + sonic-boom: 2.8.0 + thread-stream: 0.15.2 + dev: false + + /pirates/4.0.5: + resolution: {integrity: sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==} + engines: {node: '>= 6'} dev: true - /pkg-dir/2.0.0: - resolution: {integrity: sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=} + /pkg-conf/2.1.0: + resolution: {integrity: sha1-ISZRTKbyq/69FoWW3xi6V4Z/AFg=} engines: {node: '>=4'} dependencies: find-up: 2.1.0 + load-json-file: 4.0.0 dev: true /pkg-dir/4.2.0: @@ -6059,69 +10046,13 @@ packages: async: 2.6.3 debug: 3.2.7 mkdirp: 0.5.5 - dev: true - - /postcss-modules-extract-imports/3.0.0_postcss@8.3.11: - resolution: {integrity: sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==} - engines: {node: ^10 || ^12 || >= 14} - peerDependencies: - postcss: ^8.1.0 - dependencies: - postcss: 8.3.11 - dev: true - - /postcss-modules-local-by-default/4.0.0_postcss@8.3.11: - resolution: {integrity: sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==} - engines: {node: ^10 || ^12 || >= 14} - peerDependencies: - postcss: ^8.1.0 - dependencies: - icss-utils: 5.1.0_postcss@8.3.11 - postcss: 8.3.11 - postcss-selector-parser: 6.0.6 - postcss-value-parser: 4.1.0 - dev: true - - /postcss-modules-scope/3.0.0_postcss@8.3.11: - resolution: {integrity: sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==} - engines: {node: ^10 || ^12 || >= 14} - peerDependencies: - postcss: ^8.1.0 - dependencies: - postcss: 8.3.11 - postcss-selector-parser: 6.0.6 - dev: true - - /postcss-modules-values/4.0.0_postcss@8.3.11: - resolution: {integrity: sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==} - engines: {node: ^10 || ^12 || >= 14} - peerDependencies: - postcss: ^8.1.0 - dependencies: - icss-utils: 5.1.0_postcss@8.3.11 - postcss: 8.3.11 - dev: true - - /postcss-selector-parser/6.0.6: - resolution: {integrity: sha512-9LXrvaaX3+mcv5xkg5kFwqSzSH1JIObIx51PrndZwlmznwXRfxMddDvo9gve3gVR8ZTKgoFDdWkbRFmEhT4PMg==} - engines: {node: '>=4'} - dependencies: - cssesc: 3.0.0 - util-deprecate: 1.0.2 + transitivePeerDependencies: + - supports-color dev: true /postcss-value-parser/4.1.0: resolution: {integrity: sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==} - /postcss/8.3.11: - resolution: {integrity: sha512-hCmlUAIlUiav8Xdqw3Io4LcpA1DOt7h3LSTAC4G6JGHFFaWzI6qvFt9oilvl8BmkbBRX1IhM90ZAmpk68zccQA==} - engines: {node: ^10 || ^12 || >=14} - dependencies: - nanoid: 3.1.30 - picocolors: 1.0.0 - source-map-js: 0.6.2 - dev: true - /prelude-ls/1.1.2: resolution: {integrity: sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=} engines: {node: '>= 0.8.0'} @@ -6132,6 +10063,16 @@ packages: engines: {node: '>= 0.8.0'} dev: true + /prepend-http/1.0.4: + resolution: {integrity: sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=} + engines: {node: '>=0.10.0'} + dev: true + + /prepend-http/2.0.0: + resolution: {integrity: sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=} + engines: {node: '>=4'} + dev: true + /prettier-linter-helpers/1.0.0: resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} engines: {node: '>=6.0.0'} @@ -6139,8 +10080,8 @@ packages: fast-diff: 1.2.0 dev: true - /prettier/2.4.1: - resolution: {integrity: sha512-9fbDAXSBcc6Bs1mZrDYb3XKzDLm4EXXL9sC1LqKP5rZkT6KRr/rf9amVUcODVXgguK/isJz0d0hP72WeaKWsvA==} + /prettier/2.5.1: + resolution: {integrity: sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==} engines: {node: '>=10.13.0'} hasBin: true dev: true @@ -6156,16 +10097,35 @@ packages: resolution: {integrity: sha512-DR/c+pvFc52nLimLROYjnXPtolawm+uWDxr4FjuLDLUn+ktWnSN851KoHwHzzqq6rfCOjkzN8FLgDrSub6UDuA==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dependencies: - '@jest/types': 27.2.5 + '@jest/types': 27.5.1 + ansi-regex: 5.0.1 + ansi-styles: 5.2.0 + react-is: 17.0.2 + dev: true + + /pretty-format/27.5.1: + resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + dependencies: ansi-regex: 5.0.1 ansi-styles: 5.2.0 react-is: 17.0.2 dev: true + /printj/1.3.1: + resolution: {integrity: sha512-GA3TdL8szPK4AQ2YnOe/b+Y1jUFwmmGMMK/qbY7VcE3Z7FU8JstbKiKRzO6CIiAKPhTO8m01NoQ0V5f3jc4OGg==} + engines: {node: '>=0.8'} + hasBin: true + dev: true + /process-nextick-args/2.0.1: resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} dev: true + /process-warning/1.0.0: + resolution: {integrity: sha512-du4wfLyj4yCZq1VupnVSZmRsPJsNuxoDQFdCFHLaYiEbFBD7QE0a+I4D7hOxrVnh78QE/YipFAj9lXHiXocV+Q==} + dev: false + /progress/2.0.3: resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} engines: {node: '>=0.4.0'} @@ -6185,6 +10145,22 @@ packages: loose-envify: 1.4.0 object-assign: 4.1.1 react-is: 16.13.1 + + /prop-types/15.8.1: + resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} + dependencies: + loose-envify: 1.4.0 + object-assign: 4.1.1 + react-is: 16.13.1 + dev: true + + /proto-list/1.2.4: + resolution: {integrity: sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=} + dev: true + optional: true + + /protocol-buffers-schema/3.6.0: + resolution: {integrity: sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw==} dev: true /proxy-addr/2.0.7: @@ -6195,12 +10171,19 @@ packages: ipaddr.js: 1.9.1 dev: true + /pseudomap/1.0.2: + resolution: {integrity: sha1-8FKijacOYYkX7wqKw0wa5aaChrM=} + dev: true + /psl/1.8.0: resolution: {integrity: sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==} dev: true - /punycode/1.3.2: - resolution: {integrity: sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=} + /pump/3.0.0: + resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==} + dependencies: + end-of-stream: 1.4.4 + once: 1.4.0 dev: true /punycode/2.1.1: @@ -6208,11 +10191,32 @@ packages: engines: {node: '>=6'} dev: true + /q/1.5.1: + resolution: {integrity: sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=} + engines: {node: '>=0.6.0', teleport: '>=0.2.0'} + dev: true + + /qs/6.5.3: + resolution: {integrity: sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==} + engines: {node: '>=0.6'} + dev: true + optional: true + /qs/6.7.0: resolution: {integrity: sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==} engines: {node: '>=0.6'} dev: true + /qs/6.9.6: + resolution: {integrity: sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ==} + engines: {node: '>=0.6'} + dev: true + + /qs/6.9.7: + resolution: {integrity: sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==} + engines: {node: '>=0.6'} + dev: true + /querystring/0.2.0: resolution: {integrity: sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=} engines: {node: '>=0.4.x'} @@ -6223,6 +10227,19 @@ packages: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} dev: true + /quick-format-unescaped/4.0.4: + resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==} + dev: false + + /quick-lru/4.0.1: + resolution: {integrity: sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==} + engines: {node: '>=8'} + dev: true + + /ramda/0.28.0: + resolution: {integrity: sha512-9QnLuG/kPVgWvMQ4aODhsBUFKOUmnbUnsSXACv+NCQZcHbeb+v8Lodp8OVxtRULN1/xOyYLLaL6npE6dMq5QTA==} + dev: true + /randombytes/2.1.0: resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} dependencies: @@ -6234,15 +10251,113 @@ packages: engines: {node: '>= 0.6'} dev: true - /raw-body/2.4.0: - resolution: {integrity: sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==} - engines: {node: '>= 0.8'} + /raw-body/2.4.0: + resolution: {integrity: sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==} + engines: {node: '>= 0.8'} + dependencies: + bytes: 3.1.0 + http-errors: 1.7.2 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + dev: true + + /raw-body/2.4.2: + resolution: {integrity: sha512-RPMAFUJP19WIet/99ngh6Iv8fzAbqum4Li7AD6DtGaW2RpMB/11xDoalPiJMTbu6I3hkbMVkATvZrqb9EEqeeQ==} + engines: {node: '>= 0.8'} + dependencies: + bytes: 3.1.1 + http-errors: 1.8.1 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + dev: true + + /raw-body/2.4.3: + resolution: {integrity: sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==} + engines: {node: '>= 0.8'} + dependencies: + bytes: 3.1.2 + http-errors: 1.8.1 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + dev: true + + /rc/1.2.8: + resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} + hasBin: true + dependencies: + deep-extend: 0.6.0 + ini: 1.3.8 + minimist: 1.2.5 + strip-json-comments: 2.0.1 + dev: true + + /react-base16-styling/0.9.1: + resolution: {integrity: sha512-1s0CY1zRBOQ5M3T61wetEpvQmsYSNtWEcdYzyZNxKa8t7oDvaOn9d21xrGezGAHFWLM7SHcktPuPTrvoqxSfKw==} + dependencies: + '@babel/runtime': 7.17.2 + '@types/base16': 1.0.2 + '@types/lodash': 4.14.178 + base16: 1.0.0 + color: 3.2.1 + csstype: 3.0.10 + lodash.curry: 4.1.1 + dev: true + + /react-devtools-core/4.23.0: + resolution: {integrity: sha512-KkzneT1LczFtebbTJlvRphIRvzuHLhI9ghfrseVv9ktBs+l2cXy8Svw5U16lzQnwU9okVEcURmGPgH79WWrlaw==} + dependencies: + shell-quote: 1.7.3 + ws: 7.5.5 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + dev: true + + /react-devtools/4.23.0: + resolution: {integrity: sha512-3pvegA9tcO2b1QfS8fvxHEWzB7762kt8mUJNRyxQNaWz/+dPbJT3yGOF4eChkelolMbzqUSfZXE8pRyRgeAc/w==} + hasBin: true + dependencies: + cross-spawn: 5.1.0 + electron: 11.5.0 + ip: 1.1.5 + minimist: 1.2.5 + react-devtools-core: 4.23.0 + update-notifier: 2.5.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + dev: true + + /react-dnd-html5-backend/16.0.1: + resolution: {integrity: sha512-Wu3dw5aDJmOGw8WjH1I1/yTH+vlXEL4vmjk5p+MHxP8HuHJS1lAGeIdG/hze1AvNeXWo/JgULV87LyQOr+r5jw==} + dependencies: + dnd-core: 16.0.1 + dev: false + + /react-dnd/16.0.1_udcsdvdzjr5ns727jqoeu7kyda: + resolution: {integrity: sha512-QeoM/i73HHu2XF9aKksIUuamHPDvRglEwdHL4jsp784BgUuWcg6mzfxT0QDdQz8Wj0qyRKx2eMg8iZtWvU4E2Q==} + peerDependencies: + '@types/hoist-non-react-statics': '>= 3.3.1' + '@types/node': '>= 12' + '@types/react': '>= 16' + react: '>= 16.14' + peerDependenciesMeta: + '@types/hoist-non-react-statics': + optional: true + '@types/node': + optional: true + '@types/react': + optional: true dependencies: - bytes: 3.1.0 - http-errors: 1.7.2 - iconv-lite: 0.4.24 - unpipe: 1.0.0 - dev: true + '@react-dnd/invariant': 4.0.2 + '@react-dnd/shallowequal': 4.0.2 + '@types/react': 17.0.39 + dnd-core: 16.0.1 + fast-deep-equal: 3.1.3 + hoist-non-react-statics: 3.3.2 + react: 17.0.2 + dev: false /react-dom/17.0.2_react@17.0.2: resolution: {integrity: sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==} @@ -6253,27 +10368,127 @@ packages: object-assign: 4.1.1 react: 17.0.2 scheduler: 0.20.2 - dev: false + + /react-dragula/1.1.17: + resolution: {integrity: sha1-s8s1KkcKcZNnupnWpUAcYPrU9v8=} + dependencies: + atoa: 1.0.0 + dragula: 3.7.2 + dev: true + + /react-icons/4.3.1_react@17.0.2: + resolution: {integrity: sha512-cB10MXLTs3gVuXimblAdI71jrJx8njrJZmNMEMC+sQu5B/BIOmlsAjskdqpn81y8UBVEGuHODd7/ci5DvoSzTQ==} + peerDependencies: + react: '*' + dependencies: + react: 17.0.2 + dev: true /react-is/16.13.1: resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} /react-is/17.0.2: resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} + + /react-json-tree/0.16.1_udcsdvdzjr5ns727jqoeu7kyda: + resolution: {integrity: sha512-VYvU/tgekJUrPhEVR6ZC789b3x9QPO7LmRX1YMZfWpqbC8pvXb7D74S0+CE6RVk55bXOS2VH1+8ZWA2PioEyqg==} + peerDependencies: + '@types/react': ^16.3.0 || ^17.0.0 + react: ^16.3.0 || ^17.0.0 + dependencies: + '@babel/runtime': 7.17.2 + '@types/prop-types': 15.7.4 + '@types/react': 17.0.39 + prop-types: 15.8.1 + react: 17.0.2 + react-base16-styling: 0.9.1 dev: true + /react-redux/7.2.6_sfoxds7t5ydpegc3knd667wn6m: + resolution: {integrity: sha512-10RPdsz0UUrRL1NZE0ejTkucnclYSgXp5q+tB5SWx2qeG2ZJQJyymgAhwKy73yiL/13btfB6fPr+rgbMAaZIAQ==} + peerDependencies: + react: ^16.8.3 || ^17 + react-dom: '*' + react-native: '*' + peerDependenciesMeta: + react-dom: + optional: true + react-native: + optional: true + dependencies: + '@babel/runtime': 7.16.3 + '@types/react-redux': 7.1.25 + hoist-non-react-statics: 3.3.2 + loose-envify: 1.4.0 + prop-types: 15.7.2 + react: 17.0.2 + react-dom: 17.0.2_react@17.0.2 + react-is: 17.0.2 + /react-refresh/0.11.0: resolution: {integrity: sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A==} engines: {node: '>=0.10.0'} dev: true + /react-select/5.2.2_ivj6fu6x63tqzxiw3bovn75e4a: + resolution: {integrity: sha512-miGS2rT1XbFNjduMZT+V73xbJEeMzVkJOz727F6MeAr2hKE0uUSA8Ff7vD44H32x2PD3SRB6OXTY/L+fTV3z9w==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 + react-dom: ^16.8.0 || ^17.0.0 + dependencies: + '@babel/runtime': 7.17.2 + '@emotion/cache': 11.7.1 + '@emotion/react': 11.7.1_oeypub6dug5xwmzqzpvzyakzzi + '@types/react-transition-group': 4.4.4 + memoize-one: 5.2.1 + prop-types: 15.8.1 + react: 17.0.2 + react-dom: 17.0.2_react@17.0.2 + react-transition-group: 4.4.2_sfoxds7t5ydpegc3knd667wn6m + transitivePeerDependencies: + - '@babel/core' + - '@types/react' + dev: true + + /react-transition-group/4.4.2_sfoxds7t5ydpegc3knd667wn6m: + resolution: {integrity: sha512-/RNYfRAMlZwDSr6z4zNKV6xu53/e2BuaBbGhbyYIXTrmgu/bGHzmqOs7mJSJBHy9Ud+ApHx3QjrkKSp1pxvlFg==} + peerDependencies: + react: '>=16.6.0' + react-dom: '>=16.6.0' + dependencies: + '@babel/runtime': 7.17.2 + dom-helpers: 5.2.1 + loose-envify: 1.4.0 + prop-types: 15.8.1 + react: 17.0.2 + react-dom: 17.0.2_react@17.0.2 + dev: true + /react/17.0.2: resolution: {integrity: sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==} engines: {node: '>=0.10.0'} dependencies: loose-envify: 1.4.0 object-assign: 4.1.1 - dev: false + + /read-pkg-up/7.0.1: + resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} + engines: {node: '>=8'} + dependencies: + find-up: 4.1.0 + read-pkg: 5.2.0 + type-fest: 0.8.1 + dev: true + + /read-pkg/5.2.0: + resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} + engines: {node: '>=8'} + dependencies: + '@types/normalize-package-data': 2.4.1 + normalize-package-data: 2.5.0 + parse-json: 5.2.0 + type-fest: 0.6.0 + dev: true /readable-stream/2.3.7: resolution: {integrity: sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==} @@ -6294,6 +10509,11 @@ packages: inherits: 2.0.4 string_decoder: 1.3.0 util-deprecate: 1.0.2 + + /readdir-glob/1.1.1: + resolution: {integrity: sha512-91/k1EzZwDx6HbERR+zucygRFfiPl2zkIYZtv3Jjr6Mn7SkKcVct8aVO+sSRiGMc6fLf72du3d92/uY63YPdEA==} + dependencies: + minimatch: 3.0.4 dev: true /readdirp/3.6.0: @@ -6303,6 +10523,18 @@ packages: picomatch: 2.3.0 dev: true + /real-require/0.1.0: + resolution: {integrity: sha512-r/H9MzAWtrv8aSVjPCMFpDMl5q66GqtmmRkRjpHTsp4zBAa+snZyiQNlMONiUmEJcsnaw0wCauJ2GWODr/aFkg==} + engines: {node: '>= 12.13.0'} + dev: false + + /rechoir/0.7.0: + resolution: {integrity: sha512-ADsDEH2bvbjltXEP+hTIAmeFekTFK0V2BTxMkok6qILyAJEXV0AFfoWcAq4yfll5VdIMd/RVXq0lR+wQi5ZU3Q==} + engines: {node: '>= 0.10'} + dependencies: + resolve: 1.20.0 + dev: true + /rechoir/0.7.1: resolution: {integrity: sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==} engines: {node: '>= 0.10'} @@ -6318,8 +10550,83 @@ packages: strip-indent: 3.0.0 dev: true - /regenerate-unicode-properties/9.0.0: - resolution: {integrity: sha512-3E12UeNSPfjrgwjkR81m5J7Aw/T55Tu7nUyZVQYCKEOs+2dkxEY+DpPtZzO4YruuiPb7NkYLVcyJC4+zCbk5pA==} + /redeyed/2.1.1: + resolution: {integrity: sha1-iYS1gV2ZyyIEacme7v/jiRPmzAs=} + dependencies: + esprima: 4.0.1 + dev: true + + /redux-devtools-core/0.2.1: + resolution: {integrity: sha512-RAGOxtUFdr/1USAvxrWd+Gq/Euzgw7quCZlO5TgFpDfG7rB5tMhZUrNyBjpzgzL2yMk0eHnPYIGm7NkIfRzHxQ==} + deprecated: Package moved to @redux-devtools/app. + dependencies: + get-params: 0.1.2 + jsan: 3.1.14 + lodash: 4.17.21 + nanoid: 2.1.11 + remotedev-serialize: 0.1.9 + dev: true + + /redux-devtools-instrument/1.10.0_redux@4.1.2: + resolution: {integrity: sha512-X8JRBCzX2ADSMp+iiV7YQ8uoTNyEm0VPFPd4T854coz6lvRiBrFSqAr9YAS2n8Kzxx8CJQotR0QF9wsMM+3DvA==} + deprecated: Package moved to @redux-devtools/instrument. + peerDependencies: + redux: ^3.4.0 || ^4.0.0 + dependencies: + lodash: 4.17.21 + redux: 4.1.2 + symbol-observable: 1.2.0 + dev: true + + /redux-devtools-themes/1.0.0: + resolution: {integrity: sha1-xILc48U3OXYEX0ATSQfZ3LOuPV0=} + dependencies: + base16: 1.0.0 + dev: true + + /redux-logger/3.0.6: + resolution: {integrity: sha512-JoCIok7bg/XpqA1JqCqXFypuqBbQzGQySrhFzewB7ThcnysTO30l4VCst86AuB9T9tuT03MAA56Jw2PNhRSNCg==} + dependencies: + deep-diff: 0.3.8 + dev: false + + /redux-persist/6.0.0_react@17.0.2+redux@4.1.2: + resolution: {integrity: sha512-71LLMbUq2r02ng2We9S215LtPu3fY0KgaGE0k8WRgl6RkqxtGfl7HUozz1Dftwsb0D/5mZ8dwAaPbtnzfvbEwQ==} + peerDependencies: + react: '>=16' + redux: '>4.0.0' + peerDependenciesMeta: + react: + optional: true + dependencies: + react: 17.0.2 + redux: 4.1.2 + + /redux-state-sync/3.1.4: + resolution: {integrity: sha512-nhJBzaXVXPXvUhQJ7m0LdoXBnrcw+cTYQ8bzW9DeJKdq6UNYynXwQWAlVUvsbT/hDV+vB6BC4DMLXkUVGpF2yQ==} + dependencies: + broadcast-channel: 3.7.0 + dev: false + + /redux-thunk/2.4.1_redux@4.1.2: + resolution: {integrity: sha512-OOYGNY5Jy2TWvTL1KgAlVy6dcx3siPJ1wTq741EPyUKfn6W6nChdICjZwCd0p8AZBs5kWpZlbkXW2nE/zjUa+Q==} + peerDependencies: + redux: ^4 + dependencies: + redux: 4.1.2 + + /redux/4.1.2: + resolution: {integrity: sha512-SH8PglcebESbd/shgf6mii6EIoRM0zrQyjcuQ+ojmfxjTtE0z9Y8pa62iA/OJ58qjP6j27uyW4kUF4jl/jd6sw==} + dependencies: + '@babel/runtime': 7.16.3 + + /redux/4.2.0: + resolution: {integrity: sha512-oSBmcKKIuIR4ME29/AeNUnl5L+hvBq7OaJWzaptTQJAntaPvxIJqfnjbaEiCzzaIz+XmVILfqAM3Ob0aXLPfjA==} + dependencies: + '@babel/runtime': 7.17.2 + + /regenerate-unicode-properties/10.0.1: + resolution: {integrity: sha512-vn5DU6yg6h8hP/2OkQo3K7uVILvY4iu0oI4t3HFa81UPkhGJwkRwM10JEc3upjdhHjs/k8GJY1sRBhk5sr69Bw==} engines: {node: '>=4'} dependencies: regenerate: 1.4.2 @@ -6331,12 +10638,11 @@ packages: /regenerator-runtime/0.13.9: resolution: {integrity: sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==} - dev: true /regenerator-transform/0.14.5: resolution: {integrity: sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==} dependencies: - '@babel/runtime': 7.16.3 + '@babel/runtime': 7.17.2 dev: true /regexp.prototype.flags/1.3.1: @@ -6352,24 +10658,45 @@ packages: engines: {node: '>=8'} dev: true - /regexpu-core/4.8.0: - resolution: {integrity: sha512-1F6bYsoYiz6is+oz70NWur2Vlh9KWtswuRuzJOfeYUrfPX2o8n74AnUVaOGDbUqVGO9fNHu48/pjJO4sNVwsOg==} + /regexpu-core/5.0.1: + resolution: {integrity: sha512-CriEZlrKK9VJw/xQGJpQM5rY88BtuL8DM+AEwvcThHilbxiTAy8vq4iJnd2tqq8wLmjbGZzP7ZcKFjbGkmEFrw==} engines: {node: '>=4'} dependencies: regenerate: 1.4.2 - regenerate-unicode-properties: 9.0.0 - regjsgen: 0.5.2 - regjsparser: 0.7.0 + regenerate-unicode-properties: 10.0.1 + regjsgen: 0.6.0 + regjsparser: 0.8.4 unicode-match-property-ecmascript: 2.0.0 unicode-match-property-value-ecmascript: 2.0.0 dev: true - /regjsgen/0.5.2: - resolution: {integrity: sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A==} + /registry-auth-token/3.4.0: + resolution: {integrity: sha512-4LM6Fw8eBQdwMYcES4yTnn2TqIasbXuwDx3um+QRs7S55aMKCBKBxvPXl2RiUjHwuJLTyYfxSpmfSAjQpcuP+A==} + dependencies: + rc: 1.2.8 + safe-buffer: 5.2.1 + dev: true + + /registry-auth-token/4.2.1: + resolution: {integrity: sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw==} + engines: {node: '>=6.0.0'} + dependencies: + rc: 1.2.8 + dev: true + + /registry-url/3.1.0: + resolution: {integrity: sha1-PU74cPc93h138M+aOBQyRE4XSUI=} + engines: {node: '>=0.10.0'} + dependencies: + rc: 1.2.8 + dev: true + + /regjsgen/0.6.0: + resolution: {integrity: sha512-ozE883Uigtqj3bx7OhL1KNbCzGyW2NQZPl6Hs09WTvCuZD5sTI4JY58bkbQWa/Y9hxIsvJ3M8Nbf7j54IqeZbA==} dev: true - /regjsparser/0.7.0: - resolution: {integrity: sha512-A4pcaORqmNMDVwUjWoTzuhwMGpP+NykpfqAsEgI1FSH/EzC7lrN5TMd+kN8YCovX+jMpu8eaqXgXPCa0g8FQNQ==} + /regjsparser/0.8.4: + resolution: {integrity: sha512-J3LABycON/VNEu3abOviqGHuB/LOtOQj8SKmfP9anY5GfAVw/SPjwzSjxGjbZXIxbGfqTHtJw58C2Li/WkStmA==} hasBin: true dependencies: jsesc: 0.5.0 @@ -6380,6 +10707,28 @@ packages: engines: {node: '>= 0.10'} dev: true + /remote-redux-devtools/0.5.16_redux@4.1.2: + resolution: {integrity: sha512-xZ2D1VRIWzat5nsvcraT6fKEX9Cfi+HbQBCwzNnUAM8Uicm/anOc60XGalcaDPrVmLug7nhDl2nimEa3bL3K9w==} + dependencies: + jsan: 3.1.14 + querystring: 0.2.0 + redux-devtools-core: 0.2.1 + redux-devtools-instrument: 1.10.0_redux@4.1.2 + rn-host-detect: 1.2.0 + socketcluster-client: 14.3.2 + transitivePeerDependencies: + - bufferutil + - redux + - utf-8-validate + dev: true + + /remotedev-serialize/0.1.9: + resolution: {integrity: sha512-5tFdZg9mSaAWTv6xmQ7HtHjKMLSFQFExEZOtJe10PLsv1wb7cy7kYHtBvTYRro27/3fRGEcQBRNKSaixOpb69w==} + deprecated: Package moved to @redux-devtools/serialize. + dependencies: + jsan: 3.1.14 + dev: true + /renderkid/3.0.0: resolution: {integrity: sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==} dependencies: @@ -6390,6 +10739,34 @@ packages: strip-ansi: 6.0.1 dev: true + /request/2.88.2: + resolution: {integrity: sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==} + engines: {node: '>= 6'} + deprecated: request has been deprecated, see https://github.com/request/request/issues/3142 + dependencies: + aws-sign2: 0.7.0 + aws4: 1.11.0 + caseless: 0.12.0 + combined-stream: 1.0.8 + extend: 3.0.2 + forever-agent: 0.6.1 + form-data: 2.3.3 + har-validator: 5.1.5 + http-signature: 1.2.0 + is-typedarray: 1.0.0 + isstream: 0.1.2 + json-stringify-safe: 5.0.1 + mime-types: 2.1.34 + oauth-sign: 0.9.0 + performance-now: 2.1.0 + qs: 6.5.3 + safe-buffer: 5.2.1 + tough-cookie: 2.5.0 + tunnel-agent: 0.6.0 + uuid: 3.4.0 + dev: true + optional: true + /require-directory/2.1.1: resolution: {integrity: sha1-jGStX9MNqxyXbiNE/+f3kqam30I=} engines: {node: '>=0.10.0'} @@ -6404,6 +10781,9 @@ packages: resolution: {integrity: sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=} dev: true + /reselect/4.1.5: + resolution: {integrity: sha512-uVdlz8J7OO+ASpBYoz1Zypgx0KasCY20H+N8JD13oUMtPvSHQuscrHop4KbXrbsBcdB9Ds7lVK7eRkBIfO43vQ==} + /resolve-cwd/3.0.0: resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} engines: {node: '>=8'} @@ -6421,6 +10801,12 @@ packages: engines: {node: '>=8'} dev: true + /resolve-protobuf-schema/2.1.0: + resolution: {integrity: sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ==} + dependencies: + protocol-buffers-schema: 3.6.0 + dev: true + /resolve.exports/1.1.0: resolution: {integrity: sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ==} engines: {node: '>=10'} @@ -6440,6 +10826,20 @@ packages: path-parse: 1.0.7 dev: true + /responselike/1.0.2: + resolution: {integrity: sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=} + dependencies: + lowercase-keys: 1.0.1 + dev: true + + /restore-cursor/2.0.0: + resolution: {integrity: sha1-n37ih/gv0ybU/RYpI9YhKe7g368=} + engines: {node: '>=4'} + dependencies: + onetime: 2.0.1 + signal-exit: 3.0.6 + dev: true + /retry/0.13.1: resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==} engines: {node: '>= 4'} @@ -6450,6 +10850,13 @@ packages: engines: {iojs: '>=1.0.0', node: '>=0.10.0'} dev: true + /rimraf/2.6.3: + resolution: {integrity: sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==} + hasBin: true + dependencies: + glob: 7.2.0 + dev: true + /rimraf/2.7.1: resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==} hasBin: true @@ -6462,6 +10869,27 @@ packages: hasBin: true dependencies: glob: 7.2.0 + + /rn-host-detect/1.2.0: + resolution: {integrity: sha512-btNg5kzHcjZZ7t7mvvV/4wNJ9e3MPgrWivkRgWURzXL0JJ0pwWlU4zrbmdlz3HHzHOxhBhHB4D+/dbMFfu4/4A==} + dev: true + + /roarr/2.15.4: + resolution: {integrity: sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==} + engines: {node: '>=8.0'} + dependencies: + boolean: 3.2.0 + detect-node: 2.1.0 + globalthis: 1.0.2 + json-stringify-safe: 5.0.1 + semver-compare: 1.0.0 + sprintf-js: 1.1.2 + dev: true + optional: true + + /run-async/2.4.1: + resolution: {integrity: sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==} + engines: {node: '>=0.12.0'} dev: true /run-parallel/1.2.0: @@ -6470,18 +10898,33 @@ packages: queue-microtask: 1.2.3 dev: true + /rxjs/5.5.12: + resolution: {integrity: sha512-xx2itnL5sBbqeeiVgNPVuQQ1nC8Jp2WfNJhXWHmElW9YmrpS9UVnNzhP3EH3HFqexO5Tlp8GhYY+WEcqcVMvGw==} + engines: {npm: '>=2.0.0'} + dependencies: + symbol-observable: 1.0.1 + dev: true + /safe-buffer/5.1.2: resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} dev: true /safe-buffer/5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - dev: true + + /safe-stable-stringify/2.3.1: + resolution: {integrity: sha512-kYBSfT+troD9cDA85VDnHZ1rpHC50O0g1e6WlGHVCz/g+JS+9WKLj+XwFYyR8UbrZN8ll9HUpDAAddY58MGisg==} + engines: {node: '>=10'} + dev: false /safer-buffer/2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} dev: true + /sax/1.2.4: + resolution: {integrity: sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==} + dev: true + /saxes/5.0.1: resolution: {integrity: sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==} engines: {node: '>=10'} @@ -6489,12 +10932,69 @@ packages: xmlchars: 2.2.0 dev: true + /sc-auth/5.0.2: + resolution: {integrity: sha512-Le3YBsFjzv5g6wIH6Y+vD+KFkK0HDXiaWy1Gm4nXtYebMQUyNYSf1cS83MtHrYzVEMlhYElRva1b0bvZ0hBqQw==} + dependencies: + jsonwebtoken: 8.5.1 + sc-errors: 1.4.1 + dev: true + + /sc-broker-cluster/7.0.0: + resolution: {integrity: sha512-DNG8sxiFwmRSMS0sUXA25UvDV8QTwEfYnzrutqbp4HlMU9JP65FBcs6GuNFPhjQN4s9VtwAE8BBaCNK5BjNV0g==} + engines: {node: '>= 0.8.0'} + dependencies: + async: 2.0.0 + sc-broker: 6.0.0 + sc-channel: 1.2.0 + sc-errors: 1.4.1 + sc-hasher: 1.0.1 + dev: true + + /sc-broker/6.0.0: + resolution: {integrity: sha512-c1mFIllUdPnEXDDFxTiX3obYW+cT0hb56fdNM5k+Xo5DI3+3Q9MYxTc8jD23qBIXOHokt4+d/CHocmZQPlAjAQ==} + engines: {node: '>= 0.8.0'} + dependencies: + async: 2.6.3 + expirymanager: 0.9.4 + fleximap: 1.0.0 + ncom: 1.0.3 + sc-errors: 1.4.1 + uuid: 3.1.0 + dev: true + + /sc-channel/1.2.0: + resolution: {integrity: sha512-M3gdq8PlKg0zWJSisWqAsMmTVxYRTpVRqw4CWAdKBgAfVKumFcTjoCV0hYu7lgUXccCtCD8Wk9VkkE+IXCxmZA==} + dependencies: + component-emitter: 1.2.1 + dev: true + + /sc-errors/1.4.1: + resolution: {integrity: sha512-dBn92iIonpChTxYLgKkIT/PCApvmYT6EPIbRvbQKTgY6tbEbIy8XVUv4pGyKwEK4nCmvX4TKXcN0iXC6tNW6rQ==} + dev: true + + /sc-errors/2.0.1: + resolution: {integrity: sha512-JoVhq3Ud+3Ujv2SIG7W0XtjRHsrNgl6iXuHHsh0s+Kdt5NwI6N2EGAZD4iteitdDv68ENBkpjtSvN597/wxPSQ==} + dev: true + + /sc-formatter/3.0.2: + resolution: {integrity: sha512-9PbqYBpCq+OoEeRQ3QfFIGE6qwjjBcd2j7UjgDlhnZbtSnuGgHdcRklPKYGuYFH82V/dwd+AIpu8XvA1zqTd+A==} + dev: true + + /sc-hasher/1.0.1: + resolution: {integrity: sha512-whZWw70Gp5ibXXMcz6+Tulmk8xkwWMs42gG70p12hGscdUg8BICBvihS3pX2T3dWTw+yeZuGKiULr3MwL37SOQ==} + dev: true + + /sc-simple-broker/2.1.3: + resolution: {integrity: sha512-ldt0ybOS5fVZSMea5Z8qVu7lmDBTy0qO9BD6TseJjRuPx+g+stfSqmPAb0RsCsQUXRH8A1koCbwsuUnI9BOxvw==} + dependencies: + sc-channel: 1.2.0 + dev: true + /scheduler/0.20.2: resolution: {integrity: sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==} dependencies: loose-envify: 1.4.0 object-assign: 4.1.1 - dev: false /schema-utils/2.7.1: resolution: {integrity: sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==} @@ -6505,34 +11005,103 @@ packages: ajv-keywords: 3.5.2_ajv@6.12.6 dev: true - /schema-utils/3.1.1: - resolution: {integrity: sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==} - engines: {node: '>= 10.13.0'} + /schema-utils/3.1.1: + resolution: {integrity: sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==} + engines: {node: '>= 10.13.0'} + dependencies: + '@types/json-schema': 7.0.9 + ajv: 6.12.6 + ajv-keywords: 3.5.2_ajv@6.12.6 + dev: true + + /schema-utils/4.0.0: + resolution: {integrity: sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==} + engines: {node: '>= 12.13.0'} + dependencies: + '@types/json-schema': 7.0.9 + ajv: 8.8.2 + ajv-formats: 2.1.1 + ajv-keywords: 5.1.0_ajv@8.8.2 + dev: true + + /select-hose/2.0.0: + resolution: {integrity: sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=} + dev: true + + /selfsigned/2.0.0: + resolution: {integrity: sha512-cUdFiCbKoa1mZ6osuJs2uDHrs0k0oprsKveFiiaBKCNq3SYyb5gs2HxhQyDNLCmL51ZZThqi4YNDpCK6GOP1iQ==} + engines: {node: '>=10'} + dependencies: + node-forge: 1.2.1 + dev: true + + /semantic-release/19.0.2: + resolution: {integrity: sha512-7tPonjZxukKECmClhsfyMKDt0GR38feIC2HxgyYaBi+9tDySBLjK/zYDLhh+m6yjnHIJa9eBTKYE7k63ZQcYbw==} + engines: {node: '>=16 || ^14.17'} + hasBin: true + dependencies: + '@semantic-release/commit-analyzer': 9.0.2_semantic-release@19.0.2 + '@semantic-release/error': 3.0.0 + '@semantic-release/github': 8.0.2_semantic-release@19.0.2 + '@semantic-release/npm': 9.0.0_semantic-release@19.0.2 + '@semantic-release/release-notes-generator': 10.0.3_semantic-release@19.0.2 + aggregate-error: 3.1.0 + cosmiconfig: 7.0.1 + debug: 4.3.2 + env-ci: 5.5.0 + execa: 5.1.1 + figures: 3.2.0 + find-versions: 4.0.0 + get-stream: 6.0.1 + git-log-parser: 1.2.0 + hook-std: 2.0.0 + hosted-git-info: 4.1.0 + lodash: 4.17.21 + marked: 4.0.12 + marked-terminal: 5.1.1_marked@4.0.12 + micromatch: 4.0.4 + p-each-series: 2.2.0 + p-reduce: 2.1.0 + read-pkg-up: 7.0.1 + resolve-from: 5.0.0 + semver: 7.3.5 + semver-diff: 3.1.1 + signale: 1.4.0 + yargs: 16.2.0 + transitivePeerDependencies: + - encoding + - supports-color + dev: true + + /semver-compare/1.0.0: + resolution: {integrity: sha1-De4hahyUGrN+nvsXiPavxf9VN/w=} + dev: true + optional: true + + /semver-diff/2.1.0: + resolution: {integrity: sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=} + engines: {node: '>=0.10.0'} dependencies: - '@types/json-schema': 7.0.9 - ajv: 6.12.6 - ajv-keywords: 3.5.2_ajv@6.12.6 + semver: 5.7.1 dev: true - /schema-utils/4.0.0: - resolution: {integrity: sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==} - engines: {node: '>= 12.13.0'} + /semver-diff/3.1.1: + resolution: {integrity: sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==} + engines: {node: '>=8'} dependencies: - '@types/json-schema': 7.0.9 - ajv: 8.8.2 - ajv-formats: 2.1.1 - ajv-keywords: 5.1.0_ajv@8.8.2 + semver: 6.3.0 dev: true - /select-hose/2.0.0: - resolution: {integrity: sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=} + /semver-regex/3.1.3: + resolution: {integrity: sha512-Aqi54Mk9uYTjVexLnR67rTyBusmwd04cLkHy9hNvk3+G3nT2Oyg7E0l4XVbOaNwIvQ3hHeYxGcyEy+mKreyBFQ==} + engines: {node: '>=8'} dev: true - /selfsigned/1.10.11: - resolution: {integrity: sha512-aVmbPOfViZqOZPgRBT0+3u4yZFHpmnIghLMlAcb5/xhp5ZtB/RVnKhz5vl2M32CLXAqR4kha9zfhNg0Lf/sxKA==} - dependencies: - node-forge: 0.10.0 + /semver/5.3.0: + resolution: {integrity: sha1-myzl094C0XxgEq0yaqa00M9U+U8=} + hasBin: true dev: true + optional: true /semver/5.7.1: resolution: {integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==} @@ -6574,8 +11143,39 @@ packages: on-finished: 2.3.0 range-parser: 1.2.1 statuses: 1.5.0 + transitivePeerDependencies: + - supports-color + dev: true + + /send/0.17.2: + resolution: {integrity: sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==} + engines: {node: '>= 0.8.0'} + dependencies: + debug: 2.6.9 + depd: 1.1.2 + destroy: 1.0.4 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 0.5.2 + http-errors: 1.8.1 + mime: 1.6.0 + ms: 2.1.3 + on-finished: 2.3.0 + range-parser: 1.2.1 + statuses: 1.5.0 + transitivePeerDependencies: + - supports-color dev: true + /serialize-error/7.0.1: + resolution: {integrity: sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==} + engines: {node: '>=10'} + dependencies: + type-fest: 0.13.1 + dev: true + optional: true + /serialize-javascript/6.0.0: resolution: {integrity: sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==} dependencies: @@ -6593,6 +11193,8 @@ packages: http-errors: 1.6.3 mime-types: 2.1.34 parseurl: 1.3.3 + transitivePeerDependencies: + - supports-color dev: true /serve-static/1.14.1: @@ -6603,6 +11205,24 @@ packages: escape-html: 1.0.3 parseurl: 1.3.3 send: 0.17.1 + transitivePeerDependencies: + - supports-color + dev: true + + /serve-static/1.14.2: + resolution: {integrity: sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==} + engines: {node: '>= 0.8.0'} + dependencies: + encodeurl: 1.0.2 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 0.17.2 + transitivePeerDependencies: + - supports-color + dev: true + + /set-blocking/2.0.0: + resolution: {integrity: sha1-BF+XgtARrppoA93TgrJDkrPYkPc=} dev: true /setprototypeof/1.1.0: @@ -6613,6 +11233,18 @@ packages: resolution: {integrity: sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==} dev: true + /setprototypeof/1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + dev: true + + /sha.js/2.4.11: + resolution: {integrity: sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==} + hasBin: true + dependencies: + inherits: 2.0.4 + safe-buffer: 5.2.1 + dev: true + /shallow-clone/3.0.1: resolution: {integrity: sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==} engines: {node: '>=8'} @@ -6622,7 +11254,13 @@ packages: /shallowequal/1.1.0: resolution: {integrity: sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==} - dev: false + + /shebang-command/1.2.0: + resolution: {integrity: sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=} + engines: {node: '>=0.10.0'} + dependencies: + shebang-regex: 1.0.0 + dev: true /shebang-command/2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} @@ -6631,11 +11269,20 @@ packages: shebang-regex: 3.0.0 dev: true + /shebang-regex/1.0.0: + resolution: {integrity: sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=} + engines: {node: '>=0.10.0'} + dev: true + /shebang-regex/3.0.0: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} dev: true + /shell-quote/1.7.3: + resolution: {integrity: sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==} + dev: true + /side-channel/1.0.4: resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} dependencies: @@ -6648,6 +11295,29 @@ packages: resolution: {integrity: sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==} dev: true + /signale/1.4.0: + resolution: {integrity: sha512-iuh+gPf28RkltuJC7W5MRi6XAjTDCAPC/prJUpQoG4vIP3MJZ+GTydVnodXA7pwvTKb2cA0m9OFZW/cdWy/I/w==} + engines: {node: '>=6'} + dependencies: + chalk: 2.4.2 + figures: 2.0.0 + pkg-conf: 2.1.0 + dev: true + + /simple-diff/1.6.0: + resolution: {integrity: sha1-m7XZUKe0ZNHsyG8gTog2UBnVpUI=} + dev: true + + /simple-element-resize-detector/1.3.0: + resolution: {integrity: sha512-cCFTDpFMgz/OikrV9R++wOQgLbFwqrneci8FmAOH79xrfn1sQVZg9LJV2RvproMgdN2LnfZXZPrM+Z12GXN7jA==} + dev: true + + /simple-swizzle/0.2.2: + resolution: {integrity: sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=} + dependencies: + is-arrayish: 0.3.2 + dev: true + /sisteransi/1.0.5: resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} dev: true @@ -6662,6 +11332,70 @@ packages: engines: {node: '>=8'} dev: true + /slash/4.0.0: + resolution: {integrity: sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==} + engines: {node: '>=12'} + dev: true + + /sliced/1.0.1: + resolution: {integrity: sha1-CzpmK10Ewxd7GSa+qCsD+Dei70E=} + dev: true + + /socketcluster-client/14.3.2: + resolution: {integrity: sha512-xDtgW7Ss0ARlfhx53bJ5GY5THDdEOeJnT+/C9Rmrj/vnZr54xeiQfrCZJbcglwe732nK3V+uZq87IvrRl7Hn4g==} + dependencies: + buffer: 5.7.1 + clone: 2.1.1 + component-emitter: 1.2.1 + linked-list: 0.1.0 + querystring: 0.2.0 + sc-channel: 1.2.0 + sc-errors: 2.0.1 + sc-formatter: 3.0.2 + uuid: 3.2.1 + ws: 7.5.5 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + dev: true + + /socketcluster-server/14.7.2: + resolution: {integrity: sha512-PHFez3OXpxZ0jMm+JleYzshwCT7EXdldlVQnZpLCHM8BARSgbr6C+vuD5lHCvUDJc+T6kVFNEHQ1Hnhzw21CSw==} + dependencies: + async: 3.2.3 + base64id: 1.0.0 + component-emitter: 1.2.1 + lodash.clonedeep: 4.5.0 + sc-auth: 5.0.2 + sc-errors: 2.0.1 + sc-formatter: 3.0.2 + sc-simple-broker: 2.1.3 + uuid: 3.2.1 + ws: 7.5.5 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + dev: true + + /socketcluster/14.4.2: + resolution: {integrity: sha512-Z45tSQ6K/XUEyftrID1hyBXSdaK/gDeq6BMqhNR3XvjnUQ6HkkeTrxZUoXIn/In/J8KLl1WRVtvZAB0Zf9pEjA==} + hasBin: true + dependencies: + async: 2.3.0 + fs-extra: 6.0.1 + inquirer: 5.2.0 + minimist: 1.2.0 + sc-auth: 5.0.2 + sc-broker-cluster: 7.0.0 + sc-errors: 1.4.1 + socketcluster-server: 14.7.2 + uid-number: 0.0.6 + uuid: 3.2.1 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + dev: true + /sockjs/0.3.21: resolution: {integrity: sha512-DhbPFGpxjc6Z3I+uX07Id5ZO2XwYsWOrYjaSeieES78cq+JaJvVe5q/m1uvjIQhXinhIeCFRH6JgXe+mvVMyXw==} dependencies: @@ -6670,13 +11404,15 @@ packages: websocket-driver: 0.7.4 dev: true - /source-map-js/0.6.2: - resolution: {integrity: sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug==} - engines: {node: '>=0.10.0'} - dev: true + /sonic-boom/2.8.0: + resolution: {integrity: sha512-kuonw1YOYYNOve5iHdSahXPOK49GqwA+LZhI6Wz/l0rP57iKyXXIHaRagOBHAPmGwJC6od2Z9zgvZ5loSgMlVg==} + dependencies: + atomic-sleep: 1.0.0 + dev: false /source-map-resolve/0.6.0: resolution: {integrity: sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w==} + deprecated: See https://github.com/lydell/source-map-resolve#deprecated dependencies: atob: 2.1.2 decode-uri-component: 0.2.0 @@ -6703,10 +11439,36 @@ packages: engines: {node: '>= 8'} dev: true + /spawn-error-forwarder/1.0.0: + resolution: {integrity: sha1-Gv2Uc46ZmwNG17n8NzvlXgdXcCk=} + dev: true + + /spdx-correct/3.1.1: + resolution: {integrity: sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==} + dependencies: + spdx-expression-parse: 3.0.1 + spdx-license-ids: 3.0.11 + dev: true + + /spdx-exceptions/2.3.0: + resolution: {integrity: sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==} + dev: true + + /spdx-expression-parse/3.0.1: + resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} + dependencies: + spdx-exceptions: 2.3.0 + spdx-license-ids: 3.0.11 + dev: true + + /spdx-license-ids/3.0.11: + resolution: {integrity: sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==} + dev: true + /spdy-transport/3.0.0: resolution: {integrity: sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==} dependencies: - debug: 4.3.2 + debug: 4.3.4 detect-node: 2.1.0 hpack.js: 2.1.6 obuf: 1.1.2 @@ -6729,10 +11491,70 @@ packages: - supports-color dev: true + /split/1.0.1: + resolution: {integrity: sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==} + dependencies: + through: 2.3.8 + dev: true + + /split2/1.0.0: + resolution: {integrity: sha1-UuLiIdiMdfmnP5BVbiY/+WdysxQ=} + dependencies: + through2: 2.0.5 + dev: true + + /split2/3.2.2: + resolution: {integrity: sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==} + dependencies: + readable-stream: 3.6.0 + dev: true + + /split2/4.1.0: + resolution: {integrity: sha512-VBiJxFkxiXRlUIeyMQi8s4hgvKCSjtknJv/LVYbrgALPwf5zSKmEwV9Lst25AkvMDnvxODugjdl6KZgwKM1WYQ==} + engines: {node: '>= 10.x'} + dev: false + /sprintf-js/1.0.3: resolution: {integrity: sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=} dev: true + /sprintf-js/1.1.2: + resolution: {integrity: sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==} + dev: true + optional: true + + /sqlite3/5.0.2: + resolution: {integrity: sha512-1SdTNo+BVU211Xj1csWa8lV6KM0CtucDwRyA0VHl91wEH1Mgh7RxUpI4rVvG7OhHrzCSGaVyW5g8vKvlrk9DJA==} + requiresBuild: true + peerDependenciesMeta: + node-gyp: + optional: true + dependencies: + node-addon-api: 3.2.1 + node-pre-gyp: 0.11.0 + optionalDependencies: + node-gyp: 3.8.0 + transitivePeerDependencies: + - supports-color + dev: true + + /sshpk/1.17.0: + resolution: {integrity: sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==} + engines: {node: '>=0.10.0'} + hasBin: true + dependencies: + asn1: 0.2.6 + assert-plus: 1.0.0 + bcrypt-pbkdf: 1.0.2 + dashdash: 1.14.1 + ecc-jsbn: 0.1.2 + getpass: 0.1.7 + jsbn: 0.1.1 + safer-buffer: 2.1.2 + tweetnacl: 0.14.5 + dev: true + optional: true + /stack-utils/2.0.5: resolution: {integrity: sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==} engines: {node: '>=10'} @@ -6749,6 +11571,17 @@ packages: engines: {node: '>= 0.6'} dev: true + /stream-combiner2/1.1.1: + resolution: {integrity: sha1-+02KFCDqNidk4hrUeAOXvry0HL4=} + dependencies: + duplexer2: 0.1.4 + readable-stream: 2.3.7 + dev: true + + /stream-shift/1.0.1: + resolution: {integrity: sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==} + dev: false + /string-length/4.0.2: resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} engines: {node: '>=10'} @@ -6757,6 +11590,23 @@ packages: strip-ansi: 6.0.1 dev: true + /string-width/1.0.2: + resolution: {integrity: sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=} + engines: {node: '>=0.10.0'} + dependencies: + code-point-at: 1.1.0 + is-fullwidth-code-point: 1.0.0 + strip-ansi: 3.0.1 + dev: true + + /string-width/2.1.1: + resolution: {integrity: sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==} + engines: {node: '>=4'} + dependencies: + is-fullwidth-code-point: 2.0.0 + strip-ansi: 4.0.0 + dev: true + /string-width/4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} @@ -6803,6 +11653,19 @@ packages: resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} dependencies: safe-buffer: 5.2.1 + + /strip-ansi/3.0.1: + resolution: {integrity: sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=} + engines: {node: '>=0.10.0'} + dependencies: + ansi-regex: 2.1.1 + dev: true + + /strip-ansi/4.0.0: + resolution: {integrity: sha1-qEeQIusaw2iocTibY1JixQXuNo8=} + engines: {node: '>=4'} + dependencies: + ansi-regex: 3.0.0 dev: true /strip-ansi/6.0.1: @@ -6829,6 +11692,11 @@ packages: engines: {node: '>=8'} dev: true + /strip-eof/1.0.0: + resolution: {integrity: sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=} + engines: {node: '>=0.10.0'} + dev: true + /strip-final-newline/2.0.0: resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} engines: {node: '>=6'} @@ -6841,21 +11709,26 @@ packages: min-indent: 1.0.1 dev: true + /strip-json-comments/2.0.1: + resolution: {integrity: sha1-PFMZQukIwml8DsNEhYwobHygpgo=} + engines: {node: '>=0.10.0'} + dev: true + /strip-json-comments/3.1.1: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} dev: true - /style-loader/3.3.1_webpack@5.64.2: + /style-loader/3.3.1_webpack@5.69.0: resolution: {integrity: sha512-GPcQ+LDJbrcxHORTRes6Jy2sfvK2kS6hpSfI/fXhPt+spVzxF6LJ1dHLN9zIGmVaaP044YKaIatFaufENRiDoQ==} engines: {node: '>= 12.13.0'} peerDependencies: webpack: ^5.0.0 dependencies: - webpack: 5.64.2_webpack-cli@4.9.1 + webpack: 5.69.0_webpack-cli@4.9.1 dev: true - /styled-components/5.3.3_281a4fa50a045c9112baf635f3bc27a7: + /styled-components/5.3.3_fane7jikarojcev26y27hpbhu4: resolution: {integrity: sha512-++4iHwBM7ZN+x6DtPPWkCI4vdtwumQ+inA/DdAsqYd4SVgUKJie5vXyzotA00ttcFdQkCng7zc6grwlfIfw+lw==} engines: {node: '>=10'} peerDependencies: @@ -6876,7 +11749,19 @@ packages: react-is: 17.0.2 shallowequal: 1.1.0 supports-color: 5.5.0 - dev: false + + /stylis/4.0.13: + resolution: {integrity: sha512-xGPXiFVl4YED9Jh7Euv2V220mriG9u4B2TA6Ybjc1catrstKD2PpIdU3U0RKpkVBC2EhmL/F0sPCr9vrFTNRag==} + dev: true + + /sumchecker/3.0.1: + resolution: {integrity: sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==} + engines: {node: '>= 8.0'} + dependencies: + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: true /supports-color/5.5.0: resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} @@ -6891,28 +11776,108 @@ packages: has-flag: 4.0.0 dev: true - /supports-color/8.1.1: - resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} - engines: {node: '>=10'} - dependencies: - has-flag: 4.0.0 + /supports-color/8.1.1: + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} + engines: {node: '>=10'} + dependencies: + has-flag: 4.0.0 + dev: true + + /supports-hyperlinks/2.2.0: + resolution: {integrity: sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ==} + engines: {node: '>=8'} + dependencies: + has-flag: 4.0.0 + supports-color: 7.2.0 + dev: true + + /symbol-observable/1.0.1: + resolution: {integrity: sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=} + engines: {node: '>=0.10.0'} + dev: true + + /symbol-observable/1.2.0: + resolution: {integrity: sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==} + engines: {node: '>=0.10.0'} + dev: true + + /symbol-tree/3.2.4: + resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} + dev: true + + /synckit/0.8.4: + resolution: {integrity: sha512-Dn2ZkzMdSX827QbowGbU/4yjWuvNaCoScLLoMo/yKbu+P4GBR6cRGKZH27k6a9bRzdqcyd1DE96pQtQ6uNkmyw==} + engines: {node: ^14.18.0 || >=16.0.0} + dependencies: + '@pkgr/utils': 2.3.1 + tslib: 2.4.1 + dev: true + + /tapable/2.2.1: + resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} + engines: {node: '>=6'} + dev: true + + /tar-stream/2.2.0: + resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} + engines: {node: '>=6'} + dependencies: + bl: 4.1.0 + end-of-stream: 1.4.4 + fs-constants: 1.0.0 + inherits: 2.0.4 + readable-stream: 3.6.0 + dev: true + + /tar/2.2.2: + resolution: {integrity: sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==} + deprecated: This version of tar is no longer supported, and will not receive security updates. Please upgrade asap. + dependencies: + block-stream: 0.0.9 + fstream: 1.0.12 + inherits: 2.0.4 + dev: true + optional: true + + /tar/4.4.19: + resolution: {integrity: sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==} + engines: {node: '>=4.5'} + dependencies: + chownr: 1.1.4 + fs-minipass: 1.2.7 + minipass: 2.9.0 + minizlib: 1.3.3 + mkdirp: 0.5.5 + safe-buffer: 5.2.1 + yallist: 3.1.1 + dev: true + + /tarn/3.0.2: + resolution: {integrity: sha512-51LAVKUSZSVfI05vjPESNc5vwqqZpbXCsU+/+wxlOrUjk2SnFTt97v9ZgQrD4YmxYW1Px6w2KjaDitCfkvgxMQ==} + engines: {node: '>=8.0.0'} dev: true - /supports-hyperlinks/2.2.0: - resolution: {integrity: sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ==} + /temp-dir/2.0.0: + resolution: {integrity: sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==} engines: {node: '>=8'} - dependencies: - has-flag: 4.0.0 - supports-color: 7.2.0 dev: true - /symbol-tree/3.2.4: - resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} + /tempy/1.0.1: + resolution: {integrity: sha512-biM9brNqxSc04Ee71hzFbryD11nX7VPhQQY32AdDmjFvodsRFz/3ufeoTZ6uYkRFfGo188tENcASNs3vTdsM0w==} + engines: {node: '>=10'} + dependencies: + del: 6.0.0 + is-stream: 2.0.1 + temp-dir: 2.0.0 + type-fest: 0.16.0 + unique-string: 2.0.0 dev: true - /tapable/2.2.1: - resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} - engines: {node: '>=6'} + /term-size/1.2.0: + resolution: {integrity: sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=} + engines: {node: '>=4'} + dependencies: + execa: 0.7.0 dev: true /terminal-link/2.1.1: @@ -6923,7 +11888,7 @@ packages: supports-hyperlinks: 2.2.0 dev: true - /terser-webpack-plugin/5.2.5_acorn@8.6.0+webpack@5.64.2: + /terser-webpack-plugin/5.2.5_webpack@5.69.0: resolution: {integrity: sha512-3luOVHku5l0QBeYS8r4CdHYWEGMmIj3H1U64jgkdZzECcSOJAyJ9TjuqcQZvw1Y+4AOBN9SeYJPJmFn2cM4/2g==} engines: {node: '>= 10.13.0'} peerDependencies: @@ -6943,38 +11908,19 @@ packages: schema-utils: 3.1.1 serialize-javascript: 6.0.0 source-map: 0.6.1 - terser: 5.10.0_acorn@8.6.0 - webpack: 5.64.2_webpack-cli@4.9.1 - transitivePeerDependencies: - - acorn + terser: 5.10.0 + webpack: 5.69.0_webpack-cli@4.9.1 dev: true /terser/5.10.0: resolution: {integrity: sha512-AMmF99DMfEDiRJfxfY5jj5wNH/bYO09cniSqhfoyxc8sFoYIgkJy86G04UoZU5VjlpnplVu0K6Tx6E9b5+DlHA==} engines: {node: '>=10'} hasBin: true - peerDependencies: - acorn: ^8.5.0 - peerDependenciesMeta: - acorn: - optional: true - dependencies: - commander: 2.20.3 - source-map: 0.7.3 - source-map-support: 0.5.21 - dev: true - - /terser/5.10.0_acorn@8.6.0: - resolution: {integrity: sha512-AMmF99DMfEDiRJfxfY5jj5wNH/bYO09cniSqhfoyxc8sFoYIgkJy86G04UoZU5VjlpnplVu0K6Tx6E9b5+DlHA==} - engines: {node: '>=10'} - hasBin: true - peerDependencies: - acorn: ^8.5.0 peerDependenciesMeta: acorn: optional: true dependencies: - acorn: 8.6.0 + acorn: 8.7.0 commander: 2.20.3 source-map: 0.7.3 source-map-support: 0.5.21 @@ -6989,18 +11935,78 @@ packages: minimatch: 3.0.4 dev: true + /text-extensions/1.9.0: + resolution: {integrity: sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==} + engines: {node: '>=0.10'} + dev: true + /text-table/0.2.0: resolution: {integrity: sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=} dev: true + /thread-stream/0.15.2: + resolution: {integrity: sha512-UkEhKIg2pD+fjkHQKyJO3yoIvAP3N6RlNFt2dUhcS1FGvCD1cQa1M/PGknCLFIyZdtJOWQjejp7bdNqmN7zwdA==} + dependencies: + real-require: 0.1.0 + dev: false + /throat/6.0.1: resolution: {integrity: sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w==} dev: true + /through/2.3.8: + resolution: {integrity: sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=} + dev: true + + /through2/2.0.5: + resolution: {integrity: sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==} + dependencies: + readable-stream: 2.3.7 + xtend: 4.0.2 + dev: true + + /through2/4.0.2: + resolution: {integrity: sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==} + dependencies: + readable-stream: 3.6.0 + dev: true + /thunky/1.1.0: resolution: {integrity: sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==} dev: true + /ticky/1.0.1: + resolution: {integrity: sha1-t8+nHnaPHJAAxJe5FRswlHxQ5G0=} + dev: true + + /tildify/2.0.0: + resolution: {integrity: sha512-Cc+OraorugtXNfs50hU9KS369rFXCfgGLpfCfvlc+Ud5u6VWmUQsOAa9HbTvheQdYnrdJqqv1e5oIqXppMYnSw==} + engines: {node: '>=8'} + dev: true + + /timed-out/4.0.1: + resolution: {integrity: sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=} + engines: {node: '>=0.10.0'} + dev: true + + /tiny-glob/0.2.9: + resolution: {integrity: sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==} + dependencies: + globalyzer: 0.1.0 + globrex: 0.1.2 + dev: true + + /tiny-warning/1.0.3: + resolution: {integrity: sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==} + dev: true + + /tmp/0.0.33: + resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} + engines: {node: '>=0.6.0'} + dependencies: + os-tmpdir: 1.0.2 + dev: true + /tmpl/1.0.5: resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} dev: true @@ -7009,6 +12015,11 @@ packages: resolution: {integrity: sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=} engines: {node: '>=4'} + /to-readable-stream/1.0.0: + resolution: {integrity: sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==} + engines: {node: '>=6'} + dev: true + /to-regex-range/5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} @@ -7021,6 +12032,20 @@ packages: engines: {node: '>=0.6'} dev: true + /toidentifier/1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} + dev: true + + /tough-cookie/2.5.0: + resolution: {integrity: sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==} + engines: {node: '>=0.8'} + dependencies: + psl: 1.8.0 + punycode: 2.1.1 + dev: true + optional: true + /tough-cookie/4.0.0: resolution: {integrity: sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==} engines: {node: '>=6'} @@ -7030,6 +12055,10 @@ packages: universalify: 0.1.2 dev: true + /tr46/0.0.3: + resolution: {integrity: sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=} + dev: true + /tr46/2.1.0: resolution: {integrity: sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==} engines: {node: '>=8'} @@ -7037,6 +12066,15 @@ packages: punycode: 2.1.1 dev: true + /traverse/0.6.6: + resolution: {integrity: sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc=} + dev: true + + /trim-newlines/3.0.1: + resolution: {integrity: sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==} + engines: {node: '>=8'} + dev: true + /tsconfig-paths/3.12.0: resolution: {integrity: sha512-e5adrnOYT6zqVnWqZu7i/BQ3BnhzvGbjEjejFXO20lKIKpwTaupkCPgEfv4GZK1IBciJUEhYs3J3p75FdaTFVg==} dependencies: @@ -7054,15 +12092,37 @@ packages: resolution: {integrity: sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==} dev: true - /tsutils/3.21.0_typescript@4.5.2: + /tslib/2.4.1: + resolution: {integrity: sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==} + dev: true + + /tsutils/3.21.0_typescript@4.5.5: resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} engines: {node: '>= 6'} peerDependencies: typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' dependencies: tslib: 1.14.1 - typescript: 4.5.2 + typescript: 4.5.5 + dev: true + + /tunnel-agent/0.6.0: + resolution: {integrity: sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=} + dependencies: + safe-buffer: 5.2.1 + dev: true + optional: true + + /tunnel/0.0.6: + resolution: {integrity: sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==} + engines: {node: '>=0.6.11 <=0.7.0 || >=0.7.3'} + dev: true + optional: true + + /tweetnacl/0.14.5: + resolution: {integrity: sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=} dev: true + optional: true /type-check/0.3.2: resolution: {integrity: sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=} @@ -7083,6 +12143,22 @@ packages: engines: {node: '>=4'} dev: true + /type-fest/0.13.1: + resolution: {integrity: sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==} + engines: {node: '>=10'} + dev: true + optional: true + + /type-fest/0.16.0: + resolution: {integrity: sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==} + engines: {node: '>=10'} + dev: true + + /type-fest/0.18.1: + resolution: {integrity: sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==} + engines: {node: '>=10'} + dev: true + /type-fest/0.20.2: resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} engines: {node: '>=10'} @@ -7093,9 +12169,19 @@ packages: engines: {node: '>=10'} dev: true - /type-fest/2.8.0: - resolution: {integrity: sha512-O+V9pAshf9C6loGaH0idwsmugI2LxVNR7DtS40gVo2EXZVYFgz9OuNtOhgHLdHdapOEWNdvz9Ob/eeuaWwwlxA==} - engines: {node: '>=12.20'} + /type-fest/0.6.0: + resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} + engines: {node: '>=8'} + dev: true + + /type-fest/0.8.1: + resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} + engines: {node: '>=8'} + dev: true + + /type-fest/1.4.0: + resolution: {integrity: sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==} + engines: {node: '>=10'} dev: true /type-is/1.6.18: @@ -7112,12 +12198,28 @@ packages: is-typedarray: 1.0.0 dev: true - /typescript/4.5.2: - resolution: {integrity: sha512-5BlMof9H1yGt0P8/WF+wPNw6GfctgGjXp5hkblpyT+8rkASSmkUKMXrxR0Xg8ThVCi/JnHQiKXeBaEwCeQwMFw==} + /typedarray/0.0.6: + resolution: {integrity: sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=} + dev: true + + /typescript/4.5.5: + resolution: {integrity: sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==} engines: {node: '>=4.2.0'} hasBin: true dev: true + /uglify-js/3.15.1: + resolution: {integrity: sha512-FAGKF12fWdkpvNJZENacOH0e/83eG6JyVQyanIJaBXCN1J11TUQv1T1/z8S+Z0CG0ZPk1nPcreF/c7lrTd0TEQ==} + engines: {node: '>=0.8.0'} + hasBin: true + requiresBuild: true + dev: true + optional: true + + /uid-number/0.0.6: + resolution: {integrity: sha1-DqEOgDXo61uOREnwbaHHMGY7qoE=} + dev: true + /unbox-primitive/1.0.1: resolution: {integrity: sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==} dependencies: @@ -7150,32 +12252,92 @@ packages: engines: {node: '>=4'} dev: true + /unique-string/1.0.0: + resolution: {integrity: sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=} + engines: {node: '>=4'} + dependencies: + crypto-random-string: 1.0.0 + dev: true + + /unique-string/2.0.0: + resolution: {integrity: sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==} + engines: {node: '>=8'} + dependencies: + crypto-random-string: 2.0.0 + dev: true + + /universal-user-agent/6.0.0: + resolution: {integrity: sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==} + dev: true + /universalify/0.1.2: resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} engines: {node: '>= 4.0.0'} dev: true + /universalify/2.0.0: + resolution: {integrity: sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==} + engines: {node: '>= 10.0.0'} + dev: true + + /unload/2.2.0: + resolution: {integrity: sha512-B60uB5TNBLtN6/LsgAf3udH9saB5p7gqJwcFfbOEZ8BcBHnGwCf6G/TGiEqkRAxX7zAFIUtzdrXQSdL3Q/wqNA==} + dependencies: + '@babel/runtime': 7.17.2 + detect-node: 2.1.0 + /unpipe/1.0.0: resolution: {integrity: sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=} engines: {node: '>= 0.8'} dev: true + /unzip-response/2.0.1: + resolution: {integrity: sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c=} + engines: {node: '>=4'} + dev: true + + /update-notifier/2.5.0: + resolution: {integrity: sha512-gwMdhgJHGuj/+wHJJs9e6PcCszpxR1b236igrOkUofGhqJuG+amlIKwApH1IW1WWl7ovZxsX49lMBWLxSdm5Dw==} + engines: {node: '>=4'} + dependencies: + boxen: 1.3.0 + chalk: 2.4.2 + configstore: 3.1.5 + import-lazy: 2.1.0 + is-ci: 1.2.1 + is-installed-globally: 0.1.0 + is-npm: 1.0.0 + latest-version: 3.1.0 + semver-diff: 2.1.0 + xdg-basedir: 3.0.0 + dev: true + /uri-js/4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} dependencies: punycode: 2.1.1 dev: true - /url/0.11.0: - resolution: {integrity: sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=} + /url-join/4.0.1: + resolution: {integrity: sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==} + dev: true + + /url-parse-lax/1.0.0: + resolution: {integrity: sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=} + engines: {node: '>=0.10.0'} dependencies: - punycode: 1.3.2 - querystring: 0.2.0 + prepend-http: 1.0.4 + dev: true + + /url-parse-lax/3.0.0: + resolution: {integrity: sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=} + engines: {node: '>=4'} + dependencies: + prepend-http: 2.0.0 dev: true /util-deprecate/1.0.2: resolution: {integrity: sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=} - dev: true /utila/0.4.0: resolution: {integrity: sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=} @@ -7186,12 +12348,29 @@ packages: engines: {node: '>= 0.4.0'} dev: true + /uuid/3.1.0: + resolution: {integrity: sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==} + deprecated: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details. + hasBin: true + dev: true + + /uuid/3.2.1: + resolution: {integrity: sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==} + deprecated: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details. + hasBin: true + dev: true + /uuid/3.4.0: resolution: {integrity: sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==} deprecated: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details. hasBin: true dev: true + /uuid/8.3.2: + resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} + hasBin: true + dev: true + /v8-compile-cache/2.3.0: resolution: {integrity: sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==} dev: true @@ -7205,11 +12384,58 @@ packages: source-map: 0.7.3 dev: true + /validate-npm-package-license/3.0.4: + resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} + dependencies: + spdx-correct: 3.1.1 + spdx-expression-parse: 3.0.1 + dev: true + + /validate.io-array/1.0.6: + resolution: {integrity: sha1-W1osr9j4uFq7L4hroVPy2Tond00=} + dev: true + + /validate.io-function/1.0.2: + resolution: {integrity: sha1-NDoZgC7TsZaCaceA5VjpNBHAutc=} + dev: true + + /validate.io-integer-array/1.0.0: + resolution: {integrity: sha1-LKveAzKTpry+Bj/q/pHq9GsToIk=} + dependencies: + validate.io-array: 1.0.6 + validate.io-integer: 1.0.5 + dev: true + + /validate.io-integer/1.0.5: + resolution: {integrity: sha1-FoSWSAuVviJH7EQ/IjPeT4mHgGg=} + dependencies: + validate.io-number: 1.0.3 + dev: true + + /validate.io-number/1.0.3: + resolution: {integrity: sha1-9j/+2iSL8opnqNSODjtGGhZluvg=} + dev: true + + /value-or-promise/1.0.11: + resolution: {integrity: sha512-41BrgH+dIbCFXClcSapVs5M6GkENd3gQOJpEfPDNa71LsUGMXDL0jMWpI/Rh7WhX+Aalfz2TTS3Zt5pUsbnhLg==} + engines: {node: '>=12'} + dev: true + /vary/1.1.2: resolution: {integrity: sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=} engines: {node: '>= 0.8'} dev: true + /verror/1.10.0: + resolution: {integrity: sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=} + engines: {'0': node >=0.6.0} + dependencies: + assert-plus: 1.0.0 + core-util-is: 1.0.2 + extsprintf: 1.3.0 + dev: true + optional: true + /w3c-hr-time/1.0.2: resolution: {integrity: sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==} dependencies: @@ -7229,12 +12455,12 @@ packages: makeerror: 1.0.12 dev: true - /watchpack/2.2.0: - resolution: {integrity: sha512-up4YAn/XHgZHIxFBVCdlMiWDj6WaLKpwVeGQk2I5thdYxF/KmF0aaz6TfJZ/hfl1h/XlcDr7k1KH7ThDagpFaA==} + /watchpack/2.3.1: + resolution: {integrity: sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA==} engines: {node: '>=10.13.0'} dependencies: glob-to-regexp: 0.4.1 - graceful-fs: 4.2.8 + graceful-fs: 4.2.9 dev: true /wbuf/1.7.3: @@ -7243,6 +12469,10 @@ packages: minimalistic-assert: 1.0.1 dev: true + /webidl-conversions/3.0.1: + resolution: {integrity: sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=} + dev: true + /webidl-conversions/5.0.0: resolution: {integrity: sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==} engines: {node: '>=8'} @@ -7253,7 +12483,7 @@ packages: engines: {node: '>=10.4'} dev: true - /webpack-cli/4.9.1_5bf98977c75b4da48bb2f18b6135c48d: + /webpack-cli/4.9.1_cpiwtwqgcyyvqiqogay7dd4uam: resolution: {integrity: sha512-JYRFVuyFpzDxMDB+v/nanUdQYcZtqFPGzmlW4s+UkPMFhSpfRNmf1z4AwYcHJVdvEFAM7FFCQdNTpsBYhDLusQ==} engines: {node: '>=10.13.0'} hasBin: true @@ -7274,9 +12504,9 @@ packages: optional: true dependencies: '@discoveryjs/json-ext': 0.5.5 - '@webpack-cli/configtest': 1.1.0_webpack-cli@4.9.1+webpack@5.64.2 + '@webpack-cli/configtest': 1.1.0_3awzrjtbpxvmpzpfa3syzgxzq4 '@webpack-cli/info': 1.4.0_webpack-cli@4.9.1 - '@webpack-cli/serve': 1.6.0_6273684a7d018c802013d37c995d983d + '@webpack-cli/serve': 1.6.0_5ylu5qs2nejtialjducb2qdkma colorette: 2.0.16 commander: 7.2.0 execa: 5.1.1 @@ -7284,27 +12514,27 @@ packages: import-local: 3.0.3 interpret: 2.2.0 rechoir: 0.7.1 - webpack: 5.64.2_webpack-cli@4.9.1 - webpack-dev-server: 4.5.0_webpack-cli@4.9.1+webpack@5.64.2 + webpack: 5.69.0_webpack-cli@4.9.1 + webpack-dev-server: 4.7.4_3awzrjtbpxvmpzpfa3syzgxzq4 webpack-merge: 5.8.0 dev: true - /webpack-dev-middleware/5.2.2_webpack@5.64.2: - resolution: {integrity: sha512-DjZyYrsHhkikAFNvSNKrpnziXukU1EChFAh9j4LAm6ndPLPW8cN0KhM7T+RAiOqsQ6ABfQ8hoKIs9IWMTjov+w==} + /webpack-dev-middleware/5.3.1_webpack@5.69.0: + resolution: {integrity: sha512-81EujCKkyles2wphtdrnPg/QqegC/AtqNH//mQkBYSMqwFVCQrxM6ktB2O/SPlZy7LqeEfTbV3cZARGQz6umhg==} engines: {node: '>= 12.13.0'} peerDependencies: webpack: ^4.0.0 || ^5.0.0 dependencies: colorette: 2.0.16 - memfs: 3.3.0 + memfs: 3.4.1 mime-types: 2.1.34 range-parser: 1.2.1 schema-utils: 4.0.0 - webpack: 5.64.2_webpack-cli@4.9.1 + webpack: 5.69.0_webpack-cli@4.9.1 dev: true - /webpack-dev-server/4.5.0_webpack-cli@4.9.1+webpack@5.64.2: - resolution: {integrity: sha512-Ss4WptsUjYa+3hPI4iYZYEc8FrtnfkaPrm5WTjk9ux5kiCS718836srs0ppKMHRaCHP5mQ6g4JZGcfDdGbCjpQ==} + /webpack-dev-server/4.7.4_3awzrjtbpxvmpzpfa3syzgxzq4: + resolution: {integrity: sha512-nfdsb02Zi2qzkNmgtZjkrMOcXnYZ6FLKcQwpxT7MvmHKc+oTtDsBju8j+NMyAygZ9GW1jMEUpy3itHtqgEhe1A==} engines: {node: '>= 12.13.0'} hasBin: true peerDependencies: @@ -7314,33 +12544,38 @@ packages: webpack-cli: optional: true dependencies: + '@types/bonjour': 3.5.9 + '@types/connect-history-api-fallback': 1.3.5 + '@types/express': 4.17.13 + '@types/serve-index': 1.9.1 + '@types/sockjs': 0.3.33 + '@types/ws': 8.2.2 ansi-html-community: 0.0.8 bonjour: 3.5.0 - chokidar: 3.5.2 + chokidar: 3.5.3 colorette: 2.0.16 compression: 1.7.4 connect-history-api-fallback: 1.6.0 + default-gateway: 6.0.3 del: 6.0.0 express: 4.17.1 - graceful-fs: 4.2.8 + graceful-fs: 4.2.9 html-entities: 2.3.2 http-proxy-middleware: 2.0.1 - internal-ip: 6.2.0 ipaddr.js: 2.0.1 open: 8.4.0 p-retry: 4.6.1 portfinder: 1.0.28 - schema-utils: 3.1.1 - selfsigned: 1.10.11 + schema-utils: 4.0.0 + selfsigned: 2.0.0 serve-index: 1.9.1 sockjs: 0.3.21 spdy: 4.0.2 strip-ansi: 7.0.1 - url: 0.11.0 - webpack: 5.64.2_webpack-cli@4.9.1 - webpack-cli: 4.9.1_5bf98977c75b4da48bb2f18b6135c48d - webpack-dev-middleware: 5.2.2_webpack@5.64.2 - ws: 8.2.3 + webpack: 5.69.0_webpack-cli@4.9.1 + webpack-cli: 4.9.1_cpiwtwqgcyyvqiqogay7dd4uam + webpack-dev-middleware: 5.3.1_webpack@5.69.0 + ws: 8.5.0 transitivePeerDependencies: - bufferutil - debug @@ -7356,13 +12591,13 @@ packages: wildcard: 2.0.0 dev: true - /webpack-sources/3.2.2: - resolution: {integrity: sha512-cp5qdmHnu5T8wRg2G3vZZHoJPN14aqQ89SyQ11NpGH5zEMDCclt49rzo+MaRazk7/UeILhAI+/sEtcM+7Fr0nw==} + /webpack-sources/3.2.3: + resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==} engines: {node: '>=10.13.0'} dev: true - /webpack/5.64.2_webpack-cli@4.9.1: - resolution: {integrity: sha512-4KGc0+Ozi0aS3EaLNRvEppfZUer+CaORKqL6OBjDLZOPf9YfN8leagFzwe6/PoBdHFxc/utKArl8LMC0Ivtmdg==} + /webpack/5.69.0_webpack-cli@4.9.1: + resolution: {integrity: sha512-E5Fqu89Gu8fR6vejRqu26h8ld/k6/dCVbeGUcuZjc+goQHDfCPU9rER71JmdtBYGmci7Ec2aFEATQ2IVXKy2wg==} engines: {node: '>=10.13.0'} hasBin: true peerDependencies: @@ -7371,8 +12606,8 @@ packages: webpack-cli: optional: true dependencies: - '@types/eslint-scope': 3.7.1 - '@types/estree': 0.0.50 + '@types/eslint-scope': 3.7.3 + '@types/estree': 0.0.51 '@webassemblyjs/ast': 1.11.1 '@webassemblyjs/wasm-edit': 1.11.1 '@webassemblyjs/wasm-parser': 1.11.1 @@ -7380,22 +12615,22 @@ packages: acorn-import-assertions: 1.8.0_acorn@8.6.0 browserslist: 4.18.1 chrome-trace-event: 1.0.3 - enhanced-resolve: 5.8.3 + enhanced-resolve: 5.9.0 es-module-lexer: 0.9.3 eslint-scope: 5.1.1 events: 3.3.0 glob-to-regexp: 0.4.1 - graceful-fs: 4.2.8 + graceful-fs: 4.2.9 json-parse-better-errors: 1.0.2 loader-runner: 4.2.0 mime-types: 2.1.34 neo-async: 2.6.2 schema-utils: 3.1.1 tapable: 2.2.1 - terser-webpack-plugin: 5.2.5_acorn@8.6.0+webpack@5.64.2 - watchpack: 2.2.0 - webpack-cli: 4.9.1_5bf98977c75b4da48bb2f18b6135c48d - webpack-sources: 3.2.2 + terser-webpack-plugin: 5.2.5_webpack@5.69.0 + watchpack: 2.3.1 + webpack-cli: 4.9.1_cpiwtwqgcyyvqiqogay7dd4uam + webpack-sources: 3.2.3 transitivePeerDependencies: - '@swc/core' - esbuild @@ -7430,6 +12665,13 @@ packages: resolution: {integrity: sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==} dev: true + /whatwg-url/5.0.0: + resolution: {integrity: sha1-lmRU6HZUYuN2RNNib2dCzotwll0=} + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + dev: true + /whatwg-url/8.7.0: resolution: {integrity: sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==} engines: {node: '>=10'} @@ -7449,6 +12691,13 @@ packages: is-symbol: 1.0.4 dev: true + /which/1.3.1: + resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} + hasBin: true + dependencies: + isexe: 2.0.0 + dev: true + /which/2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} @@ -7457,6 +12706,19 @@ packages: isexe: 2.0.0 dev: true + /wide-align/1.1.5: + resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} + dependencies: + string-width: 4.2.3 + dev: true + + /widest-line/2.0.1: + resolution: {integrity: sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==} + engines: {node: '>=4'} + dependencies: + string-width: 2.1.1 + dev: true + /wildcard/2.0.0: resolution: {integrity: sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==} dev: true @@ -7466,6 +12728,10 @@ packages: engines: {node: '>=0.10.0'} dev: true + /wordwrap/1.0.0: + resolution: {integrity: sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=} + dev: true + /wrap-ansi/7.0.0: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} engines: {node: '>=10'} @@ -7477,6 +12743,13 @@ packages: /wrappy/1.0.2: resolution: {integrity: sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=} + + /write-file-atomic/2.4.3: + resolution: {integrity: sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==} + dependencies: + graceful-fs: 4.2.9 + imurmurhash: 0.1.4 + signal-exit: 3.0.6 dev: true /write-file-atomic/3.0.3: @@ -7501,8 +12774,8 @@ packages: optional: true dev: true - /ws/8.2.3: - resolution: {integrity: sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==} + /ws/8.5.0: + resolution: {integrity: sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==} engines: {node: '>=10.0.0'} peerDependencies: bufferutil: ^4.0.1 @@ -7514,6 +12787,11 @@ packages: optional: true dev: true + /xdg-basedir/3.0.0: + resolution: {integrity: sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=} + engines: {node: '>=4'} + dev: true + /xml-name-validator/3.0.0: resolution: {integrity: sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==} dev: true @@ -7522,11 +12800,33 @@ packages: resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} dev: true + /xss/1.0.10: + resolution: {integrity: sha512-qmoqrRksmzqSKvgqzN0055UFWY7OKx1/9JWeRswwEVX9fCG5jcYRxa/A2DHcmZX6VJvjzHRQ2STeeVcQkrmLSw==} + engines: {node: '>= 0.10.0'} + hasBin: true + dependencies: + commander: 2.20.3 + cssfilter: 0.0.10 + dev: true + + /xtend/4.0.2: + resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} + engines: {node: '>=0.4'} + dev: true + /y18n/5.0.8: resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} engines: {node: '>=10'} dev: true + /yallist/2.1.2: + resolution: {integrity: sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=} + dev: true + + /yallist/3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + dev: true + /yallist/4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} dev: true @@ -7554,7 +12854,32 @@ packages: yargs-parser: 20.2.9 dev: true + /yauzl/2.10.0: + resolution: {integrity: sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=} + dependencies: + buffer-crc32: 0.2.13 + fd-slicer: 1.1.0 + dev: true + /yocto-queue/0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} dev: true + + /zip-stream/2.1.3: + resolution: {integrity: sha512-EkXc2JGcKhO5N5aZ7TmuNo45budRaFGHOmz24wtJR7znbNqDPmdZtUauKX6et8KAVseAMBOyWJqEpXcHTBsh7Q==} + engines: {node: '>= 6'} + dependencies: + archiver-utils: 2.1.0 + compress-commons: 2.1.1 + readable-stream: 3.6.0 + dev: true + + /zip-stream/4.1.0: + resolution: {integrity: sha512-zshzwQW7gG7hjpBlgeQP9RuyPGNxvJdzR8SUM3QhxCnLjWN2E7j3dOvpeDcQoETfHx0urRS7EtmVToql7YpU4A==} + engines: {node: '>= 10'} + dependencies: + archiver-utils: 2.1.0 + compress-commons: 4.1.1 + readable-stream: 3.6.0 + dev: true diff --git a/public/_locales/zh_CN/messages.json b/public/_locales/zh_CN/messages.json new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/public/_locales/zh_CN/messages.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/public/file-icons/c.svg b/public/file-icons/c.svg new file mode 100644 index 0000000..5a6001d --- /dev/null +++ b/public/file-icons/c.svg @@ -0,0 +1 @@ +file_type_c \ No newline at end of file diff --git a/public/file-icons/cpp.svg b/public/file-icons/cpp.svg new file mode 100644 index 0000000..9563371 --- /dev/null +++ b/public/file-icons/cpp.svg @@ -0,0 +1 @@ +file_type_cpp \ No newline at end of file diff --git a/public/file-icons/csharp.svg b/public/file-icons/csharp.svg new file mode 100644 index 0000000..f102e14 --- /dev/null +++ b/public/file-icons/csharp.svg @@ -0,0 +1 @@ +file_type_csharp \ No newline at end of file diff --git a/public/file-icons/elixir.svg b/public/file-icons/elixir.svg new file mode 100644 index 0000000..20e7798 --- /dev/null +++ b/public/file-icons/elixir.svg @@ -0,0 +1 @@ +file_type_elixir \ No newline at end of file diff --git a/public/file-icons/erlang.svg b/public/file-icons/erlang.svg new file mode 100644 index 0000000..7f7692b --- /dev/null +++ b/public/file-icons/erlang.svg @@ -0,0 +1 @@ +file_type_erlang \ No newline at end of file diff --git a/public/file-icons/golang.svg b/public/file-icons/golang.svg new file mode 100644 index 0000000..07271e3 --- /dev/null +++ b/public/file-icons/golang.svg @@ -0,0 +1 @@ +file_type_go_lightblue \ No newline at end of file diff --git a/public/file-icons/java.svg b/public/file-icons/java.svg new file mode 100644 index 0000000..14121c5 --- /dev/null +++ b/public/file-icons/java.svg @@ -0,0 +1 @@ +file_type_java \ No newline at end of file diff --git a/public/file-icons/javascript.svg b/public/file-icons/javascript.svg new file mode 100644 index 0000000..92a2141 --- /dev/null +++ b/public/file-icons/javascript.svg @@ -0,0 +1 @@ +file_type_js \ No newline at end of file diff --git a/public/file-icons/kotlin.svg b/public/file-icons/kotlin.svg new file mode 100644 index 0000000..be96156 --- /dev/null +++ b/public/file-icons/kotlin.svg @@ -0,0 +1 @@ +file_type_kotlin \ No newline at end of file diff --git a/public/file-icons/php.svg b/public/file-icons/php.svg new file mode 100644 index 0000000..dd6203a --- /dev/null +++ b/public/file-icons/php.svg @@ -0,0 +1 @@ +file_type_php \ No newline at end of file diff --git a/public/file-icons/python.svg b/public/file-icons/python.svg new file mode 100644 index 0000000..677f216 --- /dev/null +++ b/public/file-icons/python.svg @@ -0,0 +1 @@ +file_type_python \ No newline at end of file diff --git a/public/file-icons/python3.svg b/public/file-icons/python3.svg new file mode 100644 index 0000000..677f216 --- /dev/null +++ b/public/file-icons/python3.svg @@ -0,0 +1 @@ +file_type_python \ No newline at end of file diff --git a/public/file-icons/racket.svg b/public/file-icons/racket.svg new file mode 100644 index 0000000..6dcfea1 --- /dev/null +++ b/public/file-icons/racket.svg @@ -0,0 +1 @@ +file_type_racket \ No newline at end of file diff --git a/public/file-icons/ruby.svg b/public/file-icons/ruby.svg new file mode 100644 index 0000000..9443db1 --- /dev/null +++ b/public/file-icons/ruby.svg @@ -0,0 +1 @@ +file_type_ruby \ No newline at end of file diff --git a/public/file-icons/rust.svg b/public/file-icons/rust.svg new file mode 100644 index 0000000..fa59601 --- /dev/null +++ b/public/file-icons/rust.svg @@ -0,0 +1 @@ +file_type_rust \ No newline at end of file diff --git a/public/file-icons/scala.svg b/public/file-icons/scala.svg new file mode 100644 index 0000000..e42c07d --- /dev/null +++ b/public/file-icons/scala.svg @@ -0,0 +1 @@ +file_type_scala \ No newline at end of file diff --git a/public/file-icons/swift.svg b/public/file-icons/swift.svg new file mode 100644 index 0000000..c232d1f --- /dev/null +++ b/public/file-icons/swift.svg @@ -0,0 +1 @@ +file_type_swift \ No newline at end of file diff --git a/public/file-icons/typescript.svg b/public/file-icons/typescript.svg new file mode 100644 index 0000000..d02aa28 --- /dev/null +++ b/public/file-icons/typescript.svg @@ -0,0 +1 @@ +file_type_typescript \ No newline at end of file diff --git a/public/icons/icon-128.png b/public/icons/icon-128.png new file mode 100644 index 0000000..5c1bf05 Binary files /dev/null and b/public/icons/icon-128.png differ diff --git a/public/icons/icon-16.png b/public/icons/icon-16.png new file mode 100644 index 0000000..25fa4bf Binary files /dev/null and b/public/icons/icon-16.png differ diff --git a/public/icons/icon-48.png b/public/icons/icon-48.png new file mode 100644 index 0000000..abf9e58 Binary files /dev/null and b/public/icons/icon-48.png differ diff --git a/public/manifest-dev.json b/public/manifest-dev.json new file mode 100644 index 0000000..c0445ea --- /dev/null +++ b/public/manifest-dev.json @@ -0,0 +1,68 @@ +{ + "name": "Refined Leetcode dev", + "description": "LeetCode 网页扩展", + "version": "0.2.1", + "manifest_version": 3, + "homepage_url": "https://github.com/XYShaoKang/refined-leetcode", + "default_locale": "zh_CN", + "icons": { + "16": "icons/icon-16.png", + "48": "icons/icon-48.png", + "128": "icons/icon-128.png" + }, + "web_accessible_resources": [ + { + "resources": [ + "/content.bundle.js", + "/*.hot-update.js", + "/*.hot-update.json", + "/*.map", + "/file-icons/*.svg" + ], + "matches": [ + "*://leetcode-cn.com/*", + "*://leetcode.cn/*" + ] + } + ], + "content_scripts": [ + { + "matches": [ + "https://leetcode-cn.com/*", + "https://leetcode.cn/*" + ], + "js": [ + "content-load.bundle.js" + ] + } + ], + "background": { + "service_worker": "background.bundle.js" + }, + "options_page": "options.html", + "action": { + "default_popup": "popup.html" + }, + "content_security_policy": { + "extension_pages": "default-src 'self' http://localhost:9100; script-src 'self' http://localhost:9100; script-src-elem 'self' http://localhost:9100; style-src 'self' 'unsafe-inline'; connect-src 'self' ws://localhost:9100 http://localhost:9100 https://leetcode-rating-predictor.herokuapp.com https://leetcode-predictor.herokuapp.com https://leetcode-cn.com https://leetcode.cn https://lccn.lbao.site https://leetcode.com" + }, + "permissions": [ + "scripting", + "storage" + ], + "host_permissions": [ + "https://leetcode-cn.com/*", + "https://leetcode.cn/*", + "http://localhost:9100/*", + "https://leetcode-rating-predictor.herokuapp.com/*", + "https://leetcode-predictor.herokuapp.com/*", + "https://lccn.lbao.site/*", + "https://leetcode.com/*" + ], + "externally_connectable": { + "matches": [ + "https://leetcode-cn.com/*", + "https://leetcode.cn/*" + ] + } +} \ No newline at end of file diff --git a/public/manifest.json b/public/manifest.json new file mode 100644 index 0000000..53be93b --- /dev/null +++ b/public/manifest.json @@ -0,0 +1,64 @@ +{ + "name": "Refined Leetcode", + "description": "LeetCode 网页扩展", + "version": "0.0.0", + "manifest_version": 3, + "homepage_url": "https://github.com/XYShaoKang/refined-leetcode", + "default_locale": "zh_CN", + "icons": { + "16": "icons/icon-16.png", + "48": "icons/icon-48.png", + "128": "icons/icon-128.png" + }, + "web_accessible_resources": [ + { + "resources": [ + "/content.bundle.js", + "/*.map", + "/file-icons/*.svg" + ], + "matches": [ + "*://leetcode-cn.com/*", + "*://leetcode.cn/*" + ] + } + ], + "content_scripts": [ + { + "matches": [ + "https://leetcode-cn.com/*", + "https://leetcode.cn/*" + ], + "js": [ + "content-load.bundle.js" + ] + } + ], + "background": { + "service_worker": "background.bundle.js" + }, + "options_page": "options.html", + "action": { + "default_popup": "popup.html" + }, + "content_security_policy": { + "extension_pages": "default-src 'self'; script-src 'self'; script-src-elem 'self'; style-src 'self' 'unsafe-inline'; connect-src 'self' https://leetcode-rating-predictor.herokuapp.com https://leetcode-predictor.herokuapp.com https://leetcode-cn.com https://leetcode.cn https://lccn.lbao.site https://leetcode.com" + }, + "permissions": [ + "storage" + ], + "host_permissions": [ + "https://leetcode-cn.com/*", + "https://leetcode.cn/*", + "https://leetcode-rating-predictor.herokuapp.com/*", + "https://leetcode-predictor.herokuapp.com/*", + "https://lccn.lbao.site/*", + "https://leetcode.com/*" + ], + "externally_connectable": { + "matches": [ + "https://leetcode-cn.com/*", + "https://leetcode.cn/*" + ] + } +} \ No newline at end of file diff --git a/public/options.html b/public/options.html new file mode 100644 index 0000000..2d9d6dd --- /dev/null +++ b/public/options.html @@ -0,0 +1,12 @@ + + + + + + Refined LeetCode + + + +
+ + diff --git a/public/popup.html b/public/popup.html new file mode 100644 index 0000000..2d9d6dd --- /dev/null +++ b/public/popup.html @@ -0,0 +1,12 @@ + + + + + + Refined LeetCode + + + +
+ + diff --git a/release.config.js b/release.config.js new file mode 100644 index 0000000..583fdcd --- /dev/null +++ b/release.config.js @@ -0,0 +1,47 @@ +module.exports = { + branches: ['master'], + preset: 'angular', + plugins: [ + '@semantic-release/commit-analyzer', + '@semantic-release/release-notes-generator', + [ + './semantic-release-build', + { + dist: 'dist', + name: 'refined-leetcode', + }, + ], + [ + '@semantic-release/changelog', + { + changelogFile: 'CHANGELOG.md', + }, + ], + [ + '@semantic-release/git', + { + assets: ['CHANGELOG.md', 'package.json'], + message: 'chore(release): ${nextRelease.version} [skip ci]', + }, + ], + [ + '@semantic-release/github', + { + assets: [ + { + path: 'refined-leetcode.crx', + name: 'refined-leetcode-${nextRelease.gitTag}.crx', + }, + { + path: 'refined-leetcode.zip', + name: 'refined-leetcode-${nextRelease.gitTag}.zip', + }, + { + path: 'refined-leetcode.crx.zip', + name: 'refined-leetcode-${nextRelease.gitTag}.crx.zip', + }, + ], + }, + ], + ], +} diff --git a/semantic-release-build/index.js b/semantic-release-build/index.js new file mode 100644 index 0000000..40b74cf --- /dev/null +++ b/semantic-release-build/index.js @@ -0,0 +1,3 @@ +const verifyConditions = require('./verifyConditions') +const prepare = require('./prepare') +module.exports = { verifyConditions, prepare } diff --git a/semantic-release-build/prepare.js b/semantic-release-build/prepare.js new file mode 100644 index 0000000..580c2f7 --- /dev/null +++ b/semantic-release-build/prepare.js @@ -0,0 +1,81 @@ +const path = require('path') +const fs = require('fs') +const SemanticReleaseError = require('@semantic-release/error') +const archiver = require('archiver') +const ChromeExtension = require('crx') + +const getKey = () => { + let { PRIVATE_KEY, PRIVATE_KEY_PATH } = process.env + if (PRIVATE_KEY) return Buffer.from(PRIVATE_KEY, 'utf-8') + + try { + const keyPath = PRIVATE_KEY_PATH || path.resolve('key.pem') + fs.accessSync(keyPath, fs.constants.W_OK) + return fs.readFileSync(keyPath) + } catch (error) { + throw new SemanticReleaseError('请设置 PRIVATE_KEY 或 PRIVATE_KEY_PATH') + } +} + +const prepare = async (pluginConfig = {}, context) => { + let { dist = 'dist', name = 'extension' } = pluginConfig + + dist = path.resolve(dist) + if (!fs.existsSync(dist)) throw new SemanticReleaseError('dist 目录不存在') + + const manifestPath = path.join(dist, 'manifest.json') + if (!fs.existsSync(manifestPath)) + throw new SemanticReleaseError('manifest.json 文件不存在') + + const { logger, nextRelease } = context + + // 修改版本号 + const version = nextRelease.version + try { + logger.log('修改 manifest.json 版本号') + const manifestData = JSON.parse(fs.readFileSync(manifestPath, 'utf-8')) + fs.writeFileSync( + manifestPath, + JSON.stringify({ ...manifestData, version }, null, 2), + 'utf-8' + ) + + logger.log('修改 package.json 版本号') + const packagePath = path.resolve('package.json') + const packageData = JSON.parse(fs.readFileSync(packagePath, 'utf-8')) + fs.writeFileSync( + packagePath, + JSON.stringify({ ...packageData, version }, null, 2), + 'utf-8' + ) + } catch (error) { + throw new SemanticReleaseError('修改版本失败') + } + + // 打包成 zip + logger.log('打包 zip') + const archive = archiver('zip', { zlib: { level: 9 } }) + const output = path.resolve(`${name}.zip`) + archive.pipe(fs.createWriteStream(output)) + archive.directory(dist, false) + archive.finalize() + + // 打包为 crx + logger.log('打包 crx') + await new ChromeExtension({ privateKey: getKey() }) + .load(dist) + .then(crx => crx.pack()) + .then(crxBuffer => { + fs.mkdir + fs.writeFileSync(path.resolve(`${name}.crx`), crxBuffer) + }) + + logger.log('打包 zip') + const crxarchive = archiver('zip', { zlib: { level: 9 } }) + const crxoutput = path.resolve(`${name}.crx.zip`) + crxarchive.pipe(fs.createWriteStream(crxoutput)) + crxarchive.file(path.resolve(`${name}.crx`), { name: `${name}.crx` }) + crxarchive.finalize() +} + +module.exports = prepare diff --git a/semantic-release-build/verifyConditions.js b/semantic-release-build/verifyConditions.js new file mode 100644 index 0000000..d78fd85 --- /dev/null +++ b/semantic-release-build/verifyConditions.js @@ -0,0 +1,11 @@ +const SemanticReleaseError = require('@semantic-release/error') + +const verifyConditions = () => { + const { PRIVATE_KEY, PRIVATE_KEY_PATH } = process.env + + if (!PRIVATE_KEY && !PRIVATE_KEY_PATH) { + throw new SemanticReleaseError('请设置 PRIVATE_KEY 或 PRIVATE_KEY_PATH') + } +} + +module.exports = verifyConditions diff --git a/src/background/hot.ts b/src/background/hot.ts new file mode 100644 index 0000000..af24e17 --- /dev/null +++ b/src/background/hot.ts @@ -0,0 +1,73 @@ +type HotUpdateMessage = { + type: 'hot-update' + url: string +} +type ReloadMessage = { + type: 'reload' +} +type RestartMessage = { + type: 'restart' +} + +type Message = HotUpdateMessage | ReloadMessage | RestartMessage +async function hotUpdate( + message: HotUpdateMessage, + sender: chrome.runtime.MessageSender, + sendResponse: (response?: any) => void +) { + const reg = /\/\.\/([\d\D]+\.hot-update\.js)/ + const url = message.url.match(reg)?.[1] + + if (url && sender.tab?.id) { + chrome.scripting.executeScript({ + target: { tabId: sender.tab!.id! }, + files: [url], + }) + + sendResponse({ data: true }) + } else { + sendResponse({ data: false }) + } +} + +async function reload( + _message: ReloadMessage, + _sender: chrome.runtime.MessageSender, + _sendResponse: (response?: any) => void +) { + console.log('start reload') + chrome.runtime.reload() +} + +async function restart( + message: RestartMessage, + sender: chrome.runtime.MessageSender, + sendResponse: (response?: any) => void +) { + chrome.tabs.reload(sender.tab!.id!) + sendResponse({ data: true }) +} + +if (module.hot) { + chrome.runtime.onMessage.addListener( + (message: Message, sender, sendResponse) => { + console.log(message) + switch (message.type) { + case 'hot-update': + hotUpdate(message, sender, sendResponse) + break + case 'reload': + reload(message, sender, sendResponse) + break + case 'restart': + restart(message, sender, sendResponse) + break + default: + break + } + return true + } + ) +} + +export {} diff --git a/src/background/index.ts b/src/background/index.ts new file mode 100644 index 0000000..3b6b12f --- /dev/null +++ b/src/background/index.ts @@ -0,0 +1,37 @@ +import './hot' +import './lcrp' + +import { defaultOptions } from '../options/options' + +chrome.runtime.onInstalled.addListener(e => { + if (e.reason === 'install') { + // 当前是首次安装,使用默认配置 + chrome.storage.local.set({ options: defaultOptions }) + } else { + chrome.storage.local.get('options').then(({ options }) => { + // 当前是更新 + if (!options) { + // 不存在配置选项,因为不确定用户之前主要使用哪些功能,所以启用所有功能,让用户决定是否关闭某些功能 + options = {} + for (const page of Reflect.ownKeys(defaultOptions)) { + options[page] = {} + for (const key of Reflect.ownKeys((defaultOptions as any)[page])) { + options[page][key] = true + } + } + } else { + // 如果存在配置,则将将当前配置与默认配置进行合并,以当前配置为主,如果发现不存在某个配置,则将其设置为默认配置 + for (const page of Reflect.ownKeys(defaultOptions)) { + if (!options[page]) options[page] = {} + for (const key of Reflect.ownKeys((defaultOptions as any)[page])) { + if (options[page][key] === undefined) + options[page][key] = (defaultOptions as any)[page][key] + } + } + } + chrome.storage.local.set({ options }) + }) + } +}) + +export {} diff --git a/src/background/lcrp.ts b/src/background/lcrp.ts new file mode 100644 index 0000000..331c6b0 --- /dev/null +++ b/src/background/lcrp.ts @@ -0,0 +1,130 @@ +// Leetcode Rating Predictor +import { gkey, graphqlApi } from '@/utils' +import { + fileIconData, + lbaoPredictorApi as predictorApi, + LbaoPredictorType, +} from './utils' + +type GetPredictionMessage = { + type: 'get-prediction' + contestSlug: string + users: { username: string; region: string }[] +} +type GetFileIcons = { + type: 'get-file-icons' +} +type GetUserRanking = { + type: 'get-user-ranking' + username: string +} + +const messageHandle = ( + message: GetPredictionMessage | GetFileIcons | GetUserRanking, + sender: chrome.runtime.MessageSender, + sendResponse: (response?: any) => void +) => { + if (message.type === 'get-prediction') { + getPredictionHandle(message, sender, sendResponse) + return true + } else if (message.type === 'get-file-icons') { + getFileIcons(message, sender, sendResponse) + return true + } else if (message.type === 'get-user-ranking') { + getUserRanking(message, sender, sendResponse) + return true + } + + const _exhaustiveCheck: never = message + return _exhaustiveCheck +} + +chrome.runtime.onMessage.addListener(messageHandle) +chrome.runtime.onMessageExternal.addListener(messageHandle) + +async function getFileIcons( + message: GetFileIcons, + sender: chrome.runtime.MessageSender, + sendResponse: (response?: any) => void +) { + const res: { [key: string]: string } = {} + for (const { slug, file } of fileIconData) { + res[slug] = `chrome-extension://${chrome.runtime.id}${file}` + } + sendResponse(res) +} + +const cache = new Map>() +async function getPredictionHandle( + message: GetPredictionMessage, + sender: chrome.runtime.MessageSender, + sendResponse: (response?: any) => void +) { + const { contestSlug, users } = message + let userCache = cache.get(contestSlug)! + if (!userCache) { + userCache = new Map() + cache.set(contestSlug, userCache) + } + try { + const tmp = users + .filter(a => !userCache.has(gkey(a.region, a.username))) + .map(a => ({ data_region: a.region, username: a.username })) + if (tmp.length) { + const data = await predictorApi(contestSlug, tmp) + for (const item of data) { + const key = gkey(item.data_region, item.username) + userCache.set(key, item) + } + } + + sendResponse( + users.map(user => userCache.get(gkey(user.region, user.username))) + ) + } catch (error) { + // TODO + } +} +async function getUserRanking( + message: GetUserRanking, + sender: chrome.runtime.MessageSender, + sendResponse: (response?: any) => void +) { + const { username } = message + try { + const { data } = await graphqlApi<{ data: any }>('https://leetcode.com', { + body: { + variables: { username: username }, + query: /* GraphQL */ ` + query userContestRankingInfo($username: String!) { + userContestRanking(username: $username) { + attendedContestsCount + rating + globalRanking + totalParticipants + topPercentage + } + userContestRankingHistory(username: $username) { + attended + trendDirection + problemsSolved + totalProblems + finishTimeInSeconds + rating + ranking + contest { + titleSlug + title + startTime + } + } + } + `, + }, + }) + + sendResponse(data) + } catch (error) { + // TODO + } +} diff --git a/src/background/utils/cache.ts b/src/background/utils/cache.ts new file mode 100644 index 0000000..112c87b --- /dev/null +++ b/src/background/utils/cache.ts @@ -0,0 +1,32 @@ +/** + * 根据 key 缓存函数执行结果 + * @param keyFn 生成缓存的 key + * @param handle 输出函数 + * @param timeout 超时设置,单位为毫秒,默认为 10 分钟,如果缓存数据超过 timeout,则重新获取结果 + * @returns + */ +export function cache( + keyFn: (...args: T) => string, + handle: (...args: T) => Promise | R, + timeout = 600000 +): (...args: T) => Promise { + const map = new Map | R, number]>() + return async (...args: T) => { + const key = keyFn(...args) + if (map.has(key)) { + const [promise, time] = map.get(key)! + if (new Date().valueOf() - time <= timeout) { + try { + const data = await promise + return data + } catch (error) { + // 如果当前缓存有错误,则舍弃缓存的结果,重新获取 + } + } + } + const promise = handle(...args) + + map.set(key, [promise, new Date().valueOf()]) + return promise + } +} diff --git a/src/background/utils/fileIconData.ts b/src/background/utils/fileIconData.ts new file mode 100644 index 0000000..5160747 --- /dev/null +++ b/src/background/utils/fileIconData.ts @@ -0,0 +1,102 @@ +export const fileIconData = [ + { + slug: 'cpp', + lang: 'C++', + file: '/file-icons/cpp.svg', + }, + { + slug: 'java', + lang: 'Java', + file: '/file-icons/java.svg', + }, + { + slug: 'python', + lang: 'Python', + file: '/file-icons/python.svg', + }, + // { + // slug: 'mysql', + // lang: 'MySQL', + // file: '/file-icons/mysql.svg', + // }, + { + slug: 'c', + lang: 'C', + file: '/file-icons/c.svg', + }, + { + slug: 'csharp', + lang: 'C#', + file: '/file-icons/csharp.svg', + }, + { + slug: 'javascript', + lang: 'JavaScript', + file: '/file-icons/javascript.svg', + }, + { + slug: 'ruby', + lang: 'Ruby', + file: '/file-icons/ruby.svg', + }, + // { + // slug: 'bash', + // lang: 'Bash', + // file: '/file-icons/bash.svg', + // }, + { + slug: 'swift', + lang: 'Swift', + file: '/file-icons/swift.svg', + }, + { + slug: 'golang', + lang: 'Go', + file: '/file-icons/golang.svg', + }, + { + slug: 'python3', + lang: 'Python3', + file: '/file-icons/python3.svg', + }, + { + slug: 'scala', + lang: 'Scala', + file: '/file-icons/scala.svg', + }, + { + slug: 'kotlin', + lang: 'Kotlin', + file: '/file-icons/kotlin.svg', + }, + { + slug: 'rust', + lang: 'Rust', + file: '/file-icons/rust.svg', + }, + { + slug: 'php', + lang: 'PHP', + file: '/file-icons/php.svg', + }, + { + slug: 'typescript', + lang: 'TypeScript', + file: '/file-icons/typescript.svg', + }, + { + slug: 'racket', + lang: 'Racket', + file: '/file-icons/racket.svg', + }, + { + slug: 'erlang', + lang: 'Erlang', + file: '/file-icons/erlang.svg', + }, + { + slug: 'elixir', + lang: 'Elixir', + file: '/file-icons/elixir.svg', + }, +] diff --git a/src/background/utils/getContest.ts b/src/background/utils/getContest.ts new file mode 100644 index 0000000..238d4bf --- /dev/null +++ b/src/background/utils/getContest.ts @@ -0,0 +1,45 @@ +import { RankingDataType, RankType, SubmissionType } from '@/utils' +import { cache } from '.' + +export const getContest = cache( + (contestId: string, page: number, region: 'local' | 'global' = 'local') => + `${contestId}-${page}-${region}`, + async function getContest( + contestId: string, + page: number, + region: 'local' | 'global' = 'local', + retry = 1 + ): Promise { + const url = `https://leetcode.cn/contest/api/ranking/${contestId}/?pagination=${page}®ion=${region}` + const res = await fetch(url) + if (res.status === 200) { + return res.json() + } + if (retry > 5) throw new Error('获取 Contest 数据失败') + return getContest(contestId, page, region, retry + 1) + } +) + +export type MyRankingType = { + my_solved: number[] + registered: boolean + fallback_local: boolean + my_submission: { [key: number]: SubmissionType } + my_rank: RankType +} + +export const getMyRanking = cache( + (contestId: string) => contestId, + async function getMyRanking( + contestId: string, + retry = 1 + ): Promise { + const url = `https://leetcode.cn/contest/api/myranking/${contestId}/` + const res = await fetch(url) + + if (res.status === 200) return res.json() + + if (retry > 5) throw new Error('获取 Rank 数据失败') + return getMyRanking(contestId, retry + 1) + } +) diff --git a/src/background/utils/index.ts b/src/background/utils/index.ts new file mode 100644 index 0000000..0ce693f --- /dev/null +++ b/src/background/utils/index.ts @@ -0,0 +1,6 @@ +export * from './sleep' +export * from './cache' +export * from './fileIconData' +export * from './predictorApi' +export * from './getContest' +export * from './lbaoAPI' diff --git a/src/background/utils/lbaoAPI.ts b/src/background/utils/lbaoAPI.ts new file mode 100644 index 0000000..6b50ef5 --- /dev/null +++ b/src/background/utils/lbaoAPI.ts @@ -0,0 +1,42 @@ +import { sleep } from '@/utils' + +export type LbaoPredictorType = { + data_region: string + username: string + delta?: number + oldRating?: number + newRating?: number +} + +export const lbaoPredictorApi = async ( + contest_name: string, + users: { data_region: string; username: string }[], + retry = 5 +): Promise => { + const res = await fetch( + 'https://lccn.lbao.site/api/v1/contest-records/predicted-rating', + { + method: 'POST', + body: JSON.stringify({ + contest_name, + users, + }), + headers: { 'content-type': 'application/json' }, + } + ) + if (retry && res.status === 503) { + await sleep(2000) + return lbaoPredictorApi(contest_name, users, retry - 1) + } + const data: { + old_rating: number + new_rating: number + delta_rating: number + }[] = await res.json() + return users.map((user, i) => ({ + ...user, + oldRating: data[i]?.old_rating, + delta: data[i]?.delta_rating, + newRating: data[i]?.new_rating, + })) +} diff --git a/src/background/utils/predictorApi.ts b/src/background/utils/predictorApi.ts new file mode 100644 index 0000000..148e5f0 --- /dev/null +++ b/src/background/utils/predictorApi.ts @@ -0,0 +1,70 @@ +import { sleep, cache } from '.' + +export type PredictorType = { + status: string + meta: { + contest_id: string + total_count: number + } + items: { + data_region: string + delta: number + _id: string + }[] +} + +// @see: https://github.com/SysSn13/leetcode-rating-predictor/blob/4a7f4057bd5bf94727723b0bc02d781be573a3eb/chrome-extension/background.js#L26 +const LCRP_API = [ + 'https://leetcode-predictor.herokuapp.com/api/v1/predictions', + 'https://leetcode-rating-predictor.herokuapp.com/api/v1/predictions', +] +let API_INDEX = 0 +const RETRY_COUNT = 5 + +const changeApiIndex = (() => { + let enable = true + return () => { + if (enable) { + API_INDEX = (API_INDEX + 1) % LCRP_API.length + + enable = false + setTimeout(() => { + enable = true + }, 2000) + } + } +})() + +export const predictorApi = cache( + ({ contestId, handles }: { contestId: string; handles: string[] }) => + contestId + ',' + handles.sort().join(','), + async function predictorApi( + { contestId, handles }, + retry = 1 + ): Promise { + const baseUrl = LCRP_API[API_INDEX] + const url = new URL(baseUrl) + url.searchParams.set('contestId', contestId) + url.searchParams.set('handles', handles.join(';')) + + try { + const res = await fetch(url.toString()) + + if (res.status === 200) { + return res.json() + } else if (retry < RETRY_COUNT) { + // 换一个 API 试试 + changeApiIndex() + await sleep(2 ** retry * 100) + return predictorApi({ contestId, handles }, retry + 1) + } else { + throw new Error('获取预测数据失败') + } + } catch (error) { + // 网络请求失败,换一个 API 试试 + changeApiIndex() + await sleep(2 ** retry * 100) + return predictorApi({ contestId, handles }, retry + 1) + } + } +) diff --git a/src/background/utils/sleep.ts b/src/background/utils/sleep.ts new file mode 100644 index 0000000..ca4d448 --- /dev/null +++ b/src/background/utils/sleep.ts @@ -0,0 +1,5 @@ +export function sleep(time: number): Promise { + return new Promise(function (resolve) { + setTimeout(resolve, time) + }) +} diff --git a/src/content/App.tsx b/src/content/App.tsx new file mode 100644 index 0000000..bd50b88 --- /dev/null +++ b/src/content/App.tsx @@ -0,0 +1,28 @@ +import { FC } from 'react' +import { withRoot } from './hoc' + +import Ranking from './pages/ranking/App' +import Home from './pages/home/App' +import Timer from './pages/problems/App' +import ShortcutKeyOption from './pages/problems/ShortcutKeyOption' +import Problemset from './pages/problemset/App' +import ProblemList from './pages/problem-list/App' +import { customEventDispatch } from './utils' +import OptimizedContestProblemsPage from '@/pages/problems/OptimizedContestProblemsPage' + +const App: FC = () => { + customEventDispatch('refinedLeetcodeGetOptions') + return ( + <> + + + + + + + + + ) +} + +export default withRoot(App) diff --git a/src/content/app/store.ts b/src/content/app/store.ts new file mode 100644 index 0000000..a9bc206 --- /dev/null +++ b/src/content/app/store.ts @@ -0,0 +1,125 @@ +import { configureStore, ConfigureStoreOptions } from '@reduxjs/toolkit' +import { + createStateSyncMiddleware, + initMessageListener, +} from 'redux-state-sync' +import { persistStore, persistReducer } from 'redux-persist' +import storage from 'redux-persist/lib/storage' +import localforage from 'localforage' + +import { apiSlice, contestInfosSlice } from '@/pages/ranking/rankSlice' +import postsReducer from '@/pages/home/postsSlice' +import blockUsersReducer from '@/pages/home/blockUsersSlice' +import globalDataReducer, { fetchGlobalData } from '@/pages/global/globalSlice' +import optionsReducer from '@/pages/global/optionsSlice' +import favoritesReducer from '@/pages/problem-list/favoriteSlice' +import questionsReducer from '@/pages/problemset/questionsSlice' + +// debug +// import logger from 'redux-logger' +// import devToolsEnhancer from 'remote-redux-devtools' +const enhancers: ConfigureStoreOptions['enhancers'] = [ + // 配置 Redux DevTools + // devToolsEnhancer({ + // hostname: 'localhost', + // port: 8000, + // realtime: true, + // }), +] + +const config = { + whitelist: [ + 'users/setBlockUserBySlug/fulfilled', + 'users/setBlockUserByPostId/fulfilled', + 'users/setBlockUserByCommunityArticleId/fulfilled', + 'users/setBlockUserBySolutionSlug/fulfilled', + 'blockUsers/unSetBlockUser', + 'blockUsers/toggleBlockUser', + 'global/fetchGlobalData/fulfilled', + 'options/toggleContestProblemShortcutKeyOption', + ], +} + +const persistConfig = { + key: 'refined-leetcode', + storage, + migrate: (state: any) => { + const key = 'BlockUserList' + const data = localStorage.getItem(key) + // 迁移老版本的数据,如果存在的话 + if (data) { + try { + const blockUserList: { + slug: string + name: string + }[] = JSON.parse(data) + + if (!state) state = {} + if (!state.entities) { + state.entities = {} + state.ids = [] + } + + for (const { slug, name } of blockUserList) { + if (!state.entities[slug]) { + state.entities[slug] = { slug, name, block: true } + state.ids.push(slug) + } + } + } catch (error) { + // + } + } + // console.log('Migration Running!', state) + return Promise.resolve(state) + }, +} + +const persistedUsersReducer = persistReducer(persistConfig, blockUsersReducer) +const persistedQuestionsReducer = persistReducer( + { + key: 'refined-leetcode-questions', + storage: localforage, + }, + questionsReducer +) +const persistedOptionsReducer = persistReducer( + { + key: 'refined-leetcode-option', + storage: localforage, + }, + optionsReducer +) + +const store = configureStore({ + reducer: { + [apiSlice.reducerPath]: apiSlice.reducer, + posts: postsReducer, + blockUsers: persistedUsersReducer, + global: globalDataReducer, + options: persistedOptionsReducer, + favorites: favoritesReducer, + questions: persistedQuestionsReducer, + contestInfos: contestInfosSlice.reducer, + }, + devTools: false, + middleware: getDefaultMiddleware => + getDefaultMiddleware({ + serializableCheck: false, + immutableCheck: false, + }) + .concat(apiSlice.middleware) + .concat(createStateSyncMiddleware(config)), //.concat(logger) + enhancers, +}) + +export const persistor = persistStore(store) + +initMessageListener(store) + +export default store + +export type RootState = ReturnType +export type AppDispatch = typeof store.dispatch + +store.dispatch(fetchGlobalData()) diff --git a/src/content/components/Button.tsx b/src/content/components/Button.tsx new file mode 100644 index 0000000..239f2d1 --- /dev/null +++ b/src/content/components/Button.tsx @@ -0,0 +1,99 @@ +import { ForwardedRef, forwardRef, ReactNode } from 'react' +import styled from 'styled-components/macro' + +import { SCProps, StyledComponent } from './utils' +import { rotate360Deg } from './animation' + +interface ButtonOwnerProps { + disabled?: boolean + loading?: boolean + children: ReactNode +} + +const Button: StyledComponent = forwardRef( + function Button( + { children, disabled, loading, ...props }: SCProps, + ref: ForwardedRef + ) { + return ( + + {loading ? : children} + + ) + } +) + +export default Button + +const Loading = styled.div` + border-radius: 50%; + background: linear-gradient(to right, #fff 10%, rgba(128, 0, 255, 0) 42%); + position: relative; + transform: translateZ(0); + height: 16px; + width: 16px; + animation: ${rotate360Deg} 0.1s infinite linear; + &::before { + width: 50%; + height: 50%; + background: #fff; + border-radius: 100% 0 0 0; + position: absolute; + top: 0; + left: 0; + content: ''; + } + &::after { + background-color: ${props => props.theme.palette.button.disable}; + width: 75%; + height: 75%; + border-radius: 50%; + content: ''; + margin: auto; + position: absolute; + top: 0; + left: 0; + bottom: 0; + right: 0; + } +` + +const ButtonStyled = styled.button.attrs<{ disabled?: boolean }>(props => ({ + disable: props.disabled, +}))` + flex-shrink: 0; + width: 70px; + color-scheme: dark; + font-feature-settings: 'tnum'; + box-sizing: border-box; + margin: 0; + border: none; + line-height: 20px; + outline: none; + user-select: none; + text-decoration: none; + display: inline-flex; + align-items: center; + justify-content: center; + transition-property: color, box-shadow, background-color, opacity; + transition-duration: 0.3s; + overflow: hidden; + cursor: ${props => (props.disabled ? '' : 'pointer')}; + opacity: 1; + font-size: 14px; + padding: 6px 12px; + border-radius: 8px; + color: ${props => props.theme.palette.button.text}; + background-color: ${props => + props.disabled + ? props.theme.palette.button.disable + : props.theme.palette.button.main}; + &:hover { + background-color: ${props => + props.disabled ? '' : `${props.theme.palette.button.hover};`}; + } + &:focus { + background-color: ${props => + props.disabled ? '' : `${props.theme.palette.button.hover};`}; + } +` diff --git a/src/content/components/Checkbox.tsx b/src/content/components/Checkbox.tsx new file mode 100644 index 0000000..759c101 --- /dev/null +++ b/src/content/components/Checkbox.tsx @@ -0,0 +1,65 @@ +import { ChangeEventHandler, FC } from 'react' +import { css } from 'styled-components/macro' +import { + CheckBoxCheckedIcon, + CheckBoxIndeterminateIcon, + CheckBoxUncheckedIcon, +} from './icons' + +interface CheckboxProps { + checked?: boolean + indeterminate?: boolean + onChange?: ChangeEventHandler + size?: number + color?: string + id?: string +} + +const Checkbox: FC = ({ + checked, + indeterminate, + onChange, + size, + color, + id, +}) => { + const Icon = indeterminate + ? CheckBoxIndeterminateIcon + : checked + ? CheckBoxCheckedIcon + : CheckBoxUncheckedIcon + const chandleChange: ChangeEventHandler = e => { + onChange?.(e) + } + return ( + + + + + ) +} + +export default Checkbox diff --git a/src/content/components/Dialog.tsx b/src/content/components/Dialog.tsx new file mode 100644 index 0000000..ab3b59f --- /dev/null +++ b/src/content/components/Dialog.tsx @@ -0,0 +1,58 @@ +import { forwardRef, ForwardedRef, ReactNode, useEffect } from 'react' +import { css } from 'styled-components/macro' + +import { Portal } from './Portal' +import { StyledComponent, SCProps } from './utils' + +export type Placement = 'top' | 'bottom' | 'left' | 'right' + +interface DialogProps { + open: boolean + children: ReactNode + onClose?: (e: any) => void +} + +const Dialog: StyledComponent = forwardRef(function Popper< + AsC extends string | React.ComponentType = 'span' +>( + { open, children, onClose, ...props }: SCProps, + _ref: ForwardedRef +) { + useEffect(() => { + const handleClose = (e: KeyboardEvent) => { + if (e.code === 'Escape') { + if (onClose) { + onClose(e) + } + } + } + if (open && children) document.body.addEventListener('keydown', handleClose) + return () => { + document.body.removeEventListener('keydown', handleClose) + } + }, [open, children, onClose]) + + if (!children) return null + + return ( + +
+
{children}
+
+
+ ) +}) + +export default Dialog diff --git a/src/content/components/DistortSvg.tsx b/src/content/components/DistortSvg.tsx new file mode 100644 index 0000000..92c32d9 --- /dev/null +++ b/src/content/components/DistortSvg.tsx @@ -0,0 +1,35 @@ +import { FC } from 'react' +import 'styled-components/macro' + +/** 实现扭曲糢糊效果 + * + * 通过 CSS 中的 filter 使用 + */ +const DistortSvg: FC = () => { + return ( + + + + + + + ) +} + +export default DistortSvg diff --git a/src/content/components/ErrorToolTip.tsx b/src/content/components/ErrorToolTip.tsx new file mode 100644 index 0000000..2137237 --- /dev/null +++ b/src/content/components/ErrorToolTip.tsx @@ -0,0 +1,56 @@ +import { FC, ReactElement, ComponentProps } from 'react' +import { ToolTip } from './ToolTip' + +interface ErrorToolTipOwnerProps { + error: { + message: string + show: boolean + } + children: ReactElement + onClose?: (e: any) => void +} + +type ErrorToolTipProps = Omit< + ComponentProps, + keyof ErrorToolTipOwnerProps +> & + ErrorToolTipOwnerProps + +const ErrorToolTip: FC< + Partial> & ErrorToolTipOwnerProps +> = ({ error, children, ...props }: ErrorToolTipProps) => { + return ( + + + + } + > + {children} + + ) +} + +export default ErrorToolTip diff --git a/src/content/components/Input.tsx b/src/content/components/Input.tsx new file mode 100644 index 0000000..623f378 --- /dev/null +++ b/src/content/components/Input.tsx @@ -0,0 +1,22 @@ +import styled from 'styled-components/macro' + +export const Input = styled.input` + overflow: visible; + height: 32px; + outline: none; + border-radius: 8px !important; + box-sizing: border-box; + width: 100%; + padding: 4px 11px; + font-size: 14px; + line-height: 1.5715; + border: 1px solid rgba(0, 0, 0, 0); + transition: all 0.3s; + touch-action: manipulation; + text-overflow: ellipsis; + color: ${props => props.theme.palette.text.main}; + background: ${props => props.theme.palette.secondary.main}; + &:focus { + background-color: ${props => props.theme.palette.secondary.hover}; + } +` diff --git a/src/content/components/Modal.tsx b/src/content/components/Modal.tsx new file mode 100644 index 0000000..c2a3471 --- /dev/null +++ b/src/content/components/Modal.tsx @@ -0,0 +1,56 @@ +import { forwardRef, ForwardedRef, ReactNode, useEffect } from 'react' +import { css } from 'styled-components/macro' + +import { Portal } from './Portal' +import { StyledComponent, SCProps } from './utils' + +export type Placement = 'top' | 'bottom' | 'left' | 'right' + +interface ModalProps { + open: boolean + children: ReactNode + onClose?: (e: any) => void +} + +const Modal: StyledComponent = forwardRef(function Popper< + AsC extends string | React.ComponentType = 'span' +>( + { open, children, onClose, ...props }: SCProps, + _ref: ForwardedRef +) { + useEffect(() => { + const handleClose = (e: KeyboardEvent) => { + if (e.code === 'Escape' && typeof onClose === 'function') { + onClose(e) + } + } + if (open && children) document.body.addEventListener('keydown', handleClose) + return () => { + document.body.removeEventListener('keydown', handleClose) + } + }, [open, children, onClose]) + + if (!children) return null + + return ( + +
+
{children}
+
+
+ ) +}) + +export default Modal diff --git a/src/content/components/Popper.tsx b/src/content/components/Popper.tsx new file mode 100644 index 0000000..07eeb04 --- /dev/null +++ b/src/content/components/Popper.tsx @@ -0,0 +1,263 @@ +import { + forwardRef, + useRef, + useCallback, + useState, + useLayoutEffect, +} from 'react' +import styled, { css } from 'styled-components/macro' +import { Portal } from './Portal' +import { StyledComponent, SCProps } from './utils' + +export type Placement = 'top' | 'bottom' | 'left' | 'right' + +export interface PopperProps { + /** + * 用于定位弹出窗口的元素 + */ + anchorEl?: HTMLElement | null + /** + * 相对于定位元素的方向 + */ + placement?: Placement + /** + * 是否显示小箭头 + */ + arrow?: boolean + offset?: { + left?: number + top?: number + } +} + +export const Popper: StyledComponent = forwardRef( + function Popper( + { + anchorEl, + placement = 'top', + arrow, + offset, + ...props + }: SCProps, + ref: React.ForwardedRef + ) { + const popperRef = useRef() + const arrowSize = 8 + const mulRef = useCallback(el => { + popperRef.current = el + if (ref) { + if (typeof ref === 'function') { + ref(el) + } else { + ref.current = el + } + } + }, []) + + const [pos, setPos] = useState<{ left: number; top: number }>({ + left: 0, + top: 0, + }) + + useLayoutEffect(() => { + if (anchorEl) setPos(() => caclPopperPos(placement, anchorEl, offset)) + }, [anchorEl, offset, placement]) + + const [arrowPos, setArrow] = useState<{ left: number; top: number }>() + + useLayoutEffect(() => { + if (arrow && popperRef.current) { + setArrow(caclArrowPos(placement, popperRef.current, arrowSize)) + } + }, [arrow, placement]) + + if (!anchorEl) return null + + return ( + + + + ) + } +) + +/** + * 计算箭头相对弹出窗口的定位信息 + * @param placement 弹出窗口相对于定位元素的方向 + * @param el 定位元素 + * @param arrowSize 箭头大小 + * @returns 返回箭头的定位信息 + */ +function caclArrowPos( + placement: Placement, + el: HTMLElement, + arrowSize: number +) { + const { offsetHeight, offsetWidth } = el + switch (placement) { + case 'top': + return { left: offsetWidth / 2 - arrowSize, top: offsetHeight } + + case 'bottom': + return { left: offsetWidth / 2 - arrowSize, top: -arrowSize * 2 } + + case 'left': + return { left: offsetWidth, top: offsetHeight / 2 - arrowSize } + + case 'right': + return { left: -arrowSize * 2, top: offsetHeight / 2 - arrowSize } + + default: + // eslint-disable-next-line no-case-declarations + const _exhaustiveCheck: never = placement + return _exhaustiveCheck + } +} + +/** + * 计算弹出窗口相对于全局的定位信息 + * @param placement 弹出窗口相对于定位元素的方向 + * @param el 定位元素 + * @returns 返回弹出窗口的定位信息 + */ +function caclPopperPos( + placement: Placement, + el: HTMLElement, + offset?: { left?: number; top?: number } +) { + let { height, width, left, top } = el.getBoundingClientRect() + + switch (placement) { + case 'top': + left += width / 2 + break + + case 'bottom': + left += width / 2 + top += height + break + case 'left': + top += height / 2 + break + case 'right': + left += width + top += height / 2 + break + default: + // eslint-disable-next-line no-case-declarations + const _exhaustiveCheck: never = placement + return _exhaustiveCheck + } + if (offset) { + left += offset.left ?? 0 + top += offset.top ?? 0 + } + return { left, top } +} + +export const PopperpStyled = styled.span<{ + left?: number | string + top?: number | string + placement: Placement + arrow?: { + arrowSize?: number + left?: number | string + top?: number | string + } +}>` + position: fixed; + transform: ${props => { + const offset = props.arrow ? 18 : 10 + switch (props.placement) { + case 'top': + return `translate(-50%, calc(-100% - ${offset}px))` + + case 'left': + return `translate(calc(-100% - ${offset}px),-50%)` + + case 'bottom': + return `translate(-50%,${offset}px)` + + case 'right': + return `translate(${offset}px,-50%)` + + default: + break + } + }}; + + color: #fff; + /* height: 32px; */ + padding: 6px 8px; + background: rgb(66, 66, 66); + border-radius: 3px; + box-shadow: 0 10px 32px rgba(0, 0, 0, 0.54); + + ${props => { + let { left, top } = props + + if (typeof left === 'number') left = `left: ${left}px;` + else if (typeof left === 'string') left = `left: ${left};` + else left = '' + + if (typeof top === 'number') top = `top: ${top}px;` + else if (typeof top === 'string') top = `top: ${top};` + else top = '' + + return css` + ${left} + ${top} + ` + }} + + ${props => { + if (!props.arrow) return '' + let { + arrow: { left, top, arrowSize } = { + left: '', + top: '', + arrowSize: 0, + }, + placement, + } = props ?? {} + + if (left) { + if (typeof left === 'number') left = `left: ${left}px;` + else if (typeof left === 'string') left = `left: ${left};` + } else left = '' + + if (top) { + if (typeof top === 'number') top = `top: ${top}px;` + else if (typeof top === 'string') top = `top: ${top};` + } else top = '' + + return css` + &::before { + position: fixed; + box-sizing: content-box; + content: ''; + display: block; + height: 0; + width: 0; + + border: ${arrowSize}px solid transparent; + border-${placement}: ${arrowSize}px solid #424242; + ${left} + ${top} + } + ` + }} +` diff --git a/src/content/components/PopperUnstyled.tsx b/src/content/components/PopperUnstyled.tsx new file mode 100644 index 0000000..df63ac0 --- /dev/null +++ b/src/content/components/PopperUnstyled.tsx @@ -0,0 +1,259 @@ +import { + forwardRef, + useRef, + useCallback, + useState, + useLayoutEffect, + useEffect, +} from 'react' +import styled, { StyledComponentProps } from 'styled-components/macro' + +import { useEvent } from '@/hooks' + +import { Portal } from './Portal' + +export type Placement = 'top' | 'bottom' | 'left' | 'right' + +type SCProps< + BaseProps extends object, + AsC extends string | React.ComponentType, + FAsC extends string | React.ComponentType = AsC +> = StyledComponentProps & { + as?: AsC | undefined + forwardedAs?: FAsC | undefined +} + +type StyledComponent< + BaseProps extends object, + DefaultAsC extends string | React.ComponentType +> = < + AsC extends string | React.ComponentType = DefaultAsC, + FAsC extends string | React.ComponentType = AsC +>( + props: SCProps, + ref?: React.Ref +) => React.ReactElement> | null + +interface PopperProps { + /** 用于定位弹出窗口的元素 + * + */ + anchorEl?: HTMLElement | null + /** 相对于定位元素的方向 + * + */ + placement?: Placement + /** Popper 元素要添加到容器,如果为空,默认为 document.body + * + */ + container?: HTMLElement + background?: boolean + followScroll?: boolean + offset?: { + left: number + top: number + } + position?: 'absolute' | 'fixed' + + /** + * 为了确保元素定位的准确,需要监听有可能影响定位元素的祖先结点的 scroll 事件 + * 但如果 position 为 absolute 时,则不需要监听所有的祖先结点,一般只需要监听到距离最近的 position 不为 static 的祖先结点 + * 有时候会动态对某个祖先结点设置 position,这时可以将这个结点作为 rootElement 传入,则在添加事件时,只添加到这个结点为止 + * 可以起到一定的优化左右,不过如果传入不正确,可能会影响最终定位的效果 + */ + rootElement?: HTMLElement +} + +const Popper: StyledComponent = forwardRef(function Popper< + AsC extends string | React.ComponentType = 'span' +>( + { + anchorEl, + placement = 'top', + container, + followScroll = true, + offset, + position, + rootElement, + ...props + }: SCProps, + ref: React.ForwardedRef +) { + if (!position) position = 'fixed' + const popperRef = useRef() + + const mulRef = useCallback(el => { + popperRef.current = el + if (ref) { + if (typeof ref === 'function') { + ref(el) + } else { + ref.current = el + } + } + }, []) + + const [pos, setPos] = useState<{ left: number; top: number }>({ + left: 0, + top: 0, + }) + + const update = useEvent(() => { + if (anchorEl) { + setPos(() => caclPopperPos(placement, anchorEl, position!, offset)) + } + }) + + useLayoutEffect(() => { + update() + }, [anchorEl, placement, update]) + + useEffect(() => { + const parents: (HTMLElement | Window)[] = [], + options: AddEventListenerOptions = { passive: true } + if (followScroll && anchorEl) { + if (position === 'fixed') { + let node = anchorEl + do { + node.addEventListener('scroll', update, options) + parents.push(node) + if (!node.parentElement) break + node = node.parentElement + } while (node !== document.documentElement) + window.addEventListener('scroll', update, options) + parents.push(window) + } else { + let node = anchorEl + do { + node.addEventListener('scroll', update, options) + parents.push(node) + if ( + node === rootElement || + getComputedStyle(node).position !== 'static' + ) + break + if (!node.parentElement) break + node = node.parentElement + } while (node !== document.documentElement) + } + } + if (anchorEl) { + window.addEventListener('resize', update, options) + } + + return () => { + if (anchorEl) { + parents.forEach(el => el.removeEventListener('scroll', update, options)) + window.removeEventListener('resize', update, options) + } + } + }, [anchorEl, followScroll, position, rootElement, update]) + + if (!anchorEl) return null + + return ( + + + + ) +}) +export default Popper + +/** 计算弹出窗口相对于全局的定位信息 + * + * @param placement 弹出窗口相对于定位元素的方向 + * @param el 定位元素 + * @returns 返回弹出窗口的定位信息 + */ +function caclPopperPos( + placement: Placement, + el: HTMLElement, + position: 'absolute' | 'fixed', + offset?: { left: number; top: number } +) { + const rect = el.getBoundingClientRect() + const { height, width } = rect + let left = 0, + top = 0 + + if (position === 'fixed') ({ left, top } = rect) + + // const { offsetHeight: height, offsetWidth: width } = el + switch (placement) { + case 'top': + left += width / 2 + break + case 'bottom': + left += width / 2 + top += height + break + case 'left': + top += height / 2 + break + case 'right': + left += width + top += height / 2 + break + default: + // eslint-disable-next-line no-case-declarations + const _exhaustiveCheck: never = placement + return _exhaustiveCheck + } + if (offset) { + left += offset.left ?? 0 + top += offset.top ?? 0 + } + return { left, top } +} + +export const PopperpStyled = styled.span.attrs<{ + left?: number | string + top?: number | string + placement: Placement + background?: boolean + position?: string +}>(props => { + let transform = '', + left = '', + top = '' + const offset = 0 + switch (props.placement) { + case 'top': + transform = `translate(-50%, calc(-100% - ${offset}px))` + break + case 'left': + transform = `translate(calc(-100% - ${offset}px),-50%)` + break + case 'bottom': + transform = `translate(-50%,${offset}px)` + break + case 'right': + transform = `translate(${offset}px,-50%)` + break + default: + break + } + + if (typeof props.left === 'number') left = `${props.left}px` + else if (typeof props.left === 'string') left = `${props.left}` + else left = '' + + if (typeof props.top === 'number') top = `${props.top}px` + else if (typeof props.top === 'string') top = `${props.top}` + else top = '' + + return { + style: { + transform, + left, + top, + position: props.position, + }, + } +})`` diff --git a/src/content/components/Portal.tsx b/src/content/components/Portal.tsx new file mode 100644 index 0000000..8179f5e --- /dev/null +++ b/src/content/components/Portal.tsx @@ -0,0 +1,14 @@ +import { ReactNode } from 'react' + +import { createPortal } from 'react-dom' + +export const Portal = function Portal({ + children, + container, +}: { + children: ReactNode + container?: HTMLElement | null +}): React.ReactPortal { + if (!container) container = document.body + return createPortal(children, container) +} diff --git a/src/content/components/SvgIcon.tsx b/src/content/components/SvgIcon.tsx new file mode 100644 index 0000000..f916919 --- /dev/null +++ b/src/content/components/SvgIcon.tsx @@ -0,0 +1,18 @@ +import { SCProps, StyledComponent } from './utils' + +interface OwnSvgIconProps { + children?: React.ReactNode + height?: number +} +export type SvgIconProps = SCProps +export type SvgIconType = StyledComponent + +const SvgIcon: SvgIconType = ({ children, height = 24, ...props }) => { + return ( + + {children} + + ) +} + +export default SvgIcon diff --git a/src/content/components/Switch.tsx b/src/content/components/Switch.tsx new file mode 100644 index 0000000..97fa602 --- /dev/null +++ b/src/content/components/Switch.tsx @@ -0,0 +1,46 @@ +import { useRef, useState } from 'react' + +interface SwitchProps { + enable?: boolean + height?: number + width?: number + onToggle?: () => void +} + +const Switch: React.FC = ({ + enable: enableProp, + height, + width, + onToggle, +}) => { + const { current: isControlled } = useRef(enableProp !== undefined) + const [state, setState] = useState() + const handleToggle = () => { + setState(!state) + if (onToggle) onToggle() + } + if (height === undefined && width === undefined) height = 24 + const enable = isControlled ? enableProp : state + return ( + + {enable ? ( + + ) : ( + + )} + + ) +} + +export default Switch diff --git a/src/content/components/ToolTip.tsx b/src/content/components/ToolTip.tsx new file mode 100644 index 0000000..d8f0d5e --- /dev/null +++ b/src/content/components/ToolTip.tsx @@ -0,0 +1,83 @@ +import React, { + forwardRef, + useRef, + useCallback, + ReactElement, + cloneElement, + ForwardedRef, +} from 'react' +import { useHover } from '@/hooks' +import { setRef } from '@/utils' +import { Popper, Placement, PopperProps } from './Popper' +import { StyledComponent, SCProps } from './utils' + +export interface TooltipOwnerProps { + title: ReactElement | string + placement?: Placement + open?: boolean + arrow?: boolean + icon?: ReactElement + delay?: number + children: React.ReactElement + keep?: boolean +} + +export const ToolTip: StyledComponent = + forwardRef(function ToolTip1< + AsC extends string | React.ComponentType = 'span' + >( + { + title, + placement = 'top', + open: openProp, + arrow: arrowProp, + icon, + delay, + keep, + children, + ...props + }: SCProps, + ref: ForwardedRef + ) { + const [setHoverRef, hover] = useHover(delay ?? 100) + const [setPopperHoverRef, popperHover] = useHover(delay ?? 100, [ + ref as any, + ]) + + const childrenRef = useRef() + + const mulRef = useCallback(el => { + setRef(el, childrenRef) + setRef(el, setHoverRef) + setRef(el, children && (children as any).ref) + }, []) + + let open = openProp + if (openProp === undefined) { + open = !!title && (hover || (keep && popperHover)) + } + let arrow = arrowProp + if (arrowProp === undefined) { + arrow = true + } + + return ( + <> + {cloneElement(children, { ...children.props, ref: mulRef })} + {open ? ( + + <> + {icon} + {title} + + + ) : null} + + ) + }) diff --git a/src/content/components/animation.tsx b/src/content/components/animation.tsx new file mode 100644 index 0000000..47c68d3 --- /dev/null +++ b/src/content/components/animation.tsx @@ -0,0 +1,11 @@ +import { keyframes } from 'styled-components/macro' + +export const rotate360Deg = keyframes` + from { + transform: rotate(0deg); + } + + to { + transform: rotate(360deg); + } +` diff --git a/src/content/components/icons/AddIcon.tsx b/src/content/components/icons/AddIcon.tsx new file mode 100644 index 0000000..fc1e149 --- /dev/null +++ b/src/content/components/icons/AddIcon.tsx @@ -0,0 +1,11 @@ +import SvgIcon, { SvgIconProps } from '../SvgIcon' + +const AddIcon: React.FC = props => { + return ( + + + + ) +} + +export default AddIcon diff --git a/src/content/components/icons/CheckBoxIcon.tsx b/src/content/components/icons/CheckBoxIcon.tsx new file mode 100644 index 0000000..1478420 --- /dev/null +++ b/src/content/components/icons/CheckBoxIcon.tsx @@ -0,0 +1,25 @@ +import SvgIcon, { SvgIconProps } from '../SvgIcon' + +export const CheckBoxCheckedIcon: React.FC = props => { + return ( + + + + ) +} + +export const CheckBoxUncheckedIcon: React.FC = props => { + return ( + + + + ) +} + +export const CheckBoxIndeterminateIcon: React.FC = props => { + return ( + + + + ) +} diff --git a/src/content/components/icons/CrownIcon.tsx b/src/content/components/icons/CrownIcon.tsx new file mode 100644 index 0000000..1436d17 --- /dev/null +++ b/src/content/components/icons/CrownIcon.tsx @@ -0,0 +1,11 @@ +import SvgIcon, { SvgIconProps } from '../SvgIcon' + +const CrownIcon: React.FC = props => { + return ( + + + + ) +} + +export default CrownIcon diff --git a/src/content/components/icons/EditIcon.tsx b/src/content/components/icons/EditIcon.tsx new file mode 100644 index 0000000..7349acc --- /dev/null +++ b/src/content/components/icons/EditIcon.tsx @@ -0,0 +1,11 @@ +import SvgIcon, { SvgIconProps } from '../SvgIcon' + +const EditIcon: React.FC = props => { + return ( + + + + ) +} + +export default EditIcon diff --git a/src/content/components/icons/HelpIcon.tsx b/src/content/components/icons/HelpIcon.tsx new file mode 100644 index 0000000..311548a --- /dev/null +++ b/src/content/components/icons/HelpIcon.tsx @@ -0,0 +1,11 @@ +import SvgIcon, { SvgIconProps } from '../SvgIcon' + +const HelpIcon: React.FC = props => { + return ( + + + + ) +} + +export default HelpIcon diff --git a/src/content/components/icons/PrivateIcon.tsx b/src/content/components/icons/PrivateIcon.tsx new file mode 100644 index 0000000..2dbe59e --- /dev/null +++ b/src/content/components/icons/PrivateIcon.tsx @@ -0,0 +1,11 @@ +import SvgIcon, { SvgIconProps } from '../SvgIcon' + +const PrivateIcon: React.FC = props => { + return ( + + + + ) +} + +export default PrivateIcon diff --git a/src/content/components/icons/PublicIcon.tsx b/src/content/components/icons/PublicIcon.tsx new file mode 100644 index 0000000..f7adb2b --- /dev/null +++ b/src/content/components/icons/PublicIcon.tsx @@ -0,0 +1,11 @@ +import SvgIcon, { SvgIconProps } from '../SvgIcon' + +const PublicIcon: React.FC = props => { + return ( + + + + ) +} + +export default PublicIcon diff --git a/src/content/components/icons/RemoveIcon.tsx b/src/content/components/icons/RemoveIcon.tsx new file mode 100644 index 0000000..aa140e4 --- /dev/null +++ b/src/content/components/icons/RemoveIcon.tsx @@ -0,0 +1,11 @@ +import SvgIcon, { SvgIconProps } from '../SvgIcon' + +const RemoveIcon: React.FC = props => { + return ( + + + + ) +} + +export default RemoveIcon diff --git a/src/content/components/icons/ResetIcon.tsx b/src/content/components/icons/ResetIcon.tsx new file mode 100644 index 0000000..24fc1a0 --- /dev/null +++ b/src/content/components/icons/ResetIcon.tsx @@ -0,0 +1,11 @@ +import SvgIcon, { SvgIconProps } from '../SvgIcon' + +const ResetIcon: React.FC = props => { + return ( + + + + ) +} + +export default ResetIcon diff --git a/src/content/components/icons/index.ts b/src/content/components/icons/index.ts new file mode 100644 index 0000000..c4a1061 --- /dev/null +++ b/src/content/components/icons/index.ts @@ -0,0 +1,7 @@ +export { default as HelpIcon } from './HelpIcon' +export { default as AddIcon } from './AddIcon' +export { default as EditIcon } from './EditIcon' +export { default as RemoveIcon } from './RemoveIcon' +export { default as PublicIcon } from './PublicIcon' +export { default as PrivateIcon } from './PrivateIcon' +export * from './CheckBoxIcon' diff --git a/src/content/components/utils.ts b/src/content/components/utils.ts new file mode 100644 index 0000000..803ee37 --- /dev/null +++ b/src/content/components/utils.ts @@ -0,0 +1,25 @@ +import { StyledComponentProps } from 'styled-components/macro' + +export type SCProps< + BaseProps extends object, + AsC extends string | React.ComponentType, + FAsC extends string | React.ComponentType = AsC +> = Omit< + StyledComponentProps, + keyof BaseProps +> & + BaseProps & { + as?: AsC | undefined + forwardedAs?: FAsC | undefined + } + +export type StyledComponent< + BaseProps extends object, + DefaultAsC extends string | React.ComponentType +> = < + AsC extends string | React.ComponentType = DefaultAsC, + FAsC extends string | React.ComponentType = AsC +>( + props: SCProps, + ref?: React.Ref +) => React.ReactElement> | null diff --git a/src/content/hoc/index.ts b/src/content/hoc/index.ts new file mode 100644 index 0000000..a5c2d27 --- /dev/null +++ b/src/content/hoc/index.ts @@ -0,0 +1,2 @@ +export * from './withRoot' +export * from './withPage' diff --git a/src/content/hoc/withPage.tsx b/src/content/hoc/withPage.tsx new file mode 100644 index 0000000..1c98de4 --- /dev/null +++ b/src/content/hoc/withPage.tsx @@ -0,0 +1,17 @@ +import { ComponentType, forwardRef } from 'react' + +import { PageName } from 'src/options/options' +import { useAppSelector } from '@/hooks' +import { selectCurrentPage } from '@/pages/global/globalSlice' + +export const withPage = + (pageName: PageName) => + >(Component: T): T => { + const App = forwardRef(function App(props: any, ref: any) { + const currentPage = useAppSelector(selectCurrentPage) + if (currentPage !== pageName) return null + return + }) + + return App as any + } diff --git a/src/content/hoc/withRoot.tsx b/src/content/hoc/withRoot.tsx new file mode 100644 index 0000000..5eb2a10 --- /dev/null +++ b/src/content/hoc/withRoot.tsx @@ -0,0 +1,70 @@ +import { + StrictMode, + ComponentType, + useState, + useEffect, + forwardRef, +} from 'react' +import { Provider } from 'react-redux' +import { PersistGate } from 'redux-persist/integration/react' +import { ThemeProvider } from 'styled-components/macro' + +import store, { persistor } from '@/app/store' +import { darkTheme, lightTheme } from '@/theme' +import { getPageName, getTheme, isBetaUI } from '@/utils' +import { setCurrentPage } from '@/pages/global/globalSlice' + +const Loading = () => <> + +export const withRoot = >(Component: T): T => { + const Root = forwardRef(function Root(props: any, ref: any) { + const [theme, setTheme] = useState(getTheme()) + useEffect(() => { + // 跟随力扣的明暗主题进行切换 + let observer: MutationObserver + void (async function () { + const beta = await isBetaUI() + const el = beta ? document.documentElement : document.body + + observer = new MutationObserver(mutationList => { + if (mutationList.some(record => record.attributeName === 'class')) { + if (el.classList.contains('dark')) { + setTheme(darkTheme) + } else { + setTheme(lightTheme) + } + } + }) + + observer.observe(el, { attributes: true }) + })() + return () => { + if (observer) observer.disconnect() + } + }, []) + useEffect(() => { + const handleUrlChange = async () => { + const pageName = getPageName() + store.dispatch(setCurrentPage(pageName)) + } + window.addEventListener('urlchange', handleUrlChange) + return () => { + window.removeEventListener('urlchange', handleUrlChange) + } + }, []) + + return ( + + } persistor={persistor}> + + + + + + + + ) + }) + + return Root as any +} diff --git a/src/content/hooks/index.ts b/src/content/hooks/index.ts new file mode 100644 index 0000000..7cb717a --- /dev/null +++ b/src/content/hooks/index.ts @@ -0,0 +1,11 @@ +import { useDispatch, useSelector } from 'react-redux' +import type { TypedUseSelectorHook } from 'react-redux' +import type { RootState, AppDispatch } from '@/app/store' +export * from './useEvent' +export * from './useHover' +export * from './useEffectMount' +export * from './useIsMount' +export * from './useObserverAncestor' + +export const useAppDispatch: () => AppDispatch = useDispatch +export const useAppSelector: TypedUseSelectorHook = useSelector diff --git a/src/content/hooks/useEffectMount.ts b/src/content/hooks/useEffectMount.ts new file mode 100644 index 0000000..6ebda88 --- /dev/null +++ b/src/content/hooks/useEffectMount.ts @@ -0,0 +1,38 @@ +import { DependencyList, useEffect } from 'react' +import { State, useUnMount } from './useIsMount' + +/** 判断当前组件是否被卸载,主要用于需要在 useEffect 中去处理一些异步任务 + * + * @param effect 传入一个函数,这个函数接收一个 state 的参数,其中 state.isMount 就是标识当前是否被卸载,另外可以通过设置 state.unmount 来运行一些卸载的时候需要处理的逻辑 + * @param deps 是否需要依赖项,默认为空数组,既默认只会在组件加载时执行,在组件卸载时执行卸载操作 + * + * @example + * ```ts + * useEffectMount( + * async state => { + * await awaitFn() + * if(!state.isMount) return // 如果当前组件已经被卸载则不去执行后面的语句 + * state.unmount.push(()=>{ }) // 执行一些卸载操作 + * }, + * [] + * ) + * ``` + */ +export const useEffectMount = ( + effect: + | ((state: State) => void | (() => void)) + | ((state: State) => Promise), + deps: DependencyList = [] +): void => { + const state = useUnMount() + useEffect(() => { + const fn = effect(state) + return () => { + while (state.unmount.length) { + const fn = state.unmount.pop() + if (fn instanceof Function) fn() + } + if (fn instanceof Function) fn() + } + }, deps) +} diff --git a/src/content/hooks/useEvent.ts b/src/content/hooks/useEvent.ts new file mode 100644 index 0000000..3a7476d --- /dev/null +++ b/src/content/hooks/useEvent.ts @@ -0,0 +1,15 @@ +import { useCallback, useLayoutEffect, useRef } from 'react' + +/** + * @see https://github.com/reactjs/rfcs/blob/useevent/text/0000-useevent.md + */ +const useEvent = any>(fn: T): T => { + const ref = useRef(fn) + useLayoutEffect(() => { + ref.current = fn + }) + + return useCallback(((...args) => ref.current(...args)) as T, []) +} + +export { useEvent } diff --git a/src/content/hooks/useHover.ts b/src/content/hooks/useHover.ts new file mode 100644 index 0000000..9d20868 --- /dev/null +++ b/src/content/hooks/useHover.ts @@ -0,0 +1,58 @@ +import { setRef } from '@/utils' +import { useCallback, useRef, useState } from 'react' +import { useEvent } from './useEvent' + +/** + * 处理 hover 逻辑的钩子 + * @param delay hover 效果消失的延迟时间 + */ +export const useHover = ( + delay = 0, + refs?: React.Ref[] +): [ + bindRef: (el: T | null) => void, + hover: boolean, + ref: React.MutableRefObject +] => { + const ref = useRef() + const [hover, setHover] = useState(false) + const timer = useRef>() + + const clearTimer = () => { + if (timer.current !== undefined) { + clearTimeout(timer.current) + timer.current = undefined + } + } + + const handleMouseEnter = useEvent((_e: MouseEvent) => { + setHover(true) + clearTimer() + }) + + const handleMouseLeave = useEvent((_e: MouseEvent) => { + timer.current = setTimeout(() => setHover(false), delay) + }) + + const refcb = useCallback((el: T | null) => { + if (ref.current) { + // ref 会在卸载时被设置为 null + // 所以不用另外在 useEffect 去设置针对组件卸载时删除事件侦听器的逻辑,只要在这里设置即可 + + clearTimer() + setHover(false) + + ref.current.removeEventListener('mouseenter', handleMouseEnter) + ref.current.removeEventListener('mouseleave', handleMouseLeave) + } + + refs?.forEach(ref => setRef(el, ref)) + ref.current = el + if (ref.current) { + ref.current.addEventListener('mouseenter', handleMouseEnter) + ref.current.addEventListener('mouseleave', handleMouseLeave) + } + }, []) + + return [refcb, hover, ref] +} diff --git a/src/content/hooks/useIsMount.ts b/src/content/hooks/useIsMount.ts new file mode 100644 index 0000000..8d1fc23 --- /dev/null +++ b/src/content/hooks/useIsMount.ts @@ -0,0 +1,24 @@ +import { useEffect, useRef } from 'react' + +export type State = { + isMount: boolean + unmount: Array<() => void> +} + +/** + * 处理组件卸载逻辑 + */ +export const useUnMount = (): State => { + const { current: state } = useRef({ isMount: true, unmount: [] }) + useEffect(() => { + state.isMount = true + return () => { + state.isMount = false + while (state.unmount.length) { + const fn = state.unmount.pop() + if (fn instanceof Function) fn() + } + } + }, []) + return state +} diff --git a/src/content/hooks/useObserverAncestor.ts b/src/content/hooks/useObserverAncestor.ts new file mode 100644 index 0000000..cfe391d --- /dev/null +++ b/src/content/hooks/useObserverAncestor.ts @@ -0,0 +1,94 @@ +import { DependencyList, useEffect, useRef } from 'react' +import { useEvent } from './useEvent' +import { State, useUnMount } from './useIsMount' + +/** 用于当祖先元素发生变化时,执行特定的操作 + * + * 原理是通过 MutationObserver 监听对应祖先元素是否被删除,如果被删除, + * 则需要重新挂载元素或绑定事件,并将新元素的祖先结点重新绑定 MutationObserver 事件 + * + * 主要针对某个结点其祖先元素有可能会被删除的场景 + * + * @param onChange 当祖先元素发生变化时,需要执行的操作 + * @param getAncestor 获取监听的祖先元素 + * @param check 检查是否满足变化的条件 + * + * @todo 当同时有多个地方使用 useObserverAncestor 时,尝试合并监听的事件,以提升性能 + */ +export const useObserverAncestor = ( + onChange: ( + state: State + ) => HTMLElement | undefined | null | Promise, + deps: DependencyList = [] +): void => { + const state = useUnMount() + const ancestorRef = useRef({ + nodes: [] as HTMLElement[], + nodeSet: new Set(), + observers: [] as MutationObserver[], + }) + + const mount = useEvent(async () => { + const root = await onChange(state) + if (!root) return + let el = root + const { nodes, nodeSet, observers } = ancestorRef.current + const els: HTMLElement[] = [] + + //#region 找到新元素和旧元素的公共祖先结点,然后将旧元素到公共祖先结点之间的元素删除,并删除对应的 MutationObserver + while (el && !nodeSet.has(el) && el !== document.body) { + els.push(el) + el = el.parentElement! + } + const pop = () => { + const node = nodes.pop()! + nodeSet.delete(node) + observers.pop()!.disconnect() + return node + } + + while (nodes.length) { + const node = pop() + if (el === node) break + } + + //#endregion + + // 添加新元素变化的部分祖先结点,并添加对应的 MutationObserver + // 要判断当前结点是否被删除,必须要将 MutationObserver 挂载到父元素上 + + while (els.length) { + const el = els.pop()! + const observer = new MutationObserver(mutations => { + const checked = mutations.some(({ removedNodes }) => + Array.prototype.some.call(removedNodes, node => node === el) + ) + if (checked) { + while (nodes.length) { + const ancestor = pop() + if (ancestor === el) break + } + mount() + } + }) + nodes.push(el) + nodeSet.add(el) + observers.push(observer) + observer.observe(el.parentElement!, { childList: true }) + } + + state.unmount.push(() => { + while (observers.length) pop() + }) + }) + + useEffect(() => { + mount() + return () => { + while (state.unmount.length) { + const fn = state.unmount.pop() + if (fn instanceof Function) fn() + } + } + }, deps) +} diff --git a/src/content/hooks/useThrottle.ts b/src/content/hooks/useThrottle.ts new file mode 100644 index 0000000..f29eda8 --- /dev/null +++ b/src/content/hooks/useThrottle.ts @@ -0,0 +1,10 @@ +import { useMemo } from 'react' +import { throttle } from 'src/utils' + +export function useThrottle< + T extends (...args: any) => Promise | boolean | void, + R = (...args: Parameters) => Promise +>(fn: T, interval = 0): R { + const handle = useMemo(() => throttle(fn, interval), []) as R + return handle +} diff --git a/src/content/index.tsx b/src/content/index.tsx new file mode 100644 index 0000000..893296f --- /dev/null +++ b/src/content/index.tsx @@ -0,0 +1,15 @@ +import { initUrlChangeEvent } from '@/utils' +import { render } from 'react-dom' + +import App from './App' + +initUrlChangeEvent() + +const rootId = 'Refined-LeetCode-Root' +let root = document.getElementById(rootId) +if (!root) { + root = document.createElement('div') + root.id = rootId + document.body.append(root) +} +render(, root) diff --git a/src/content/load.ts b/src/content/load.ts new file mode 100644 index 0000000..b432713 --- /dev/null +++ b/src/content/load.ts @@ -0,0 +1,58 @@ +import { customEventDispatch } from './utils' + +__webpack_public_path__ = chrome.runtime.getURL('.') + '/' + +if (module.hot) { + module.hot.addStatusHandler(async status => { + if (status === 'abort') { + return awaitReload() + } + }) +} + +function awaitReload() { + return new Promise(function (resolve) { + console.log('sendMessage reload') + chrome.runtime.sendMessage({ type: 'reload' }, () => { + resolve() + }) + }) +} + +function loadScript(url: string) { + const script = document.createElement('script') + + // 将扩展 id 添加到脚本标签中,方便网页脚本通过 id 跟扩展通讯 + script.id = 'refined-leetcode' + script.dataset.extensionid = chrome.runtime.id + script.src = url + document.body.append(script) +} + +let isLoad = false +if (!isLoad) { + isLoad = true + loadScript(chrome.runtime.getURL('content.bundle.js')) +} + +window.addEventListener('refinedLeetcodeGetOptions', () => { + chrome.storage.local.get('options', ({ options }) => { + customEventDispatch('refinedLeetcodeOptionsChange', { options }) + }) +}) + +chrome.storage.onChanged.addListener(e => { + if ('options' in e) { + const options = e.options.newValue + customEventDispatch('refinedLeetcodeOptionsChange', { options }) + } +}) + +window.addEventListener( + 'refinedLeetcodeSaveOptions', + ({ detail: { options } }) => { + chrome.storage.local.set({ options }) + } +) + +export {} diff --git a/src/content/pages/global/globalSlice.ts b/src/content/pages/global/globalSlice.ts new file mode 100644 index 0000000..6b6f80b --- /dev/null +++ b/src/content/pages/global/globalSlice.ts @@ -0,0 +1,94 @@ +import { createSlice, createAsyncThunk } from '@reduxjs/toolkit' + +import { RootState } from '@/app/store' +import { + LeetCodeApi, + GlobalData, + ProblemsetPageProps, + ProblemRankData, + getProblemRankData, + getPageName, +} from '@/utils' +import { PageName } from 'src/options/options' + +const api = new LeetCodeApi(location.origin) + +export const fetchGlobalData = createAsyncThunk< + GlobalData, + undefined, + { state: RootState } +>('global/fetchGlobalData', async () => { + const res = await api.queryGlobalData() + return res +}) + +export const fetchProblemsetPageProps = createAsyncThunk< + ProblemsetPageProps, + undefined, + { state: RootState } +>('global/fetchProblemsetPageProps', async () => { + const res = await api.getProblemsetPageProps() + return res +}) + +export const fetchProblemRankData = createAsyncThunk< + ProblemRankData[], + undefined, + { state: RootState } +>('global/fetchProblemRankData', async () => { + const res = await getProblemRankData() + return res +}) + +const initialState: { + globalData?: GlobalData + problemsetPageProps?: ProblemsetPageProps + ProblemRankData: { [key: string]: ProblemRankData } + currentPage?: PageName +} = { ProblemRankData: {}, currentPage: getPageName() } + +export const globalDataSlice = createSlice({ + name: 'global', + initialState, + reducers: { + setCurrentPage: (state, action) => { + state.currentPage = action.payload + }, + }, + extraReducers(builder) { + builder + .addCase(fetchGlobalData.fulfilled, (state, action) => { + state.globalData = action.payload + }) + .addCase(fetchProblemsetPageProps.fulfilled, (state, action) => { + state.problemsetPageProps = action.payload + }) + .addCase(fetchProblemRankData.fulfilled, (state, action) => { + for (const rank of action.payload) { + state.ProblemRankData[rank.TitleSlug] = rank + } + }) + }, +}) + +export const { setCurrentPage } = globalDataSlice.actions + +export const selectIsPremium = (state: RootState): boolean | undefined => + state.global.globalData?.userStatus?.isPremium +export const selectIsSignedIn = (state: RootState): boolean | undefined => + state.global.globalData?.userStatus?.isSignedIn + +export const selectFeaturedLists = ( + state: RootState +): ProblemsetPageProps['featuredLists'] | undefined => + state.global.problemsetPageProps?.featuredLists + +export const selectProblemRankDataByTitleSlug = ( + state: RootState, + titleSlug: string +): ProblemRankData | undefined => state.global.ProblemRankData[titleSlug] + +export const selectCurrentPage = (state: RootState): PageName | undefined => + state.global.currentPage + +export default globalDataSlice.reducer diff --git a/src/content/pages/global/optionsSlice.ts b/src/content/pages/global/optionsSlice.ts new file mode 100644 index 0000000..6b413b1 --- /dev/null +++ b/src/content/pages/global/optionsSlice.ts @@ -0,0 +1,109 @@ +import { createSlice, current, PayloadAction } from '@reduxjs/toolkit' + +import store, { RootState } from '@/app/store' +import { OptionsType, PageName } from 'src/options/options' +import { customEventDispatch } from '@/utils' + +export interface RandomOptionType { + skipAC: boolean +} + +export const labelOfKey = { + skipAC: '跳过已解答题目', +} + +const defaultRandomOption = (): RandomOptionType => ({ skipAC: false }) + +interface OptionsState { + random: { + [key: string]: RandomOptionType + } + options?: OptionsType +} + +const initialState: OptionsState = { + random: { + all: defaultRandomOption(), + }, +} + +function saveOption(options: OptionsType) { + customEventDispatch('refinedLeetcodeSaveOptions', { options }) +} + +export const optionsSlice = createSlice({ + name: 'options', + initialState, + reducers: { + setRandomOption: (state, action) => { + const { favorite, option } = action.payload + + state.random[favorite] = { + ...(state.random[favorite] ?? defaultRandomOption()), + ...option, + } + }, + disableProblemRating({ options }, { payload }: PayloadAction) { + if (options) { + if (payload === 'problemsetPage') { + options.problemsetPage.problemRating = false + } else if (payload === 'problemListPage') { + options.problemListPage.problemRating = false + } + saveOption(current(options)) + } + }, + enableProblemRating({ options }, { payload }: PayloadAction) { + if (options) { + if (payload === 'problemsetPage') { + options.problemsetPage.problemRating = true + } else if (payload === 'problemListPage') { + options.problemListPage.problemRating = true + } + saveOption(current(options)) + } + }, + toggleContestProblemShortcutKeyOption({ options }) { + if (options) { + options.contestProblemsPage.disableShortcutkey = + !options.contestProblemsPage.disableShortcutkey + saveOption(current(options)) + } + }, + setOptions: (state, action) => { + state.options = action.payload + }, + setContestProblemViewWidth: ( + { options }, + { payload }: PayloadAction + ) => { + if (options) { + options.contestProblemsPage.problemViewWidth = payload + saveOption(current(options)) + } + }, + }, +}) + +export const { + setRandomOption, + disableProblemRating, + enableProblemRating, + toggleContestProblemShortcutKeyOption, + setOptions, + setContestProblemViewWidth, +} = optionsSlice.actions + +export const selectRandomOption = ( + state: RootState, + key: string +): RandomOptionType => state.options.random[key] ?? defaultRandomOption() + +export const selectOptions = (state: RootState): OptionsType | undefined => + state.options.options + +window.addEventListener('refinedLeetcodeOptionsChange', e => { + store.dispatch(setOptions(e.detail.options)) +}) + +export default optionsSlice.reducer diff --git a/src/content/pages/home/App.tsx b/src/content/pages/home/App.tsx new file mode 100644 index 0000000..1aaffdf --- /dev/null +++ b/src/content/pages/home/App.tsx @@ -0,0 +1,52 @@ +import { FC, useState } from 'react' +import { DndProvider } from 'react-dnd' +import { HTML5Backend } from 'react-dnd-html5-backend' + +import DistortSvg from '@/components/DistortSvg' +import { withPage } from '@/hoc' +import { useAppSelector, useEffectMount } from '@/hooks' + +import GlobalStyle from './GlobalStyle' +import BlockUser from './BlockUser' +import { selectOptions } from '../global/optionsSlice' +import { css } from 'styled-components/macro' +import { useBlock } from './useBlock' +import { findElement } from '@/utils' +import { Portal } from '@/components/Portal' + +const App: FC = () => { + useBlock() + const options = useAppSelector(selectOptions) + const [root, setRoot] = useState() + useEffectMount(async state => { + const parent = await findElement('.css-kktm6n-RightContainer') + const root = document.createElement('div') + if (state.isMount) { + parent.prepend(root) + setRoot(root) + state.unmount.push(() => root.remove()) + } + }, []) + + if (!root || !options?.homePage.block) return null + return ( + +
+ + + + + +
+
+ ) +} + +export default withPage('homePage')(App) diff --git a/src/content/pages/home/BlockUser.tsx b/src/content/pages/home/BlockUser.tsx new file mode 100644 index 0000000..c7b94c7 --- /dev/null +++ b/src/content/pages/home/BlockUser.tsx @@ -0,0 +1,82 @@ +import React, { FC, useEffect, useRef, useState } from 'react' +import styled from 'styled-components/macro' + +import BlockUserList from './BlockUserList' +import DragAndDrop from './DragAndDrop' + +const Container = styled.div` + display: flex; + justify-content: space-between; + align-items: center; + font-size: 14px; + width: 100%; + padding: 5px 16px; + border-radius: 8px; + box-sizing: border-box; + cursor: pointer; + line-height: 20px; + background: ${props => props.theme.palette.primary.main}; + color: ${props => props.theme.palette.text.main}; + box-shadow: ${props => props.theme.shadows[1]}; +` + +const BlockUser: FC = () => { + const ref = useRef(null) + const listRef = useRef(null) + const [showEdit, setShowEdit] = useState(false) + const handleClick = () => { + setShowEdit(state => !state) + } + useEffect(() => { + // 滚动页面时,隐藏黑名单列表窗口 + const handleScroll = () => setShowEdit(false), + option: AddEventListenerOptions = { passive: true } + document.body.addEventListener('scroll', handleScroll, option) + return () => { + document.body.removeEventListener('scroll', handleScroll, option) + } + }, []) + + useEffect(() => { + if (!showEdit) return + const handleClick = (e: MouseEvent) => { + const el = e.target as Node + if (!el) return + if (ref.current?.contains(el) || listRef.current?.contains(el)) return + setShowEdit(false) + } + document.addEventListener('click', handleClick) + return () => { + document.removeEventListener('click', handleClick) + } + }, [showEdit]) + + return ( + <> + +
黑名单管理
+ + + +
+ {showEdit && ( + + )} + + + + ) +} + +export default BlockUser diff --git a/src/content/pages/home/BlockUserList.tsx b/src/content/pages/home/BlockUserList.tsx new file mode 100644 index 0000000..12082f6 --- /dev/null +++ b/src/content/pages/home/BlockUserList.tsx @@ -0,0 +1,304 @@ +import React, { + useState, + ChangeEventHandler, + KeyboardEventHandler, + useContext, + useRef, + forwardRef, + ForwardedRef, +} from 'react' +import styled, { ThemeContext } from 'styled-components/macro' + +import { Placement, Popper } from '@/components/Popper' +import { ToolTip } from '@/components/ToolTip' +import Button from '@/components/Button' +import { useAppDispatch, useAppSelector } from '@/hooks' + +import { + setBlockUserBySlug, + selectAllBlockUsers, + unSetBlockUser, + toggleBlockUser, +} from './blockUsersSlice' + +interface BlockUserListProps { + placement?: Placement + anchorEl?: HTMLElement | null +} + +const List = styled.ul` + padding: 0; + margin: 0; +` + +const Item = styled.li` + list-style: none; + line-height: 1.42857; + box-sizing: border-box; + height: 30px; + display: flex; + -webkit-box-align: center; + align-items: center; + -webkit-box-pack: justify; + justify-content: space-between; + font-size: 14px; + border-radius: 5px; + padding: 0px 8px; + font-weight: 400; + transition: all 0.2s ease 0s; + cursor: pointer; + color: ${props => props.theme.palette.text.main}; + &:hover { + background-color: ${props => props.theme.palette.secondary.hover}; + } +` + +const Input = styled.input` + overflow: visible; + height: 32px; + outline: none; + border-radius: 8px !important; + box-sizing: border-box; + margin: 0 10px 0 0; + width: 100%; + padding: 4px 11px; + font-size: 14px; + line-height: 1.5715; + border: 1px solid rgba(0, 0, 0, 0); + transition: all 0.3s; + touch-action: manipulation; + text-overflow: ellipsis; + color: ${props => props.theme.palette.text.main}; + background: ${props => props.theme.palette.secondary.main}; + &:focus { + background-color: ${props => props.theme.palette.secondary.hover}; + } +` + +const Clear = styled.div` + border-radius: 50%; + height: 24px; + width: 24px; + display: flex; + justify-content: center; + align-items: center; + &:hover { + background-color: ${props => props.theme.palette.secondary.main}; + } + & > svg { + height: 16px; + width: 16px; + fill: currentcolor; + } +` + +const BlockUserList = forwardRef(function BlockUserList( + props: BlockUserListProps, + ref: ForwardedRef +) { + const [slug, setData] = useState('') + const users = useAppSelector(selectAllBlockUsers) + const [status, setStatus] = useState('idle') + const [showToolTip, setShowToolTip] = useState(false) + const [errorMessage, setErrorMessage] = useState('') + const timer = useRef>() + const dispatch = useAppDispatch() + const [top, setTop] = useState(0) + + const listRef = (ref: HTMLUListElement) => { + setTop(ref?.getBoundingClientRect().top ?? 0) + } + + const showMessage = (error: string) => { + hideMessage() + setErrorMessage(error) + setShowToolTip(true) + timer.current = setTimeout(hideMessage, 1000) + } + const hideMessage = () => { + if (timer.current !== undefined) { + clearTimeout(timer.current) + } + setShowToolTip(false) + setErrorMessage('') + } + + let width = 0 + if (props.anchorEl) { + width = props.anchorEl.getClientRects()[0].width + } + const handleChange: ChangeEventHandler = e => { + setData(e.target.value) + } + /** 添加黑名单用户 + * + * 1. 查找是否已存在对应的用户,如果已存在则不用重复添加 + * 2. 检查 slug 是否有效 + * 3. 将 {slug,name} 存到 LocalStorage 中 + */ + const handleAdd = async () => { + if (status !== 'idle' || !slug) return + try { + setStatus('loading') + if (users.find(user => user.slug === slug)) { + showMessage('已存在用户,无需重复添加!') + } else { + const res = await dispatch(setBlockUserBySlug(slug)).unwrap() + if (res) { + hideMessage() + setData('') + } else { + showMessage('无效的 slug!') + } + } + } catch (error) { + showMessage( + (error as { message: string; name: string; stack: string }).message + ) + } finally { + setStatus('idle') + } + } + + const handleKeyDown: KeyboardEventHandler = e => { + if (e.key === 'Enter') { + handleAdd() + } + } + const handleDelete = (slug: string) => { + dispatch(unSetBlockUser(slug)) + } + const themeContext = useContext(ThemeContext) + + return ( + +
+ + + + } + > + + + +
+ +
+
+
+ + {users.map(({ slug, name, block }) => ( + + +
+ { + dispatch(toggleBlockUser(slug)) + }} + > + {block ? ( + + ) : ( + + )} + + { + e.stopPropagation() + handleDelete(slug) + }} + > + + + + +
+
+ ))} +
+
+ ) +}) + +export default BlockUserList diff --git a/src/content/pages/home/DragAndDrop.tsx b/src/content/pages/home/DragAndDrop.tsx new file mode 100644 index 0000000..38c8083 --- /dev/null +++ b/src/content/pages/home/DragAndDrop.tsx @@ -0,0 +1,121 @@ +import React, { FC, useState } from 'react' +import { DropTargetMonitor, useDrop } from 'react-dnd' +import { NativeTypes } from 'react-dnd-html5-backend' + +import { useAppDispatch } from '@/hooks' + +import PostItem, { ItemTypes, PostItemType } from './PostItem' +import DropContainer from './DropContainer' +import { + setBlockUserByCommunityArticleId, + setBlockUserByPostId, + setBlockUserBySolutionSlug, +} from './blockUsersSlice' +import Mask from './Mask' + +type NativeTypeHTML = { + html: string + dataTransfer: { + dropEffect: string + effectAllowed: string + files: FileList + items: DataTransferItemList + types: [] + } +} + +function geturl(monitor: DropTargetMonitor) { + const itemType = monitor.getItemType(), + item = monitor.getItem() + + if (itemType === ItemTypes.POST) { + return (item as PostItemType).url ?? '' + } else if (itemType === NativeTypes.HTML) { + const div = document.createElement('div') + div.innerHTML = (item as NativeTypeHTML).html + const a = div.querySelector(':scope>a') + if (!(a instanceof HTMLAnchorElement)) return '' + return a.href + } else { + return '' + } +} + +export function isValid(url: string): boolean { + try { + const URI = new URL(url) + if (URI.host !== 'leetcode.cn') return false + const strs = URI.pathname.split('/').filter(Boolean) + + if (strs[0] === 'circle') { + // 帖子 + if (strs[1] !== 'discuss' && strs[1] !== 'article') return false + return !!strs[2] + } else if (strs[0] === 'problems' && strs[2] === 'solution') { + // 题解 + return !!strs[3] + } + return false + } catch (error) { + return false + } +} + +const DragAndDrop: FC = () => { + const dispatch = useAppDispatch() + const [open, setOpen] = useState(false) + + const [{ canDrop, isOver }, drop] = useDrop( + () => ({ + accept: [ItemTypes.POST, NativeTypes.HTML], + async drop(item, monitor) { + const url = geturl(monitor) + if (!url) { + console.error('无效源') + return + } + + if (!isValid(url)) { + console.error('无效链接') + return + } + + const strs = new URL(url).pathname.split('/').filter(Boolean) + try { + if (strs[1] === 'discuss') { + // 讨论帖 + const postId = strs[2] + await dispatch(setBlockUserByPostId(postId)).unwrap() + } else if (strs[1] === 'article') { + // 文章 + const id = strs[2] + await dispatch(setBlockUserByCommunityArticleId(id)).unwrap() + } else { + // 题解 + const solutionSlug = strs[3] + await dispatch(setBlockUserBySolutionSlug(solutionSlug)).unwrap() + } + } catch (error) { + console.error((error as { message: string }).message) + } + }, + collect: monitor => { + return { + isOver: monitor.isOver(), + canDrop: monitor.canDrop(), + } + }, + }), + [] + ) + + return ( + <> + + {} + {open && } + + ) +} + +export default DragAndDrop diff --git a/src/content/pages/home/DropContainer.tsx b/src/content/pages/home/DropContainer.tsx new file mode 100644 index 0000000..b6e85ec --- /dev/null +++ b/src/content/pages/home/DropContainer.tsx @@ -0,0 +1,52 @@ +import React, { FC } from 'react' +import styled from 'styled-components/macro' +import { ConnectDropTarget } from 'react-dnd' +import { Portal } from '@/components/Portal' + +const Container = styled.div<{ active?: boolean }>` + position: fixed; + right: 50px; + top: 50%; + width: 100px; + height: 150px; + background: ${props => (props.active ? '#3cb97f' : '#49ab7e')}; + transform: translate(0, -50%); + color: white; + border-radius: 5px; + padding: 4px; + z-index: 9999; +` + +const SVG = styled.svg` + height: 1em; + fill: currentcolor; + font-size: 1.5rem; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + margin: auto; +` + +type BlockDropContainerProps = { + drop: ConnectDropTarget + active?: boolean +} + +const DropContainer: FC = ({ drop, active }) => { + return ( + + + 拖动到此 +
+ 加入黑名单 + + + +
+
+ ) +} + +export default DropContainer diff --git a/src/content/pages/home/GlobalStyle.tsx b/src/content/pages/home/GlobalStyle.tsx new file mode 100644 index 0000000..70b56c9 --- /dev/null +++ b/src/content/pages/home/GlobalStyle.tsx @@ -0,0 +1,27 @@ +import { createGlobalStyle } from 'styled-components/macro' + +const styled = { createGlobalStyle } +const GlobalStyle = styled.createGlobalStyle` + /* 隐藏黑名单用户发的帖子 */ + .refined-leetcode-block { + display: none; + } + /* 隐藏帖子相邻的分割元素 */ + .refined-leetcode-block + div.css-1vwizfm-Divider { + display: none; + } + + /* 临时显示帖子,但对内容进行糢糊处理,以区别 */ + .refined-leetcode-temp { + display: flex; + filter: url(#refined-leetcode-noise); + } + .refined-leetcode-block.refined-leetcode-temp + div.css-1vwizfm-Divider { + display: block; + } + /* 当悬浮鼠标时,取消糢糊效果 */ + .refined-leetcode-block.refined-leetcode-temp:hover { + filter: none; + } +` +export default GlobalStyle diff --git a/src/content/pages/home/Mask.tsx b/src/content/pages/home/Mask.tsx new file mode 100644 index 0000000..60160bb --- /dev/null +++ b/src/content/pages/home/Mask.tsx @@ -0,0 +1,55 @@ +import { useEffect, FC } from 'react' +import 'styled-components/macro' + +import { Portal } from '@/components/Portal' + +import { isValid } from './DragAndDrop' + +type MaskProps = { + open: boolean + setOpen: React.Dispatch> +} + +/** 遮罩层 + * + * 拖拽时显示,用以遮挡其余无关元素,突出显示拖拽源和目标容器 + */ +const Mask: FC = ({ open, setOpen }) => { + useEffect(() => { + let el: HTMLElement | null = null + const handleDragstart = (e: DragEvent) => { + el = e.target as HTMLElement + if (!(el instanceof HTMLAnchorElement)) return + if (!isValid(el.href)) return + setTimeout(() => setOpen(true), 100) + } + const handleDragend = () => { + setOpen(false) + } + document.body.addEventListener('dragstart', handleDragstart) + document.body.addEventListener('dragend', handleDragend) + return () => { + document.body.removeEventListener('dragstart', handleDragstart) + document.body.removeEventListener('dragend', handleDragend) + } + }, []) + if (!open) return null + + return ( + +
+ + ) +} + +export default Mask diff --git a/src/content/pages/home/PostItem.tsx b/src/content/pages/home/PostItem.tsx new file mode 100644 index 0000000..26068eb --- /dev/null +++ b/src/content/pages/home/PostItem.tsx @@ -0,0 +1,152 @@ +import React, { FC, useEffect, useRef, useState } from 'react' +import { css } from 'styled-components/macro' +import { useDrag } from 'react-dnd' + +import Popper from '@/components/PopperUnstyled' +import { useHover } from '@/hooks' + +export const ItemTypes = { + POST: 'post', +} + +export type PostItemType = { + PostElement: HTMLElement | null + url: string +} + +/** 帖子列表拖拽手柄 + * + * 当鼠标悬浮在帖子元素上时,动态显示手柄图标,拖过拖动图标,可以将对应的帖子作者加入黑名单 + */ +const PostItem: FC<{ + setOpen: React.Dispatch> +}> = ({ setOpen }) => { + const [container, setContainer] = useState(null) + const postElements = useRef([]) + const [hoverRef, hoverIcon] = useHover() + const [hoverContainer, setHoverContainer] = useState(false) + const timer = useRef>() + + const handleMouseEnter = (e: MouseEvent) => { + const el = e.target as HTMLDivElement + + if (el && !el.classList.contains('refined-leetcode-block')) { + if (timer.current) clearTimeout(timer.current) + setContainer(el) + setHoverContainer(true) + } + } + + const handleMouseLeave = () => { + timer.current = setTimeout(() => { + setHoverContainer(false) + }, 100) + } + + useEffect(() => { + postElements.current.push( + ...document.querySelectorAll( + '.css-1tc14ag-card-layer1-card-MainContentConainer > [type=QUESTION],.css-1tc14ag-card-layer1-card-MainContentConainer > [type=SOLUTION]' + ) + ) + postElements.current.forEach(el => { + el.addEventListener('mouseenter', handleMouseEnter) + el.addEventListener('mouseleave', handleMouseLeave) + }) + + return () => { + postElements.current.forEach(el => { + el.removeEventListener('mouseenter', handleMouseEnter) + el.removeEventListener('mouseleave', handleMouseLeave) + }) + postElements.current = [] + } + }, []) + + useEffect(() => { + const observer = new MutationObserver(mutationList => { + for (const mutation of mutationList) { + for (const node of mutation.addedNodes) { + if (node instanceof HTMLElement) { + const type = node.getAttribute('type') + if (type === 'QUESTION' || type === 'SOLUTION') { + postElements.current.push(node) + node.addEventListener('mouseenter', handleMouseEnter) + node.addEventListener('mouseleave', handleMouseLeave) + } + } + } + } + }) + const MainContentConainer = document.querySelector( + '.css-1tc14ag-card-layer1-card-MainContentConainer' + ) + if (MainContentConainer) { + observer.observe(MainContentConainer, { + childList: true, + }) + } + + return () => { + observer.disconnect() + } + }, []) + + const [{ isDragging }, drag, preview] = useDrag( + () => ({ + type: ItemTypes.POST, + item: { + PostElement: container, + url: + ( + container?.querySelector( + ':scope>div:nth-of-type(1)>a' + ) as HTMLAnchorElement + )?.href ?? '', + }, + collect: monitor => ({ isDragging: !!monitor.isDragging() }), + }), + [container] + ) + + useEffect(() => { + if (container) { + if (isDragging) { + setOpen(true) + } else { + setOpen(false) + } + } + }, [container, isDragging, setOpen]) + + if (!hoverContainer && !hoverIcon && !isDragging) return null + preview(container) + + return ( + { + hoverRef(ref) + drag(ref) + }} + offset={{ top: 36, left: 339 }} + > + props.theme.palette.text.main}; + cursor: move; + transform: rotateX(180deg); + `} + focusable="false" + viewBox="0 0 24 24" + > + + + + ) +} + +export default PostItem diff --git a/src/content/pages/home/blockUsersSlice.ts b/src/content/pages/home/blockUsersSlice.ts new file mode 100644 index 0000000..7e1ce17 --- /dev/null +++ b/src/content/pages/home/blockUsersSlice.ts @@ -0,0 +1,132 @@ +import { + createSlice, + createAsyncThunk, + createEntityAdapter, + PayloadAction, +} from '@reduxjs/toolkit' + +import { RootState } from '@/app/store' +import { + LeetCodeApi, + UserProfilePublicProfile, + QAQuestion, + SolutionArticle, + CommunityArticle, +} from '@/utils' + +const api = new LeetCodeApi(location.origin) + +export const setBlockUserBySlug = createAsyncThunk< + UserProfilePublicProfile, + string, + { state: RootState } +>('users/setBlockUserBySlug', async slug => { + const data = await api.getUserInfoBySlug(slug) + return data +}) +export const setBlockUserByPostId = createAsyncThunk< + QAQuestion, + string, + { state: RootState } +>('users/setBlockUserByPostId', async postId => { + const data = await api.queryQAQuestionByUUID(postId) + + return data +}) + +export const setBlockUserByCommunityArticleId = createAsyncThunk< + CommunityArticle, + string, + { state: RootState } +>('users/setBlockUserByCommunityArticleId', async id => { + const data = await api.queryCommunityArticleById(id) + + return data +}) + +export const setBlockUserBySolutionSlug = createAsyncThunk< + SolutionArticle, + string, + { state: RootState } +>('users/setBlockUserBySolutionSlug', async slug => { + const data = await api.querySolutionArticleBySlug(slug) + + return data +}) + +type BlockUser = { + slug: string + name: string + block: boolean +} + +export const blockUsersAdapter = createEntityAdapter({ + selectId: user => user.slug, +}) + +const initialState = blockUsersAdapter.getInitialState() + +const blockUsersSlice = createSlice({ + name: 'blockUsers', + initialState, + reducers: { + unSetBlockUser(state, action: PayloadAction) { + blockUsersAdapter.removeOne(state, action.payload) + }, + toggleBlockUser(state, action: PayloadAction) { + const user = state.entities[action.payload] + if (user) { + user.block = !user.block + } + }, + }, + extraReducers(builder) { + builder + .addCase(setBlockUserBySlug.fulfilled, (state, action) => { + if (action.payload) { + const { + profile: { userSlug: slug, realName: name }, + } = action.payload + blockUsersAdapter.upsertOne(state, { slug, name, block: true }) + } + }) + .addCase(setBlockUserByPostId.fulfilled, (state, action) => { + if (action.payload) { + const { + contentAuthor: { userSlug: slug, realName: name }, + } = action.payload + blockUsersAdapter.upsertOne(state, { slug, name, block: true }) + } + }) + .addCase(setBlockUserBySolutionSlug.fulfilled, (state, action) => { + if (action.payload) { + const { + author: { + profile: { userSlug: slug, realName: name }, + }, + } = action.payload + blockUsersAdapter.upsertOne(state, { slug, name, block: true }) + } + }) + .addCase(setBlockUserByCommunityArticleId.fulfilled, (state, action) => { + if (action.payload) { + const { + author: { + profile: { userSlug: slug, realName: name }, + }, + } = action.payload + blockUsersAdapter.upsertOne(state, { slug, name, block: true }) + } + }) + }, +}) + +export const { + selectAll: selectAllBlockUsers, + selectById: selecBlockUserById, + selectIds: selecBlockUserIds, +} = blockUsersAdapter.getSelectors(state => state.blockUsers) + +export const { unSetBlockUser, toggleBlockUser } = blockUsersSlice.actions + +export default blockUsersSlice.reducer diff --git a/src/content/pages/home/postsSlice.ts b/src/content/pages/home/postsSlice.ts new file mode 100644 index 0000000..0506dd8 --- /dev/null +++ b/src/content/pages/home/postsSlice.ts @@ -0,0 +1,61 @@ +import { + createSlice, + createAsyncThunk, + createEntityAdapter, +} from '@reduxjs/toolkit' + +import { RootState } from '@/app/store' +import { LeetCodeApi, NotyArticleType, NotyItem } from '@/utils' + +const api = new LeetCodeApi(location.origin) + +type Post = { + feedContent: { + uuid: string + author: { userSlug: string } + } + meta: { link: string } +} + +const postsAdapter = createEntityAdapter({ + selectId: post => post.feedContent.uuid, +}) + +export const fetchPosts = createAsyncThunk< + NotyItem, + number, + { state: RootState } +>('posts/fetchPosts', async (limit, { getState }) => { + const nextToken = getState().posts.nextToken + const res = await api.getNoty(nextToken, limit) + return res +}) + +const initialState = postsAdapter.getInitialState({ + nextToken: '', +}) + +const postsSlice = createSlice({ + name: 'posts', + initialState, + reducers: {}, + extraReducers(builder) { + builder.addCase(fetchPosts.fulfilled, (state, action) => { + state.nextToken = action.payload.nextToken + + const data = action.payload.rows.filter( + a => a.feedContent.__typename === 'Article' + ) as { feedContent: NotyArticleType; meta: { link: string } }[] + + postsAdapter.upsertMany(state, data) + }) + }, +}) + +export const { + selectAll: selectAllPosts, + selectById: selectPostById, + selectIds: selectPostIds, +} = postsAdapter.getSelectors(state => state.posts) + +export default postsSlice.reducer diff --git a/src/content/pages/home/useBlock.ts b/src/content/pages/home/useBlock.ts new file mode 100644 index 0000000..cd82e2f --- /dev/null +++ b/src/content/pages/home/useBlock.ts @@ -0,0 +1,90 @@ +import { useEffect } from 'react' + +import { useAppDispatch, useAppSelector, useEvent } from '@/hooks' + +import { selectAllPosts, fetchPosts } from './postsSlice' +import { selectAllBlockUsers } from './blockUsersSlice' + +// TODO: 分离获取列表和处理隐藏 +export const useBlock = (): void => { + const posts = useAppSelector(selectAllPosts) + const users = useAppSelector(selectAllBlockUsers) + const dispatch = useAppDispatch() + + const handleBlock = useEvent(() => { + const blockUsers = new Set( + users.filter(user => user.block).map(user => user.slug) + ), + tempUnBlockUsers = new Set( + users.filter(user => !user.block).map(user => user.slug) + ) + + const blockPosts = new Set(), + tmpUnBlockPosts = new Set() + + for (const post of posts) { + const userSlug = post.feedContent.author.userSlug + if (blockUsers.has(userSlug)) { + blockPosts.add(post.meta.link) + } else if (tempUnBlockUsers.has(userSlug)) { + tmpUnBlockPosts.add(post.meta.link) + } + } + + const postEls = document.querySelectorAll( + '.css-1tc14ag-card-layer1-card-MainContentConainer>.css-1pej3s6-FeedContainer>div:nth-of-type(1)>a:nth-of-type(1)' + ) + + Array.prototype.forEach.call(postEls, (el: HTMLAnchorElement) => { + const p = el.parentElement?.parentElement + if (p) { + if (blockPosts.has(el.pathname)) { + // 处于黑名单中的元素 + p.classList.add('refined-leetcode-block') + p.classList.remove('refined-leetcode-temp') + } else if (tmpUnBlockPosts.has(el.pathname)) { + // 处于临时解锁中的元素 + p.classList.add('refined-leetcode-block') + p.classList.add('refined-leetcode-temp') + } else if (p.classList.contains('refined-leetcode-block')) { + // 不处于黑名单中的元素 + p.classList.remove('refined-leetcode-block', 'refined-leetcode-temp') + } + } + }) + }) + useEffect(() => { + handleBlock() + }, [posts, users]) + + useEffect(() => { + dispatch(fetchPosts(30)) + + const handleFetchPost = async () => { + await dispatch(fetchPosts(10)).unwrap() + // 防止某些元素加载比较慢的情况,延迟再触发一次 + setTimeout(handleBlock, 500) + } + + const handleClick = (e: Event) => { + const el = e.target + const cls = 'css-1csfdb4-BaseButtonComponent-LoadMoreButton' + if ( + el instanceof HTMLElement && + (el.classList.contains(cls) || + el.parentElement?.classList.contains(cls)) + ) { + handleFetchPost() + } + } + const root = document.querySelector('.css-185cq5e-LeftContainer') + if (root) { + root.addEventListener('click', handleClick) + } + return () => { + if (root) { + root.removeEventListener('click', handleClick) + } + } + }, []) +} diff --git a/src/content/pages/problem-list/AddFavorite.tsx b/src/content/pages/problem-list/AddFavorite.tsx new file mode 100644 index 0000000..3c745df --- /dev/null +++ b/src/content/pages/problem-list/AddFavorite.tsx @@ -0,0 +1,56 @@ +import { AddIcon } from '@/components/icons' +import { css } from 'styled-components/macro' +import Editor from './Editor' + +interface AddFavoriteProps { + onSave?: (text: string) => void | Promise + onCancel?: (...arg: any) => void | Promise + toggleEnableEdit: (...arg: any) => void | Promise + enableEdit: boolean +} + +const AddFavorite: React.FC = ({ + enableEdit, + toggleEnableEdit, + ...props +}) => { + return ( +
+ {enableEdit ? ( + + ) : ( +
props.theme.palette.secondary.main}; + &:hover { + background-color: ${props => props.theme.palette.secondary.hover}; + } + `} + onClick={toggleEnableEdit} + > + + 创建新题单 +
+ )} +
+ ) +} + +export default AddFavorite diff --git a/src/content/pages/problem-list/App.tsx b/src/content/pages/problem-list/App.tsx new file mode 100644 index 0000000..377ff08 --- /dev/null +++ b/src/content/pages/problem-list/App.tsx @@ -0,0 +1,49 @@ +import Rank from '../problemset/Rank' +import { FC, useEffect, useState } from 'react' +import { useAppSelector, useEffectMount } from '@/hooks' +import { selectOptions } from '../global/optionsSlice' +import { awaitFn, problemsetPageIsLoad } from '@/utils' +import { Portal } from '@/components/Portal' +import ProblemList from './ProblemList' +import { withPage } from '@/hoc' +// import { fixRandom } from './fixRandom' +import { useSetProblemListRoot } from './useSetProblemListRoot' + +const App: FC = () => { + const options = useAppSelector(selectOptions) + const [problemListRoot, setProblemListRoot] = useState() + const [isLoad, setIsLoad] = useState(false) + useEffectMount(async state => { + await awaitFn(async () => { + const res = await problemsetPageIsLoad() + return !res + }) + if (state.isMount) setIsLoad(true) + }) + useSetProblemListRoot( + '//*[@id="__next"]/div/div[2]/div/div[2]/div/*//span[text()="精选题单"]/../..', + isLoad, + setProblemListRoot + ) + + useEffect(() => { + if (!isLoad) return + // fixRandom() + }, [isLoad]) + + if (!isLoad) return null + const showProblemList = !!options?.problemListPage.problemList + const showRank = !!options?.problemListPage.problemRating + return ( + <> + + {showProblemList && problemListRoot && ( + + + + )} + + ) +} + +export default withPage('problemListPage')(App) diff --git a/src/content/pages/problem-list/Editor.tsx b/src/content/pages/problem-list/Editor.tsx new file mode 100644 index 0000000..de0a31c --- /dev/null +++ b/src/content/pages/problem-list/Editor.tsx @@ -0,0 +1,104 @@ +import { ChangeEventHandler, FC, useEffect, useState } from 'react' + +import { Input } from '@/components/Input' +import Button from '@/components/Button' +import ErrorToolTip from '@/components/ErrorToolTip' +import { css } from 'styled-components/macro' +import { useUnMount } from '@/hooks' + +interface EditorProps { + text?: string + onSave?: (text: string) => void | Promise + onCancel?: (...arg: any) => void +} + +const Editor: FC = ({ text: initText = '', onSave, onCancel }) => { + const [text, setText] = useState(initText) + const [error, setError] = useState({ message: '', show: false }) + const [loading, setLoading] = useState(false) + // 判断当前组件是否挂载,还是已被卸载 + const mountState = useUnMount() + useEffect(() => { + if (error.show) { + setTimeout(() => { + setError({ ...error, show: false }) + }, 1000) + } + }, [error]) + + const handleChange: ChangeEventHandler = e => { + setText(e.target.value) + } + + const handleSave = async () => { + setLoading(true) + if (typeof onSave === 'function') { + try { + await onSave(text) + if (mountState.isMount) setText('') + } catch (error: any) { + setError({ message: error.message, show: true }) + } + } + if (mountState.isMount) setLoading(false) + } + const handleCancel = () => { + if (typeof onCancel === 'function') { + onCancel() + } + } + + return ( +
+ + + +
+ + +
+
+ ) +} + +export default Editor diff --git a/src/content/pages/problem-list/FavoriteItem.tsx b/src/content/pages/problem-list/FavoriteItem.tsx new file mode 100644 index 0000000..1486d99 --- /dev/null +++ b/src/content/pages/problem-list/FavoriteItem.tsx @@ -0,0 +1,395 @@ +import { + FC, + MouseEventHandler, + useEffect, + useLayoutEffect, + useRef, + useState, +} from 'react' +import { css } from 'styled-components/macro' + +import { useAppSelector, useAppDispatch, useHover } from '@/hooks' +import Button from '@/components/Button' +import Modal from '@/components/Modal' +import ErrorToolTip from '@/components/ErrorToolTip' +import { ToolTip } from '@/components/ToolTip' +import { rotate360Deg } from '@/components/animation' + +import { + selectFavoriteById, + removeFavorite, + toggleFavoritePublicState, + updateFavoriteName, + checkIsInAudit, + fetchFavoriteDetails, +} from './favoriteSlice' +import Editor from './Editor' +import { routerTo } from '@/utils' +import { + EditIcon, + PrivateIcon, + PublicIcon, + RemoveIcon, +} from '@/components/icons' + +const DEFAULT_COVER = + 'https://static.leetcode.cn/cn-frontendx-assets/production/_next/static/images/default-logo-5a15811cf52298855a46a3f400663063.png' +const DEFAULT_FAVORITE_NAME = 'Favorite' + +interface FavoriteItemProps { + idHash: string + current: boolean + showEditIcon?: boolean +} + +const FavoriteItem: FC = ({ + idHash, + current, + showEditIcon, +}) => { + const favorite = useAppSelector(state => selectFavoriteById(state, idHash)) + const dispatch = useAppDispatch() + const [hoverRef, hover] = useHover() + const [enableEdit, setEnableEdit] = useState(false) + const [showRemove, setShowRemove] = useState(false) + const [togglePublicStateError, setTogglePublicStateError] = useState({ + message: '', + show: false, + }) + const [isOverflow, setIsOverflow] = useState(false) + + const nameRef = useRef(null) + useLayoutEffect(() => { + if (nameRef && nameRef.current) { + setIsOverflow(nameRef.current.scrollWidth !== nameRef.current.offsetWidth) + } + }, [hover]) + + useEffect(() => { + if (togglePublicStateError.show) { + setTimeout(() => { + setTogglePublicStateError({ message: '', show: false }) + }, 1000) + } + }, [togglePublicStateError]) + + useLayoutEffect(() => { + // 当较快的关闭和展开题单时,会出现题单列表文字被选中的问题 + // 通过「每次展开时,取消对文字的选中效果」解决这个问题 + ;(window as any).getSelection().removeAllRanges() + }, []) + + useEffect(() => { + let timer: ReturnType | null = null + if (favorite?.isInAudit) { + let time = 1000 + void (async function test() { + try { + await dispatch(checkIsInAudit(idHash)).unwrap() + timer = null + dispatch(fetchFavoriteDetails([idHash])) + } catch (error) { + timer = setTimeout(() => { + time = Math.max(time + 500, 3000) + test() + }, time) + } + })() + } + return () => { + if (timer !== null) clearTimeout(timer) + } + }, [dispatch, favorite?.isInAudit, idHash]) + + if (!favorite) return null + + const handleClick: MouseEventHandler = e => { + e.preventDefault() + if (!current) { + routerTo(`/problem-list/${idHash}/`) + } + } + const handleRemove: MouseEventHandler = async e => { + e.stopPropagation() + e.preventDefault() + dispatch(removeFavorite(idHash)) + } + const handleToggleFavoritePublicState: MouseEventHandler = async e => { + e.stopPropagation() + e.preventDefault() + if (favorite.isInAudit) { + setTogglePublicStateError({ + message: '题单处于审核中,不可编辑', + show: true, + }) + return + } + + try { + await dispatch(toggleFavoritePublicState(idHash)).unwrap() + } catch (error: any) { + setTogglePublicStateError({ message: error.message, show: true }) + } + } + const toggleEnableEdit: (e?: React.MouseEvent) => void = e => { + if (e) { + e.stopPropagation() + e.preventDefault() + } + setEnableEdit(enableEdit => !enableEdit) + } + const updateName = async (name: string) => { + if (favorite.isInAudit) { + throw new Error('题单处于审核中,不可编辑') + } + + await dispatch( + updateFavoriteName({ favoriteId: favorite!.idHash, name }) + ).unwrap() + dispatch(fetchFavoriteDetails([idHash])) + toggleEnableEdit() + } + const toggleShowRemove: (e?: React.MouseEvent) => void = e => { + if (e) { + e.stopPropagation() + e.preventDefault() + } + setShowRemove(showRemove => !showRemove) + } + + const name = favorite.showName ?? favorite.name + + return ( +
  • + {current && ( +
    + )} + props.theme.palette.text.light}; + align-items: center; + border-radius: 5px; + &:hover { + background-color: ${props => props.theme.palette.secondary.hover}; + } + `} + onClick={handleClick} + > + {name} +
    props.theme.palette.text.light}; + `} + > + + + {favorite.isInAudit && ( + + 审 + + )} + {name} + + + {showEditIcon && ( +
    + {hover && favorite.name !== DEFAULT_FAVORITE_NAME && ( + <> + {!favorite.isInAudit && ( + + )} + + + )} + + +
    + {favorite.isPublicFavorite ? ( + + ) : ( + + )} +
    +
    +
    + )} +
    +
    + {enableEdit && ( + +
    props.theme.shadows[2]}; + background-color: ${props => props.theme.palette.primary.main}; + border-radius: 8px; + padding: 1px 20px 15px; + `} + > +
    + 修改题单名称 +
    + +
    +
    + )} + {showRemove && ( + +
    props.theme.shadows[2]}; + background-color: ${props => props.theme.palette.primary.main}; + border-radius: 8px; + padding: 1px 20px 15px; + min-width: 400px; + `} + > +
    + 你确认要删除题单“{name}”吗? +
    +
    删除此列表后,将无法再恢复
    +
    + + +
    +
    +
    + )} +
  • + ) +} + +export default FavoriteItem diff --git a/src/content/pages/problem-list/FavoriteList.tsx b/src/content/pages/problem-list/FavoriteList.tsx new file mode 100644 index 0000000..2679ee9 --- /dev/null +++ b/src/content/pages/problem-list/FavoriteList.tsx @@ -0,0 +1,87 @@ +import { FC, useEffect, useState } from 'react' +import { useAppSelector } from '@/hooks' +import { selectFavoriteIdsByCategory, FavoriteCategory } from './favoriteSlice' +import { selectFeaturedLists } from '../global/globalSlice' +import FavoriteItem from './FavoriteItem' +import FavoriteWrap from './FavoriteWrap' +import { css } from 'styled-components/macro' + +const getCurrentId = () => { + const strs = location.pathname.split('/').filter(Boolean) + if (strs[0] === 'problem-list') return strs[1] + return '' +} + +const nameByCategory = { + official: '官方题单', + custom: '自定义题单', + third: '第三方题单', +} + +interface FavoriteListProps { + category: FavoriteCategory +} + +const FavoriteList: FC = ({ category }) => { + const [open, setOpen] = useState(false) + const toggle = () => setOpen(open => !open) + const ids = useAppSelector(selectFavoriteIdsByCategory(category)) + + const featuredLists = useAppSelector(selectFeaturedLists) + const name = nameByCategory[category] + const [currentId, setCurrentId] = useState(getCurrentId()) + + const isCustom = category === 'custom' + + useEffect(() => { + if (currentId && ids.includes(currentId)) { + if ( + featuredLists && + featuredLists.every(favorite => favorite.idHash !== currentId) + ) { + setOpen(true) + } + } else { + setOpen(false) + } + }, [currentId]) + + useEffect(() => { + const handleUrlChange = () => { + setCurrentId(getCurrentId()) + } + window.addEventListener('urlchange', handleUrlChange) + return () => { + window.removeEventListener('urlchange', handleUrlChange) + } + }, []) + + return ( + +
      + {ids.map(idHash => ( + + ))} +
    +
    + ) +} + +export default FavoriteList diff --git a/src/content/pages/problem-list/FavoriteWrap.tsx b/src/content/pages/problem-list/FavoriteWrap.tsx new file mode 100644 index 0000000..220608d --- /dev/null +++ b/src/content/pages/problem-list/FavoriteWrap.tsx @@ -0,0 +1,134 @@ +import { HelpIcon } from '@/components/icons' +import { useAppDispatch, useHover } from '@/hooks' +import { FC, useRef, useState } from 'react' +import { css } from 'styled-components/macro' +import AddFavorite from './AddFavorite' +import { + saveFavorite, + addFavorite, + fetchFavoriteDetails, + toggleFavoriteAuditStatus, + updateShowName, +} from './favoriteSlice' +import HelpHead from './HelpHead' + +interface FavoriteListProps { + children: React.ReactNode + title?: string | React.ReactNode + onChange?: (e: React.MouseEvent) => void + expanded?: boolean + showHelp?: boolean + showAdd?: boolean +} + +const FavoriteWrap: FC = ({ + children, + title, + expanded: expandedProp, + onChange, + showHelp, + showAdd, +}) => { + const controlled = useRef(expandedProp !== undefined) + const [expanded, setExpanded] = useState(expandedProp) + const open = controlled.current ? expandedProp : expanded + const [hoverHelpRef, hoverHelp] = useHover() + const [enableEdit, setEnableEdit] = useState(false) + const dispatch = useAppDispatch() + + const toggleEnableEdit = () => { + setEnableEdit(enableEdit => !enableEdit) + } + const handleAddFavorite = async (text: string) => { + const { ok, favoriteIdHash } = await dispatch(saveFavorite(text)).unwrap() + if (ok) { + await dispatch(addFavorite(favoriteIdHash)) + await dispatch(fetchFavoriteDetails([favoriteIdHash])) + await dispatch(toggleFavoriteAuditStatus(favoriteIdHash)) + await dispatch(updateShowName({ idHash: favoriteIdHash, showName: text })) + } + toggleEnableEdit() + } + + const toggle = (e: React.MouseEvent) => { + if (!controlled.current) { + setExpanded(expanded => !expanded) + } + if (onChange) { + onChange(e) + } + } + + return ( +
    props.theme.shadows[2]}; + background-color: ${props => props.theme.palette.primary.main}; + border-radius: 8px; + padding: ${open ? '8px 0' : ''}; + margin: 16px 0; + `} + > + {title && ( +
    props.theme.palette.text.main}; + height: 36px; + display: flex; + align-items: center; + justify-content: space-between; + cursor: pointer; + `} + onClick={toggle} + > +
    +
    + {title} +
    + {showHelp && ( +
    e.stopPropagation()}> + +
    + )} +
    +
    +
    + + + +
    + )} + {open && ( + <> + {showHelp && hoverHelp && } + {children} + {showAdd && ( + + )} + + )} +
    + ) +} + +export default FavoriteWrap diff --git a/src/content/pages/problem-list/HelpHead.tsx b/src/content/pages/problem-list/HelpHead.tsx new file mode 100644 index 0000000..e6add85 --- /dev/null +++ b/src/content/pages/problem-list/HelpHead.tsx @@ -0,0 +1,34 @@ +import { css } from 'styled-components/macro' + +const HelpHead: React.FC = () => { + return ( +
    +
    props.theme.palette.text.light}; + `} + > + 图标 + 题单名称 + 编辑 + 删除 + 公开 +
    +
    + ) +} + +export default HelpHead diff --git a/src/content/pages/problem-list/ProblemList.tsx b/src/content/pages/problem-list/ProblemList.tsx new file mode 100644 index 0000000..e9a0362 --- /dev/null +++ b/src/content/pages/problem-list/ProblemList.tsx @@ -0,0 +1,47 @@ +import { FC, useEffect } from 'react' + +import { useAppDispatch, useAppSelector } from '@/hooks' + +import FavoriteList from './FavoriteList' +import { + fetchFavoriteDetails, + fetchFavoriteMyFavorites, + fetchFavorites, +} from './favoriteSlice' +import { + fetchProblemsetPageProps, + selectIsSignedIn, +} from '../global/globalSlice' + +const App: FC = () => { + const dispatch = useAppDispatch() + const isSignedIn = useAppSelector(selectIsSignedIn) + useEffect(() => { + void (async function () { + dispatch(fetchProblemsetPageProps()) + const res = await dispatch(fetchFavorites()).unwrap() + const data = isSignedIn + ? await dispatch(fetchFavoriteMyFavorites()).unwrap() + : [] + const ids = [ + ...new Set( + res.allFavorites + .concat(res.officialFavorites) + .map(({ idHash }) => idHash) + .concat(data.map(a => a.idHash)) + ), + ] + dispatch(fetchFavoriteDetails(ids)) + })() + }, [isSignedIn]) + + return ( + <> + {isSignedIn && } + {isSignedIn && } + + + ) +} + +export default App diff --git a/src/content/pages/problem-list/favoriteSlice.ts b/src/content/pages/problem-list/favoriteSlice.ts new file mode 100644 index 0000000..55e6ab5 --- /dev/null +++ b/src/content/pages/problem-list/favoriteSlice.ts @@ -0,0 +1,264 @@ +import { + createSlice, + createAsyncThunk, + createEntityAdapter, + PayloadAction, +} from '@reduxjs/toolkit' + +import { RootState } from '@/app/store' +import { + LeetCodeApi, + Favorite, + FavoriteDetail, + AddFavoriteResult, +} from '@/utils' + +const api = new LeetCodeApi(location.origin) + +type FavoriteType = Favorite & + Partial> & { + showName?: string + isInAudit?: boolean + } + +const favoritesAdapter = createEntityAdapter({ + selectId: favorite => favorite.idHash, +}) + +export const fetchFavorites = createAsyncThunk< + { + allFavorites: Favorite[] + officialFavorites: Favorite[] + }, + undefined, + { state: RootState } +>('favorites/fetchFavorites', async () => { + const res = await api.getFavorites() + return res +}) + +export const fetchFavoriteMyFavorites = createAsyncThunk< + FavoriteDetail[], + undefined, + { state: RootState } +>('favorites/fetchFavoriteMyFavorites', () => api.getFavoriteMyFavorites()) + +export const fetchFavoriteDetails = createAsyncThunk< + FavoriteDetail[], + string[], + { state: RootState } +>('favorites/fetchFavoriteDetails', favoriteIds => + api.getFavoriteDetail(favoriteIds) +) + +export const saveFavorite = createAsyncThunk< + AddFavoriteResult, + string, + { state: RootState } +>('favorites/saveFavorite', favoriteName => api.addFavorite(favoriteName)) + +export const removeFavorite = createAsyncThunk< + void, + string, + { state: RootState } +>('favorites/removeFavorite', favoriteId => api.deleteFavorite(favoriteId)) + +export const checkIsInAudit = createAsyncThunk< + void, + string, + { state: RootState } +>('favorites/checkIsInAudit', async favoriteId => { + try { + await api.setFavorite({ + favorite_id_hash: favoriteId, + }) + } catch (error: any) { + if (error.message === '题单处于审核中,不可编辑') { + throw new Error('题单处于审核中,不可编辑') + } + } +}) + +export const toggleFavoritePublicState = createAsyncThunk< + void, + string, + { state: RootState } +>( + 'favorites/toggleFavoritePublicState', + async (favoriteId, { getState, dispatch }) => { + const state = getState() + const favorite = selectFavoriteById(state, favoriteId) + if (!favorite) { + throw new Error('无效的 FavoriteId,可能是缓存问题,尝试刷新页面后重试') + } + await dispatch(checkIsInAudit(favoriteId)).unwrap() + await api.setFavorite({ + favorite_id_hash: favorite.idHash, + name: favorite.name, + is_public_favorite: !favorite.isPublicFavorite, + }) + } +) + +export const updateFavoriteName = createAsyncThunk< + string, + { favoriteId: string; name: string }, + { state: RootState } +>( + 'favorites/updateFavoriteName', + async ({ favoriteId, name }, { getState, dispatch }) => { + const state = getState() + const favorite = selectFavoriteById(state, favoriteId) + if (!favorite) { + throw new Error('无效的 FavoriteId,可能是缓存问题,尝试刷新页面后重试') + } + await dispatch(checkIsInAudit(favoriteId)).unwrap() + + await api.setFavorite({ + favorite_id_hash: favorite.idHash, + name: name, + is_public_favorite: favorite.isPublicFavorite, + }) + return name + } +) + +export const addQuestionsToFavorite = createAsyncThunk< + { + questionId: string + __typename: string + }[], + { favoriteId: string; frontendQuestionIds: string[] }, + { state: RootState } +>( + 'favorites/addQuestionsToFavorite', + async ({ favoriteId, frontendQuestionIds }) => { + return await api.addQuestionToFavorite(favoriteId, frontendQuestionIds) + } +) + +const initialState = favoritesAdapter.getInitialState({ + customFavoriteIds: [] as string[], + officialFavoriteIds: [] as string[], + thirdPartyFavoriteIds: [] as string[], +}) + +const favoritesSlice = createSlice({ + name: 'favorites', + initialState, + reducers: { + addFavorite(state, action: PayloadAction) { + state.customFavoriteIds.push(action.payload) + }, + toggleFavoriteAuditStatus(state, action: PayloadAction) { + const favorite = state.entities[action.payload] + if (favorite) favorite.isInAudit = !favorite.isInAudit + }, + updateShowName( + state, + action: PayloadAction<{ idHash: string; showName: string }> + ) { + const favorite = state.entities[action.payload.idHash] + if (favorite) favorite.showName = action.payload.showName + }, + }, + extraReducers(builder) { + builder + .addCase(fetchFavorites.fulfilled, (state, action) => { + const { allFavorites, officialFavorites } = action.payload + state.customFavoriteIds = allFavorites.map(({ idHash }) => idHash) + state.officialFavoriteIds = officialFavorites.map( + ({ idHash }) => idHash + ) + + favoritesAdapter.upsertMany(state, allFavorites) + favoritesAdapter.upsertMany(state, officialFavorites) + for (const favorite of allFavorites) { + if (favorite.name.startsWith('待审核')) { + state.entities[favorite.idHash]!.isInAudit = true + } + } + }) + .addCase(fetchFavoriteDetails.fulfilled, (state, action) => { + favoritesAdapter.upsertMany(state, action.payload as any) + }) + .addCase(fetchFavoriteMyFavorites.fulfilled, (state, action) => { + const set = new Set( + state.customFavoriteIds.concat(state.officialFavoriteIds) + ) + const data = action.payload.filter(item => !set.has(item.idHash)) + state.thirdPartyFavoriteIds = data.map(item => item.idHash) + favoritesAdapter.upsertMany(state, data as any) + }) + .addCase(removeFavorite.fulfilled, (state, action) => { + state.customFavoriteIds = state.customFavoriteIds.filter( + id => id !== action.meta.arg + ) + }) + .addCase(checkIsInAudit.fulfilled, (state, action) => { + const favorite = state.entities[action.meta.arg] + if (favorite && favorite.isInAudit) { + favorite.isInAudit = false + } + }) + .addCase( + toggleFavoritePublicState.fulfilled, + (state, { meta: { arg: id } }) => { + const favorite = state.entities[id] + if (favorite) favorite.isPublicFavorite = !favorite.isPublicFavorite + } + ) + .addCase( + updateFavoriteName.fulfilled, + ( + state, + { + meta: { + arg: { favoriteId }, + }, + payload: name, + } + ) => { + const favorite = state.entities[favoriteId] + if (favorite) { + favorite.showName = name + favorite.isInAudit = true + } + } + ) + }, +}) + +export const { + selectAll: selectAllFavorites, + selectById: selectFavoriteById, + selectIds: selectFavoriteIds, +} = favoritesAdapter.getSelectors(state => state.favorites) + +export type FavoriteCategory = 'custom' | 'official' | 'third' + +export const selectFavoriteIdsByCategory = + (category: FavoriteCategory) => + (state: RootState): string[] => + state.favorites[ + category === 'custom' + ? 'customFavoriteIds' + : category === 'official' + ? 'officialFavoriteIds' + : 'thirdPartyFavoriteIds' + ] + +export const selectFavoriteByCategory = + (category: FavoriteCategory) => + (state: RootState): FavoriteType[] => + state.favorites[ + category === 'custom' + ? 'customFavoriteIds' + : category === 'official' + ? 'officialFavoriteIds' + : 'thirdPartyFavoriteIds' + ].map(id => state.favorites.entities[id]!) + +export const { addFavorite, toggleFavoriteAuditStatus, updateShowName } = + favoritesSlice.actions +export default favoritesSlice.reducer diff --git a/src/content/pages/problem-list/fixRandom.ts b/src/content/pages/problem-list/fixRandom.ts new file mode 100644 index 0000000..01d674b --- /dev/null +++ b/src/content/pages/problem-list/fixRandom.ts @@ -0,0 +1,42 @@ +import store from '@/app/store' +import { findElementByXPath, LeetCodeApi, routerTo } from '@/utils' + +import { selectIsPremium } from '../global/globalSlice' +import { selectOptions } from '../global/optionsSlice' + +const getCurrentId = () => { + const strs = location.pathname.split('/').filter(Boolean) + if (strs[0] === 'problem-list') return strs[1] + return '' +} +const api = new LeetCodeApi(location.origin) +const handleRandom = async (e: MouseEvent) => { + const options = selectOptions(store.getState()) + if (options?.problemListPage.fixRandomQuestion) { + e.preventDefault() + e.stopPropagation() + const id = getCurrentId() + let questions = await api.getProblemsetQuestionListAll({ + filters: { listId: id }, + }) + const isPremium = selectIsPremium(store.getState()) + if (!isPremium) questions = questions.filter(q => !q.paidOnly) + + const i = Math.floor(Math.random() * (questions.length - 1)) + const url = `/problems/${questions[i].titleSlug}/?favorite=${id}` + routerTo(url) + } +} +const randomXpath = + '//*[@id="__next"]/div/div[2]/div/div[2]/div/*//span[text()="随机开始"]' + +export const fixRandom = async (): Promise => { + const spans = await findElementByXPath({ + xpath: randomXpath, + nodeType: 'UNORDERED_NODE_ITERATOR_TYPE', + }) + for (const el of spans) { + el.parentElement?.removeEventListener('click', handleRandom) // 如果存在旧的监听器,先删除掉 + el.parentElement?.addEventListener('click', handleRandom) + } +} diff --git a/src/content/pages/problem-list/useSetProblemListRoot.ts b/src/content/pages/problem-list/useSetProblemListRoot.ts new file mode 100644 index 0000000..ee99e31 --- /dev/null +++ b/src/content/pages/problem-list/useSetProblemListRoot.ts @@ -0,0 +1,39 @@ +import { useEffectMount } from '@/hooks' +import { findElementByXPath } from '@/utils' +import { debounce } from 'src/utils' + +export const useSetProblemListRoot = ( + problemListXPath: string, + isLoad: boolean, + setProblemListRoot: (root: HTMLElement) => void +): void => { + useEffectMount( + async state => { + if (!isLoad) return + const handleMount = async () => { + const el = await findElementByXPath(problemListXPath) + + if (state.isMount && el.parentNode) { + const root = document.createElement('div') + el.parentNode.insertBefore(root, el) + setProblemListRoot(root) + state.unmount.push(() => root.remove()) + const handleChange = debounce(async () => { + const el = await findElementByXPath(problemListXPath) + + if (el.previousSibling === root) return + if (!state.isMount) return + observer.disconnect() + root.remove() + state.unmount = [] + handleMount() + }, 100) + const observer = new MutationObserver(handleChange) + observer.observe(el.parentNode, { childList: true }) + } + } + handleMount() + }, + [isLoad] + ) +} diff --git a/src/content/pages/problems/App.tsx b/src/content/pages/problems/App.tsx new file mode 100644 index 0000000..2ee3672 --- /dev/null +++ b/src/content/pages/problems/App.tsx @@ -0,0 +1,31 @@ +import { FC, useState } from 'react' + +import { withPage } from '@/hoc' +import { isBetaUI } from '@/utils' +import Beta from './Beta' +import Legacy from './Legacy' +import { useEffectMount } from '@/hooks' +import DynamicLayout from './DynamicLayout' + +const App: FC<{ beta?: boolean }> = () => { + const [beta, setBeta] = useState() + + useEffectMount(async state => { + const beta = await isBetaUI() + if (!state.isMount) return + setBeta(beta) + }, []) + if (localStorage.getItem('used-dynamic-layout') === 'true') { + return + } + + if (beta === undefined) return null + + if (beta) { + return + } else { + return + } +} + +export default withPage('problemsPage')(App) diff --git a/src/content/pages/problems/Beta.tsx b/src/content/pages/problems/Beta.tsx new file mode 100644 index 0000000..cb96350 --- /dev/null +++ b/src/content/pages/problems/Beta.tsx @@ -0,0 +1,65 @@ +import { FC, useState } from 'react' + +import { useAppSelector, useObserverAncestor } from '@/hooks' + +import { selectOptions } from '../global/optionsSlice' +import Timer from './Timer' +import { findElement } from '@/utils' +import { getRoot } from './utils' +import { Portal } from '@/components/Portal' +import Random from './Random' + +const Beta: FC<{ beta?: boolean }> = () => { + const options = useAppSelector(selectOptions) + const [timerRoot, setTimerRoot] = useState() + const [randomRoot, setRandomRoot] = useState() + + const showTimer = !!options?.problemsPage.timer + const showRandomQuestion = false + useObserverAncestor( + async state => { + if (!showRandomQuestion) return + // 创建「随机一题」按钮根元素 + const nav = await findElement( + '#__next > div > div > div > nav > div > div > div:nth-child(2)' + ) + if (!state.isMount) return + const randomRoot = document.createElement('div') + randomRoot.style.lineHeight = '0' + setRandomRoot(randomRoot) + nav.append(randomRoot) + state.unmount.push(() => randomRoot && randomRoot.remove()) + return randomRoot + }, + [showRandomQuestion] + ) + + useObserverAncestor( + async state => { + if (!showTimer) return + // 创建「计时器」按钮根元素 + const parent = await getRoot() + if (!state.isMount) return + + const root = document.createElement('div') + parent.prepend(root) + setTimerRoot(root) + state.unmount.push(() => root && root.remove()) + return root! + }, + [showTimer] + ) + + return ( + <> + {showTimer && timerRoot && } + {randomRoot && showRandomQuestion && ( + + + + )} + + ) +} + +export default Beta diff --git a/src/content/pages/problems/DynamicLayout.tsx b/src/content/pages/problems/DynamicLayout.tsx new file mode 100644 index 0000000..5574b2a --- /dev/null +++ b/src/content/pages/problems/DynamicLayout.tsx @@ -0,0 +1,42 @@ +import { FC, useState } from 'react' + +import { useAppSelector, useObserverAncestor } from '@/hooks' + +import { selectOptions } from '../global/optionsSlice' +import Timer from './Timer' +import { getRoot } from './utils' + +const DynamicLayout: FC<{ beta?: boolean }> = () => { + const options = useAppSelector(selectOptions) + const [timerRoot, setTimerRoot] = useState() + + const showTimer = !!options?.problemsPage.timer + + useObserverAncestor( + async state => { + if (!showTimer) return + const parent = await getRoot(true) + + // 创建「计时器」按钮根元素 + if (!parent || !state.isMount) return + + const root = document.createElement('div') + parent.style.display = 'flex' + parent.append(root) + setTimerRoot(root) + state.unmount.push(() => root && root.remove()) + return root! + }, + [showTimer] + ) + + return ( + <> + {showTimer && timerRoot && ( + + )} + + ) +} + +export default DynamicLayout diff --git a/src/content/pages/problems/Legacy.tsx b/src/content/pages/problems/Legacy.tsx new file mode 100644 index 0000000..c6484a3 --- /dev/null +++ b/src/content/pages/problems/Legacy.tsx @@ -0,0 +1,35 @@ +import { FC, useState } from 'react' + +import { useAppSelector, useObserverAncestor } from '@/hooks' + +import { selectOptions } from '../global/optionsSlice' +import Timer from './Timer' +import { getRoot } from './utils' + +const Legacy: FC<{ beta?: boolean }> = () => { + const options = useAppSelector(selectOptions) + const [timerRoot, setTimerRoot] = useState() + const showTimer = !!options?.problemsPage.timer + + useObserverAncestor( + async state => { + if (!showTimer) return + const parent = await getRoot() + if (!state.isMount) return + + const root = document.createElement('div') + root.style.marginRight = '15px' + parent.prepend(root) + setTimerRoot(root) + state.unmount.push(() => root && root.remove()) + return root + }, + [showTimer] + ) + + return ( + <>{showTimer && timerRoot && } + ) +} + +export default Legacy diff --git a/src/content/pages/problems/OptimizedContestProblemsPage.tsx b/src/content/pages/problems/OptimizedContestProblemsPage.tsx new file mode 100644 index 0000000..1844344 --- /dev/null +++ b/src/content/pages/problems/OptimizedContestProblemsPage.tsx @@ -0,0 +1,234 @@ +import { createGlobalStyle } from 'styled-components/macro' +import { useAppDispatch, useAppSelector } from '@/hooks' +import { useCallback, useEffect, useState } from 'react' +import { + selectOptions, + setContestProblemViewWidth, +} from '@/pages/global/optionsSlice' +import { Portal } from '@/components/Portal' +import { withPage } from '@/hoc' + +const GlobalStyle = createGlobalStyle` + body { + display: flex; + flex-direction: column; + } + + body .content-wrapper { + height: 0; + min-height: 0 !important; + flex: 1; + display: flex; + flex-direction: column; + padding-bottom: 0 !important; + } + + .content-wrapper #base_content { + display: flex; + overflow: hidden; + height: 0; + flex: 1; + flex-direction: var(--layout-direction, row); + } + + .content-wrapper #base_content.is-reverse { + flex-direction: row-reverse; + } + + .content-wrapper #base_content > .container { + width: var(--problem-view-width); + overflow: scroll; + } + + .content-wrapper #base_content > .container .question-content { + overflow: unset !important; + } + + .content-wrapper #base_content > .container .question-content > pre { + white-space: break-spaces; + } + + .content-wrapper #base_content > .editor-container { + flex: 1; + overflow: scroll; + } + + .content-wrapper #base_content > .editor-container .container { + width: 100% !important; + } + + .content-wrapper #base_content > .resize-container { + width: 6px; + height: 100%; + margin: 0 2px; + position: relative; + } + + .resize-container .custom-resize { + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100%; + background: #eee; + cursor: ew-resize; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + transition: .2s all; + } + + .resize-container .custom-resize:hover { + background: #1a90ff; + } + + .resize-container .custom-resize .resize-dot { + width: 2px; + height: 2px; + background-color: #666; + border-radius: 50%; + } + + .resize-container .custom-resize:hover .resize-dot { + background-color: white; + } + + .resize-container .custom-resize .resize-dot:not(:first-of-type) { + margin-top: 3px; + } +` + +const Variables = createGlobalStyle<{ + $problemViewWidth?: string + $layoutDirection?: 'row' | 'row-reverse' +}>` + :root { + --problem-view-width: ${props => props.$problemViewWidth || '40%'}; + --layout-direction: ${props => props.$layoutDirection ?? 'row'} + } +` + +const OptimizedContestProblemsPage = (): JSX.Element => { + const options = useAppSelector(selectOptions) + const dispatch = useAppDispatch() + + const modifyPageLayout = !!options?.contestProblemsPage.modifyPageLayout + const reverseLayout = !!options?.contestProblemsPage.reverseLayout + const problemViewWidth = options?.contestProblemsPage.problemViewWidth + + const [currentResize, setCurrentResize] = useState({ + isResizing: false, + startX: 0, + currentX: 0, + initialSize: 0, + }) + + const newSize = (state: typeof currentResize, isReverse: boolean) => { + const deltaX = state.currentX - state.startX + return state.initialSize + (isReverse ? -deltaX : deltaX) + } + + const baseContent = document.querySelector( + '.content-wrapper #base_content' + ) as HTMLElement | null + if (baseContent?.children.length == 2) { + const $resizeContainer = document.createElement('div') + baseContent.insertBefore($resizeContainer, baseContent.children[1]) + $resizeContainer.classList.add('resize-container') + } + + const onMouseDown = useCallback(e => { + if (!baseContent?.children[0]) return + e.preventDefault() + setCurrentResize({ + isResizing: true, + initialSize: baseContent?.children[0].getBoundingClientRect().width, + startX: e.clientX, + currentX: e.clientX, + }) + }, []) + + const onMouseMove = useCallback( + e => { + if (!currentResize.isResizing) return + e.preventDefault() + setCurrentResize(state => ({ + ...state, + currentX: e.clientX, + })) + }, + [currentResize] + ) + + const onMouseUp = useCallback( + e => { + if (!currentResize.isResizing) return + e.preventDefault() + setCurrentResize(state => { + return { + ...state, + isResizing: false, + currentX: e.clientX, + } + }) + Promise.resolve().then(() => { + dispatch( + setContestProblemViewWidth( + `${newSize(currentResize, reverseLayout)}px` + ) + ) + }) + }, + [currentResize, reverseLayout] + ) + + useEffect(() => { + window.addEventListener('mousemove', onMouseMove) + window.addEventListener('mouseup', onMouseUp) + + return () => { + window.removeEventListener('mousemove', onMouseMove) + window.removeEventListener('mouseup', onMouseUp) + } + }, [onMouseMove, onMouseUp]) + + return ( + <> + {modifyPageLayout && } + + {baseContent && ( + +
    + {Array(3) + .fill(0) + .map((_, i) => ( +
    + ))} +
    + + )} + + ) +} + +export default withPage('contestProblemsPage')(OptimizedContestProblemsPage) diff --git a/src/content/pages/problems/Random.tsx b/src/content/pages/problems/Random.tsx new file mode 100644 index 0000000..3ea474f --- /dev/null +++ b/src/content/pages/problems/Random.tsx @@ -0,0 +1,124 @@ +import { FC, useCallback, useEffect, useRef, useState } from 'react' +import styled from 'styled-components/macro' + +import { + LeetCodeApi, + ProblemsetQuestion, + QuestionType, + routerTo, +} from '@/utils' +import { useAppSelector, useHover } from '@/hooks' + +import { selectIsPremium } from '../global/globalSlice' +import { selectRandomOption } from '../global/optionsSlice' +import RandomOption from './RandomOption' + +const StyledBtn = styled.button` + line-height: 0; + color: ${props => + props.theme.mode === 'dark' ? 'rgb(219 219 219)' : 'rgb(38 38 38)'}; + & > svg { + height: 18px; + width: 18px; + } +` + +const api = new LeetCodeApi(location.origin) + +const Random: FC = () => { + const isPremium = useAppSelector(selectIsPremium) + const [favorite, setFavorite] = useState( + new URL(location.href).searchParams.get('favorite') ?? 'all' + ) + const [hoverRef, hover] = useHover(100) + const [hoverOptionRef, hoverOption] = useHover(100) + const ref = useRef() + const mulRef = useCallback(el => { + ref.current = el + hoverRef(el) + }, []) + const option = useAppSelector(state => selectRandomOption(state, favorite)) + + useEffect(() => { + const handle = () => { + setFavorite(new URL(location.href).searchParams.get('favorite') ?? 'all') + } + + window.addEventListener('urlchange', handle) + return () => window.removeEventListener('urlchange', handle) + }, []) + + const handldClick = async () => { + let allQuestions: { + titleSlug: string + paidOnly?: boolean + isPaidOnly?: boolean + }[] + + const currentTitleSlug = location.pathname.split('/').filter(Boolean)[1] + const predicates: ((question: any) => boolean | undefined)[] = [] + // 过滤当前题目 + predicates.push(({ titleSlug }) => titleSlug === currentTitleSlug) + if (favorite !== 'all') { + allQuestions = await api.getProblemsetQuestionListAll({ + filters: { listId: favorite }, + }) + type Question = ProblemsetQuestion + // 过滤会员题 + predicates.push(({ paidOnly }: Question) => !isPremium && paidOnly) + // 过滤已 AC 的题目 + predicates.push( + ({ status }: Question) => option.skipAC && status === 'AC' + ) + } else { + allQuestions = await api.getAllQuestions() + type Question = QuestionType + // 过滤会员题 + predicates.push(({ isPaidOnly }: Question) => !isPremium && isPaidOnly) + // 过滤已 AC 的题目 + predicates.push( + ({ status }: Question) => option.skipAC && status === 'ac' + ) + } + allQuestions = allQuestions.filter( + question => !predicates.some(f => f(question)) + ) + + if (!allQuestions.length) return + + const i = Math.floor(Math.random() * (allQuestions.length - 1)) + + let nextUrl = `/problems/${allQuestions[i].titleSlug}/` + if (favorite !== 'all') nextUrl += `?favorite=${favorite}` + routerTo(nextUrl, false) + } + + return ( + <> + + + + + + {(hover || hoverOption) && ( + + )} + + ) +} + +export default Random diff --git a/src/content/pages/problems/RandomOption.tsx b/src/content/pages/problems/RandomOption.tsx new file mode 100644 index 0000000..d57e005 --- /dev/null +++ b/src/content/pages/problems/RandomOption.tsx @@ -0,0 +1,113 @@ +import { forwardRef, ForwardedRef } from 'react' + +import { useAppSelector, useAppDispatch } from '@/hooks' +import PopperUnstyled, { Placement } from '@/components/PopperUnstyled' + +import { + selectRandomOption, + RandomOptionType, + setRandomOption, + labelOfKey, +} from '../global/optionsSlice' +import { css } from 'styled-components/macro' + +interface RandomOptionProps { + anchorEl?: HTMLElement | null + placement?: Placement + favorite: string +} + +type RandomOptionKey = keyof RandomOptionType + +const RandomOption = forwardRef(function RandomOption( + { favorite, ...props }: RandomOptionProps, + ref: ForwardedRef +) { + const option = useAppSelector(state => selectRandomOption(state, favorite)) + const dispatch = useAppDispatch() + const toggle = (key: RandomOptionKey) => () => { + dispatch( + setRandomOption({ + favorite, + option: { ...option, [key]: !option[key] }, + }) + ) + } + const keys: RandomOptionKey[] = Object.keys(option) as any + + return ( + +
    props.theme.palette.primary.light}; + border-radius: 0.5rem; + padding: 0.625rem; + box-shadow: ${props => props.theme.shadows[1]}; + margin-left: 10px; + `} + > + {keys.map(key => ( +
  • theme.palette.text.light}; + `} + > + + props.theme.palette.checkbox.backgroundColor}; + &:checked { + background-color: ${props => + props.theme.palette.checkbox.checkedBackgroundColor}; + } + &:checked::before { + content: url('data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16px" height="16px" fill="rgb(255 255 255)" aria-hidden="true"%3E%3Cpath fill-rule="evenodd" d="M9.688 15.898l-3.98-3.98a1 1 0 00-1.415 1.414L8.98 18.02a1 1 0 001.415 0L20.707 7.707a1 1 0 00-1.414-1.414l-9.605 9.605z" clip-rule="evenodd"%3E%3C/path%3E%3C/svg%3E'); + } + `} + /> + +
  • + ))} +
    +
    + ) +}) + +export default RandomOption diff --git a/src/content/pages/problems/ShortcutKeyOption.tsx b/src/content/pages/problems/ShortcutKeyOption.tsx new file mode 100644 index 0000000..cf6cdf1 --- /dev/null +++ b/src/content/pages/problems/ShortcutKeyOption.tsx @@ -0,0 +1,99 @@ +import { useEffect, useState, FC } from 'react' +import { Portal } from '@/components/Portal' +import { findElement } from '@/utils' +import { css } from 'styled-components/macro' +import { useAppDispatch, useAppSelector, useEffectMount } from '@/hooks' +import { + selectOptions, + toggleContestProblemShortcutKeyOption, +} from '../global/optionsSlice' +import { withPage } from '@/hoc' +import { useThrottle } from '@/hooks/useThrottle' + +const ShortcutKeyOption: FC = () => { + const options = useAppSelector(selectOptions) + const [optionEl, setOptionEl] = useState() + + const disableShortcutKey = + options && options.contestProblemsPage.disableShortcutkey + const dispatch = useAppDispatch() + + const toggle = useThrottle(() => { + dispatch(toggleContestProblemShortcutKeyOption()) + }, 500) + + useEffectMount(async state => { + const handleClick = async () => { + try { + const content = await findElement( + '.rc-dialog-body>.modal-body.description__21Ft' + ) + if (!state.isMount) return + setOptionEl(content) + } catch (error) { + // + } + } + handleClick() + const settingBtn = await findElement('.setting-btn') + if (!state.isMount) return + settingBtn.addEventListener('click', handleClick) + state.unmount.push( + () => settingBtn && settingBtn.removeEventListener('click', handleClick) + ) + }) + + useEffect(() => { + if (!disableShortcutKey) return + let editor: HTMLElement | null = null + const handleClick = (e: KeyboardEvent) => { + e.stopPropagation() + } + void (async function () { + editor = await findElement('.editor-base') + editor?.addEventListener('keydown', handleClick) + })() + return () => { + editor && editor.removeEventListener('keydown', handleClick) + } + }, [disableShortcutKey]) + + if (!optionEl) return <> + return ( + +
    +
    +
    禁用快捷键
    + + + {disableShortcutKey ? ( + + ) : ( + + )} + +
    +
    + ) +} + +export default withPage('contestProblemsPage')(ShortcutKeyOption) diff --git a/src/content/pages/problems/Timer.tsx b/src/content/pages/problems/Timer.tsx new file mode 100644 index 0000000..d0eb94a --- /dev/null +++ b/src/content/pages/problems/Timer.tsx @@ -0,0 +1,476 @@ +import React, { FC, useEffect, useState } from 'react' +import styled, { css } from 'styled-components/macro' + +import { + sleep, + LeetCodeApi, + SuccessCheckReturnType, + findElement, + findElementByXPath, + findAllElement, +} from '@/utils' +import { useEvent, useHover, useObserverAncestor } from '@/hooks' +import { ToolTip } from '@/components/ToolTip' + +import { + submissionOnMarkChange, + checkIfSubmitKey, + checkIfGlobalSubmitIsDisabled, + getRoot, +} from './utils' +import { useTimer } from './useTimer' +import { logger } from '../../../utils' +import { Portal } from '@/components/Portal' +import ResetIcon from '@/components/icons/ResetIcon' + +const log = logger.child({ prefix: 'Clock' }) + +const Container = styled.div` + display: flex; + justify-content: center; + align-items: center; + font-size: 14px; +` + +const Content = styled.div<{ beta: boolean }>` + height: ${props => (props.beta ? 33 : 35)}px; + border-radius: 3px 0 0 3px; + border: 1px solid palevioletred; + border-right-width: 0; + display: flex; + align-items: center; + padding: 0 15px; + white-space: nowrap; +` + +const Button = styled.button<{ + primary?: boolean + width: number + center: boolean + height: number +}>` + display: flex; + align-items: center; + justify-content: center; + background: transparent; + + color: palevioletred; + text-align: center; + cursor: pointer; + border: 1px solid palevioletred; + border-radius: 0; + width: ${props => props.width}px; + height: ${props => props.height}px; + ${({ center }) => + center + ? css` + border-right: 0; + margin-right: 0; + padding: 0; + line-height: 16px; + ` + : css` + border-radius: 0 3px 3px 0; + padding: 0px 15px; + `} +` + +interface TimerProps { + beta?: boolean + root?: HTMLElement + dynamicLayout?: boolean +} + +const Timer: FC = ({ beta, root, dynamicLayout }) => { + const pathnames = location.pathname.split('/').filter(Boolean) + const slug = pathnames[1] + + const [leetCodeApi] = useState(new LeetCodeApi(location.origin)) + const [hidden, setHidden] = useState(false) + const [editEl, setEditEl] = useState() + + const { time, isDone, done, restart } = useTimer() + + useEffect(() => restart(), [slug]) + + const [hoverRef, hover] = useHover() + + const handleHidden = () => { + setHidden(hidden => !hidden) + } + + /** 获取 SubmissionId + * + * 从提交请求的返回值中获取 SubmissionId + * @returns 返回 SubmissionId + */ + async function getSubmissionIdByXML(): Promise { + return new Promise(function (resolve, reject) { + const originalOpen = XMLHttpRequest.prototype.open + XMLHttpRequest.prototype.open = function newOpen( + this: XMLHttpRequest, + method: string, + url: string, + async?: boolean, + user?: string, + password?: string + ) { + log.debug('open: %s %s', method, url) + if ( + method.toLocaleLowerCase() === 'post' && + url === `/problems/${slug}/submit/` + ) { + log.debug('拦截发送请求 %s %s', method, url) + this.addEventListener('readystatechange', function (event) { + log.debug('readystatechange %o %d', event, this.readyState) + const DONE = XMLHttpRequest.DONE ?? 4 + if (this.readyState === DONE) { + log.debug('readystatechange done') + const status = this.status + if (status === 0 || (status >= 200 && status < 400)) { + log.debug('readystatechange state %s', this.responseText) + const data = JSON.parse(this.responseText) + log.debug('还原 open') + if (XMLHttpRequest.prototype.open === newOpen) { + XMLHttpRequest.prototype.open = originalOpen + } + + resolve(data.submission_id + '') + } else { + if (status === 429) { + log.debug(`状态 429,等待重试`) + } else { + if (XMLHttpRequest.prototype.open === newOpen) { + XMLHttpRequest.prototype.open = originalOpen + } + log.error(`获取 SubmissionId 失败`) + reject(`提交错误,状态 ${status}`) + } + } + } + }) + } + originalOpen.apply(this, [method, url, async!, user, password]) + } + }) + } + /** 获取 SubmissionId + * + * 从提交请求的返回值中获取 SubmissionId + * @returns 返回 SubmissionId + */ + async function getSubmissionIdByFetch(): Promise<{ + submissionId: string + statusMsg: string + }> { + const originalFetch = window.fetch + const res: { submissionId: string; statusMsg: string } = { + submissionId: '', + statusMsg: '', + } + return new Promise(function (resolve) { + window.fetch = async function fetch(...args) { + const [url, request] = args + if (url === `/problems/${slug}/submit/` && request?.method === 'POST') { + // 获取 submissionId + const response = await originalFetch(...args) + const tmp = response.clone() + const { submission_id } = await tmp.json() + res.submissionId = submission_id + return response + } else if ( + res.submissionId && + url === `/submissions/detail/${res.submissionId}/check/` + ) { + // 获取当前提交的结果 + const response = await originalFetch(...args) + const tmp = response.clone() + const { state, status_msg } = await tmp.json() + if (state === 'SUCCESS') { + res.statusMsg = status_msg + window.fetch = originalFetch + resolve(res) + } + return response + } + return originalFetch(...args) + } + }) + } + + /** 检查提交是否通过 + * + * @param submissionId 提交的 Id + * @param maxRetry 最多重试次数 + * @param count 当前已经重试的次数 + * @returns + */ + async function check( + submissionId: string, + maxRetry = 10, + count = 1 + ): Promise { + if (count > maxRetry) throw new Error('获取提交状态结果超时') + + await sleep(1000 + count * 500) + const state = await leetCodeApi.check(submissionId) + + if (state.state === 'SUCCESS') { + return state + } else { + return await check(submissionId, count + 1) + } + } + + /** 提交成功时的处理函数 + */ + const submitSuccess = useEvent(async submissionId => { + log.debug('提交成功') + // 提交成功 + done(time) + + setHidden(false) + + await leetCodeApi.submissionCreateOrUpdateSubmissionComment( + submissionId, + 'RED', + time.map(t => t.toString().padStart(2, '0')).join(' : ') + ) + + log.debug('已添加备注') + if (!beta || localStorage.getItem('dynamicLayoutGuide') === 'true') { + // 新版 UI 会自动刷新备注,所以不需要再手动刷新了 + // 对当前提交添加备注 + await sleep(500) + await submissionOnMarkChange(submissionId) + log.debug('刷新备注') + } + }) + + /** 提交事件 + */ + const handleClick = useEvent(async () => { + log.debug('提交开始') + if (beta) { + const { submissionId, statusMsg } = await getSubmissionIdByFetch() + if (statusMsg === 'Accepted') { + submitSuccess(submissionId) + } + } else { + const submissionId = await getSubmissionIdByXML() + log.debug('获取 submissionId %s', submissionId) + const state = await check(submissionId) + log.debug('获取提交状态 %s', state.status_msg) + + if (state.status_msg === 'Accepted') { + submitSuccess(submissionId) + } + } + }) + + const getSubMitBtn = async () => { + let submitBtn: HTMLElement + if (dynamicLayout) { + const xpath = "//span[text()='提交']" + submitBtn = await findElementByXPath(xpath) + submitBtn = submitBtn.parentElement! + } else if (beta) { + const parent = await getRoot() + if (parent) { + submitBtn = [...parent.children].slice(-1)[0] as HTMLElement + } else { + throw new Error('未找到提交按钮') + } + } else { + submitBtn = await findElement('.submit__-6u9') + } + return submitBtn + } + + // TODO: 使用 useEffectMount 重构 + useEffect(() => { + if (!root) return + log.info('加载 Clock 组件') + const cancel: { current: (() => void) | null | 'unmount' } = { + current: null, + } + + void (async function () { + // 当前组件已经被卸载,就不需要挂载事件 + let submitBtn: HTMLElement = await getSubMitBtn() + + const mount = async () => { + submitBtn = await getSubMitBtn() + if (cancel.current === 'unmount') return + log.debug('挂载按钮') + + submitBtn.addEventListener('click', handleClick) + } + + const unmount = async () => { + log.debug('卸载按钮') + submitBtn.removeEventListener('click', handleClick) + } + + const observer = new MutationObserver(function ( + mutationsList, + _observer + ) { + let isRemove = false, + isAdd = false + const check = (nodes: NodeList) => + Array.from(nodes).some( + node => (node as HTMLElement).innerText === '提交' + ) + + for (const mutation of mutationsList) { + if (mutation.type === 'childList') { + if (check(mutation.removedNodes)) isRemove = true + if (check(mutation.addedNodes)) isAdd = true + } + } + if (isRemove) { + // 删除提交按钮 + log.debug('提交按钮被删除,卸载监听提交事件') + unmount() + } else if (isAdd) { + // 添加提交按钮 + log.debug('提交按钮被添加,挂载监听提交事件') + mount() + } + }) + + if (cancel.current === 'unmount') return + + mount() + observer.observe(submitBtn.parentElement!, { childList: true }) + + cancel.current = () => { + unmount() + observer.disconnect() + } + })() + + return () => { + logger.info('卸载 Clock 组件') + if (typeof cancel.current === 'function') { + cancel.current() + } else { + cancel.current = 'unmount' + } + } + }, [root]) + + //#region 快捷键提交 + /** 使用快捷键提交的事件 + */ + const handleKeydown = async (e: KeyboardEvent) => { + if (!checkIfSubmitKey(e)) return + const globalSubmitIsDisabled = await checkIfGlobalSubmitIsDisabled() + if (globalSubmitIsDisabled) return + log.debug('使用快捷键提交') + handleClick() + } + + const getEditEl = async () => { + let editEl: HTMLElement + + if (beta) { + const editEls = await findAllElement( + '.monaco-editor', + els => + !!els.find(el => el.parentElement?.dataset.modeId !== 'plaintext') + ) + editEl = editEls.find( + el => el.parentElement?.dataset.modeId !== 'plaintext' + )! + } else { + editEl = await findElement('.euyvu2f0') + } + return editEl + } + useObserverAncestor(async state => { + const editEl: HTMLElement = await getEditEl() + if (!state.isMount) return + setEditEl(editEl) + return editEl + }) + useEffect(() => { + if (!editEl) return + editEl.addEventListener('keydown', handleKeydown) + return () => editEl.removeEventListener('keydown', handleKeydown) + }, [editEl]) + //#endregion + + if (!root) return null + + return ( + + + {!hidden && ( + + {`${isDone ? '本次耗时: ' : ''}${time + .map(t => t.toString().padStart(2, '0')) + .join(' : ')}`} + + )} + {!isDone ? ( +
    + {!hidden && hover && ( + +
    + +
    +
    + )} + + + +
    + ) : ( + + )} +
    +
    + ) +} + +export default Timer diff --git a/src/content/pages/problems/useTimer.ts b/src/content/pages/problems/useTimer.ts new file mode 100644 index 0000000..bc967a6 --- /dev/null +++ b/src/content/pages/problems/useTimer.ts @@ -0,0 +1,64 @@ +import { useEffect, useMemo, useRef, useState } from 'react' +import { logger } from '../../../utils' + +const log = logger.child({ prefix: 'useTimer' }) + +type Time = [house: number, minute: number, second: number] + +function formatTime(time: number): Time { + const house = Math.floor(time / 3600) + const minute = Math.floor((time / 60) % 60) + const second = Math.floor(time % 60) + return [house, minute, second] +} + +type UseTimeReturn = { + time: Time + isDone: boolean + done: (time: Time) => void + restart: () => void +} + +/** + * 计时器钩子 + * @returns 返回当前累计的时间 `time`;是否已结束 `isDone`;结束当前计时函数 `done`;重新开始函数 `restart` + */ +const useTimer = (): UseTimeReturn => { + const start = useRef(new Date()) + const [isDone, setIsDone] = useState(false) + const [value, setValue] = useState(0) + const time = useMemo(() => { + return formatTime(value) + }, [value]) + + useEffect(() => { + let timer: ReturnType + if (!isDone) { + timer = setInterval(async () => { + setValue(Math.floor((Date.now() - start.current.valueOf()) / 1000)) + }, 100) + } + + return () => { + if (timer) { + clearInterval(timer) + } + } + }, [isDone]) + + const restart = () => { + log.debug('重新开始计时') + setIsDone(false) + start.current = new Date() + setValue(0) + } + + const done = () => { + log.debug('结束计时') + setIsDone(true) + } + + return { time, isDone, done, restart } +} + +export { useTimer } diff --git a/src/utils.ts b/src/content/pages/problems/utils.ts similarity index 50% rename from src/utils.ts rename to src/content/pages/problems/utils.ts index 5570bd6..2df6e95 100644 --- a/src/utils.ts +++ b/src/content/pages/problems/utils.ts @@ -1,37 +1,8 @@ -function download(str: string, filename = 'contest.md'): void { - const blob = new Blob([str], { type: 'text/plain' }) - const url = URL.createObjectURL(blob) +import { IS_MAC, findElement, isBetaUI, findElementByXPath } from '@/utils' - const a = document.createElement('a') - a.href = url - a.download = filename - document.body.appendChild(a) - a.click() +import { logger } from '../../../utils' - document.body.removeChild(a) -} - -function getElement( - query: string, - fn: (e: NodeListOf) => boolean = e => e.length > 0, - timeout = 10000 -): Promise> { - const delay = 100 - return new Promise(function (resolve, reject) { - const timer = setInterval(() => { - const element = document.querySelectorAll(query) - if (fn(element)) { - clearInterval(timer) - resolve(element) - } - if (timeout <= 0) { - clearInterval(timer) - reject('超时') - } - timeout -= delay - }, delay) - }) -} +const log = logger.child({ prefix: 'Clock' }) interface RootNode { name: string @@ -107,13 +78,13 @@ function getFiber(el: Element): FiberRoot | null { return null } -function submissionOnMarkChange(submissionId: string): void { - const root = getFiber( - document.querySelectorAll(`[data-row-key="${submissionId}"]`)?.[0] - ) +async function submissionOnMarkChange(submissionId: string): Promise { + const submissionRowEl = await findElement(`[data-row-key="${submissionId}"]`) + + const root = getFiber(submissionRowEl) if (!root) { - console.log(`leetcode-extend: 未找到提交记录容器的 root`) + log.error(`refined-leetcode: 未找到提交记录容器的 root`) return } @@ -133,8 +104,81 @@ function submissionOnMarkChange(submissionId: string): void { if (onMarkChange) { onMarkChange(submissionId) } else { - console.log(`leetcode-extend: 未找到 onMarkChange`) + log.error(`refined-leetcode: 未找到 onMarkChange`) } } -export { download, getElement, submissionOnMarkChange } +/** 检查是否按了提交快捷键 + * + */ +const checkIfSubmitKey = (e: KeyboardEvent): boolean => { + let mate = false + + // 检查是否按下对应的快捷键,如果是 Mac 电脑为 Command 键,Window 或 Linux 为 Ctrl 键 + if (IS_MAC) { + if (e.metaKey === true && e.ctrlKey === false) mate = true + } else { + if (e.ctrlKey === true && e.metaKey === false) mate = true + } + + if ( + mate && + e.code === 'Enter' && + e.altKey === false && + e.shiftKey === false + ) { + return true + } + + return false +} + +/** 检查全局提交快捷键是否被禁用 + * + */ +const checkIfGlobalSubmitIsDisabled = async (): Promise => { + const useBetaUI = await isBetaUI() + if (useBetaUI) { + try { + const editorSetting = JSON.parse( + localStorage.getItem('EDITOR_SETTING') || '{}' + ) + return !editorSetting?.state?.shortcuts?.enableQuickSubmit + } catch (error) { + return false + } + } + return localStorage.getItem('global_disabled_submit_code') === 'false' +} + +/** 答题页内获取需要放置计时组件的 root + * + * 根据是否为新版 UI 选择不同的元素 + */ +async function getRoot(dynamicLayout?: boolean): Promise { + if (dynamicLayout) { + const xpath = "//span[text()='提交']" + let parent = await findElementByXPath(xpath) + for (let i = 0; i < 10; i++) { + if (!parent) break + parent = parent.parentElement! + } + return parent + } + const useBetaUI = await isBetaUI() + if (useBetaUI) { + const xpath = "//button[text()='提交']" + const submit = await findElementByXPath(xpath) + return submit.parentElement! + } else { + const parent = await findElement('.container__Kjnx>.action__KaAP') + return parent + } +} + +export { + submissionOnMarkChange, + checkIfSubmitKey, + checkIfGlobalSubmitIsDisabled, + getRoot, +} diff --git a/src/content/pages/problemset/AddQuestion.tsx b/src/content/pages/problemset/AddQuestion.tsx new file mode 100644 index 0000000..686fd1b --- /dev/null +++ b/src/content/pages/problemset/AddQuestion.tsx @@ -0,0 +1,200 @@ +import SvgIcon from '@/components/SvgIcon' +import { ToolTip } from '@/components/ToolTip' +import { css } from 'styled-components/macro' +import Popper from '@/components/PopperUnstyled' +import { useHover, useAppSelector, useAppDispatch } from '@/hooks' +import { + forwardRef, + MouseEventHandler, + ReactNode, + useEffect, + useMemo, + useState, +} from 'react' +import { + fetchFavoriteDetails, + selectFavoriteIdsByCategory, +} from '../problem-list/favoriteSlice' + +import Item from './Item' +import Wrap from '../problem-list/FavoriteWrap' +import { parseParamsToBody } from './utils' +import store from '@/app/store' +import { selectQuestonsByOption } from './questionsSlice' + +const getCurrentId = () => { + const paths = location.pathname.split('/').filter(Boolean) + if (paths[0] === 'problem-list') return paths[1] + return '' +} + +interface BoxProps { + children: ReactNode + onClick?: MouseEventHandler +} + +export const Box = forwardRef(function Box( + { children, onClick }, + ref +) { + const handleClicl: MouseEventHandler = e => + onClick && onClick(e) + return ( +
    + props.theme.mode === 'dark' ? '#ffffff1a' : '#000a200d'}; + box-shadow: ${props => + props.theme.mode === 'dark' + ? css`rgba(0, 0, 0, 0) 0px 0px 0px 0px, + rgba(0, 0, 0, 0) 0px 0px 0px 0px, rgba(0, 0, 0, 0.24) 0px 1px 3px 0px, + rgba(0, 0, 0, 0.16) 0px 2px 8px 0px` + : css`rgba(0, 0, 0, 0) 0px 0px 0px 0px, rgba(0, 0, 0, 0) 0px 0px 0px 0px, rgba(0, 0, 0, 0.04) 0px 1px 3px 0px, rgba(0, 0, 0, 0.08) 0px 2px 8px 0px`}; + &:hover { + background-color: ${props => + props.theme.mode === 'dark' ? '#ffffff24' : '#000a201a'}; + } + `} + onClick={handleClicl} + > + {children} +
    + ) +}) + +const AddQuestion: React.FC = () => { + const [bindRef, hover, ref] = useHover(100) + const [bindPopperRef, , popperRef] = useHover(100) + const [openPopper, setOpenPopper] = useState(false) + const ids = useAppSelector(selectFavoriteIdsByCategory('custom')) + const allIds = useAppSelector(state => state.favorites.ids) + const [currentId, setCurrentId] = useState(getCurrentId()) + const dispatch = useAppDispatch() + + const questions = useMemo(() => { + const body = parseParamsToBody() + const { data } = selectQuestonsByOption(store.getState(), { + ...body, + skip: 0, + limit: Infinity, + }) + const questions = data.problemsetQuestionList.questions + return questions + }, [ + JSON.stringify({ + ...parseParamsToBody(), + skip: 0, + limit: Infinity, + }), + allIds, + ]) + + useEffect(() => { + if (!allIds.includes(currentId)) { + dispatch(fetchFavoriteDetails([currentId])) + } + }, [currentId]) + + useEffect(() => { + const handleUrlChange = () => { + setCurrentId(getCurrentId()) + } + window.addEventListener('urlchange', handleUrlChange) + return () => { + window.removeEventListener('urlchange', handleUrlChange) + } + }, []) + + const toggleOpen: React.MouseEventHandler = e => { + e.stopPropagation() + setOpenPopper(open => !open) + } + useEffect(() => { + const handleClick = (e: MouseEvent) => { + const el = e.target as Node + if (!popperRef.current?.contains(el) && !ref.current?.contains(el)) { + setOpenPopper(false) + } + } + + document.addEventListener('mousedown', handleClick, { capture: true }) + return () => + document.removeEventListener('mousedown', handleClick, { capture: true }) + }, []) + return ( + <> + + + + + + + + {openPopper && ( + +
    + +
    + 当前选中题目: + + {questions.length} + + 道 +
    +
      + {ids.map(idHash => ( + + ))} +
    +
    +
    +
    + )} + + ) +} + +export default AddQuestion diff --git a/src/content/pages/problemset/App.tsx b/src/content/pages/problemset/App.tsx new file mode 100644 index 0000000..de354e7 --- /dev/null +++ b/src/content/pages/problemset/App.tsx @@ -0,0 +1,43 @@ +import Rank from './Rank' +import './intercept' +import { FC, useState } from 'react' +import { useAppSelector, useEffectMount } from '@/hooks' +import { selectOptions } from '../global/optionsSlice' +import { awaitFn, problemsetPageIsLoad } from '@/utils' +import { Portal } from '@/components/Portal' +import ProblemList from '../problem-list/ProblemList' +import { withPage } from '@/hoc' +import { useSetProblemListRoot } from '../problem-list/useSetProblemListRoot' + +const App: FC = () => { + const options = useAppSelector(selectOptions) + const [problemListRoot, setProblemListRoot] = useState() + const [isLoad, setIsLoad] = useState(false) + + useEffectMount(async state => { + await awaitFn(() => problemsetPageIsLoad()) + if (state.isMount) setIsLoad(true) + }) + useSetProblemListRoot( + '//*[@id="__next"]/*//div[text()="热门企业题库"]/../../..', + isLoad, + setProblemListRoot + ) + + if (!isLoad) return null + + const showProblemList = !!options?.problemsetPage.problemList + const showRank = !!options?.problemsetPage.problemRating + return ( + <> + + {showProblemList && problemListRoot && ( + + + + )} + + ) +} + +export default withPage('problemsetPage')(App) diff --git a/src/content/pages/problemset/Item.tsx b/src/content/pages/problemset/Item.tsx new file mode 100644 index 0000000..5d428cf --- /dev/null +++ b/src/content/pages/problemset/Item.tsx @@ -0,0 +1,270 @@ +import { + FC, + MouseEventHandler, + useEffect, + useLayoutEffect, + useRef, + useState, +} from 'react' +import { css } from 'styled-components/macro' + +import { useAppSelector, useAppDispatch, useHover } from '@/hooks' +import Button from '@/components/Button' +import { ToolTip } from '@/components/ToolTip' +import { rotate360Deg } from '@/components/animation' + +import { + selectFavoriteById, + checkIsInAudit, + fetchFavoriteDetails, +} from '../problem-list/favoriteSlice' +import { parseParamsToBody } from './utils' +import { LeetCodeApi, ProblemsetQuestion } from '@/utils' +import { selectQuestonsByOption } from './questionsSlice' +import store from '@/app/store' +import ErrorToolTip from '@/components/ErrorToolTip' + +const api = new LeetCodeApi(location.origin) + +interface ItemProps { + idHash: string + current: boolean +} + +const Item: FC = ({ idHash, current }) => { + const favorite = useAppSelector(state => selectFavoriteById(state, idHash)) + const dispatch = useAppDispatch() + const [hoverRef, hover] = useHover() + const [loading, setLoading] = useState(false) + const [error, setError] = useState({ message: '', show: false }) + + const [togglePublicStateError, setTogglePublicStateError] = useState({ + message: '', + show: false, + }) + const [isOverflow, setIsOverflow] = useState(false) + + const nameRef = useRef(null) + useLayoutEffect(() => { + if (nameRef && nameRef.current) { + setIsOverflow(nameRef.current.scrollWidth !== nameRef.current.offsetWidth) + } + }, [hover]) + + useEffect(() => { + if (togglePublicStateError.show) { + setTimeout(() => { + setTogglePublicStateError({ message: '', show: false }) + }, 1000) + } + }, [togglePublicStateError]) + + useLayoutEffect(() => { + // 当较快的关闭和展开题单时,会出现题单列表文字被选中的问题 + // 通过「每次展开时,取消对文字的选中效果」解决这个问题 + ;(window as any).getSelection().removeAllRanges() + }, []) + + useEffect(() => { + let timer: ReturnType | null = null + if (favorite?.isInAudit) { + let time = 1000 + void (async function test() { + try { + await dispatch(checkIsInAudit(idHash)).unwrap() + timer = null + dispatch(fetchFavoriteDetails([idHash])) + } catch (error) { + timer = setTimeout(() => { + time = Math.max(time + 500, 3000) + test() + }, time) + } + })() + } + return () => { + if (timer !== null) clearTimeout(timer) + } + }, [favorite?.isInAudit]) + + useEffect(() => { + if (error.show) { + setTimeout(() => { + setError({ ...error, show: false }) + }, 1000) + } + }, [error]) + + if (!favorite) return null + + const handleAddQuestions = + (idHash: string): MouseEventHandler => + async e => { + e.stopPropagation() + e.preventDefault() + setLoading(true) + try { + const body = parseParamsToBody() + let questions: (ProblemsetQuestion & { questionId?: string })[] + + if (!favorite) { + throw new Error('题单不存在') + } + + const { data } = selectQuestonsByOption(store.getState(), { + ...body, + skip: 0, + limit: Infinity, + }) + questions = data.problemsetQuestionList.questions + + const set = new Set( + favorite?.questionIds?.map(id => id.toString()) ?? [] + ) + // 排除已经在题单中的题目 + questions = questions.filter(q => !set.has(q.questionId ?? '')) + + const state = store.getState(), + ids: string[] = [] + for (const question of questions) { + const q = state.questions.entities[question.frontendQuestionId] + if (q && q.questionId) { + ids.push(q.questionId) + } + } + + if (ids.length + favorite.questionIds!.length > 200) { + throw new Error('🐸☕题单题目超出上限: 200') + } + + await api.addQuestionToFavorite(idHash, ids) + await dispatch(fetchFavoriteDetails([idHash])) + } catch (error: any) { + setError({ message: error.message, show: true }) + } finally { + setLoading(false) + } + } + + const name = favorite.showName ?? favorite.name + + return ( +
  • +
    props.theme.palette.text.light}; + align-items: center; + &:hover { + background-color: ${props => props.theme.palette.secondary.hover}; + } + `} + > + +
    +
    + {favorite.questionIds?.length} +
    +
    +
    +
    props.theme.palette.text.light}; + `} + > + + + {favorite.isInAudit && ( + + 审 + + )} + {name} + + + + + +
    +
    +
  • + ) +} + +export default Item diff --git a/src/content/pages/problemset/Open.tsx b/src/content/pages/problemset/Open.tsx new file mode 100644 index 0000000..a293194 --- /dev/null +++ b/src/content/pages/problemset/Open.tsx @@ -0,0 +1,88 @@ +import { useHover } from '@/hooks' +import { FC } from 'react' +import { css, keyframes } from 'styled-components/macro' + +import SvgIcon from '@/components/SvgIcon' + +export type Pos = { right: number; bottom: number } +interface OpenProps { + onEnable?: () => void + pos?: Pos +} + +const defaultPos = { right: 30, bottom: 151 } + +const makeMove = ({ right, bottom }: Pos) => keyframes` + from { + right: ${right}px; + bottom: ${bottom}px; + } + + to { + right: 30px; + bottom: 151px; + } +` + +const Open: FC = ({ onEnable, pos }) => { + const [ref, hover] = useHover() + + const handleClick = () => { + if (onEnable) onEnable() + } + if (!pos) { + pos = defaultPos + } + const move = makeMove(pos) + + return ( +
    + props.theme.mode === 'dark' ? '#282828' : '#fff'}; + color: ${props => + props.theme.mode === 'dark' ? `#eff1f6bf` : `#262626`}; + box-shadow: ${props => + props.theme.mode === 'dark' + ? css`rgba(0, 0, 0, 0) 0px 0px 0px 0px, + rgba(0, 0, 0, 0) 0px 0px 0px 0px, rgba(0, 0, 0, 0.24) 0px 1px 3px 0px, + rgba(0, 0, 0, 0.16) 0px 2px 8px 0px` + : css`rgba(0, 0, 0, 0) 0px 0px 0px 0px, rgba(0, 0, 0, 0) 0px 0px 0px 0px, rgba(0, 0, 0, 0.04) 0px 1px 3px 0px, rgba(0, 0, 0, 0.08) 0px 2px 8px 0px`}; + `} + onClick={handleClick} + > + {hover ? ( +
    + 打开评分 +
    + ) : ( +
    + + + +
    + )} +
    + ) +} + +export default Open diff --git a/src/content/pages/problemset/Rank.tsx b/src/content/pages/problemset/Rank.tsx new file mode 100644 index 0000000..e87aa72 --- /dev/null +++ b/src/content/pages/problemset/Rank.tsx @@ -0,0 +1,328 @@ +import { FC, useEffect, useMemo, useState } from 'react' +import { css } from 'styled-components/macro' +import { Portal } from '@/components/Portal' +import Popper from '@/components/PopperUnstyled' +import SvgIcon from '@/components/SvgIcon' +import { useAppDispatch, useAppSelector, useHover, useUnMount } from '@/hooks' +import { findElementByXPath, routerTo } from '@/utils' +import { debounce } from 'src/utils' +import { + fetchProblemRankData, + selectCurrentPage, + selectIsSignedIn, +} from '../global/globalSlice' +import { + disableProblemRating, + enableProblemRating, +} from '../global/optionsSlice' + +import RankItem from './RankItem' +import RankTitle from './Title' +import RankRange from './RankRange' +import Open, { Pos } from './Open' +import { fetchAllQuestionIds, fetchAllQuestions } from './questionsSlice' +import { OrderBy, parseParams, SORT_KEY, serializationPrams } from './utils' +import AddQuestion from './AddQuestion' + +/** + * + * 当按照 Rank 排序时,使用 Next.js 的路由,跳转到带自定义排序参数的 url, + * 然后通过拦截请求,返回通过 Rank 排序的数据, + * 但如果请求是除了自定义排序的参数外,其他参数都相同,则 Next.js 会缓存前一次的数据, + * 导致没有拦截请求的机会,这时候可以通过每次传入不同的参数,让 Next.js 每次都重新去请求。 + * + * 但这样会有一个问题,因为我们拦截请求返回的是通过 Rank 排序的数据, + * 如果之后用户不进行取消 Rank 排序,但其他的参数相同时, + * 则因为缓存的关系,依然会返回按照 Rank 排序的数据,导致结果错误。 + * + * 通过测试发现,对于 sorting 的参加,其中包含一个 sortOrder 的属性, + * 如果这个属性赋值为正整数的话,那么会按照 ASCENDING 去处理, + * 但如果赋值不同的正整数,Next.js 每次还会重新去获取数据。 + * + * 利用这个性质,我们每次在 Rank 的参数中,每次将一个递增的正整数赋值给 sortOrder, + * 这样既能让 Next.js 每次重新去获取数据,也不会造成其他排序的错误。 + * + * 这样会有另外一个问题,就是如果之前的 sorking 的参数跟当前参数不同时 + * (比如 orderBy 不同,或是 sortOrder 不为 ASCENDING 或正整数时), + * 则 Next.js 会重定向到对应的参数,这时候可以提前先将 sortOrder 设置为 ASCENDING, + * 然后在跳转到 Rank 排序,就不会进行重定向了。 + * + * 最后如果用户直接在地址栏里面输入一个 Rank 排序的 url,这是因为是第一次访问, + * 则会先被重定向,所以需要进行一些特殊处理。 + * + * 考虑上面的情况,最后采用一个自定义参数,其中包含排序相关,以及 Rank 范围相关的参数, + * 而原先的排序参数则来放累加的 id,防止使用自定义排序时,阻止缓存生效。 + * 而且利用这样一个参数,可以非常方便的区分是否需要拦截请求。 + */ + +const Rank: FC<{ enable: boolean }> = ({ enable }) => { + const width = 90 + const currentPage = useAppSelector(selectCurrentPage) + const [tableEl, setTableEl] = useState() + const titleRow = tableEl?.children[0]?.children[0]?.children[0] as HTMLElement + + const [rankRangeWrap, setRankRangeWrap] = useState( + null + ) + const [rows, setRows] = useState([]) + const dispatch = useAppDispatch() + const [pos, setPos] = useState() + const [bindPopperRef, hoverPopper, popperRef] = useHover(100) + const [bindRanRangeRef, hoverRankRange, rankRangeRef] = useHover(100) + const isSignedIn = useAppSelector(selectIsSignedIn) + const mountState = useUnMount() + + const handleDisable = () => { + const { right, bottom } = popperRef.current!.getBoundingClientRect() + setPos({ + right: window.innerWidth - right, + bottom: window.innerHeight - bottom, + }) + dispatch(disableProblemRating(currentPage!)) + setTimeout(() => { + // 清理自定义相关的参数 + const params = parseParams() + if (params.custom) { + delete params.sorting + // 如果之前是其他排序,那么需要保留这个排序选项 + if (params.custom.sort && params.custom.sort.orderBy !== 'RANKING') { + params.sorting = [params.custom.sort] + } + delete params.custom + } + const url = location.pathname + '?' + serializationPrams(params) + routerTo(url) + }, 500) + } + const handleEnable = () => { + dispatch(enableProblemRating(currentPage!)) + } + async function handleSetTableEl() { + const tableEl = await findElementByXPath( + { + xpath: '//div[@role="table"]', + nodeType: 'UNORDERED_NODE_ITERATOR_TYPE', + }, + els => !!els.filter(el => el.childElementCount > 0) + ) + if (!mountState.isMount) return + setTableEl(tableEl.find(el => el.childElementCount > 0)) + } + + useEffect(() => { + handleSetTableEl() + }, []) + useEffect(() => { + if (currentPage !== 'problemListPage') return + // 当 url 发生变化的时候,重新去获取 tableEl + // 主要针对的场景是「不存在的题单」 + // 如果是打开一个「不存在的题单」,那么就不会显示题目区域,也就没有 tableEl + // 而从一个「不存在的题单」跳转到一个存在的题单时,会重新加载题目区域 + // 这时候需要重新去获取 tableEl + window.addEventListener('urlchange', handleSetTableEl) + return () => { + window.removeEventListener('urlchange', handleSetTableEl) + } + }, [currentPage]) + + useEffect(() => { + if (!tableEl || currentPage !== 'problemListPage') return + // 当 tableEl 被删除时,这时候应该将 tableEl 设置为空。 + const observer = new MutationObserver(mutationList => { + for (const mutation of mutationList) { + if (mutation.type === 'childList') { + for (const node of mutation.removedNodes) { + if (node === tableEl) { + setTableEl(undefined) + observer.disconnect() + return + } + } + } + } + }) + + observer.observe(document.body, { childList: true, subtree: true }) + + return () => { + observer.disconnect() + } + }, [tableEl, currentPage]) + + useEffect(() => { + // 管理原来的排序按钮 + if (enable) { + void (async function () { + // root.style.display = 'block' + dispatch(fetchProblemRankData()) + const res = await dispatch(fetchAllQuestions()) + if (res) { + // 如果返回值为空,则说明当前没有更新新的题目,也就没有必要去更新 id 了 + dispatch(fetchAllQuestionIds()) + } + })() + } else { + // root.style.display = 'none' + } + }, [enable]) + + useEffect(() => { + // 获取当前所有行,用以在行中去渲染题目对应的评分。 + + // 最后一页有可能题目比较少,则渲染的行会变少, + // 当跳转到其他页时,则题目变多,会重新渲染多出来的行, + // 这时候就需要重新获取所有行。另外改变每页的条数是也会发生这种情况。 + if (enable && tableEl) { + const rowgroup = tableEl.children[0]?.children[1] + if (!rowgroup || !(rowgroup instanceof HTMLDivElement)) return + const handleRowChange = debounce(() => { + const rows: HTMLDivElement[] = [] + ;[...(rowgroup.children ?? [])].forEach( + el => el instanceof HTMLDivElement && rows.push(el) + ) + setRows(rows) + }, 500) + handleRowChange() + const observer = new MutationObserver(handleRowChange) + observer.observe(rowgroup, { childList: true }) + return () => observer.disconnect() + } else { + setRows([]) + } + }, [enable, tableEl?.children]) + + useEffect(() => { + // 添加「题目评分范围筛选组件」的根结点 + if (enable && tableEl) { + const div = document.createElement('div') + div.setAttribute( + 'style', + `display: flex; + justify-content: end;` + ) + tableEl.parentElement?.before(div) + setRankRangeWrap(div) + return () => { + setRankRangeWrap(null) + } + } else { + setRankRangeWrap(null) + } + }, [enable, tableEl?.parentElement]) + + const otherRoots = useMemo(() => { + if (!enable) return {} + // 获取其他排序选项的结点,用以控制排序 + const otherRoots: { [key in OrderBy]?: HTMLElement } = {} + if (titleRow) { + const children = [...titleRow.children].filter( + el => + el && el.textContent && !new Set(['状态', '企业']).has(el.textContent) + ) + for (let i = 0; i < SORT_KEY.length; i++) { + const child = children[i] + if (child instanceof HTMLElement) { + child.style.padding = '0' + otherRoots[SORT_KEY[i].key] = child + } + } + } + return otherRoots + }, [enable, titleRow]) + if (!tableEl) return null + return ( + <> + {enable && titleRow && ( + <> + +
    + +
    +
    + + )} + {enable && rankRangeWrap && ( + +
    + props.theme.mode === 'dark' ? '#303030' : '#f7f8fa'}; + color: ${props => + props.theme.mode === 'dark' ? '#eff1f6bf' : '#262626bf'}; + border-radius: 6px; + border-bottom-right-radius: 0; + `} + > + {isSignedIn && } + +
    +
    + )} + {(hoverRankRange || hoverPopper) && ( + +
    + props.theme.mode === 'dark' ? '#303030' : '#f7f8fa'}; + + height: 56px; + display: flex; + align-items: center; + padding: 10px 10px 10px 16px; + margin-left: -6px; + margin-top: 0px; + cursor: pointer; + border-top-right-radius: 6px; + border-bottom-right-radius: 6px; + `} + onClick={handleDisable} + > + + + +
    +
    + )} + {enable && + rows.map((row, i) => ( + +
    + +
    +
    + ))} + {!enable && ( + + + + )} + + ) +} + +export default Rank diff --git a/src/content/pages/problemset/RankItem.tsx b/src/content/pages/problemset/RankItem.tsx new file mode 100644 index 0000000..5cdf4df --- /dev/null +++ b/src/content/pages/problemset/RankItem.tsx @@ -0,0 +1,95 @@ +import { FC, useEffect, useState } from 'react' + +import { useAppSelector } from '@/hooks' + +import { selectProblemRankDataByTitleSlug } from '../global/globalSlice' +import { css } from 'styled-components/macro' + +interface RankProps { + row: HTMLElement +} + +const color = (rating: number, themeMode: 'dark' | 'light') => { + let res: { dark: string; light: string } + if (rating < 1200) { + // Newbie + res = { dark: '#808080', light: '#808080' } + } else if (rating < 1400) { + // Pupil + res = { dark: '#008000', light: '#008000' } + } else if (rating < 1600) { + // Specialist + res = { dark: '#03a89e', light: '#03a89e' } + } else if (rating < 1900) { + // Expert + res = { dark: '#008ed3', light: '#00f' } + } else if (rating < 2100) { + // Candidate Master + res = { dark: '#a0a', light: '#a0a' } + } else if (rating < 2300) { + // Master + res = { dark: '#dbaf75', light: '#dbaf75' } + } else if (rating < 2400) { + // International Master + res = { dark: '#dba049', light: '#dba049' } + } else if (rating < 2600) { + // Grandmaster + res = { dark: '#db6666', light: '#db6666' } + // } else if (rating < 3000) { + // // International Grandmaster + // return '#FF0000' + } else { + // Legendary Grandmaster + res = { dark: '#c70000', light: '#FF0000' } + } + return res[themeMode] +} + +const RankItem: FC = ({ row }) => { + const getTitleSlug = () => + row.children[1] + ?.querySelector('a') + ?.pathname.split('/') + .filter(Boolean)[1] ?? '' + const [titleSlug, setTitleSlug] = useState(getTitleSlug()) + const rank = useAppSelector(state => + selectProblemRankDataByTitleSlug(state, titleSlug) + ) + + useEffect(() => { + const observer = new MutationObserver(() => { + const titleSlug = getTitleSlug() + if (titleSlug) { + setTitleSlug(titleSlug) + } + }) + observer.observe(row.children[1], { childList: true }) + return () => { + observer.disconnect() + } + }, []) + + if (!rank) return null + + return ( +
    color(rank.Rating, props.theme.mode)}; + font-weight: bold; + text-align: center; + ${rank.Rating >= 3000 + ? css` + &::first-letter { + color: ${props => + props.theme.mode === 'dark' ? '#fff' : '#000'}; + } + ` + : ''} + `} + > + {rank?.Rating.toFixed(0) ?? ''} +
    + ) +} + +export default RankItem diff --git a/src/content/pages/problemset/RankRange.tsx b/src/content/pages/problemset/RankRange.tsx new file mode 100644 index 0000000..d14ab27 --- /dev/null +++ b/src/content/pages/problemset/RankRange.tsx @@ -0,0 +1,122 @@ +import { + ChangeEventHandler, + Dispatch, + FC, + KeyboardEventHandler, + SetStateAction, + useState, +} from 'react' + +import { css } from 'styled-components/macro' +import { Input } from '@/components/Input' +import Button from '@/components/Button' + +import { + getId, + parseParams, + serializationPrams, + ParamType, + once, +} from './utils' +import { routerTo } from '@/utils' +import { ToolTip } from '@/components/ToolTip' +import CrownIcon from '@/components/icons/CrownIcon' +import { Box } from './AddQuestion' + +const StyledInput: FC<{ + value: string + setValue: Dispatch> + onKeyDown?: KeyboardEventHandler +}> = ({ value, setValue, onKeyDown }) => { + const handleChange: ChangeEventHandler = e => { + setValue(e.target.value) + } + return ( + + ) +} + +const RankRange: FC = () => { + const params: ParamType = parseParams() + const [min, setMin] = useState(params.custom?.min ?? '') + const [max, setMax] = useState(params.custom?.max ?? '') + const [includePremium, setIncludePremium] = useState( + params.custom?.includePremium ?? true + ) + + const handleApply = async (includePremium: boolean) => { + const params: ParamType = parseParams() + + let id = getId(true) + if ( + params.sorting?.[0].orderBy !== 'FRONTEND_ID' || + params.sorting?.[0].sortOrder === 'DESCENDING' + ) { + routerTo( + location.pathname + + '?' + + serializationPrams({ + ...params, + sorting: [{ orderBy: 'FRONTEND_ID', sortOrder: id }], + custom: undefined, + }) + ) + + // 第一次是等待上面的跳转 + await once('routeChangeComplete') + // 第二次是因为上面 sortOrder 使用 id,力扣会重新跳转到 sortOrder 为 ‘ASCENDING’ 的页面 + await once('routeChangeComplete') + } + id = getId(true) + params.sorting = [{ orderBy: 'FRONTEND_ID', sortOrder: id }] + params.custom = { ...params.custom, min, max, includePremium } + const url = location.pathname + '?' + serializationPrams(params) + routerTo(url) + } + const handleEnter: KeyboardEventHandler = e => { + if (e.code === 'Enter') handleApply(includePremium) + } + const handleChangeIncludePremium = () => { + setIncludePremium(!includePremium) + handleApply(!includePremium) + } + return ( + <> + + + + + + 难度范围: + - + + + + ) +} + +export default RankRange diff --git a/src/content/pages/problemset/Title.tsx b/src/content/pages/problemset/Title.tsx new file mode 100644 index 0000000..ae3d74b --- /dev/null +++ b/src/content/pages/problemset/Title.tsx @@ -0,0 +1,205 @@ +import { FC, useEffect, useState } from 'react' +import { css } from 'styled-components/macro' + +import { useAppSelector, useEffectMount } from '@/hooks' + +import { + OrderBy, + ParamType, + parseParams, + serializationPrams, + getId, + once, + SORT_KEY, +} from './utils' +import TitleBase from './TitleBase' +import { Portal } from '@/components/Portal' +import { routerTo } from '@/utils' +import { selectCurrentPage, selectIsPremium } from '../global/globalSlice' + +interface RankTitleProps { + otherRoots: { [key in OrderBy]?: HTMLElement } +} + +const RankTitle: FC = ({ otherRoots }) => { + const [params, setParams] = useState(parseParams()) + const isPremium = useAppSelector(selectIsPremium) + const currentPage = useAppSelector(selectCurrentPage) + + useEffect(() => { + SORT_KEY.forEach(({ key }) => { + const child = otherRoots[key]?.children[0] + if (child && child instanceof HTMLElement) { + child.style.display = 'none' + } + }) + return () => { + SORT_KEY.forEach(({ key }) => { + const child = otherRoots[key]?.children[0] + if (child && child instanceof HTMLElement) { + child.style.display = 'flex' + child.style.padding = '11px 0' + } + }) + } + }, []) + + useEffectMount(async state => { + // 如果第一次访问的 url 中,包含 customSort,则需要进行特殊的处理。 + if (params.custom) { + /** + * 在题库页中,如果包含 custom,那么一定是包含 id 的 sroting, + * 则一定会重定向到 sroting 等于 `ASCENDING`, + * 需要等待重定向完成后,再通过路由跳转到到包含自定义参数的 url + * + * 而在题单页中,则不会进行重定向,就不用去等待 + */ + if (currentPage === 'problemsetPage') { + await once('routeChangeComplete') + } + if (state.isMount) { + handleCustomSort()() + } + } + }, []) + + const handleCustomSort = (key?: OrderBy, isSwitch?: boolean) => async () => { + if (!key) key = 'FRONTEND_ID' + const tmp: ParamType = { ...params } + + /** 判断当前 url 中的 sortOrder 是否为 ASCENDING,或者等于 id.current + * + * 如果不是的话,直接跳转会被导航到包含 {sortOrder,orderBy} 的 url, + * 而这样对这个 url 返回结果的话,会被缓存,而之后如果取消自定义排序, + * 而进行对应的 {sortOrder,orderBy} 去排序时,则会使用这次缓存的结果, + * 导致数据错误,所以这种情况下,需要先跳转到 sortOrder=‘ASCENDING’ 的 url, + * 然后在跳转到自定排序的 url,其中将 sortOrder 设置为 id.current, + * 因为保证 id.current 都为正数,在官方的代码中会被判定为 ‘ASCENDING’, + * 但因为 id.current 每次会递增,所以每次我们跳转时,都会重新去获取新的结果, + * 而不会被缓存。 + */ + + let id = getId(true) + if ( + tmp.sorting?.[0].orderBy !== 'FRONTEND_ID' || + tmp.sorting?.[0].sortOrder === 'DESCENDING' + ) { + routerTo( + location.pathname + + '?' + + serializationPrams({ + ...params, + sorting: [{ orderBy: 'FRONTEND_ID', sortOrder: id }], + custom: undefined, + }) + ) + + // 第一次是等待上面的跳转 + await once('routeChangeComplete') + // 第二次是因为上面 sortOrder 使用 id,力扣会重新跳转到 sortOrder 为 ‘ASCENDING’ 的页面 + await once('routeChangeComplete') + } + + id = getId(true) + tmp.sorting = [{ orderBy: 'FRONTEND_ID', sortOrder: id }] + + /** 判断是页面第一次加载,还是点击排序按钮进行切换 + * + * 如果是进行切换,并且将自定义排序的参数设置为下一项, + * 如果是页面第一次加载,则只需要将 id 修改一致即可 + */ + + if (isSwitch) { + if (!tmp.custom?.sort || key !== tmp.custom.sort.orderBy) { + tmp.custom = { + ...tmp.custom, + sort: { sortOrder: 'DESCENDING', orderBy: key }, + } + } else if (tmp.custom?.sort?.sortOrder === 'DESCENDING') { + tmp.custom = { + ...tmp.custom, + sort: { sortOrder: 'ASCENDING', orderBy: key }, + } + } else { + delete tmp.custom.sort + } + } + + const url = location.pathname + '?' + serializationPrams(tmp) + routerTo(url) + } + + useEffect(() => { + // 每次 url 地址发生变化的时候,重新解析参数 + const handleUrlchange = () => setParams(parseParams()) + window.addEventListener('urlchange', handleUrlchange) + return () => { + window.removeEventListener('urlchange', handleUrlchange) + } + }, []) + + return ( + <> + {SORT_KEY.map(({ key, title }) => { + let orderBy = params.sorting?.[0].orderBy, + sortOrder = params.sorting?.[0].sortOrder + if (params.custom) { + orderBy = params.custom?.sort?.orderBy + sortOrder = params.custom?.sort?.sortOrder + } + return ( + + + + ) + })} + +
    + props.theme.mode === 'dark' ? '#303030' : '#f7f8fa'}; + `} + > + + 题目评分数据来自 + + zerotrac/leetcode_problem_rating + +
    + } + /> +
    + + ) +} + +export default RankTitle diff --git a/src/content/pages/problemset/TitleBase.tsx b/src/content/pages/problemset/TitleBase.tsx new file mode 100644 index 0000000..b6d02c8 --- /dev/null +++ b/src/content/pages/problemset/TitleBase.tsx @@ -0,0 +1,150 @@ +import { MouseEventHandler, ReactElement, forwardRef } from 'react' +import { css } from 'styled-components/macro' + +import { ToolTip } from '@/components/ToolTip' + +interface TitleProps { + title: string + help?: ReactElement | string + showHelpIcon?: boolean + isSort?: boolean + sortOrder?: string | number + onSort?: (...args: any) => void +} + +const TitleBase = forwardRef(function TitleBase( + { title, help, isSort, sortOrder, onSort, showHelpIcon }, + ref +) { + const handleClick: MouseEventHandler = e => { + if (e.currentTarget.contains(e.target as any)) { + e.nativeEvent.stopImmediatePropagation() + if (onSort && typeof onSort === 'function') { + onSort() + } + } + } + return ( +
    span, + &:hover > div { + color: ${props => + props.theme.mode === 'dark' ? '#b3b3b3' : '#595959'}; + } + `} + onClick={handleClick} + > + + props.theme.mode === 'dark' + ? css` + && { + background: #e9e9e9; + color: #1a1a1a; + font-weight: bold; + } + &&::before { + border-bottom-color: #e9e9e9; + } + ` + : css` + && { + background: #2a2a2a; + color: #fff; + font-weight: bold; + } + &&::before { + border-bottom-color: #2a2a2a; + } + `} + `} + title={help ?? ''} + offset={{ top: 2 }} + > +
    + props.theme.mode === 'dark' ? '#eff2f699' : '#3c3c4399'}; + `} + > + + props.theme.mode === 'dark' ? '#eff2f699' : '#3c3c4399'}; + `} + > + {title} + + {showHelpIcon && ( + + + + )} +
    +
    + {!!onSort && ( +
    + props.theme.mode === 'dark' ? '#5c5c5c' : '#bfbfbf'}; + `} + > + {!isSort ? ( + + + + ) : ( + + {sortOrder === 'DESCENDING' ? ( + + ) : ( + + )} + + )} +
    + )} +
    + ) +}) +export default TitleBase diff --git a/src/content/pages/problemset/intercept.tsx b/src/content/pages/problemset/intercept.tsx new file mode 100644 index 0000000..e798a20 --- /dev/null +++ b/src/content/pages/problemset/intercept.tsx @@ -0,0 +1,170 @@ +import store from '@/app/store' +import { awaitFn } from '@/utils' +import { fetchFavoriteDetails } from '../problem-list/favoriteSlice' + +import { selectQuestonsByOption } from './questionsSlice' +import { parseParams } from './utils' + +// 拦截请求相关 + +const originalOpen = XMLHttpRequest.prototype.open + +export function intercept(): void { + XMLHttpRequest.prototype.open = function newOpen( + this: XMLHttpRequest, + method: string, + url: string, + async?: boolean, + user?: string, + password?: string, + disbaleIntercept?: boolean + ) { + let pathname = url + try { + const urlObj = new URL(url) + pathname = urlObj.pathname + } catch (error) { + // + } + if ( + !disbaleIntercept && + method.toLocaleLowerCase() === 'post' && + pathname === `/graphql/` + ) { + const originalSend = this.send + + this.send = async str => { + const state = store.getState() + const { options } = state.options, + { currentPage } = state.global + // 只有在启用对应功能的时候,才去拦截相关请求 + if ( + (currentPage === 'problemsetPage' && + options?.problemsetPage.problemRating) || + (currentPage === 'problemListPage' && + options?.problemListPage.problemRating) + ) { + try { + if (typeof str === 'string') { + const body = JSON.parse(str) + if ( + body.query && + body.query.includes('query problemsetQuestionList') + ) { + const sortOrder = body.variables.filters?.sortOrder + + const params = parseParams() + + if (params.custom) { + const listId = body.variables.filters?.listId + // 如果参数中包含某个题单,当前有没有这个题单的数据,则需要去请求这个题单的数据 + // 一般是在浏览第三方题单的时候 + if (listId && !store.getState().favorites.entities[listId]) { + store.dispatch(fetchFavoriteDetails([listId])) + } + // 如果当前页面处于自定义参数之下,则使用在本地缓存的数据进行操作 + for (const key of ['response', 'responseText']) { + Object.defineProperty(this, key, { + get: () => { + const state = store.getState() + if (!body.variables.filters) body.variables.filters = {} + body.variables.filters = { + ...body.variables.filters, + custom: params.custom, + } + const data = selectQuestonsByOption( + state, + body.variables + ) + return JSON.stringify(data) + }, + configurable: true, + }) + } + + for (const key of ['onreadystatechange', 'onload'] as const) { + const fn = this[key] + this[key] = async (...args) => { + if (key === 'onload') { + // 等待所需数据都加载完成 + // TODO: 尝试设计一个更优雅的实现 + await awaitFn(() => { + const state = store.getState() + if (!state.questions.ids.length) return false + if ( + listId && + !state.favorites.entities[listId]?.questionIds + ) + return false + if ( + !Reflect.ownKeys(state.global.ProblemRankData) + .length + ) + return false + return true + }, 20000) + } + fn?.apply(this, args as any) + } + } + } + + if ( + sortOrder && + sortOrder !== 'DESCENDING' && + sortOrder !== 'ASCENDING' + ) { + body.variables.filters.sortOrder = 'ASCENDING' + str = JSON.stringify(body) + } + } + } + } catch (error) { + // + } + } else if (typeof str === 'string') { + try { + const body = JSON.parse(str) + const sortOrder = body?.variables?.filters?.sortOrder + if ( + sortOrder && + sortOrder !== 'DESCENDING' && + sortOrder !== 'ASCENDING' + ) { + body.variables.filters.sortOrder = 'DESCENDING' + str = JSON.stringify(body) + } + } catch (error) { + // + } + } + return originalSend.call(this, str) + } + } + originalOpen.apply(this, [method, url, async!, user, password]) + } +} + +export function restore(): void { + XMLHttpRequest.prototype.open = originalOpen +} + +intercept() + +if ((window as any).next) { + // 监听 Next.js 路由事件 + const routerEventNames = [ + 'routeChangeStart', + 'routeChangeComplete', + 'beforeHistoryChange', + ] + + // 转发 next 路由事件 + const { router } = (window as any).next + for (const event of routerEventNames) { + const handle = (...args: any) => { + window.dispatchEvent(new CustomEvent(event, { detail: args })) + } + router.events.on(event, handle) + } +} diff --git a/src/content/pages/problemset/questionsSlice.ts b/src/content/pages/problemset/questionsSlice.ts new file mode 100644 index 0000000..c7f8c74 --- /dev/null +++ b/src/content/pages/problemset/questionsSlice.ts @@ -0,0 +1,285 @@ +import { + createSlice, + createAsyncThunk, + createEntityAdapter, + EntityId, +} from '@reduxjs/toolkit' +import { differenceInHours } from 'date-fns/fp' + +import { RootState } from '@/app/store' +import { + CategorySlugType, + LeetCodeApi, + ProblemsetQuestion, + ProblemsetQuestionList, + ProblemsetQuestionListFilterType, + QuestionStatus, + QuestionType, + userProfileQuestion, +} from '@/utils' + +import { selectFavoriteById } from '../problem-list/favoriteSlice' +import { CustomFilter } from './utils' + +const api = new LeetCodeApi(location.origin) + +const questionsAdapter = createEntityAdapter< + ProblemsetQuestion & { questionId?: string } +>({ + selectId: question => question.frontendQuestionId, +}) + +export const fetchAllQuestions = createAsyncThunk< + Map | null, + undefined, + { state: RootState } +>('questions/fetchAllQuestions', async (_, { getState, dispatch }) => { + const questions = getState().questions + const date = new Date(questions.update) + const dif = differenceInHours(date)(new Date()) + let total: number | undefined = undefined + + if (dif < 24) { + total = (await api.getProblemsetQuestionList({ skip: 0, limit: 1 })).total + // 如果上次更新时间不超过一天,并且题目总数没有变化时,则不用去更新全部内容, + // 只需要更新一些最新的变化既可以,比如在上次更新时间之后的成功提交,会造成 status 的变化 + // 另外如果原本没有会员,新开了会员之后,是可以获取到 freqBar [出现频率] 这个信息的, + // 这时候就需要重新去获取一下。 + if (total === questions.total) { + // 更新最近提交的题目状态 + await dispatch(fetchLastACQuestions({ last: date, status: 'ACCEPTED' })) + await dispatch(fetchLastACQuestions({ last: date, status: 'FAILED' })) + return null + } + } + + return api.getAllQuestion() +}) + +export const fetchLastACQuestions = createAsyncThunk< + userProfileQuestion[], + { last: Date; status: QuestionStatus }, + { state: RootState } +>('questions/fetchLastACQuestions', async ({ last, status }) => + api.queryACQuestions(last, status) +) + +export const fetchAllQuestionIds = createAsyncThunk< + QuestionType[], + undefined, + { state: RootState } +>('questions/fetchAllQuestionIds', async () => api.getAllQuestions()) + +const initData = { + total: 0, + update: 0, +} as { + total: number + update: number +} & { [key in CategorySlugType]: string[] } + +const initialState = questionsAdapter.getInitialState(initData) + +const questionsSlice = createSlice({ + name: 'posts', + initialState, + reducers: {}, + extraReducers(builder) { + builder + .addCase(fetchAllQuestions.fulfilled, (state, action) => { + const map = action.payload + if (map) { + const allQuestions = map.get('all-code-essentials')! + questionsAdapter.upsertMany(state, allQuestions) + state.total = allQuestions.length + state.update = new Date().valueOf() + for (const [category, questions] of map) { + if (category === 'all-code-essentials') continue + state[category] = questions.map(q => q.frontendQuestionId) + } + } + }) + .addCase(fetchAllQuestionIds.fulfilled, (state, action) => { + for (const q of action.payload) { + const question = state.entities[q.questionFrontendId] + question && (question.questionId = q.questionId) + } + }) + .addCase(fetchLastACQuestions.fulfilled, (state, action) => { + for (const q of action.payload) { + const question = state.entities[q.frontendId] + if (!question) continue + if (action.meta.arg.status === 'ACCEPTED') { + question.status = 'AC' + } else if (action.meta.arg.status === 'FAILED') { + question.status = 'TRIED' + } + } + }) + }, +}) + +export const { + selectAll: selectAllQuestions, + selectById: selectQuestionById, + selectIds: selectQuestionIds, +} = questionsAdapter.getSelectors(state => state.questions) + +export type Option = { + categorySlug?: CategorySlugType + skip?: number + limit?: number + filters?: ProblemsetQuestionListFilterType & { custom?: CustomFilter } +} +export const selectQuestonsByOption = ( + state: RootState, + option: Option +): { data: { problemsetQuestionList: ProblemsetQuestionList } } => { + let res: ProblemsetQuestion[] = [] + const { questions } = state + let ids = questions.ids + if (option?.filters?.listId) { + const map = new Map() + for (const id of questions.ids) { + // allQuestions 这个 API 无法获取最新的一个会员题,遇到这种情况直接跳过 + if (!questions.entities[id]!.questionId) continue + + map.set(questions.entities[id]!.questionId!, questions.entities[id]!) + } + const list = selectFavoriteById(state, option.filters!.listId!) + if (!list) + return { + data: { + problemsetQuestionList: { + __typename: 'QuestionListNode', + questions: [], + hasMore: false, + total: 0, + }, + }, + } + + ids = + (list.questionIds + ?.map((id: number) => map.get(id.toString())?.frontendQuestionId) + .filter(Boolean) as EntityId[]) ?? [] + } + + if (option.categorySlug && option.categorySlug !== 'all-code-essentials') { + const set = new Set(questions[option.categorySlug]) + for (const id of ids) { + const question = questions.entities[id] + if (!question || !set.has(question.frontendQuestionId)) continue + res.push(question) + } + } else { + res = ids.map(id => questions.entities[id]!) + } + + if (option.filters) { + const { difficulty, status, tags, premiumOnly, custom } = option.filters + const ratingFilter = custom && (custom.min || custom.max) + + const min = Number(custom?.min ? custom.min : 0), + max = Number(custom?.max ? custom.max : Infinity) + const rankData = state.global.ProblemRankData + res = res.filter(a => { + // 难度 + if (difficulty && a.difficulty !== difficulty) return false + // 状态 + if (status && a.status !== status) return false + // 只包含会员题 + if (premiumOnly && !a.paidOnly) return false + // 不包含会员题 + if (custom?.includePremium === false && a.paidOnly) return false + // 标签 + if (tags) { + const set = new Set(a.topicTags.map(b => b.slug)) + if (tags.some(tag => !set.has(tag))) return false + } + // 题目评分 + if (ratingFilter) { + if (!rankData[a.titleSlug]) return false + const rating = rankData[a.titleSlug]?.Rating + if (rating < min || rating > max) return false + } + return true + }) + + if (custom && custom.sort) { + const { sortOrder, orderBy } = custom.sort + const defalutValue = sortOrder === 'DESCENDING' ? 0 : Infinity + const getValue = (q: ProblemsetQuestion): number => { + switch (orderBy) { + case 'SOLUTION_NUM': + return q.solutionNum + case 'AC_RATE': + return q.acRate + case 'DIFFICULTY': + return q.difficulty === 'EASY' + ? 0 + : q.difficulty === 'MEDIUM' + ? 1 + : 2 + case 'FREQUENCY': + return q.freqBar + case 'RANKING': + return rankData[q.titleSlug]?.Rating ?? defalutValue + } + return 0 + } + const compareId = (a: ProblemsetQuestion, b: ProblemsetQuestion) => { + const x = Number(a.frontendQuestionId), + y = Number(b.frontendQuestionId) + if (isNaN(x)) { + if (isNaN(y)) { + return a.frontendQuestionId > b.frontendQuestionId ? 1 : -1 + } + return 1 + } else { + if (isNaN(y)) { + return -1 + } + return x - y + } + } + if (sortOrder === 'DESCENDING') { + res.sort((a, b) => { + if (orderBy === 'FRONTEND_ID') return compareId(b, a) + + const x = getValue(a), + y = getValue(b) + if (x === y) { + return compareId(a, b) + } + return y - x + }) + } else { + res.sort((a, b) => { + if (orderBy === 'FRONTEND_ID') return compareId(a, b) + + const x = getValue(a), + y = getValue(b) + if (x === y) { + return compareId(a, b) + } + return x - y + }) + } + } + } + const start = option.skip ?? 0, + end = start + (option.limit ?? 50) + return { + data: { + problemsetQuestionList: { + __typename: 'QuestionListNode', + questions: res.slice(start, end), + hasMore: end < res.length, + total: res.length, + }, + }, + } +} + +export default questionsSlice.reducer diff --git a/src/content/pages/problemset/utils.ts b/src/content/pages/problemset/utils.ts new file mode 100644 index 0000000..3862fb8 --- /dev/null +++ b/src/content/pages/problemset/utils.ts @@ -0,0 +1,163 @@ +import { CategorySlugType, ProblemsetQuestionListFilterType } from '@/utils' +import { Option } from './questionsSlice' + +export type OrderBy = + | 'FRONTEND_ID' + | 'SOLUTION_NUM' + | 'AC_RATE' + | 'DIFFICULTY' + | 'FREQUENCY' + | 'RANKING' + +export const SORT_KEY: { key: OrderBy; title: string }[] = [ + { key: 'FRONTEND_ID', title: '题目' }, + { key: 'SOLUTION_NUM', title: '题解' }, + { key: 'AC_RATE', title: '通过率' }, + { key: 'DIFFICULTY', title: '难度' }, + { key: 'FREQUENCY', title: '出现频率' }, +] + +export type CustomFilter = { + sort?: { sortOrder: 'DESCENDING' | 'ASCENDING'; orderBy: OrderBy } + min?: string // 评分最小值 + max?: string // 评分最大值 + includePremium?: boolean // 是否包含会员题,默认包含会员题 +} +export interface ParamType { + sorting?: [ + { + sortOrder: 'DESCENDING' | 'ASCENDING' | number + orderBy: OrderBy + } + ] // 排序字段 + topicSlugs?: string[] // 标签 + page?: number // 当前页数 + status?: 'NOT_STARTED' | 'AC' | 'TRIED' // 状态: + difficulty?: 'EASY' | 'MEDIUM' | 'HARD' // 难度 + listId?: string // 题单 + custom?: CustomFilter // 自定义参数 +} + +const map = { + sorting: (s: string) => JSON.parse(window.atob(s)), + topicSlugs: (s: string) => s.split(','), + page: (s: string) => Number(s), + status: (s: string) => s, + difficulty: (s: string) => s, + listId: (s: string) => s, + custom: (s: string) => JSON.parse(window.atob(s)), + search: (s: string) => s, +} + +/** 解析 url 参数 + * + */ +export function parseParams(): ParamType { + const search = new URLSearchParams(location.search) + const params: ParamType = {} + for (const arr of search) { + const [key, value] = arr as [keyof ParamType, string] + if (map[key]) params[key] = map[key](value) as any + } + return params +} + +export function parseParamsToBody(): Option { + const search = new URLSearchParams(location.search) + const body: Option = { categorySlug: '', filters: {} } + const paths = location.pathname.split('/').filter(Boolean) + if (paths[0] === 'problemset' && paths[1] !== 'all') { + body.categorySlug = paths[1] as CategorySlugType + } else if (paths[0] === 'problem-list') { + body.filters!.listId = paths[1] + } + if (search.has('page')) { + const page = Number(search.get('page')) + if (!isNaN(page)) { + const itemsPerPage = Number( + localStorage.getItem('problem-list:itemsPerPage') ?? '50' + ) + body.limit = itemsPerPage + body.skip = itemsPerPage * (page - 1) + } + } + if (body.filters) { + if (search.has('custom')) { + body.filters.custom = map.custom(search.get('custom')!) + } else if (search.has('sorting')) { + const [{ orderBy, sortOrder }] = map.sorting(search.get('sorting')!) + if (orderBy) { + body.filters = { ...body.filters, orderBy, sortOrder } + } + } + if (search.has('search')) { + body.filters.searchKeywords = search.get('search')! + } + if (search.has('topicSlugs')) { + body.filters.tags = search.get('topicSlugs')!.split(',') + } + type KeyType = keyof ProblemsetQuestionListFilterType + for (const key of ['listId', 'difficulty', 'status'] as KeyType[]) { + if (search.has(key)) body.filters[key] = search.get(key)! as any + } + } + + return body +} + +/** 将参数序列化为字符串 + * + */ +export function serializationPrams(params: ParamType): string { + const search = new URLSearchParams() + for (const key of Object.keys(params).sort() as (keyof ParamType)[]) { + if (!params[key]) continue + if (key === 'sorting' || key === 'custom') { + search.append( + key, + window.btoa( + JSON.stringify(params[key], [ + 'sortOrder', + 'orderBy', + 'id', + 'sort', + 'min', + 'max', + 'includePremium', + ]) + ) + ) + } else { + search.append(key, params[key]!.toString()) + } + } + return search.toString() +} + +const idKey = 'refined-leetcode-sorting-id' + +/** 获取 Id + * + * @param add 是否需要自增 + * @returns + */ +export function getId(add = false): number { + let text = localStorage.getItem(idKey) + if (!text) text = '1' + let res = Number(text) + if (isNaN(res)) { + res = 1 + localStorage.setItem(idKey, '1') + } else if (add) { + res++ + if (res > 1000) res = 1 + localStorage.setItem(idKey, res.toString()) + } + return res +} + +export function once(name: string): Promise { + return new Promise(r => { + window.addEventListener(name, r, { once: true }) + }) +} diff --git a/src/content/pages/ranking/App.tsx b/src/content/pages/ranking/App.tsx new file mode 100644 index 0000000..bad8970 --- /dev/null +++ b/src/content/pages/ranking/App.tsx @@ -0,0 +1,253 @@ +import { FC, useEffect, useState } from 'react' + +import { withPage } from '@/hoc' +import { useAppDispatch, useAppSelector, useEffectMount } from '@/hooks' + +import { selectOptions } from '../global/optionsSlice' +import { Portal } from '@/components/Portal' +import { findElement, findAllElement, isBetaUI } from '@/utils' +import Predict from './Predict' +import { useUrlChange } from './Item' +import Title from './Title' +import { LanguageIconRow } from './LanguageIcon' +import { debounce } from 'src/utils' +import { + fetchContestRanking, + fetchContestInfo, + selectContestInfo, + fetchMyRank, + selectPreviousRatingUpdateTime, +} from './rankSlice' +import { RealTimePredict } from './RealTimePredict' +import { User } from './utils' +import { format } from 'date-fns' +import { css } from 'styled-components/macro' +import { BetaApp } from './BetaApp' + +const App = () => { + const [beta, setBeta] = useState() + + useEffectMount(async state => { + const beta = await isBetaUI() + if (!state.isMount) return + setBeta(beta) + }, []) + if (beta === undefined) return null + if (beta) { + return + } + return +} +const LegacyApp: FC = () => { + const options = useAppSelector(selectOptions) + const [titleRoot, setTitleRoot] = useState() + const [rows, setRows] = useState() + const [param] = useUrlChange() + const dispatch = useAppDispatch() + const hasMyRank = rows?.[0]?.className === 'success' ? true : false + const [userInfos, setUserInfos] = useState([]) + + useEffect(() => { + void (async () => { + if (!rows?.length) return + const res = await dispatch( + fetchContestRanking({ + contestSlug: param.contestId, + page: param.page, + region: param.region, + }) + ).unwrap() + const userInfos = res.total_rank.map(a => { + return { + region: a.data_region, + username: a.user_slug, + oldUsername: a.username, + } + }) + if (hasMyRank) { + userInfos.unshift({ + region: 'CN', + username: (window as any).LeetCodeData.userStatus.user_slug, + oldUsername: (window as any).LeetCodeData.userStatus.username, + }) + } + setUserInfos(userInfos) + })() + }, [dispatch, param, hasMyRank, rows]) + + useEffect(() => { + dispatch(fetchContestInfo(param.contestId)) + }, [dispatch, param.contestId]) + + useEffectMount(async state => { + const handleChange = debounce(async () => { + const parent = await findElement('.table-responsive>table>thead>tr') + const trs = await findAllElement( + '.table-responsive>table>tbody>tr', + els => + !!els.length && + (els[0]?.className === 'success' ? els.length > 1 : true) + ) + if (state.isMount) { + setTitleRoot(parent) + setRows([...trs]) + } + }, 100) + handleChange() + + window.addEventListener('urlchange', handleChange) + }, []) + + useEffect(() => { + if (hasMyRank) { + dispatch(fetchMyRank(param.contestId)) + } + }, [dispatch, hasMyRank, param]) + + const contestInfo = useAppSelector(state => + selectContestInfo(state, param.contestId) + ) + const updateTime = useAppSelector(state => + selectPreviousRatingUpdateTime(state, param.contestId) + ) + + const showPredictordelta = !!options?.contestRankingPage.ratingPredictor + const showLanguageIcon = !!options?.contestRankingPage.languageIcon + const showNewRating = !!options?.contestRankingPage.showNewRating + const showOldRating = !!options?.contestRankingPage.showOldRating + const showPredict = !!options?.contestRankingPage.showPredict + const realTimePredict = !!options?.contestRankingPage.realTimePredict + const showExpectingRanking = !!options?.contestRankingPage.expectingRanking + const widescreen = + (showPredict || realTimePredict) && + (showPredictordelta || showNewRating || showOldRating) + + useEffectMount( + async state => { + if (!widescreen) return + + const container = await findElement('#contest-app .container') + if (!state.isMount) return + container.style.width = '98%' + container.style.maxWidth = '1440px' + state.unmount.push(() => { + container.style.width = '' + container.style.maxWidth = '' + }) + }, + [widescreen] + ) + + if (!contestInfo || !rows) return null + + return ( + <> + {(((showPredictordelta || showNewRating || showOldRating) && + (showPredict || realTimePredict)) || + showExpectingRanking) && + titleRoot && ( + + {showPredict && ( + + + 预测数据来自 + <a + href="https://lccn.lbao.site/" + target="_blank" + rel="noreferrer" + style={{ paddingLeft: 2 }} + > + lccn.lbao.site + </a> + </> + } + /> + </th> + )} + {realTimePredict && ( + <th + css={css` + &&&& { + border: 2px dashed #ddd; + border-bottom-style: solid; + } + `} + > + <Title + showOldRating={showOldRating} + showPredictordelta={showPredictordelta} + showNewRating={showNewRating} + showExpectingRanking={showExpectingRanking} + realTime={true} + help={ + <div> + 实时预测,仅供参考,详细说明查看帖子 + <a + href="https://leetcode.cn/circle/discuss/0OHPDu/" + target="_blank" + rel="noreferrer" + > + 实时预测功能 + </a> + <br /> + {updateTime + ? `当前数据更新时间为:「${format( + new Date(updateTime), + 'yyyy-MM-dd HH:mm' + )}」` + : ''} + </div> + } + /> + </th> + )} + </Portal> + )} + {(((showPredictordelta || showNewRating || showOldRating) && + (showPredict || realTimePredict)) || + showExpectingRanking) && + rows && ( + <> + <Predict + userInfos={userInfos} + rows={rows} + hasMyRank={hasMyRank} + showOldRating={showOldRating} + showPredictordelta={showPredictordelta} + showNewRating={showNewRating} + showExpectingRanking={showExpectingRanking} + /> + {realTimePredict && ( + <RealTimePredict + rows={rows} + hasMyRank={hasMyRank} + showOldRating={showOldRating} + showPredictordelta={showPredictordelta} + showNewRating={showNewRating} + showExpectingRanking={showExpectingRanking} + /> + )} + </> + )} + {showLanguageIcon && + rows?.map((row, i) => ( + <LanguageIconRow + contestSlug={param.contestId} + key={i} + row={row} + i={i} + hasMyRank={hasMyRank} + /> + ))} + </> + ) +} + +export default withPage('contestRankingPage')(App) diff --git a/src/content/pages/ranking/BetaApp.tsx b/src/content/pages/ranking/BetaApp.tsx new file mode 100644 index 0000000..ee14b96 --- /dev/null +++ b/src/content/pages/ranking/BetaApp.tsx @@ -0,0 +1,278 @@ +import { FC, useEffect, useState } from 'react' + +import { useAppDispatch, useAppSelector, useEffectMount } from '@/hooks' + +import { selectOptions } from '../global/optionsSlice' +import { Portal } from '@/components/Portal' +import { findElementByXPath } from '@/utils' +import Predict from './Predict' +import { useUrlChange } from './Item' +import Title from './Title' +import { LanguageIconRow } from './LanguageIcon' +import { debounce } from 'src/utils' +import { + fetchContestRanking, + fetchContestInfo, + selectContestInfo, + fetchMyRank, + selectPreviousRatingUpdateTime, +} from './rankSlice' +import { RealTimePredict } from './RealTimePredict' +import { User } from './utils' +import { format } from 'date-fns' +import { css } from 'styled-components/macro' + +export const BetaApp: FC = () => { + const options = useAppSelector(selectOptions) + const [titleRoot, setTitleRoot] = useState<HTMLElement>() + const [rows, setRows] = useState<HTMLElement[]>() + const [param] = useUrlChange(true) + const dispatch = useAppDispatch() + const hasMyRank = !!rows?.[0]?.parentElement?.className.includes( + 'from-ranking-primary' + ) + const [userInfos, setUserInfos] = useState<User[]>([]) + + useEffect(() => { + void (async () => { + if (!rows?.length) return + const res = await dispatch( + fetchContestRanking({ + contestSlug: param.contestId, + page: param.page, + region: param.region, + }) + ).unwrap() + + const userInfos = res.total_rank.map(a => { + return { + region: a.data_region, + username: a.user_slug, + oldUsername: a.username, + } + }) + if (hasMyRank) { + const a = rows[0].children[0].children[0] + .children[0] as HTMLAnchorElement + const username = a.pathname.split('/').filter(Boolean)[1] + userInfos.unshift({ + region: 'CN', + username, + oldUsername: username, + }) + } + setUserInfos(userInfos) + })() + }, [dispatch, param, hasMyRank, rows]) + + useEffect(() => { + dispatch(fetchContestInfo(param.contestId)) + }, [dispatch, param.contestId]) + + useEffectMount(async state => { + const handleChange = debounce(async () => { + const el = await findElementByXPath( + '//*[@id="__next"]//div[text()="用户名"]', + el => { + let p = el + while (p && p !== document.body) { + if (p.nextElementSibling?.textContent === '得分') { + return true + } + p = p.parentElement + } + return false + } + ) + let p: HTMLElement + if (el) { + p = el + while (p && p !== document.body) { + if (p.nextElementSibling?.textContent === '得分') { + break + } + p = p.parentElement! + } + const trs = p.parentElement!.parentElement! + .children as unknown as HTMLElement[] + if (state.isMount) { + setTitleRoot(trs[0]) + setRows([...trs].slice(1).map(a => a.children[0]) as HTMLElement[]) + } + } + }, 100) + handleChange() + + window.addEventListener('urlchange', handleChange) + const el = await findElementByXPath( + '//*[@id="__next"]//button[text()="全国"]' + ) + el.parentElement!.addEventListener('click', handleChange) + }, []) + + useEffect(() => { + if (hasMyRank) { + dispatch(fetchMyRank(param.contestId)) + } + }, [dispatch, hasMyRank, param]) + + const contestInfo = useAppSelector(state => + selectContestInfo(state, param.contestId) + ) + const updateTime = useAppSelector(state => + selectPreviousRatingUpdateTime(state, param.contestId) + ) + + const showPredictordelta = !!options?.contestRankingPage.ratingPredictor + const showLanguageIcon = !!options?.contestRankingPage.languageIcon + const showNewRating = !!options?.contestRankingPage.showNewRating + const showOldRating = !!options?.contestRankingPage.showOldRating + const showPredict = !!options?.contestRankingPage.showPredict + const realTimePredict = !!options?.contestRankingPage.realTimePredict + const showExpectingRanking = !!options?.contestRankingPage.expectingRanking + const widescreen = + (showPredict || realTimePredict) && + (showPredictordelta || showNewRating || showOldRating) + + useEffectMount(async () => { + if (!widescreen) return + let p = titleRoot + while (p && p !== document.body) { + if (getComputedStyle(p).maxWidth !== 'none') { + p.style.maxWidth = 'unset' + p.style.alignItems = 'center' + break + } + p = p.parentElement! + } + }, [widescreen, titleRoot]) + if (!contestInfo || !rows) return null + + return ( + <> + {(((showPredictordelta || showNewRating || showOldRating) && + (showPredict || realTimePredict)) || + showExpectingRanking) && + titleRoot && ( + <Portal container={titleRoot}> + <> + {showPredict && ( + <div + style={{ + height: '100%', + display: 'flex', + alignItems: 'center', + width: 200, + }} + > + <Title + showOldRating={showOldRating} + showPredictordelta={showPredictordelta} + showNewRating={showNewRating} + showExpectingRanking={showExpectingRanking} + realTime={false} + help={ + <> + 预测数据来自 + <a + href="https://lccn.lbao.site/" + target="_blank" + rel="noreferrer" + style={{ paddingLeft: 2 }} + > + lccn.lbao.site + </a> + </> + } + /> + </div> + )} + {realTimePredict && ( + <div + css={css` + &&&& { + border: 2px dashed #888; + border-bottom-style: solid; + } + `} + style={{ + height: '100%', + display: 'flex', + alignItems: 'center', + width: 300, + padding: 8, + }} + > + <Title + showOldRating={showOldRating} + showPredictordelta={showPredictordelta} + showNewRating={showNewRating} + showExpectingRanking={showExpectingRanking} + realTime={true} + help={ + <div> + 实时预测,仅供参考,详细说明查看帖子 + <a + href="https://leetcode.cn/circle/discuss/0OHPDu/" + target="_blank" + rel="noreferrer" + > + 实时预测功能 + </a> + <br /> + {updateTime + ? `当前数据更新时间为:「${format( + new Date(updateTime), + 'yyyy-MM-dd HH:mm' + )}」` + : ''} + </div> + } + /> + </div> + )} + </> + </Portal> + )} + {(((showPredictordelta || showNewRating || showOldRating) && + (showPredict || realTimePredict)) || + showExpectingRanking) && + rows && ( + <> + <Predict + userInfos={userInfos} + rows={rows} + hasMyRank={hasMyRank} + showOldRating={showOldRating} + showPredictordelta={showPredictordelta} + showNewRating={showNewRating} + showExpectingRanking={showExpectingRanking} + beta={true} + /> + {realTimePredict && ( + <RealTimePredict + rows={rows} + hasMyRank={hasMyRank} + showOldRating={showOldRating} + showPredictordelta={showPredictordelta} + showNewRating={showNewRating} + showExpectingRanking={showExpectingRanking} + beta={true} + /> + )} + </> + )} + {showLanguageIcon && + rows?.map((row, i) => ( + <LanguageIconRow + contestSlug={param.contestId} + key={i} + row={row} + i={i} + hasMyRank={hasMyRank} + beta={true} + /> + ))} + </> + ) +} diff --git a/src/content/pages/ranking/Item.tsx b/src/content/pages/ranking/Item.tsx new file mode 100644 index 0000000..a81ce71 --- /dev/null +++ b/src/content/pages/ranking/Item.tsx @@ -0,0 +1,193 @@ +import { useAppSelector, useEffectMount } from '@/hooks' +import { FC, memo, useState } from 'react' +import { css } from 'styled-components/macro' + +import { debounce } from 'src/utils' + +import { selectUserPredict, selectContestInfo } from './rankSlice' +import { findElementByXPath } from '@/utils' + +type ItmeType = { + contestSlug: string + region: string + username: string + showOldRating: boolean + showPredictordelta: boolean + showNewRating: boolean + showExpectingRanking: boolean + realTime: boolean + beta?: boolean +} + +export type PageParamType = { + contestId: string + page: number + username?: string + region: 'local' | 'global' +} + +function getParam(beta?: boolean): PageParamType { + const [, contestId, , pageStr = '1'] = location.pathname + .split('/') + .filter(Boolean) + const page = Number(pageStr) + let region: 'local' | 'global' = 'local' + if (beta) { + const btn = document.evaluate( + '//*[@id="__next"]//button[text()="全国"]', + document, + null, + XPathResult['FIRST_ORDERED_NODE_TYPE'], + null + ).singleNodeValue as HTMLButtonElement + if (btn && btn.dataset.state !== 'active') { + region = 'global' + } + } else { + const checkbox = document.querySelector( + '.checkbox>label>input' + ) as HTMLInputElement + region = checkbox?.checked ? 'global' : 'local' + } + + return { contestId, page, region } +} + +export function useUrlChange(beta?: boolean): [PageParamType] { + const [param, setParam] = useState(getParam(beta)) + useEffectMount(state => { + const handle = debounce(() => { + if (state.isMount) setParam(getParam(beta)) + }, 100) + window.addEventListener('urlchange', handle) + state.unmount.push(() => { + handle.cancel() + window.removeEventListener('urlchange', handle) + }) + }, []) + // 是否选中「显示全球」 + useEffectMount(async state => { + const handle = debounce((_e: Event) => { + if (state.isMount) setParam(getParam(beta)) + }, 100) + if (beta) { + const el = await findElementByXPath( + '//*[@id="__next"]//button[text()="全国"]' + ) + el.parentElement!.addEventListener('click', handle) + state.unmount.push(() => { + handle.cancel() + el.parentElement!.removeEventListener('change', handle) + }) + } else { + const checkbox = document.querySelector( + '.checkbox>label>input' + ) as HTMLInputElement + if (!checkbox) return + checkbox.addEventListener('change', handle) + state.unmount.push(() => { + handle.cancel() + checkbox.removeEventListener('change', handle) + }) + } + }) + return [param] +} + +export const Item: FC<ItmeType> = memo(function Item({ + contestSlug, + region, + username, + showOldRating, + showPredictordelta, + showNewRating, + showExpectingRanking, + realTime, + beta, +}) { + let { delta, oldRating, erank, rank, isStable } = + useAppSelector(state => + selectUserPredict(state, contestSlug, region, username, !!realTime) + ) ?? {} + const info = useAppSelector(state => selectContestInfo(state, contestSlug)) + if (!oldRating || !info) return <></> + + let deltaEl, newRatingEl + if (typeof delta !== 'number') { + deltaEl = <></> + newRatingEl = <></> + } else { + const deltaNum = Number(delta.toFixed(1)) + deltaEl = ( + <div + css={css` + font-weight: bold; + color: ${delta >= 0 + ? `rgb(0 136 0 / ${Math.min(delta / 100, 1) * 70 + 30}%)` + : `rgb(64 64 64 / ${Math.min(-delta / 100, 1) * 70 + 30}%)`}; + width: 60px; + ${beta && delta < 0 ? `filter: invert(100%);;` : ''} + `} + > + {deltaNum > 0 ? `+${deltaNum}` : deltaNum} + </div> + ) + const newRating = Number(((delta ?? 0) + oldRating).toFixed(1)) + newRatingEl = ( + <div + css={ + showPredictordelta + ? // 如果有显示分数变化,则新分数只需要区分颜色 + css` + width: 70px; + font-weight: bold; + color: ${delta >= 0 + ? `rgb(0 136 0 / ${Math.min(delta / 100, 1) * 70 + 30}%)` + : `rgb(64 64 64 / ${Math.min(-delta / 100, 1) * 70 + 30}%)`}; + ${beta && delta < 0 ? `filter: invert(100%);;` : ''} + ` + : // 如果没有显示分数变化,则需要将分数变化反应到颜色的深浅中 + css` + width: 70px; + font-weight: bold; + color: ${delta >= 0 + ? `rgb(0 136 0 / ${Math.min(delta / 100, 1) * 70 + 30}%)` + : `rgb(64 64 64 / ${Math.min(-delta / 100, 1) * 70 + 30}%)`}; + ${beta && delta < 0 ? `filter: invert(100%);;` : ''} + ` + } + > + {newRating} + </div> + ) + } + + oldRating = Number(oldRating.toFixed(1)) + const { start_time, duration } = info.contest + const inContest = new Date().valueOf() <= (start_time + duration) * 1000 + + const color = beta ? 'rgba(255, 255, 255, 0.6)' : '#000' + + return ( + <div + css={css` + display: flex; + height: 100%; + align-items: center; + `} + > + {showOldRating && <div style={{ width: 60 }}>{oldRating}</div>} + {showPredictordelta && deltaEl} + {showNewRating && newRatingEl} + {showExpectingRanking && realTime && erank && ( + <div style={{ display: 'flex' }}> + <span style={{ color: isStable || !inContest ? color : '#bbb' }}> + {rank} + </span> + <span style={{ margin: '0 10px' }}>/</span> + <span>{Math.round(erank)}</span> + </div> + )} + </div> + ) +}) diff --git a/src/content/pages/ranking/LanguageIcon.tsx b/src/content/pages/ranking/LanguageIcon.tsx new file mode 100644 index 0000000..157e4f1 --- /dev/null +++ b/src/content/pages/ranking/LanguageIcon.tsx @@ -0,0 +1,143 @@ +import { FC, memo, useEffect, useMemo, useState } from 'react' +import styled from 'styled-components/macro' + +import { debounce } from '../../../utils' + +import { + selectUserRanking, + selectContestInfo, + useGetFileIconsQuery, +} from './rankSlice' +import { Portal } from '@/components/Portal' +import { useAppSelector } from '@/hooks' +import { useUser } from './utils' + +type ItmeType = { + parent: HTMLElement + lang?: string + beta?: boolean +} + +const DefaultIcon = styled.span` + &::before { + content: '\f1c9'; + } +` + +const StyleSvg = styled.svg<{ size?: number }>` + height: 1em; + width: 1em; + transform: translateY(0.125em) translateX(-5px) scale(1.4); + + & > image { + height: 1em; + width: 1em; + } + + ${({ size }) => (size ? `font-size: ${size}px;` : '')} +` + +function setDisplay(el: Element | undefined, display: string) { + if (el instanceof HTMLElement || el instanceof SVGElement) { + el.style.display = display + } +} +function isShow(parent: HTMLElement) { + return parent.textContent && !!parent.textContent.trim() +} + +const LanguageIcon: FC<ItmeType> = ({ parent, lang, beta }) => { + const [show, setShow] = useState(isShow(parent)) + const { data: iconFiles } = useGetFileIconsQuery() + + useEffect(() => { + const p = beta ? parent.children[0].children[0] : parent.children[0] + const handleChange = debounce(() => { + const show = isShow(parent) + setShow(show) + if (show) { + if (p?.nodeName !== 'DIV') { + setDisplay(p?.children[0], 'none') + } + } + }, 10) + handleChange() + const observer = new MutationObserver(handleChange) + observer.observe(parent, { childList: true }) + return () => { + handleChange.cancel() + observer.disconnect() + setDisplay(p?.children[0], '') + } + }, [beta]) + + if (!show || !lang || !iconFiles) return null + if (parent.childNodes[0]?.nodeName === '#text') { + // 当前处于比赛中,则需要手动创建一个元素用于图标的渲染 + const span = document.createElement('span') + parent.insertBefore(span, parent.childNodes[0]) + span.style.display = 'inline-block' + } + + const iconFile = iconFiles[lang] + return ( + <Portal + container={ + beta + ? (parent.children[0].children[0] as HTMLElement) + : (parent.children[0] as HTMLElement) + } + > + {!iconFile ? ( + <DefaultIcon className="fa fa-file-code-o" /> + ) : ( + <StyleSvg> + <image href={iconFile} /> + </StyleSvg> + )} + </Portal> + ) +} + +export const LanguageIconRow: FC<{ + contestSlug: string + row: HTMLElement + i: number + hasMyRank: boolean + beta?: boolean +}> = memo(function LanguageIconRow({ contestSlug, row, i, hasMyRank, beta }) { + const { username, region } = useUser(hasMyRank, i, row, beta) + + const user = useAppSelector(state => + selectUserRanking(state, contestSlug, region, username) + ) + const contestInfo = useAppSelector(state => + selectContestInfo(state, contestSlug) + ) + + const tds = useMemo(() => { + if (beta) { + return Array.prototype.slice.call(row.children, 3, 7) + } + return Array.prototype.slice.call(row.children, 4, 8) + }, [beta, row]) + + if (!user || !contestInfo) return null + + const { questions } = contestInfo + + return ( + <> + {tds.map((td, j) => ( + <LanguageIcon + key={j} + parent={td} + lang={user.submission[questions[j].question_id]?.lang} + beta={beta} + /> + ))} + </> + ) +}) + +export default LanguageIcon diff --git a/src/content/pages/ranking/Predict.tsx b/src/content/pages/ranking/Predict.tsx new file mode 100644 index 0000000..4ed3b21 --- /dev/null +++ b/src/content/pages/ranking/Predict.tsx @@ -0,0 +1,101 @@ +import { FC, memo, useEffect } from 'react' + +import { fetchPrediction } from './rankSlice' +import { Portal } from '@/components/Portal' +import { Item, useUrlChange } from './Item' +import { User, useUser } from './utils' +import { useAppDispatch, useAppSelector } from '@/hooks' +import { selectOptions } from '../global/optionsSlice' + +interface PredictItemProps { + hasMyRank: boolean + showOldRating: boolean + showPredictordelta: boolean + showNewRating: boolean + showExpectingRanking: boolean + index: number + row: HTMLElement + beta?: boolean +} +const PredictItem = memo(function PredictItem({ + hasMyRank, + row, + index, + beta, + ...props +}: PredictItemProps) { + const { username, region } = useUser(hasMyRank, index, row, beta) + const [{ contestId: contestSlug }] = useUrlChange(beta) + + return ( + <Item + realTime={false} + {...{ ...props, username, region, contestSlug }} + beta={beta} + /> + ) +}) + +interface PredictProps { + rows: HTMLElement[] + hasMyRank: boolean + showOldRating: boolean + showPredictordelta: boolean + showNewRating: boolean + showExpectingRanking: boolean + userInfos: User[] + beta?: boolean +} +const Predict = memo(function Predict({ + hasMyRank, + rows, + userInfos, + ...props +}: PredictProps) { + const [{ contestId }] = useUrlChange(props.beta) + const options = useAppSelector(selectOptions) + + const dispatch = useAppDispatch() + useEffect(() => { + dispatch( + fetchPrediction({ + contestSlug: contestId, + users: userInfos.map(a => ({ + region: a.region, + username: a.oldUsername!, + })), + }) + ) + }, [dispatch, contestId, JSON.stringify(userInfos)]) + + const showPredict = !!options?.contestRankingPage.showPredict + return ( + <> + {rows.map((row, i) => ( + <Portal container={row} key={i}> + {showPredict ? ( + <TDWrap beta={props.beta} style={{ height: '100%', width: 200 }}> + <PredictItem {...{ ...props, hasMyRank, index: i, row }} /> + </TDWrap> + ) : ( + <TDWrap style={{ display: 'none', width: 200 }} /> + )} + </Portal> + ))} + </> + ) +}) + +type TDWrapProps = React.HTMLAttributes<HTMLElement> & { + beta?: boolean + children?: React.ReactNode +} + +export const TDWrap: FC<TDWrapProps> = ({ beta, children, ...props }) => { + if (beta) { + return <div {...props}>{children}</div> + } + return <td {...props}>{children}</td> +} + +export default Predict diff --git a/src/content/pages/ranking/RealTimePredict.tsx b/src/content/pages/ranking/RealTimePredict.tsx new file mode 100644 index 0000000..ccb2a81 --- /dev/null +++ b/src/content/pages/ranking/RealTimePredict.tsx @@ -0,0 +1,88 @@ +import { FC } from 'react' +import { Portal } from '@/components/Portal' +import { Item, useUrlChange } from './Item' + +import { useFetchPreviousRatingData, usePredict, useUser } from './utils' +import { TDWrap } from './Predict' + +interface RealTimePredictItemProps { + isVirtual?: boolean + hasMyRank: boolean + showOldRating: boolean + showPredictordelta: boolean + showNewRating: boolean + showExpectingRanking: boolean + index: number + row: HTMLElement + beta?: boolean +} +export const RealTimePredictItem: FC<RealTimePredictItemProps> = ({ + hasMyRank, + index, + row, + beta, + ...props +}) => { + const { username, region } = useUser(hasMyRank, index, row, beta) + const [{ contestId: contestSlug }] = useUrlChange(beta) + + usePredict({ + username, + region, + contestSlug, + }) + + return ( + <Item + realTime={true} + {...{ ...props, contestSlug, region, username }} + beta={beta} + /> + ) +} +interface RealTimePredictProps { + rows: HTMLElement[] + hasMyRank: boolean + showOldRating: boolean + showPredictordelta: boolean + showNewRating: boolean + showExpectingRanking: boolean + beta?: boolean +} + +export const RealTimePredict: FC<RealTimePredictProps> = ({ + rows, + hasMyRank, + ...props +}) => { + const [{ contestId: contestSlug }] = useUrlChange(props.beta) + useFetchPreviousRatingData(contestSlug) + + const borderColor = props.beta ? '#888' : '#ddd' + + return ( + <> + {rows.map((row, i) => ( + <Portal container={row} key={i}> + <TDWrap + style={{ + borderLeft: `2px dashed ${borderColor}`, + borderRight: `2px dashed ${borderColor}`, + borderBottom: + i === rows.length - 1 ? `2px dashed ${borderColor}` : '', + height: '100%', + width: 300, + padding: 8, + }} + beta={props.beta} + > + <RealTimePredictItem + row={row} + {...{ ...props, hasMyRank, index: i }} + /> + </TDWrap> + </Portal> + ))} + </> + ) +} diff --git a/src/content/pages/ranking/Title.tsx b/src/content/pages/ranking/Title.tsx new file mode 100644 index 0000000..d043e9d --- /dev/null +++ b/src/content/pages/ranking/Title.tsx @@ -0,0 +1,117 @@ +import { FC, ReactNode } from 'react' +import styled from 'styled-components/macro' + +import { ToolTip } from '@/components/ToolTip' + +const HelpIcon = styled.span` + position: relative; + cursor: pointer; + font-family: 'Glyphicons Halflings'; + font-style: normal; + font-weight: 400; + color: rgba(0, 0, 0, 0.65); + line-height: 1; + top: 1px; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + + &::before { + content: '\\e085'; + } +` + +const Content = styled.div` + color: #fff; + text-align: center; + white-space: nowrap; +` + +const Help = ({ content }: { content: string | ReactNode }) => { + return ( + <ToolTip + placement="left" + arrow={false} + keep={true} + title={<Content>{content}</Content>} + offset={{ left: 70, top: 40 }} + > + <HelpIcon /> + </ToolTip> + ) +} + +interface TitleProps { + showOldRating: boolean + showPredictordelta: boolean + showNewRating: boolean + showExpectingRanking: boolean + realTime: boolean + help?: string | ReactNode +} + +const Title: FC<TitleProps> = ({ + showNewRating, + showPredictordelta, + showOldRating, + showExpectingRanking, + realTime, + help, +}) => { + return ( + <> + <div + style={{ + display: 'flex', + }} + > + {showOldRating && ( + <div style={{ width: 60 }}> + 旧分数 + {!showPredictordelta && !showNewRating && help && ( + <Help content={help} /> + )} + </div> + )} + {showPredictordelta && ( + <div + style={{ + width: 55, + paddingLeft: showNewRating ? 10 : 0, + }} + > + <span>{showNewRating ? 'Δ' : '预测'}</span> + {!showNewRating && help && <Help content={help} />} + </div> + )} + + {showNewRating && ( + <div style={{ width: 70 }}> + 新分数 + {help && <Help content={help} />} + </div> + )} + + {showExpectingRanking && realTime && ( + <div> + <span>Rk/Exp</span> + <Help + content={ + <div> + <div>当前全球排名(Rk)/期望全球排名(Exp)</div> + <div> + 榜单数据更新有延迟,对于还不确定的「当前全球排名」标记为 + <span style={{ color: '#bbb' }}>灰色</span> + ,如果已经确定,则标记为 + <span style={{ color: '#000' }}>黑色</span> + </div> + </div> + } + /> + </div> + )} + </div> + </> + ) +} + +export default Title diff --git a/src/content/pages/ranking/rankSlice.ts b/src/content/pages/ranking/rankSlice.ts new file mode 100644 index 0000000..bd9adf2 --- /dev/null +++ b/src/content/pages/ranking/rankSlice.ts @@ -0,0 +1,562 @@ +import { createApi, BaseQueryFn } from '@reduxjs/toolkit/query/react' + +import { + calcSeed, + ContestInfo, + ContestRanking, + getERank, + getExtensionId, + getPreviousRatingData, + gkey, + LeetCodeApi, + MyRanking, + predict, + PreviousRatingDataType, + RankingDataType, + Rating, + SubmissionType, +} from '@/utils' +import { + createAsyncThunk, + createSlice, + current, + Draft, + PayloadAction, +} from '@reduxjs/toolkit' +import { RootState } from '@/app/store' +import { findRank } from './utils' + +export type ParamType = { + contestSlug: string + users: { username: string; region: string }[] +} + +type GetPredictionMessage = + | { + type: 'get-prediction' + contestSlug: string + users: { username: string; region: string }[] + } + | { + type: 'get-file-icons' + } + | { + type: 'get-user-ranking' + username: string + } + +type ArgsType = { message: GetPredictionMessage } + +const extensionId = getExtensionId()! +const customBaseQuery = (): BaseQueryFn<ArgsType, unknown, unknown> => { + return async ({ message }) => { + return new Promise(function (resolve) { + chrome.runtime.sendMessage(extensionId, message, function (response) { + resolve({ data: response }) + }) + }) + } +} +const query = async <T>({ message }: { message: GetPredictionMessage }) => { + return new Promise<T>(function (resolve) { + chrome.runtime.sendMessage(extensionId, message, function (response) { + resolve(response) + }) + }) +} + +export const apiSlice = createApi({ + reducerPath: 'api', + baseQuery: customBaseQuery(), + endpoints: builder => ({ + getPrediction: builder.query<any, ParamType>({ + query: params => ({ + message: { + type: 'get-prediction', + ...params, + }, + }), + }), + getFileIcons: builder.query<any, void>({ + query: () => ({ + message: { + type: 'get-file-icons', + }, + }), + }), + }), +}) + +export const { useGetPredictionQuery, useGetFileIconsQuery } = apiSlice + +const api = new LeetCodeApi(location.origin) + +/** 获取比赛信息 + * + */ +export const fetchContestInfo = createAsyncThunk< + ContestInfo, + string, + { state: RootState } +>('contestInfos/fetchContestInfo', async contestSlug => { + const res = await api.getContestInfo(contestSlug) + return res +}) + +/** 获取比赛对应页的用户答题和 Rank 等信息 + * + */ +export const fetchContestRanking = createAsyncThunk< + RankingDataType, + { contestSlug: string; page: number; region: 'local' | 'global' }, + { state: RootState } +>('contestInfos/fetchContestRanking', async ({ contestSlug, page, region }) => { + const res = await api.getContest(contestSlug, page, region) + return res +}) + +/** 从预测数据源获取预测数据 + * + */ +export const fetchPrediction = createAsyncThunk< + { + data_region: string + username: string + delta?: number + oldRating?: number + }[], + { contestSlug: string; users: { region: string; username: string }[] }, + { state: RootState } +>('contestInfos/fetchPrediction', async ({ contestSlug, users }) => { + const res = await query< + { + data_region: string + username: string + delta?: number + }[] + >({ + message: { type: 'get-prediction', contestSlug, users }, + }) + return res +}) + +/** 获取实时预测需要的数据 + * + */ +export const fetchPreviousRatingData = createAsyncThunk< + PreviousRatingDataType, + { contestSlug: string }, + { state: RootState } +>('contestInfos/fetchPreviousRatingData', async ({ contestSlug }) => { + const res = await getPreviousRatingData(contestSlug) + return res +}) + +/** 获取自己的 Rank 数据 + * + */ +export const fetchMyRank = createAsyncThunk< + MyRanking, + string, + { state: RootState } +>('contestInfos/fetchMyRank', async contestSlug => { + const res = await api.getGlobalyRanking(contestSlug) + return res +}) + +/** 获取用户的 Rating 数据 + * + * 主要是当 PreviousRatingData 不包含某个用户的信息时,则需要实时去 LeetCode 获取数据,用于实时预测 + * + */ +export const fetchUserRating = createAsyncThunk< + RealPredict, + { region: string; username: string; contestSlug: string }, + { state: RootState } +>( + 'contestInfos/fetchUserRating', + async ({ region, username, contestSlug }, { getState }) => { + let res: Rating + if (region.toLocaleLowerCase() === 'cn') { + res = await api.getRating(username, true) + } else { + res = await query({ message: { type: 'get-user-ranking', username } }) + } + const { start_time } = getState().contestInfos[contestSlug].info!.contest + + const history = res.userContestRankingHistory?.filter(a => a.attended) ?? [] + let l = -1, + r = history.length - 1 + while (l < r) { + const m = (l + r + 1) >> 1 + if (history[m].contest.startTime < start_time) { + l = m + } else { + r = m - 1 + } + } + + return { oldRating: history[l]?.rating ?? 1500, acc: l + 1 } + } +) + +type User = { + username: string + rank?: number + finishTime: number + score: number + region: string + submission: { [key: number]: SubmissionType } +} + +type RealPredict = { + oldRating?: number + delta?: number + acc?: number + rank?: number + preCache?: number // 用以保存上次计算时的缓存,避免重复计算,由 rank*1e4+oldRating 计算而成 + erank?: number + isStable?: boolean +} + +export type Status = 'idle' | 'loading' | 'succeeded' | 'failed' + +type Previous = { + RatingData?: PreviousRatingDataType + seeds?: number[] + status: Status + lastTime?: number +} +type State = { + [contestSlug: string]: { + info?: ContestInfo + myRanking?: MyRanking + // ranking: Ranking + previous: Previous + users: { [key: string]: User } + predict: { + [key: string]: { + oldRating?: number + delta?: number + } + } + realPredict: { [key: string]: RealPredict } + fetchContestRankingState: Status + } +} & { myRating?: ContestRanking } + +const initialState: State = {} +const setDefaultState = (state: State, contestSlug: string) => { + if (!state[contestSlug]) { + state[contestSlug] = { + users: {}, + predict: {}, + realPredict: {}, + previous: { status: 'idle' }, + fetchContestRankingState: 'idle', + } + } +} + +const setRealPredict = ( + realPredict: Draft<{ [key: string]: RealPredict }>, + key: string, + score: number, + finishTime: number, + previous: Previous, + totalScore: number +) => { + const { oldRating, acc, preCache } = realPredict[key] ?? {} + const { RatingData, seeds, lastTime } = previous + if (RatingData && seeds && oldRating !== undefined) { + const rank = findRank(RatingData, score, finishTime) + const cache = rank * 1e4 + oldRating! + if (cache !== preCache) { + const delta = predict(seeds, oldRating, rank, acc ?? 0) + realPredict[key].rank = rank + realPredict[key].delta = delta + realPredict[key].preCache = cache + realPredict[key].erank = getERank(seeds, oldRating) + realPredict[key].isStable = + score === totalScore && finishTime <= lastTime! + } + } +} +export const contestInfosSlice = createSlice({ + name: 'contestInfos', + initialState, + reducers: { + setUserRating( + state, + action: PayloadAction<{ + contestSlug: string + key: string + rating?: number + acc?: number + rank?: number + }> + ) { + const { contestSlug, key, rating, acc, rank } = action.payload + setDefaultState(state, contestSlug) + state[contestSlug].realPredict[key] = Object.assign( + state[contestSlug].realPredict[key] ?? {}, + { oldRating: rating, acc, rank } + ) + }, + setUserDelta( + state, + action: PayloadAction<{ + contestSlug: string + key: string + }> + ) { + const { contestSlug, key } = action.payload + const { realPredict, users, previous } = state[contestSlug] + const { score, finishTime } = users[key] + const totalScore = + state[contestSlug].info?.questions.reduce((a, b) => a + b.credit, 0) ?? + Infinity + setRealPredict(realPredict, key, score, finishTime, previous, totalScore) + }, + }, + extraReducers(builder) { + builder + .addCase(fetchContestInfo.fulfilled, (state, action) => { + setDefaultState(state, action.meta.arg) + state[action.meta.arg].info = action.payload + }) + .addCase(fetchPreviousRatingData.rejected, (state, action) => { + const { contestSlug } = action.meta.arg + setDefaultState(state, contestSlug) + state[contestSlug].previous.status = 'failed' + }) + .addCase(fetchPreviousRatingData.pending, (state, action) => { + const { contestSlug } = action.meta.arg + setDefaultState(state, contestSlug) + state[contestSlug].previous.status = 'loading' + }) + .addCase(fetchPreviousRatingData.fulfilled, (state, action) => { + const { totalRank } = action.payload + totalRank.sort((a, b) => { + if (a.score !== b.score) return b.score - a.score + return a.finish_time - b.finish_time + }) + const { contestSlug } = action.meta.arg + setDefaultState(state, contestSlug) + const { previous, realPredict, users } = state[contestSlug] + const cur = JSON.stringify(current(previous).RatingData ?? {}) + if (cur === JSON.stringify(action.payload)) { + previous.status = 'succeeded' + return + } + previous.RatingData = action.payload + + for (const rank of totalRank) { + const key = gkey(rank.data_region, rank.username) + realPredict[key] = { + oldRating: rank.rating, + acc: rank.acc, + } + } + + const ratings = totalRank.filter(a => a.score).map(a => a.rating) + const seeds = calcSeed(ratings) + + let lastCNTime = 0, + lastEUTime = 0 + for (const rank of totalRank) { + const time = rank.finish_time - (rank.fail_count ?? 0) * 5 * 60 + if (rank.data_region.toLocaleLowerCase() === 'cn') { + lastCNTime = Math.max(lastCNTime, time) + } else { + lastEUTime = Math.max(lastEUTime, time) + } + } + previous.seeds = seeds + previous.lastTime = Math.min(lastCNTime, lastEUTime) + for (const { region, username, score, finishTime } of Object.values( + users + )) { + const key = gkey(region, username) + if (!realPredict[key]) continue + const totalScore = + state[contestSlug].info?.questions.reduce( + (a, b) => a + b.credit, + 0 + ) ?? Infinity + setRealPredict( + realPredict, + key, + score, + finishTime, + previous, + totalScore + ) + } + + previous.status = 'succeeded' + }) + .addCase(fetchMyRank.fulfilled, (state, action) => { + const contestSlug = action.meta.arg + setDefaultState(state, contestSlug) + state[contestSlug].myRanking = action.payload + const { + my_rank: { + username, + finish_time: finishTime, + score, + data_region: region, + }, + my_submission, + } = action.payload + const key = gkey(region, username) + state[contestSlug].users[key] = { + username, + finishTime, + score, + region, + submission: my_submission, + } + }) + .addCase(fetchUserRating.fulfilled, (state, action) => { + const { contestSlug, region, username } = action.meta.arg + state[contestSlug].realPredict[gkey(region, username)] = action.payload + }) + .addCase(fetchContestRanking.rejected, (state, action) => { + const { contestSlug } = action.meta.arg + setDefaultState(state, contestSlug) + state[contestSlug].fetchContestRankingState = 'failed' + }) + .addCase(fetchContestRanking.pending, (state, action) => { + const { contestSlug } = action.meta.arg + setDefaultState(state, contestSlug) + state[contestSlug].fetchContestRankingState = 'loading' + }) + .addCase(fetchContestRanking.fulfilled, (state, action) => { + const { contestSlug } = action.meta.arg + setDefaultState(state, contestSlug) + const { submissions, total_rank } = action.payload + const n = total_rank.length + const { realPredict, users, previous } = state[contestSlug] + for (let i = 0; i < n; i++) { + const { + username, + finish_time: finishTime, + score, + data_region: region, + } = total_rank[i] + const key = gkey(region, username) + const user = users[key] + if (!user || user.score !== score || user.finishTime !== finishTime) { + state[contestSlug].users[key] = { + username, + finishTime, + score, + region, + submission: submissions[i], + } + } + const totalScore = + state[contestSlug].info?.questions.reduce( + (a, b) => a + b.credit, + 0 + ) ?? Infinity + setRealPredict( + realPredict, + key, + score, + finishTime, + previous, + totalScore + ) + } + state[contestSlug].fetchContestRankingState = 'succeeded' + }) + .addCase(fetchPrediction.fulfilled, (state, action) => { + const { contestSlug } = action.meta.arg + setDefaultState(state, contestSlug) + if (!action.payload) return + for (const { + username, + data_region, + oldRating, + delta, + } of action.payload) { + const key = gkey(data_region, username) + state[contestSlug].predict[key] = { + oldRating, + delta, + } + } + }) + }, +}) + +export const selectContestInfo = ( + state: RootState, + contestSlug: string +): ContestInfo | undefined => state.contestInfos[contestSlug]?.info +export const selectPreviousRatingData = ( + state: RootState, + contestSlug: string +): PreviousRatingDataType | undefined => + state.contestInfos[contestSlug]?.previous.RatingData +export const selectPreviousSeeds = ( + state: RootState, + contestSlug: string +): number[] | undefined => state.contestInfos[contestSlug]?.previous.seeds + +export const selectMyRanking = ( + state: RootState, + contestSlug: string +): MyRanking | undefined => state.contestInfos[contestSlug]?.myRanking +export const selectMyRating = ( + state: RootState, + userSlug?: string +): ContestRanking | undefined => + userSlug ? state.contestInfos.myRating : undefined + +export const selectPreviousRatingDataStatus = ( + state: RootState, + contestSlug?: string +): Status | undefined => + contestSlug ? state.contestInfos[contestSlug].previous.status : undefined +export const selectPreviousRatingUpdateTime = ( + state: RootState, + contestSlug?: string +): number | undefined => + contestSlug + ? state.contestInfos[contestSlug]?.previous?.RatingData?.update + : undefined +export const selectFetchContestRankingState = ( + state: RootState, + contestSlug?: string +): Status | undefined => + contestSlug + ? state.contestInfos[contestSlug].fetchContestRankingState + : undefined + +export const selectUserRanking = ( + state: RootState, + contestSlug: string, + region: string, + username: string +): User | undefined => + contestSlug && region && username + ? state.contestInfos[contestSlug]?.users[gkey(region, username)] + : undefined + +export const selectUserPredict = ( + state: RootState, + contestSlug: string, + region: string, + username: string, + realPredict: boolean +): RealPredict | undefined => + contestSlug && region && username + ? state.contestInfos[contestSlug]?.[ + realPredict ? 'realPredict' : 'predict' + ][gkey(region, username)] + : undefined + +export const { setUserRating, setUserDelta } = contestInfosSlice.actions diff --git a/src/content/pages/ranking/utils.ts b/src/content/pages/ranking/utils.ts new file mode 100644 index 0000000..2b52f36 --- /dev/null +++ b/src/content/pages/ranking/utils.ts @@ -0,0 +1,236 @@ +import { + useAppDispatch, + useAppSelector, + useEffectMount, + useEvent, +} from '@/hooks' +import { gkey, PreviousRatingDataType } from '@/utils' +import { useEffect, useState } from 'react' +import { debounce } from 'src/utils' +import { + fetchPreviousRatingData, + selectUserPredict, + selectPreviousSeeds, + setUserDelta, + selectPreviousRatingDataStatus, + fetchUserRating, + selectUserRanking, + selectFetchContestRankingState, +} from './rankSlice' + +export type User = { region: string; username: string; oldUsername?: string } + +/** 获取当前行的用户信息 + * + * @param hasMyRank 当前用户是否参赛 + * @param index 第几行 + * @param row 行元素 + * @returns + */ +export function getUsername( + hasMyRank: boolean, + index: number, + row: HTMLElement, + beta?: boolean +): User { + let region = '', + username = '' + if (!beta && index === 0 && hasMyRank) { + region = 'CN' + username = (window as any)?.LeetCodeData?.userStatus?.user_slug + } else { + if (beta) { + const a = row.children[0].children[0].children[0] as HTMLAnchorElement + if (a.host === 'leetcode.com') { + region = 'US' + } else { + region = 'CN' + } + username = a.pathname?.split('/').filter(Boolean)[1] + } else { + const a = row.children[1].children[0] as HTMLAnchorElement + if (a.host === 'leetcode.com') { + region = 'US' + username = a.pathname.split('/').filter(Boolean)[0] + } else { + region = 'CN' + username = a.pathname.split('/').filter(Boolean)[1] + } + } + } + return { region, username } +} + +/** 当前行发生改变是触发事件 + */ +export const useRowChange = (row: HTMLElement, onChange: () => void): void => { + useEffect(() => { + const handleChange = debounce(() => { + onChange() + }, 100) + handleChange() + const observer = new MutationObserver(handleChange) + observer.observe(row, { attributes: true, childList: true }) + return () => { + handleChange.cancel() + observer.disconnect() + } + }, [onChange, row]) +} + +/** 响应式获取当前行的用户信息 + */ +export const useUser = ( + hasMyRank: boolean, + index: number, + row: HTMLElement, + beta?: boolean +): User => { + const [state, setState] = useState(getUsername(hasMyRank, index, row, beta)) + const handleChange = useEvent(() => { + setState(getUsername(hasMyRank, index, row, beta)) + }) + useRowChange(row, handleChange) + return state +} + +/** 获取预测数据 + * + */ +export const useFetchPreviousRatingData = (contestSlug: string): void => { + const dispatch = useAppDispatch() + useEffectMount( + async state => { + let cnt = 5 + while (cnt--) { + if (!state.isMount) break + try { + const promise = dispatch( + fetchPreviousRatingData({ contestSlug: contestSlug }) + ) + state.unmount.push(() => promise.abort()) + await promise + break + } catch (error) { + // + } + } + }, + [dispatch, contestSlug] + ) +} + +// TODO: 研究是否有更快的实现 +export const usePredict = ({ + contestSlug, + region, + username, +}: { + region: string + username: string + contestSlug: string +}): void => { + const dispatch = useAppDispatch() + const { oldRating, acc, preCache, rank } = + useAppSelector(state => + selectUserPredict(state, contestSlug, region, username, true) + ) ?? {} + + const seeds = useAppSelector(state => selectPreviousSeeds(state, contestSlug)) + const previousRatingDataStatus = useAppSelector(state => + selectPreviousRatingDataStatus(state, contestSlug) + ) + const fetchContestRankingState = useAppSelector(state => + selectFetchContestRankingState(state, contestSlug) + ) + + const user = useAppSelector(state => + selectUserRanking(state, contestSlug, region, username) + ) + + useEffect(() => { + if ( + previousRatingDataStatus === 'succeeded' && + fetchContestRankingState === 'succeeded' && + oldRating === undefined + ) { + // 表示 previousRatingData 中不包含指定用户的数据,这时需要实时从 LeetCode 中获取数据,以完成实时预测 + dispatch(fetchUserRating({ region, username, contestSlug })) + } + }, [ + previousRatingDataStatus, + oldRating, + dispatch, + region, + username, + contestSlug, + fetchContestRankingState, + ]) + + useEffectMount(async () => { + if ( + previousRatingDataStatus !== 'succeeded' || + fetchContestRankingState !== 'succeeded' || + !user + ) + return + + if (seeds && oldRating !== undefined) { + if (rank) { + const cache = rank * 1e4 + oldRating + // 如果 rank 和 oldRating 一样的话,则计算结果也会一样,就没必要重复计算了 + if (preCache === cache) return + } + const key = gkey(region, username) + dispatch( + setUserDelta({ + contestSlug, + key, + }) + ) + } + }, [ + rank, + seeds, + acc, + oldRating, + region, + username, + dispatch, + contestSlug, + preCache, + previousRatingDataStatus, + fetchContestRankingState, + user, + ]) +} + +export function findRank( + previousRatingData: PreviousRatingDataType, + user_score: number, + user_finishTime: number +): number { + // 通过用户当前的分数和完成时间,计算 Rank + // 对于正在进行的比赛来说,榜单上的 Rank 并不是实时的,会有一定的延迟 + // 而这种方式计算 Rank 则比较依赖于 previousRatingData 数据的准确性 + const { totalRank } = previousRatingData + const check = (m: number) => { + const { score, finish_time } = totalRank[m] + return ( + user_score < score || + (user_score === score && user_finishTime > finish_time) + ) + } + let l = 0, + r = totalRank.length + + while (l < r) { + const m = (l + r) >> 1 + if (check(m)) { + l = m + 1 + } else { + r = m + } + } + return l + 1 +} diff --git a/src/content/theme/index.ts b/src/content/theme/index.ts new file mode 100644 index 0000000..8105f91 --- /dev/null +++ b/src/content/theme/index.ts @@ -0,0 +1,79 @@ +import { DefaultTheme } from 'styled-components/macro' + +export const darkTheme: DefaultTheme = { + mode: 'dark', + palette: { + primary: { + main: `rgba(40, 40, 40, 1)`, + dark: `rgba(26, 26, 26, 1)`, + light: `rgba(48, 48, 48, 1)`, + hover: `rgba(52, 52, 52, 1)`, + }, + secondary: { + main: `rgba(80, 80, 80, 1)`, + light: `rgba(85, 85, 85, 1)`, + dark: `rgba(75, 75, 75, 1)`, + hover: `rgba(90, 90, 90, 1)`, + }, + text: { + main: `rgba(239, 242, 246, 0.6)`, + light: `rgba(239, 242, 246, 1)`, + dark: `rgba(239, 242, 246, 0.3)`, + }, + button: { + main: `rgba(10, 102, 204, 1)`, + dark: `rgba(8, 89, 180, 1)`, + light: `rgba(11, 113, 229, 1)`, + hover: `rgba(7, 72, 146, 1)`, + text: `rgba(255, 255, 255, 1)`, + disable: `rgb(110 110 110)`, + }, + checkbox: { + backgroundColor: 'hsla(0,0%,100%,.14)', + checkedBackgroundColor: 'rgb(10, 132, 255)', + }, + }, + shadows: { + 1: `0 1px 2px rgba(0, 0, 0, 0.3), 0 4px 4px rgba(0, 0, 0, 0.25)`, + 2: `rgba(0, 0, 0, 0) 0px 0px 0px 0px, rgba(0, 0, 0, 0) 0px 0px 0px 0px, rgba(0, 0, 0, 0.24) 0px 1px 3px 0px, rgba(0, 0, 0, 0.16) 0px 2px 8px 0px`, + }, +} + +export const lightTheme: DefaultTheme = { + mode: 'light', + palette: { + primary: { + main: `rgba(255, 255, 255, 1)`, + light: `rgba(255, 255, 255, 1)`, + dark: `rgba(235, 235, 235, 1)`, + hover: `rgba(220, 220, 220, 1)`, + }, + secondary: { + main: `rgba(235, 235, 235, 1)`, + light: `rgba(245, 245, 245, 1)`, + dark: `rgba(225, 225, 225, 1)`, + hover: `rgba(220, 220, 220, 1)`, + }, + text: { + main: `hsl(0deg 0% 15%)`, + light: `hsl(0deg 0% 3%)`, + dark: `hsl(0deg 0% 10%)`, + }, + button: { + main: `rgba(0, 110, 230, 1)`, + dark: `rgba(0, 100, 208, 1)`, + light: `rgba(0, 122, 255, 1)`, + hover: `rgba(0, 90, 216)`, + text: `rgba(255, 255, 255, 1)`, + disable: `rgb(110 110 110)`, + }, + checkbox: { + backgroundColor: 'rgba(0,10,32,.05)', + checkedBackgroundColor: 'rgb(0, 122, 255)', + }, + }, + shadows: { + 1: `0 2px 8px rgba(0, 0, 0, 0.08),0 1px 2px rgba(0, 0, 0, 0.1)`, + 2: `rgba(0, 0, 0, 0) 0px 0px 0px 0px, rgba(0, 0, 0, 0) 0px 0px 0px 0px, rgba(0, 0, 0, 0.04) 0px 1px 3px 0px, rgba(0, 0, 0, 0.08) 0px 2px 8px 0px`, + }, +} diff --git a/src/content/types/customEvent.d.ts b/src/content/types/customEvent.d.ts new file mode 100644 index 0000000..360b0c9 --- /dev/null +++ b/src/content/types/customEvent.d.ts @@ -0,0 +1,22 @@ +type CustomMap = { + refinedLeetcodeOptionsChange: { + options: import('src/options/options').OptionsType + } + refinedLeetcodeSaveOptions: { + options: import('src/options/options').OptionsType + } + refinedLeetcodeGetOptions: void +} + +type CustomEventMap<T> = { [K in keyof T]: CustomEvent<T[K]> } + +// eslint-disable-next-line @typescript-eslint/no-empty-interface +interface WindowEventMap extends CustomEventMap<CustomMap> { + urlchange: {} +} + +type Args<T> = CustomMap[T] extends undefined + ? [name: T] + : [name: T, data: CustomMap[T]] + +type CustomEventDispatch = <K extends keyof CustomMap>(...args: Args<K>) => void diff --git a/src/types/global.d.ts b/src/content/types/global.d.ts similarity index 76% rename from src/types/global.d.ts rename to src/content/types/global.d.ts index f783586..4961dfd 100644 --- a/src/types/global.d.ts +++ b/src/content/types/global.d.ts @@ -6,3 +6,5 @@ interface HTMLElement { _internalRoot?: FiberRoot } } + +declare let REFINED_LEETCODE_LOG_LEVEL: string diff --git a/src/content/types/styled.d.ts b/src/content/types/styled.d.ts new file mode 100644 index 0000000..3e6eea5 --- /dev/null +++ b/src/content/types/styled.d.ts @@ -0,0 +1,44 @@ +// import original module declarations +import 'styled-components/macro' +import type {} from 'styled-components/cssprop' + +// and extend them! +declare module 'styled-components' { + export interface DefaultTheme { + mode: 'dark' | 'light' + palette: { + primary: { + main: string + light: string + dark: string + hover: string + } + secondary: { + main: string + light: string + dark: string + hover: string + } + text: { + main: string + light: string + dark: string + } + button: { + main: string + light: string + dark: string + hover: string + text: string + disable: string + } + checkbox: { + backgroundColor: string + checkedBackgroundColor: string + } + } + shadows: { + [key: number]: string + } + } +} diff --git a/src/content/utils/conv.ts b/src/content/utils/conv.ts new file mode 100644 index 0000000..9905e1b --- /dev/null +++ b/src/content/utils/conv.ts @@ -0,0 +1,111 @@ +/** + * @see https://github.com/meooow25/carrot/blob/20045fba44ebba404b62a2f9d0ac20fe4514a084/carrot/src/util/conv.js + */ + +export class FFTConv { + public n: number + public wr: number[] + public wi: number[] + public rev: number[] + public constructor(n: number) { + let k = 1 + while (1 << k < n) { + k++ + } + this.n = 1 << k + const n2 = this.n >> 1 + this.wr = [] + this.wi = [] + const ang = (2 * Math.PI) / this.n + for (let i = 0; i < n2; i++) { + this.wr[i] = Math.cos(i * ang) + this.wi[i] = Math.sin(i * ang) + } + this.rev = [0] + for (let i = 1; i < this.n; i++) { + this.rev[i] = (this.rev[i >> 1] >> 1) | ((i & 1) << (k - 1)) + } + } + + public reverse(a: number[]): void { + for (let i = 1; i < this.n; i++) { + if (i < this.rev[i]) { + const tmp = a[i] + a[i] = a[this.rev[i]] + a[this.rev[i]] = tmp + } + } + } + + public transform(ar: number[], ai: number[]): void { + this.reverse(ar) + this.reverse(ai) + const wr = this.wr + const wi = this.wi + for (let len = 2; len <= this.n; len <<= 1) { + const half = len >> 1 + const diff = this.n / len + for (let i = 0; i < this.n; i += len) { + let pw = 0 + for (let j = i; j < i + half; j++) { + const k = j + half + const vr = ar[k] * wr[pw] - ai[k] * wi[pw] + const vi = ar[k] * wi[pw] + ai[k] * wr[pw] + ar[k] = ar[j] - vr + ai[k] = ai[j] - vi + ar[j] += vr + ai[j] += vi + pw += diff + } + } + } + } + + public convolve(a: number[], b: number[]): number[] { + if (a.length === 0 || b.length === 0) { + return [] + } + const n = this.n + const resLen = a.length + b.length - 1 + if (resLen > n) { + throw new Error( + `a.length + b.length - 1 is ${a.length} + ${b.length} - 1 = ${resLen}, ` + + `expected <= ${n}` + ) + } + const cr = new Array(n).fill(0) + const ci = new Array(n).fill(0) + // cr.splice(0, a.length, ...a) + for (let i = 0; i < a.length; i++) { + cr[i] = a[i] + } + // ci.splice(0, b.length, ...b) + for (let i = 0; i < b.length; i++) { + ci[i] = b[i] + } + this.transform(cr, ci) + + cr[0] = 4 * cr[0] * ci[0] + ci[0] = 0 + for (let i = 1, j = n - 1; i <= j; i++, j--) { + const ar = cr[i] + cr[j] + const ai = ci[i] - ci[j] + const br = ci[j] + ci[i] + const bi = cr[j] - cr[i] + cr[i] = ar * br - ai * bi + ci[i] = ar * bi + ai * br + cr[j] = cr[i] + ci[j] = -ci[i] + } + + this.transform(cr, ci) + const res = [] + res[0] = cr[0] / (4 * n) + for (let i = 1, j = n - 1; i <= j; i++, j--) { + res[i] = cr[j] / (4 * n) + res[j] = cr[i] / (4 * n) + } + res.splice(resLen) + return res + } +} diff --git a/src/content/utils/index.ts b/src/content/utils/index.ts new file mode 100644 index 0000000..fc96ec9 --- /dev/null +++ b/src/content/utils/index.ts @@ -0,0 +1,3 @@ +export * from './utils' +export * from './leetcode-api' +export * from './predict' diff --git a/src/content/utils/leetcode-api.ts b/src/content/utils/leetcode-api.ts new file mode 100644 index 0000000..307b21f --- /dev/null +++ b/src/content/utils/leetcode-api.ts @@ -0,0 +1,2322 @@ +import { previousMonday } from 'date-fns/fp' +import JSON5 from 'json5' +import { logger } from '../../utils' +import { isObject, sleep } from './utils' + +const log = logger.child({ prefix: 'page-utils' }) + +export function globalGetStatusText(e: number): string { + switch (e) { + case 10: + return 'Accepted' + case 11: + return 'Wrong Answer' + case 12: + return 'Memory Limit Exceeded' + case 13: + return 'Output Limit Exceeded' + case 14: + return 'Time Limit Exceeded' + case 15: + return 'Runtime Error' + case 16: + return 'Internal Error' + case 20: + return 'Compile Error' + case 21: + return 'Unknown Error' + case 30: + return 'Timeout' + default: + return 'Invalid Error Code' + } +} + +export function graphqlApi<T>( + REGION_URL: string, + { + endpoint, + method, + body, + }: { endpoint?: string; method?: string; body?: unknown }, + retry = 1 +): Promise<T> { + method = method || 'POST' + const RETRY_TIME = 3000, + RETRY_COUNT = 5 + const url = endpoint ? `${REGION_URL}/${endpoint}` : `${REGION_URL}/graphql/` + return fetch(url, { + headers: { + 'content-type': 'application/json', + }, + referrer: `${REGION_URL}/`, + referrerPolicy: 'strict-origin-when-cross-origin', + body: JSON.stringify(body), + method, + mode: 'cors', + credentials: 'include', + }).then(res => { + if (res.status >= 200 && res.status < 300) { + return res.json() + } + + if (res.status === 429) { + log.debug(`超出接口限制,休息一下,等待第${retry}次重试...`) + if (retry > RETRY_COUNT) { + throw new Error( + `已重试 ${RETRY_COUNT} 次,仍然无法获取,可能力扣君生气了,晚点在试试吧...` + ) + } + // 触发限制之后,等一会儿在进行请求 + return sleep(RETRY_TIME).then(() => + graphqlApi(REGION_URL, { method, body }, retry + 1) + ) + } + + throw new Error(`未知状态: ${res.status}`) + }) +} + +export function baseApi( + REGION_URL: string, + url: string, + method = 'GET', + body: null | object = null, + retry = 1 +): Promise<any> { + const RETRY_TIME = 20000, + RETRY_COUNT = 10 + + method = method.toUpperCase() + let bodyStr: null | string + const headers: HeadersInit = { + accept: 'application/json, text/plain, */*', + } + + if (method === 'GET') { + bodyStr = null + } else { + if (isObject(body)) { + bodyStr = isObject(body) ? JSON.stringify(body) : body + headers['content-type'] = 'application/json' + } else { + bodyStr = body + } + } + + return fetch(REGION_URL + url, { + headers, + referrer: location.href, + referrerPolicy: 'strict-origin-when-cross-origin', + body: bodyStr, + method, + mode: 'cors', + credentials: 'include', + }).then(async res => { + if (res.status >= 200 && res.status < 300) { + return res + } + + if (res.status === 429) { + log.debug(`超出接口限制,休息一下,等待第${retry}次重试...`) + if (retry > RETRY_COUNT) { + throw new Error( + `已重试 ${RETRY_COUNT} 次,仍然无法获取,可能力扣君生气了,晚点在试试吧...` + ) + } + // 触发限制之后,等一会儿在进行请求 + return sleep(RETRY_TIME).then(() => + baseApi(REGION_URL, url, method, body, retry + 1) + ) + } + if (res.status === 400) { + let error: string + try { + const data = await res.json() + error = data.error + } catch (error) { + throw new Error(`错误状态: ${res.status}`) + } + throw new Error(error) + } + throw new Error(`未知状态: ${res.status}`) + }) +} + +interface GlobalSubmissionDetail { + submissionData: { + status_code: number + runtime: string + memory: string + total_correct: string + total_testcases: string + compare_result: string + input_formatted: string + input: string + expected_output: string + code_output: string + last_testcase: string + } + questionId: string + submissionId: string + sessionId: string + getLangDisplay: string + submissionCode: string + editCodeUrl: string + checkUrl: string + runtimeDistributionFormatted: string + memoryDistributionFormatted: string + langs: [] + runtime: string + memory: string + enableMemoryDistribution: string + nonSufficientMsg: string +} + +export type SuccessCheckReturnType = { + status_code: number + lang: string + run_success: boolean + status_runtime: string + memory: number + question_id: string + elapsed_time: number + compare_result: string + code_output: string + std_output: string + last_testcase: string + expected_output: string + task_finish_time: number + task_name: string + finished: boolean + state: 'SUCCESS' + fast_submit: boolean + total_correct: number + total_testcases: number + submission_id: string + status_memory: string + memory_percentile: number + pretty_lang: string +} & ( + | { + status_msg: 'Accepted' + runtime_percentile: number + memory_percentile: number + } + | { + status_msg: 'Wrong Answer' + runtime_percentile: null + memory_percentile: null + input_formatted: string + input: string + } +) + +type CheckReturnType = + | { state: 'STARTED' } + | { state: 'PENDING' } + | SuccessCheckReturnType + +export type NotyArticleType = { + summary: string + uuid: string + slug: string + title: string + articleType: 'QAQUESTION' | 'CIRCLE_ARTICLE' | 'SOLUTION' // "CIRCLE_ARTICLE": 文章;"SOLUTION": 题解 + createdAt: string + updatedAt: string + thumbnail: string + author: { + userSlug: string + } + __typename: 'Article' +} +export type NotyLeetBookType = { + summary: string + slug: string + image: string + modifiedAt: string + title: string + __typename: 'LeetBook' +} +export type NotyBookPageType = { + leetbook: { + slug: string + image: string + summary: string + __typename: string + } + title: string + summary: string + __typename: 'BookPage' +} +export type NotyItem = { + nextToken: string + rows: { + feedContent: NotyArticleType | NotyLeetBookType | NotyBookPageType + meta: { link: string } + }[] +} + +export type UserProfilePublicProfile = { + profile: { + userSlug: string + realName: string + } +} | null + +export type QAQuestion = { + ipRegion: string + uuid: string + slug: string + title: string + thumbnail: string + summary: string + content: string + sunk: boolean + pinned: boolean + pinnedGlobally: boolean + byLeetcode: boolean + isRecommended: boolean + isRecommendedGlobally: boolean + subscribed: boolean + hitCount: number + numAnswers: number + numPeopleInvolved: number + numSubscribed: number + createdAt: string + updatedAt: null + status: string + identifier: string + resourceType: string + articleType: string + alwaysShow: false + alwaysExpand: false + score: null + favoriteCount: number + isMyFavorite: false + isAnonymous: false + canEdit: false + reactionType: null + atQuestionTitleSlug: string + reactionsV2: { + count: number + reactionType: string + __typename: string + }[] + tags: { + name: string + nameTranslated: string + slug: string + imgUrl: null + tagType: string + __typename: string + }[] + subject: { + slug: string + title: string + __typename: string + } + contentAuthor: { + username: string + userSlug: string + realName: string + avatar: string + __typename: string + } + realAuthor: null + __typename: string +} | null + +export type SolutionArticle = { + ipRegion: string + rewardEnabled: null + canEditReward: boolean + uuid: string + title: string + slug: string + sunk: boolean + chargeType: string + status: string + identifier: string + canEdit: boolean + canSee: boolean + reactionType: null + hasVideo: boolean + favoriteCount: number + upvoteCount: number + reactionsV2: { + count: number + reactionType: string + }[] + tags: { + name: string + nameTranslated: string + slug: string + tagType: string + }[] + createdAt: string + thumbnail: string + author: { + username: string + profile: { + userAvatar: string + userSlug: string + realName: string + reputation: number + } + } + summary: string + topic: { + id: number + commentCount: number + viewCount: number + pinned: boolean + } + byLeetcode: false + isMyFavorite: false + isMostPopular: false + isEditorsPick: false + hitCount: number + videosInfo: [] +} | null + +export type CommunityArticle = { + slug: string + uuid: string + title: string + author: { + username: string + profile: { + realName: string + userSlug: string + userAvatar: string + __typename: string + } + __typename: string + } +} + +export type GlobalData = { + userStatus: { + isSignedIn: boolean + isPremium: boolean + username: string + realName: string + avatar: string + userSlug: string + isAdmin: boolean + checkedInToday: boolean + useTranslation: boolean + premiumExpiredAt: number + isTranslator: boolean + isSuperuser: boolean + isPhoneVerified: boolean + isVerified: boolean + } + jobsMyCompany: { + nameSlug: string + } | null + commonNojPermissionTypes: any[] +} + +export type ProblemsetQuestion = { + acRate: number + difficulty: 'EASY' | 'MEDIUM' | 'HARD' + freqBar: number + frontendQuestionId: string + isFavor: boolean + paidOnly: boolean + solutionNum: number + status: 'NOT_STARTED' | 'AC' | 'TRIED' + title: string + titleCn: string + titleSlug: string + topicTags: Array<{ + name: string + nameTranslated: string + id: string + slug: string + }> + extra: Array<{ + companyTagNum: number + hasVideoSolution: boolean + topCompanyTags: { + imgUrl: string + slug: string + numSubscribed: number + } + }> +} + +export type ProblemsetQuestionList = { + hasMore: boolean + total: number + questions: ProblemsetQuestion[] + __typename: string +} + +export type QuestionType = { + translatedTitle: string + title: string + questionFrontendId: string + titleSlug: string + questionId: string + categoryTitle: string + isPaidOnly: boolean + status: string + difficulty: string + __typename: string +} + +export type Favorite = { + idHash: string + name: string + id: string + isPublicFavorite: boolean + viewCount: number + questions: { + questionId: string + title: string + titleSlug: string + __typename: string + }[] + topic_id: number + __typename: string +} + +export type FavoriteDetail = { + description: string + idHash: string + name: string + creator: { + realName: string + userAvatar: string + userSlug: string + } + link: string + isFavored: boolean + coverUrl: string + questionIds: number[] + tags: { + name: string + nameTranslated: string + slug: string + tagType: string + }[] + __typename: string +} + +export type AddFavoriteResult = { + ok: boolean + error: null | string + name: string + isPublicFavorite: boolean + favoriteIdHash: string + questionId: string + __typename: string +} +export type RemoveFavoriteResult = { + error: null | string + favoriteIdHash: string + ok: boolean + questionId: string +} + +export type ProblemsetPageProps = { + featuredLists: Pick< + FavoriteDetail, + 'coverUrl' | 'creator' | 'description' | 'idHash' | 'link' | 'name' | 'tags' + >[] +} + +export type CategorySlugType = + | '' + | 'all-code-essentials' + | 'algorithms' + | 'database' + | 'shell' + | 'concurrency' + | 'pandas' + | 'javascript' + +export type ProblemsetQuestionListFilterType = { + listId?: string + difficulty?: 'EASY' | 'MEDIUM' | 'HARD' + status?: 'NOT_STARTED' | 'AC' | 'TRIED' + tags?: string[] + premiumOnly?: boolean + orderBy?: + | 'FRONTEND_ID' + | 'SOLUTION_NUM' + | 'AC_RATE' + | 'DIFFICULTY' + | 'FREQUENCY' + sortOrder?: 'DESCENDING' | 'ASCENDING' + searchKeywords?: string +} + +export type userProfileQuestion = { + difficulty: 'EASY' | 'MEDIUM' | 'HARD' + frontendId: `${number}` + lastSubmissionSrc: null + lastSubmittedAt: number + numSubmitted: number + title: string + titleSlug: string + translatedTitle: string + __typename: 'ProgressQuestionNode' +} + +export type QuestionStatus = 'ACCEPTED' | 'FAILED' | 'UNTOUCHED' + +export type ContestInfo = { + contest: { + id: number + title: string + title_slug: string + duration: number + start_time: number + is_virtual: boolean + origin_start_time: number + is_private: boolean + } + questions: Question[] +} + +export type MyRanking = { + my_submission: { + [solvedId: string]: { + contest_id: number + data_region: string + date: number + fail_count: number + id: number + lang: string + question_id: number + status: number + submission_id: number + } + } + my_rank: { + contest_id: number + username: string + user_slug: string + real_name: string + country_code: string + country_name: string + rank: number + score: number + finish_time: number + global_ranking: number + data_region: string + avatar_url: string + rank_v2: number + } + my_solved: number[] + registered: boolean +} + +export type ContestRanking = { + attendedContestsCount: number + globalRanking: number + globalTotalParticipants: number + localRanking: number + localTotalParticipants: number + rating: number + topPercentage: number +} + +export type Rating = { + userContestRanking: ContestRanking + userContestRankingHistory: { + finishTimeInSeconds: number + ranking: number + rating: number + score: number + totalProblems: number + trendingDirection: null + attended: boolean + contest: { + startTime: number + title: string + titleCn: string + } + }[] +} + +export type SubmissionType = { + id: number + date: number + question_id: number + submission_id: number + status: number + contest_id: number + data_region: string + fail_count: number + lang: string +} + +export type RankType = { + contest_id: number + username: string + user_slug: string + real_name: string + country_code: string + country_name: string + rank: number + score: number + finish_time: number + global_ranking: number + data_region: string + avatar_url: string + rank_v2: number +} +export type Question = { + id: number + question_id: number + credit: number + title: string + english_title: string + title_slug: string + category_slug: string +} +export type RankingDataType = { + is_past: boolean + submissions: { + [key: number]: SubmissionType + }[] + questions: Question[] + total_rank: RankType[] + user_num: number +} + +class LeetCodeApi { + public graphqlApi: ( + { method, body }: { endpoint?: string; method?: string; body?: unknown }, + retry?: number + ) => Promise<any> + public baseApi: ( + url: string, + method?: string | undefined, + body?: object | null | undefined, + retry?: number | undefined + ) => Promise<any> + public REGION_URL: string + + public constructor(REGION_URL: string) { + this.REGION_URL = REGION_URL + this.graphqlApi = graphqlApi.bind(null, REGION_URL) + this.baseApi = baseApi.bind(null, REGION_URL) + } + + /** 获取所有题目 + * + * @param useCache 是否使用缓存,使用缓存的话,会将查询结果缓存到 LocalStorage 中,更新间隔为每个礼拜一,如果发现上次缓存是在礼拜一之前的话,就重新获取 + * TODO: 重新设计使用缓存时机 + * 通过判断当前官网拥有的题目总数量,来决定要不要更新 + * 通过判断官网最小的一题是否在缓存中,来决定是否要更新 + */ + public async getAllQuestions(useCache = true): Promise<QuestionType[]> { + if (useCache) { + const cache = localStorage.getItem('lc-extend:allQuestions') + if (cache) { + try { + const res = JSON.parse(cache) + if (res.update && new Date(res.update) > previousMonday(new Date())) { + return res.questions + } + } catch (error) { + console.log('解析缓存失败') + } + } + } + const body = { + operationName: 'allQuestions', + variables: {}, + query: /* GraphQL */ ` + query allQuestions { + allQuestions { + title + titleSlug + translatedTitle + questionId + questionFrontendId + status + difficulty + isPaidOnly + categoryTitle + __typename + } + } + `, + } + + return this.graphqlApi({ body }).then(data => { + const questions = data?.data?.allQuestions + if (questions) { + localStorage.setItem( + 'lc-extend:allQuestions', + JSON.stringify({ questions: questions, update: new Date() }) + ) + return questions + } + throw new Error('获取题目列表失败,返回结果为: ' + JSON.stringify(data)) + }) + } + + /** 获取提交列表 + * + */ + public async getSubmissions( + questionSlug: string, + limit = 40, + offset = 0 + ): Promise<{ + lastKey: string + hasNext: boolean + submissions: { + id: string + statusDisplay: string + lang: string + runtime: string + timestamp: string + url: string + isPending: string + memory: string + submissionComment: { + comment: string + flagType: string + __typename: string + } + __typename: string + }[] + __typename: string + }> { + const body = { + operationName: 'submissions', + variables: { + offset, + limit, + lastKey: null, + questionSlug, + }, + query: /* GraphQL */ ` + query submissions( + $offset: Int! + $limit: Int! + $lastKey: String + $questionSlug: String! + ) { + submissionList( + offset: $offset + limit: $limit + lastKey: $lastKey + questionSlug: $questionSlug + ) { + lastKey + hasNext + submissions { + id + statusDisplay + lang + runtime + timestamp + url + isPending + memory + __typename + } + __typename + } + } + `, + } + return this.graphqlApi({ body }).then(({ data }) => data.submissionList) + } + + /** 获取提交详情 + * + */ + private async getSubmissionDetailByLocal(submissionId: string): Promise<{ + id: string + code: string + runtime: string + memory: string + rawMemory: string + statusDisplay: string + timestamp: number + lang: string + passedTestCaseCnt: number + totalTestCaseCnt: number + sourceUrl: string + question: { + titleSlug: string + title: string + translatedTitle: string + questionId: string + __typename: string + } + outputDetail: { + codeOutput: string + expectedOutput: string + input: string + compileError: string + runtimeError: string + lastTestcase: string + __typename: string + } + __typename: string + submissionComment: null + }> { + const body = { + operationName: 'mySubmissionDetail', + variables: { id: submissionId }, + query: /* GraphQL */ ` + query mySubmissionDetail($id: ID!) { + submissionDetail(submissionId: $id) { + id + code + runtime + memory + rawMemory + statusDisplay + timestamp + lang + passedTestCaseCnt + totalTestCaseCnt + sourceUrl + question { + titleSlug + title + translatedTitle + questionId + __typename + } + ... on GeneralSubmissionNode { + outputDetail { + codeOutput + expectedOutput + input + compileError + runtimeError + lastTestcase + __typename + } + __typename + } + submissionComment { + comment + flagType + __typename + } + __typename + } + } + `, + } + + return this.graphqlApi({ body }).then(({ data }) => data.submissionDetail) + } + + /** 获取提交分布信息 + * + */ + private async getDistributionLocal(submissionId: string): Promise<{ + runtimeDistribution: { + lang: string + distribution: [string, number][] + } | null + memoryDistribution: { + lang: string + distribution: [string, number][] + } | null + }> { + const runtimeApi = `/submissions/api/runtime_distribution/${submissionId}/` + const runtimeDistribution = await this.baseApi(runtimeApi) + .then(res => res.json()) + .then(({ runtime_distribution_formatted }) => + runtime_distribution_formatted + ? JSON.parse(runtime_distribution_formatted) + : null + ) + const memoryApi = `/submissions/api/memory_distribution/${submissionId}/` + const memoryDistribution = await this.baseApi(memoryApi) + .then(res => res.json()) + .then(({ memory_distribution_formatted }) => + memory_distribution_formatted + ? JSON.parse(memory_distribution_formatted) + : null + ) + + return { runtimeDistribution, memoryDistribution } + } + + /** 获取提交详情(世界服) + * + */ + private async getSubmissionDetailByGlobal( + submissionId: string + ): Promise<GlobalSubmissionDetail> { + const text = await fetch( + `https://leetcode.com/submissions/detail/${submissionId}/`, + { + headers: { + accept: + 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9', + }, + referrer: 'https://leetcode.com/', + referrerPolicy: 'strict-origin-when-cross-origin', + body: null, + method: 'GET', + mode: 'cors', + credentials: 'include', + } + ).then(res => res.text()) + + const dataText = text.match(/var pageData = ([\d\D]+?});/)?.[1] + + const data = eval(`(function (){return ${dataText}})()`) + + return data + } + + /** 获取提交详情,根据当前 REGION_URL 确定是从国服还是世界服获取 + * + */ + public async getSubmissionDetail(submissionId: string): Promise<{ + id: string // submissionId + code: string // submissionCode + runtime: string // runtime + memory: string // submissionData.memory + rawMemory: string // memory + statusDisplay: string // status_code + // timestamp: string + lang: string // getLangDisplay + passedTestCaseCnt: number // submissionData.total_correct + totalTestCaseCnt: number // submissionData.total_testcases + sourceUrl: string // editCodeUrl + questionId: string + runtimeDistribution?: { lang: string; distribution: [string, number][] } + memoryDistribution?: { lang: string; distribution: [string, number][] } + }> { + if (/(leetcode-cn\.com)|(leetcode\.cn)/.test(this.REGION_URL)) { + const data = await this.getSubmissionDetailByLocal(submissionId) + const { runtimeDistribution, memoryDistribution } = + await this.getDistributionLocal(submissionId) + return { + ...data, + questionId: data.question.questionId, + runtimeDistribution: runtimeDistribution + ? runtimeDistribution + : { lang: data.lang, distribution: [] }, + memoryDistribution: memoryDistribution + ? memoryDistribution + : { + lang: data.lang, + distribution: [], + }, + } + } else { + const data = await this.getSubmissionDetailByGlobal(submissionId) + return { + id: data.submissionId, + code: data.submissionCode, + runtime: data.runtime, + memory: data.submissionData.memory, + rawMemory: data.memory, + statusDisplay: globalGetStatusText(data.submissionData.status_code), + lang: data.getLangDisplay, + passedTestCaseCnt: Number(data.submissionData.total_correct), + totalTestCaseCnt: Number(data.submissionData.total_testcases), + sourceUrl: data.editCodeUrl, + questionId: data.questionId, + runtimeDistribution: JSON.parse(data.runtimeDistributionFormatted), + memoryDistribution: JSON.parse(data.memoryDistributionFormatted), + } + } + } + + /** 获取对应提交时间的详细代码(旧版) + * + */ + public getCodeByTime( + lang: string, + questionId: string, + time: string + ): Promise<string> { + const api = `/submissions/api/detail/${questionId}/${lang}/${time}/` + + return this.baseApi(api) + .then(res => res.json()) + .then(data => data.code) + } + + /** 获取对应提交内存的详细代码(旧版) + * + */ + public getCodeByMemory( + lang: string, + questionId: string, + memory: string + ): Promise<string> { + const api = `/submissions/api/detail/${questionId}/${lang}/memory/${memory}/` + + return this.baseApi(api) + .then(res => res.json()) + .then(data => data.code) + } + + /** 检查对应提交的状态 + * + */ + public check(submissionId: string): Promise<CheckReturnType> { + const api = `/submissions/detail/${submissionId}/check/` + return this.baseApi(api).then(res => res.json()) + } + + /** 添加备注信息 + * + */ + public submissionCreateOrUpdateSubmissionComment( + submissionId: string, + flagType: 'BLUE' | 'ORANGE' | 'GREEN' | 'PURPLE' | 'RED', + comment: string + ): Promise<{ ok: boolean; __typename: string }> { + const body = { + operationName: 'submissionCreateOrUpdateSubmissionComment', + variables: { + submissionId: submissionId, + flagType: flagType, + comment: comment, + }, + query: /* GraphQL */ ` + mutation submissionCreateOrUpdateSubmissionComment( + $submissionId: ID! + $flagType: SubmissionFlagTypeEnum! + $comment: String! + ) { + submissionCreateOrUpdateSubmissionComment( + comment: $comment + flagType: $flagType + submissionId: $submissionId + ) { + ok + __typename + } + } + `, + } + + return this.graphqlApi({ body }).then( + ({ data }) => data.submissionCreateOrUpdateSubmissionComment + ) + } + + /** 获取首页帖子列表 + * + * @param nextToken 下一组帖子的 token,如果为空,则获取最新的一组帖子 + */ + public getNoty(nextToken = '', limit = 30): Promise<NotyItem> { + const body = { + operationName: 'myFeed', + variables: { version: 1, nextToken, limit }, + query: /* GraphQL */ ` + query myFeed($nextToken: String, $limit: Int!, $version: Int) { + myFeed(nextToken: $nextToken, limit: $limit, version: $version) { + nextToken + rows { + tags { + name + slug + tagType + __typename + } + feedContent { + ... on Article { + summary + uuid + slug + title + articleType + createdAt + updatedAt + thumbnail + author { + userSlug + } + __typename + } + ... on LeetBook { + summary + slug + image + modifiedAt + title + __typename + } + ... on BookPage { + leetbook { + slug + image + summary + __typename + } + title + summary + __typename + } + __typename + } + actor { + userSlug + avatar + realName + __typename + } + verb + subscribed + timestamp + recommended + questionInfo { + title + Slug + __typename + } + meta { + link + __typename + } + __typename + } + __typename + } + } + `, + } + return this.graphqlApi({ endpoint: 'graphql/noty', body }).then( + ({ data }) => data.myFeed + ) + } + + /** 获取用户信息 + * + * @param slug 用户 slug + */ + public getUserInfoBySlug(slug: string): Promise<UserProfilePublicProfile> { + const body = { + query: /* GraphQL */ ` + query userProfilePublicProfile($userSlug: String!) { + userProfilePublicProfile(userSlug: $userSlug) { + haveFollowed + siteRanking + profile { + userSlug + realName + aboutMe + asciiCode + userAvatar + gender + websites + skillTags + globalLocation { + country + province + city + } + socialAccounts { + provider + profileUrl + } + skillSet { + langLevels { + langName + langVerboseName + level + } + topics { + slug + name + translatedName + } + topicAreaScores { + score + topicArea { + name + slug + } + } + } + } + educationRecordList { + unverifiedOrganizationName + } + occupationRecordList { + unverifiedOrganizationName + jobTitle + } + } + } + `, + variables: { userSlug: slug }, + } + + return this.graphqlApi({ body }).then( + ({ data }) => data.userProfilePublicProfile + ) + } + + /** 获取讨论帖信息 + * + */ + public queryQAQuestionByUUID(uuid: string): Promise<QAQuestion> { + const body = { + operationName: 'qaQuestion', + variables: { + uuid, + }, + query: /* GraphQL */ ` + query qaQuestion($uuid: ID!) { + qaQuestion(uuid: $uuid) { + ...qaQuestion + __typename + } + } + + fragment qaQuestion on QAQuestionNode { + ipRegion + uuid + slug + title + thumbnail + summary + content + sunk + pinned + pinnedGlobally + byLeetcode + isRecommended + isRecommendedGlobally + subscribed + hitCount + numAnswers + numPeopleInvolved + numSubscribed + createdAt + updatedAt + status + identifier + resourceType + articleType + alwaysShow + alwaysExpand + score + favoriteCount + isMyFavorite + isAnonymous + canEdit + reactionType + atQuestionTitleSlug + reactionsV2 { + count + reactionType + __typename + } + tags { + name + nameTranslated + slug + imgUrl + tagType + __typename + } + subject { + slug + title + __typename + } + contentAuthor { + ...contentAuthor + __typename + } + realAuthor { + ...realAuthor + __typename + } + __typename + } + + fragment contentAuthor on ArticleAuthor { + username + userSlug + realName + avatar + __typename + } + + fragment realAuthor on UserNode { + username + profile { + userSlug + realName + userAvatar + __typename + } + __typename + } + `, + } + + return this.graphqlApi({ body }).then(({ data }) => data.qaQuestion) + } + + /** 获取题解信息 + * + */ + public querySolutionArticleBySlug(slug: string): Promise<SolutionArticle> { + const body = { + query: /* GraphQL */ ` + query solutionArticle($slug: String!) { + solutionArticle(slug: $slug) { + ipRegion + rewardEnabled + canEditReward + uuid + title + slug + sunk + chargeType + status + identifier + canEdit + canSee + reactionType + hasVideo + favoriteCount + upvoteCount + reactionsV2 { + count + reactionType + } + tags { + name + nameTranslated + slug + tagType + } + createdAt + thumbnail + author { + username + profile { + userAvatar + userSlug + realName + reputation + } + } + summary + topic { + id + commentCount + viewCount + pinned + } + byLeetcode + isMyFavorite + isMostPopular + isEditorsPick + hitCount + videosInfo { + videoId + coverUrl + duration + } + } + } + `, + variables: { + slug, + }, + } + return this.graphqlApi({ body }).then(({ data }) => data.solutionArticle) + } + /** 获取共享文章信息 + * + */ + public queryCommunityArticleBySlug(slug: string): Promise<CommunityArticle> { + const body = { + operationName: 'columnsArticle', + variables: { + slug, + }, + query: /* GraphQL */ ` + query columnsArticle($slug: String!) { + columnsArticle(slug: $slug) { + ...communityArticle + __typename + } + } + + fragment communityArticle on ColumnArticleNode { + slug + uuid + title + hitCount + pinnedGlobally + pinned + sunk + createdAt + updatedAt + thumbnail + identifier + resourceType + articleType + score + subject { + title + slug + __typename + } + tags { + name + slug + nameTranslated + __typename + } + author { + username + profile { + userSlug + realName + userAvatar + __typename + } + __typename + } + reactionType + reactionsV2 { + count + reactionType + __typename + } + isMyFavorite + topic { + id + commentCount + __typename + } + summary + isEditorsPick + byLeetcode + status + favoriteCount + __typename + } + `, + } + return this.graphqlApi({ body }).then(({ data }) => data.columnsArticle) + } + /** 获取共享文章信息 + * + */ + public queryCommunityArticleById(id: string): Promise<CommunityArticle> { + const body = { + operationName: 'communityArticleDetail', + variables: { id }, + query: /* GraphQL */ ` + query communityArticleDetail($id: ID!) { + columnsArticleById(uuid: $id) { + ...communityArticleDetail + __typename + } + } + + fragment communityArticleDetail on ColumnArticleNode { + ipRegion + slug + uuid + title + thumbnail + content + reactionType + reactionsV2 { + count + reactionType + __typename + } + hitCount + createdAt + updatedAt + subscribed + isMyFavorite + identifier + resourceType + pinnedGlobally + pinned + sunk + isEditorsPick + byLeetcode + articleType + status + summary + author { + username + profile { + realName + userSlug + userAvatar + __typename + } + __typename + } + tags { + name + slug + nameTranslated + tagType + __typename + } + subject { + title + slug + __typename + } + topic { + id + lastComment { + post { + creationDate + __typename + } + __typename + } + __typename + } + nextArticle { + title + uuid + __typename + } + __typename + } + `, + } + return this.graphqlApi({ body }).then(({ data }) => data.columnsArticleById) + } + + /** 获取全局状态 + * + */ + public queryGlobalData(): Promise<GlobalData> { + const body = { + variables: {}, + query: /* GraphQL */ ` + query globalData { + userStatus { + isSignedIn + isPremium + username + realName + avatar + userSlug + isAdmin + checkedInToday + useTranslation + premiumExpiredAt + isTranslator + isSuperuser + isPhoneVerified + isVerified + } + jobsMyCompany { + nameSlug + } + commonNojPermissionTypes + } + `, + } + return this.graphqlApi({ body }).then(({ data }) => data) + } + + /** 获取题单题目列表 + * + */ + public async getProblemsetQuestionList({ + categorySlug = '', + skip = 0, + limit = 100, + filters = {}, + }: { + categorySlug?: CategorySlugType + skip?: number + limit?: number + filters?: ProblemsetQuestionListFilterType + } = {}): Promise<ProblemsetQuestionList> { + const body = { + operationName: 'problemsetQuestionList', + query: /* GraphQL */ ` + query problemsetQuestionList( + $categorySlug: String + $limit: Int + $skip: Int + $filters: QuestionListFilterInput + ) { + problemsetQuestionList( + categorySlug: $categorySlug + limit: $limit + skip: $skip + filters: $filters + ) { + hasMore + total + questions { + acRate + difficulty + freqBar + frontendQuestionId + isFavor + paidOnly + solutionNum + status + title + titleCn + titleSlug + topicTags { + name + nameTranslated + id + slug + } + extra { + hasVideoSolution + topCompanyTags { + imgUrl + slug + numSubscribed + } + } + } + } + } + `, + variables: { categorySlug, skip, limit, filters }, + } + return this.graphqlApi({ body }).then( + ({ data }) => data.problemsetQuestionList + ) + } + + /** 获取筛选过后的列表的所有题目 + * + * // TODO: 如果获取的总数过大,一次请求有可能会造成超时,尝试分成多次请求 + */ + public async getProblemsetQuestionListAll( + { + categorySlug = '', + filters = {}, + }: { + categorySlug?: CategorySlugType + filters?: ProblemsetQuestionListFilterType + } = {}, + total?: number + ): Promise<ProblemsetQuestion[]> { + // 获取列表中题目的总数量 + if (total === undefined) { + total = ( + await this.getProblemsetQuestionList({ + categorySlug, + filters, + skip: 0, + limit: 1, + }) + ).total + } + const n = Math.ceil(total / 100) + const filterStr = JSON5.stringify(filters, { quote: '"' }) + + const str = [...new Array(n).keys()].map( + i => /* GraphQL */ ` + q${i}: problemsetQuestionList( + categorySlug: "${categorySlug}", + limit: 100, + skip: ${i * 100}, + filters: ${filterStr} + ) { + ...questionFragment + }` + ) + + const body = { + operationName: 'problemsetQuestionList', + query: /* GraphQL */ ` + query problemsetQuestionList { + ${str} + } + fragment questionFragment on QuestionListNode { + hasMore + total + questions { + acRate + difficulty + freqBar + frontendQuestionId + isFavor + paidOnly + solutionNum + status + title + titleCn + titleSlug + topicTags { + name + nameTranslated + id + slug + } + extra { + hasVideoSolution + topCompanyTags { + imgUrl + slug + numSubscribed + } + } + } + __typename + } + `, + variables: {}, + } + const { data } = await this.graphqlApi({ body }) + const res: ProblemsetQuestion[] = [] + for (let i = 0; i < n; i++) { + res.push(...data[`q${i}`].questions) + } + return res + } + + public async getAllQuestion(): Promise< + Map<CategorySlugType, ProblemsetQuestion[]> + > { + const CategorySlugs = [ + 'algorithms', + 'database', + 'shell', + 'concurrency', + 'pandas', + 'javascript', + ] as const + const res = new Map<CategorySlugType, ProblemsetQuestion[]>([ + ['all-code-essentials', []], + ]), + set = new Set<string>() + for (const categorySlug of CategorySlugs) { + if (!res.has(categorySlug)) res.set(categorySlug, []) + const questions = await this.getProblemsetQuestionListAll({ + categorySlug, + }) + for (const question of questions) { + if (!set.has(question.titleSlug)) { + res.get('all-code-essentials')!.push(question) + set.add(question.titleSlug) + } + res.get(categorySlug)!.push(question) + } + } + return res + } + + /** 获取题单(收藏夹)列表,包括自己创建的和官方题单 + * + */ + public getFavorites(): Promise<{ + allFavorites: Favorite[] + officialFavorites: Favorite[] + }> { + const body = { + operationName: 'allFavorites', + variables: {}, + query: /* GraphQL */ ` + query allFavorites { + favoritesLists { + allFavorites { + idHash + name + isPublicFavorite + questions { + questionId + __typename + } + __typename + } + officialFavorites { + idHash + name + questions { + questionId + __typename + } + __typename + } + __typename + } + } + `, + } + return this.graphqlApi({ body }).then(({ data }) => data.favoritesLists) + } + + /** 获取题单(收藏夹)列表,包括自己创建的和收藏的第三方题单 + * + */ + public async getFavoriteMyFavorites( + limit = 20, + skip = 0 + ): Promise<FavoriteDetail[]> { + const body = { + operationName: 'favoriteMyFavorites', + variables: { limit, skip }, + query: /* GraphQL */ ` + query favoriteMyFavorites($limit: Int, $skip: Int) { + __typename + favoriteMyFavorites(limit: $limit, skip: $skip) { + hasMore + total + favorites { + acNumber + coverUrl + created + isPublicFavorite + name + link + idHash + questionNumber + creator { + realName + userSlug + __typename + } + __typename + } + __typename + } + } + `, + } + const data = await this.graphqlApi({ body }).then( + ({ data }) => data.favoriteMyFavorites + ) + + if (data.hasMore) { + const next = await this.getFavoriteMyFavorites(20, limit + skip) + data.favorites = data.favorites.concat(next) + } + return data.favorites + } + + /** 获取题单(收藏夹)详细信息 + * + */ + public async getFavoriteDetail( + favoriteIdHashs: string[] + ): Promise<FavoriteDetail[]> { + const body = { + query: /* GraphQL */ ` + query featuredListDetail { + ${favoriteIdHashs.map( + (favoriteIdHash, i) => /* GraphQL */ ` + favorite_${i}:favoriteDetail(favoriteIdHash:"${favoriteIdHash}" ) { + description + idHash + name + creator { + realName + userAvatar + userSlug + } + link + isFavored + coverUrl + questionIds + tags { + name + nameTranslated + slug + tagType + } + __typename + }` + )} + + } + `, + operationName: 'featuredListDetail', + variables: {}, + } + + const data = await this.graphqlApi({ body }).then(({ data }) => data) + const res: FavoriteDetail[] = [] + for (let i = 0; i < favoriteIdHashs.length; i++) { + res[i] = data[`favorite_${i}`] + } + return res + } + + /** 添加题单(收藏夹) + * + */ + public async addFavorite(favoriteName: string): Promise<AddFavoriteResult> { + const body = { + operationName: 'addQuestionToNewFavorite', + variables: { + questionId: '1', + isPublicFavorite: false, + name: favoriteName, + }, + query: /* GraphQL */ ` + mutation addQuestionToNewFavorite( + $name: String! + $isPublicFavorite: Boolean! + $questionId: String! + ) { + addQuestionToNewFavorite( + name: $name + isPublicFavorite: $isPublicFavorite + questionId: $questionId + ) { + ok + error + name + isPublicFavorite + favoriteIdHash + questionId + __typename + } + } + `, + } + const res = (await this.graphqlApi({ body }).then( + ({ data }) => data.addQuestionToNewFavorite + )) as AddFavoriteResult + if (!res.ok) { + throw new Error(res.error!) + } + await this.deleteQuestionFromFavorite(res.favoriteIdHash, ['1']) + return res + } + + /** 删除除单(收藏夹) + * + */ + public async deleteFavorite(favoriteId: string): Promise<void> { + await this.baseApi(`/list/api/${favoriteId}`, 'DELETE') + } + + /** 删除对第三方除单(收藏夹)的收藏 + * + */ + public async deleteThirdFavorite( + favoriteId: string + ): Promise<{ error: null | string; ok: boolean; __typename: string }> { + const body = { + operationName: 'favoriteRemoveFavoriteFromMyCollection', + variables: { favoriteIdHash: favoriteId }, + query: /* GraphQL */ ` + mutation favoriteRemoveFavoriteFromMyCollection( + $favoriteIdHash: String! + ) { + __typename + favoriteRemoveFavoriteFromMyCollection( + favoriteIdHash: $favoriteIdHash + ) { + error + ok + __typename + } + } + `, + } + + return this.graphqlApi({ body }).then( + ({ data }) => data.favoriteRemoveFavoriteFromMyCollection + ) + } + + /** 批量添加题目到题单(收藏夹)中 + * + * 当一次性添加的熟练超过 100 以后,很大概率会 502, + * 如果超过 100,通过分两次添加 + * + */ + public async addQuestionToFavorite( + favoriteId: string, + questionIds: string[] + ): Promise<{ questionId: string; __typename: string }[]> { + if (questionIds.length > 200) { + throw new Error('题单题目超出上限: 200') + } + if (questionIds.length > 100) { + return ( + await this.addQuestionToFavorite(favoriteId, questionIds.slice(0, 100)) + ).concat( + await this.addQuestionToFavorite(favoriteId, questionIds.slice(100)) + ) + } + const body = { + query: /* GraphQL */ ` + mutation addQuestionToFavorite { + ${questionIds + .map( + (questionId, i) => /* GraphQL */ ` + add${i}: addQuestionToFavorite( + favoriteIdHash: "${favoriteId}", + questionId: "${questionId}") { + questionId + __typename + }` + ) + .join('\n')} + }`, + operationName: 'addQuestionToFavorite', + variables: {}, + } + const { data } = await this.graphqlApi({ body }) + return questionIds.map((_, i) => data[`q${i}`]) + } + + /** 从题单(收藏夹)中的批量删除题目 + * + */ + public async deleteQuestionFromFavorite( + favoriteId: string, + questionIds: string[] + ): Promise<RemoveFavoriteResult[]> { + const str = questionIds.map( + (id, i) => /* GraphQL */ ` + q${i}: removeQuestionFromFavorite( + favoriteIdHash: "${favoriteId}" + questionId: "${id}" + ) { + ok + error + favoriteIdHash + questionId + }` + ) + const body = { + query: /* GraphQL */ ` + mutation removeQuestionFromFavorite { + ${str} + } + `, + variables: {}, + } + const res: RemoveFavoriteResult[] = [] + const { data } = await this.graphqlApi({ body }) + for (let i = 0; i < questionIds.length; i++) { + res[i] = data[`q${i}`] + } + return res + } + + /** 更新题单(收藏夹)信息 + * + * 可以通过不传递 name 和 is_public_favorite 检测当前是否处于审核状态 + */ + public async setFavorite(data: { + favorite_id_hash: string + name?: string + is_public_favorite?: boolean + }): Promise<void> { + await this.baseApi(`/list/api/`, 'PUT', data) + } + + /** 获取 PageProps + * + * 其中包含 featuredLists(精选题单的列表) + * + */ + public getProblemsetPageProps(): Promise<ProblemsetPageProps> { + return this.baseApi( + `/_next/data/${ + (window as any).__NEXT_DATA__.buildId + }/problemset/all.json?slug=all` + ) + .then(res => res.json()) + .then(res => res.pageProps) + } + + /** 查询当前用户题目的状态 + * + */ + public async queryQuestionsStatus( + skip = 0, + limit = 100, + status: QuestionStatus = 'ACCEPTED', + sortField: + | 'LAST_SUBMITTED_AT' + | 'QUESTION_FRONTEND_ID' + | 'NUM_SUBMITTED' = 'LAST_SUBMITTED_AT', + sortOrder: 'ASCENDING' | 'DESCENDING' = 'DESCENDING', + difficulty: ('EASY' | 'MEDIUM' | 'HARD')[] = [] + ): Promise<{ questions: userProfileQuestion[]; totalNum: number }> { + const body = { + operationName: 'userProfileQuestions', + variables: { + status, + skip, + first: limit, + sortField, + sortOrder, + difficulty, + }, + query: /* GraphQL */ ` + query userProfileQuestions( + $status: StatusFilterEnum! + $skip: Int! + $first: Int! + $sortField: SortFieldEnum! + $sortOrder: SortingOrderEnum! + $keyword: String + $difficulty: [DifficultyEnum!] + ) { + userProfileQuestions( + status: $status + skip: $skip + first: $first + sortField: $sortField + sortOrder: $sortOrder + keyword: $keyword + difficulty: $difficulty + ) { + totalNum + questions { + translatedTitle + frontendId + titleSlug + title + difficulty + lastSubmittedAt + numSubmitted + lastSubmissionSrc { + sourceType + ... on SubmissionSrcLeetbookNode { + slug + title + pageId + __typename + } + __typename + } + __typename + } + __typename + } + } + `, + } + return this.graphqlApi({ body }).then( + ({ data }) => data.userProfileQuestions + ) + } + + /** 查询最近某种状态的题目 + * + */ + public async queryACQuestions( + last: Date, + status: QuestionStatus = 'ACCEPTED', + skip = 0, + limit = 100 + ): Promise<userProfileQuestion[]> { + const compare = (q: userProfileQuestion) => + q.lastSubmittedAt * 1000 >= last.valueOf() + const { questions, totalNum } = await this.queryQuestionsStatus( + skip, + limit, + status + ) + if (!questions.length) return [] + if (!compare(questions.at(-1)!)) { + // 因为是按照提交日期排序的,并且当前拿到的最后一个元素已经是在指定日期之前的, + // 那后面就肯定没有满足要求的提交,可以不用在继续请求,直接返回当前满足条件的题目提交 + return questions.filter(compare) + } + if (skip + limit >= totalNum) { + // 已经没有更多提交了 + return questions + } + return questions.concat( + await this.queryACQuestions(last, status, skip + limit, limit) + ) + } + + public async getContestInfo(contestSlug: string): Promise<ContestInfo> { + return this.baseApi(`/contest/api/info/${contestSlug}/`).then(res => + res.json() + ) + } + public async getGlobalyRanking(contestSlug: string): Promise<MyRanking> { + return this.baseApi( + `/contest/api/myranking/${contestSlug}/?region=global` + ).then(res => res.json()) + } + public async getContest( + contestSlug: string, + page: number, + region: 'local' | 'global' = 'local' + ): Promise<RankingDataType> { + return this.baseApi( + `/contest/api/ranking/${contestSlug}/?pagination=${page}®ion=${region}` + ).then(res => res.json()) + } + + public getRating( + userSlug: string, + hasHistory?: false + ): Promise<{ userContestRanking: ContestRanking }> + public getRating(userSlug: string, hasHistory: true): Promise<Rating> + public getRating(userSlug: string, hasHistory?: boolean): Promise<Rating> { + const body = { + variables: { userSlug }, + query: /* GraphQL */ ` + query userContestRankingInfo($userSlug: String!) { + userContestRanking(userSlug: $userSlug) { + attendedContestsCount + rating + globalRanking + localRanking + globalTotalParticipants + localTotalParticipants + topPercentage + } + ${ + hasHistory + ? /* GraphQL */ ` + userContestRankingHistory(userSlug: $userSlug) { + attended + totalProblems + trendingDirection + finishTimeInSeconds + rating + score + ranking + contest { + title + titleCn + startTime + } + }` + : '' + } + } + `, + } + return this.graphqlApi({ endpoint: 'graphql/noj-go/', body }).then( + ({ data }) => data + ) + } +} + +export { LeetCodeApi } diff --git a/src/content/utils/predict.ts b/src/content/utils/predict.ts new file mode 100755 index 0000000..e29cb82 --- /dev/null +++ b/src/content/utils/predict.ts @@ -0,0 +1,99 @@ +import { FFTConv } from './conv' + +/** + * @param k 参赛次数 + */ +const f = (() => { + let cache: number[] + return (k: number) => { + if (k > 100) return 3.5 + if (!cache) { + cache = [] + for (let i = 0; i <= 100; i++) { + cache[i] = (cache[i - 1] ?? 0) + Math.pow(5 / 7, i) + } + } + return cache[k] ?? 3.5 + } +})() + +/** 预测算法 + * + * @param seeds 种子数据 + * @param rating 当前选手的分数 + * @param rank 当前算寿的排名 + * @param attendedContestsCount 当前选手参赛次数 + * @returns + */ +export const predict = ( + seeds: number[], + rating: number, + rank: number, + attendedContestsCount: number +): number => { + const erank = getERank(seeds, rating) + + const m = Math.sqrt(erank * rank) + + let l = 0, + r = MAX_RATING + while (l < r) { + const mid = Math.floor((l + r) / 2) + if (getSeed(seeds, mid) < m) { + r = mid + } else { + l = mid + 1 + } + } + + const d = (l - rating * ACCURACY) / (1 + f(attendedContestsCount)) + return d / ACCURACY +} + +//#region 由 [@tiger2005](https://leetcode.cn/u/tiger2005/) 编写 +const ACCURACY = 10 +const MAX_RATING = 8000 * ACCURACY + +/** 预处理 seeds + * + * @param previousRatings 当前比赛所有选手的 rating 数据 + * @returns + */ +export const calcSeed = (previousRatings: number[]): number[] => { + const FFT = new FFTConv(3 * MAX_RATING + 1) + + const ELO_PROB_REV = new Array(2 * MAX_RATING + 1) + for (let i = -MAX_RATING; i <= MAX_RATING; i++) { + ELO_PROB_REV[i + MAX_RATING] = 1 / (1 + Math.pow(10, i / (400 * ACCURACY))) + } + const freq: number[] = new Array(MAX_RATING + 1).fill(0) + for (let rating of previousRatings) { + rating = Math.round(rating * ACCURACY) + freq[rating]++ + } + + const seeds = FFT.convolve(ELO_PROB_REV, freq) + return seeds +} + +/** 获取当前选手的期望胜率 + * + * @param seeds 种子数据 + * @param x 当前选手的 rating + * @returns + */ +export const getERank = (seeds: number[], x: number): number => { + x = Math.round(x * ACCURACY) + return seeds[x + MAX_RATING] + 0.5 +} + +/** 获取某个分数 x 的期望胜率 + * + * @param seeds 种子数据 + * @param x 真实分数*ACCURACY + * @returns + */ +export const getSeed = (seeds: number[], x: number): number => { + return seeds[x + MAX_RATING] + 1 +} +//#endregion diff --git a/src/content/utils/utils.ts b/src/content/utils/utils.ts new file mode 100644 index 0000000..261f80c --- /dev/null +++ b/src/content/utils/utils.ts @@ -0,0 +1,644 @@ +import { DefaultTheme } from 'styled-components/macro' +import { darkTheme, lightTheme } from '@/theme' +import { debounce } from 'src/utils' +import { PageName } from 'src/options/options' + +export function download(str: string, filename = 'contest.md'): void { + const blob = new Blob([str], { type: 'text/plain' }) + const url = URL.createObjectURL(blob) + + const a = document.createElement('a') + a.href = url + a.download = filename + document.body.appendChild(a) + a.click() + + document.body.removeChild(a) +} + +/** 等待匹配函数成功,或者超时 + * + * @param fn 判断是否成功的函数 + * @param timeout 超时,时间 ms(毫秒) + * @param delay 延时时间,时间 ms(毫秒) + */ +export function awaitFn( + fn: (...args: any) => boolean | Promise<boolean>, + timeout = 10000, + delay = 100 +): Promise<void> { + const start = new Date().valueOf() + return new Promise<void>(function (resolve, reject) { + const timer = setInterval(async () => { + if (await fn()) { + clearInterval(timer) + resolve() + } else { + if (new Date().valueOf() - start > timeout) { + clearInterval(timer) + reject('超时') + } + } + }, delay) + }) +} + +async function findBase<T>( + find: () => any, + fn: (el: T) => boolean, + time = 10000, + delay = 100 +): Promise<T> { + let element: T + await awaitFn( + () => { + element = find() + return fn(element) + }, + time, + delay + ) + return element! +} + +/** 查找匹配选择器的所有元素 + * + * 返回一个 Promise,当找到任何与选择器匹配的元素时,则 resolve 一个包含所有与选择器匹配元素的数组;如果在超时时间内未找到与选择器匹配的元素时,则 Promise 会被拒绝. + * @param selectors 需要匹配的选择器 + * @param fn 判断是否找到元素的函数 + * @param timeout 超时设置,默认为 10000 + * @returns 返回找到的所有元素 + */ +export async function findAllElement<T = HTMLElement>( + selectors: string, + fn = (e: T[]) => e.length > 0, + timeout = 10000 +): Promise<T[]> { + const elements = await findBase<T[]>( + () => Array.from(document.querySelectorAll(selectors)), + fn, + timeout + ) + return elements +} + +/** 查找匹配选择器的第一个元素 + * 返回一个 Promise,当找到第一个与选择器匹配的元素时,则 resolve 找到的这个元素;如果在超时时间内未找到与选择器匹配的元素时,则 Promise 会被拒绝. + * @param selectors 需要匹配的选择器 + * @param fn 判断是否找到元素的函数 + * @param timeout 超时设置,默认为 10000 + * @returns 返回找到的元素 + */ +export async function findElement<T = HTMLElement>( + selectors: string, + fn = (el: T | null) => !!el, + timeout = 10000 +): Promise<T> { + const element = await findBase<T>( + () => document.querySelector(selectors), + fn, + timeout + ) + return element +} + +// https://developer.mozilla.org/en-US/docs/Web/API/Document/evaluate +type NodeType = + | 'ANY_TYPE' + | 'NUMBER_TYPE' + | 'STRING_TYPE' + | 'BOOLEAN_TYPE' + | 'UNORDERED_NODE_ITERATOR_TYPE' + | 'ORDERED_NODE_ITERATOR_TYPE' + | 'UNORDERED_NODE_SNAPSHOT_TYPE' + | 'ORDERED_NODE_SNAPSHOT_TYPE' + | 'ANY_UNORDERED_NODE_TYPE' + | 'FIRST_ORDERED_NODE_TYPE' + +/** 通过 XPath 查找元素 + * 返回一个 Promise,当找与 XPath 匹配的元素时,返回找到的这个元素;如果在超时时间内未找到与选择器匹配的元素时,则 Promise 会被拒绝. + * @param xpath 需要匹配的 XPath + * @param fn 判断是否找到元素的函数 + * @param timeout 超时设置,默认为 10000 + * @returns 返回找到的元素 + */ +export function findElementByXPath<T = HTMLElement>( + evaluateParam: string, + fn?: (el: T | null) => boolean, + timeout?: number +): Promise<T> +export async function findElementByXPath<T = HTMLElement>( + evaluateParam: { + xpath: string + nodeType: 'ANY_UNORDERED_NODE_TYPE' | 'FIRST_ORDERED_NODE_TYPE' + }, + fn?: (el: T) => boolean, + timeout?: number +): Promise<T> +export async function findElementByXPath<T = XPathResult>( + evaluateParam: { + xpath: string + nodeType: 'ANY_TYPE' + }, + fn?: (el: T) => boolean, + timeout?: number +): Promise<T> +export async function findElementByXPath<T = number>( + evaluateParam: { + xpath: string + nodeType: 'NUMBER_TYPE' + }, + fn?: (el: T) => boolean, + timeout?: number +): Promise<T> +export async function findElementByXPath<T = string>( + evaluateParam: { + xpath: string + nodeType: 'STRING_TYPE' + }, + fn?: (el: T) => boolean, + timeout?: number +): Promise<T> +export async function findElementByXPath<T = boolean>( + evaluateParam: { + xpath: string + nodeType: 'BOOLEAN_TYPE' + }, + fn?: (el: T) => boolean, + timeout?: number +): Promise<T> +export async function findElementByXPath<T = HTMLElement[]>( + evaluateParam: { xpath: string; nodeType: NodeType }, + fn?: (el: T) => boolean, + timeout?: number +): Promise<T> +export async function findElementByXPath<T = HTMLElement | HTMLElement[]>( + evaluateParam: string | { xpath: string; nodeType: NodeType }, + fn?: (el: T) => boolean, + timeout = 10000 +): Promise<T> { + let xpath: string, + nodeType: NodeType = 'FIRST_ORDERED_NODE_TYPE' + if (typeof evaluateParam === 'string') { + xpath = evaluateParam + } else { + xpath = evaluateParam.xpath + nodeType = evaluateParam.nodeType ?? 'ANY_TYPE' + } + if (!fn) { + if ( + nodeType === 'UNORDERED_NODE_ITERATOR_TYPE' || + nodeType === 'ORDERED_NODE_ITERATOR_TYPE' || + nodeType === 'ORDERED_NODE_SNAPSHOT_TYPE' || + nodeType === 'UNORDERED_NODE_SNAPSHOT_TYPE' + ) { + fn = el => !!(Array.isArray(el) && el.length) + } else { + fn = (el: T | null) => el !== null && el !== undefined + } + } + const element = await findBase<T>( + () => { + const result = document.evaluate( + xpath, + document, + null, + XPathResult[nodeType], + null + ) + if ( + nodeType === 'FIRST_ORDERED_NODE_TYPE' || + nodeType === 'ANY_UNORDERED_NODE_TYPE' + ) { + return result.singleNodeValue + } + if (nodeType === 'ANY_TYPE') { + return result + } + if (nodeType === 'NUMBER_TYPE') { + return result.numberValue + } + if (nodeType === 'STRING_TYPE') { + return result.stringValue + } + if (nodeType === 'BOOLEAN_TYPE') { + return result.booleanValue + } + + const res: any[] = [] + if ( + nodeType === 'UNORDERED_NODE_ITERATOR_TYPE' || + nodeType === 'ORDERED_NODE_ITERATOR_TYPE' + ) { + let it = result.iterateNext() + while (it) { + res.push(it) + it = result.iterateNext() + } + } else if ( + nodeType === 'ORDERED_NODE_SNAPSHOT_TYPE' || + nodeType === 'UNORDERED_NODE_SNAPSHOT_TYPE' + ) { + for (let i = 0; i < result.snapshotLength; i++) { + res.push(result.snapshotItem(i)) + } + } + + return res + }, + fn, + timeout + ) + return element +} + +/** 添加监听 url 变化的事件 + * + */ +export const initUrlChangeEvent = (() => { + let isLoad = false + const load = () => { + if (isLoad) return + isLoad = true + + const oldPushState = history.pushState + const oldReplaceState = history.replaceState + let preUrl: string | undefined = undefined + const onChange = debounce(() => { + const url = location.href + if (url !== preUrl) { + preUrl = url + window.dispatchEvent(new Event('urlchange')) + } + }, 100) + history.pushState = function pushState(...args) { + const res = oldPushState.apply(this, args) + onChange() + return res + } + + history.replaceState = function replaceState(...args) { + const res = oldReplaceState.apply(this, args) + onChange() + return res + } + + window.addEventListener('popstate', () => { + window.dispatchEvent(new Event('urlchange')) + }) + } + return load +})() + +/** 获取当前力扣的主题 + * + */ +export const getTheme = (): DefaultTheme => { + const lcDarkDide = localStorage.getItem('lc-dark-side') + if (lcDarkDide === 'dark') { + return darkTheme + } + return lightTheme +} + +export const IS_MAC = + navigator.platform.indexOf('Mac') === 0 || navigator.platform === 'iPhone' + +export function isObject(obj: unknown): obj is object { + return typeof obj === 'object' && obj !== null +} + +/** 延时函数 + * + * + * @param time 时间 + * @returns + */ +export function sleep(time: number): Promise<void> { + return new Promise(function (resolve) { + setTimeout(resolve, time) + }) +} + +export function getExtensionId(): string | undefined { + const extensionId = + document.getElementById('refined-leetcode')?.dataset.extensionid + return extensionId +} + +/** 判断当前是否使用新版 UI + * + */ +export const isBetaUI: () => Promise<boolean> = (() => { + let beta: boolean | null = null, + promise: Promise<HTMLElement> | null = null + return async function isBetaUI() { + if (beta !== null) return beta + if (!promise) { + promise = Promise.race([ + findElement('#__next'), // 新版 UI + findElement('#app'), // 旧版 UI + findElement('body.pc-body'), // 祖传 UI + ]) + } + + const root = await promise + beta = root.id === '__next' + return beta + } +})() + +export interface ProblemRankData { + Rating: number + ID: number // questionFrontendId + Title: string + TitleZH: string + TitleSlug: string + ContestSlug: string + ProblemIndex: string + ContestID_en: string + ContestID_zh: string +} + +export const getProblemRankData = async (): Promise<ProblemRankData[]> => { + const dataUrls = [ + 'https://raw.githubusercontent.com/zerotrac/leetcode_problem_rating/main/data.json', + 'https://cdn.jsdelivr.net/gh/zerotrac/leetcode_problem_rating/data.json', + 'https://testingcf.jsdelivr.net/gh/zerotrac/leetcode_problem_rating/data.json', + 'https://fastly.jsdelivr.net/gh/zerotrac/leetcode_problem_rating/data.json', + 'https://gcore.jsdelivr.net/gh/zerotrac/leetcode_problem_rating/data.json', + ] + const data = await Promise.race( + dataUrls.map(url => + fetch(url) + .then(res => res.json()) + .catch(() => new Promise((res, rej) => setTimeout(rej, 10000))) + ) + ) + + return data +} + +export type PreviousRatingDataType = { + info: {} + totalRank: { + username: string + data_region: string + rating: number + acc: number + score: number + finish_time: number + fail_count?: number + }[] + rankUpdate?: number + update?: number +} + +export const getPreviousRatingData = async ( + contestSlug: string +): Promise<PreviousRatingDataType> => { + const dataUrls = [ + `https://leetcode-predictor.oss-cn-beijing.aliyuncs.com/data/${contestSlug}.json`, + ] + try { + const { sha } = await getGitHubCommit( + 'XYShaoKang', + 'leetcode-predictor', + 'master' + ) + dataUrls.push( + `https://raw.githubusercontent.com/XYShaoKang/leetcode-predictor/${sha}/data/${contestSlug}.json`, + `https://cdn.jsdelivr.net/gh/XYShaoKang/leetcode-predictor@${sha}/data/${contestSlug}.json` + ) + } catch (error) { + // + } + + try { + const data = await Promise.race( + dataUrls.map(url => + fetch(url) + .then(res => res.json()) + .catch(() => new Promise((res, rej) => setTimeout(rej, 10000))) + ) + ) + if (data) return data + throw new Error('获取数据错误') + } catch (error) { + // + } + throw new Error('获取数据错误') +} + +type GitHubCommit = { + url: string + sha: string + node_id: string + html_url: string + comments_url: string + commit: { + url: string + author: { + name: string + email: string + date: string + } + committer: { + name: string + email: string + date: string + } + message: string + tree: { + url: string + sha: string + } + comment_count: number + verification: { + verified: boolean + reason: string + signature: null + payload: null + } + } + author: { + login: string + id: number + node_id: string + avatar_url: string + gravatar_id: string + url: string + html_url: string + followers_url: string + following_url: string + gists_url: string + starred_url: string + subscriptions_url: string + organizations_url: string + repos_url: string + events_url: string + received_events_url: string + type: string + site_admin: boolean + } + committer: { + login: string + id: number + node_id: string + avatar_url: string + gravatar_id: string + url: string + html_url: string + followers_url: string + following_url: string + gists_url: string + starred_url: string + subscriptions_url: string + organizations_url: string + repos_url: string + events_url: string + received_events_url: string + type: string + site_admin: false + } + parents: [ + { + url: string + sha: string + } + ] + stats: { + additions: number + deletions: number + total: number + } + files: [ + { + filename: string + additions: number + deletions: number + changes: number + status: string + raw_url: string + blob_url: string + patch: string + } + ] +} + +export const getGitHubCommit = async ( + owner: string, + repo: string, + ref: string +): Promise<GitHubCommit> => { + const res: any = await Promise.race([ + fetch(`https://api.github.com/repos/${owner}/${repo}/commits/${ref}`, { + cache: 'no-cache', + credentials: 'omit', + }), + new Promise((res, rej) => setTimeout(rej, 1000)), + ]) + const result = await res.json() + if (res.status === 403) { + throw new Error(result.message) + } + + return result +} + +// 通过页面包含的一些独特特征判断是否已经跳转到某个页面 +export const problemsetPageIsLoad = async (): Promise<boolean> => { + const el = await findElementByXPath(`//li/a[text()="题库"]/..`) + return el.classList.contains('nav-li-after') +} + +export function routerTo(url: string, shallow = true): void { + const next = (window as any).next + if (!next) return + next.router.push(url, undefined, { shallow }) +} + +export function setRef<T>(el: T, ref?: React.Ref<T>): void { + if (ref) { + if (typeof ref === 'function') { + ref(el) + } else if ('current' in ref) { + ;(ref as React.MutableRefObject<T>).current = el + } + } +} + +export function autoMount( + xpath: string, + mount: (...args: any) => void | Promise<void>, + findAncestor: (el: HTMLElement[]) => HTMLElement | null | undefined, + unmount?: (...args: any) => void | Promise<void>, + defaultAncestor: HTMLElement = document.body +): [mount: () => Promise<void>, unmount: () => void] { + let _observer: MutationObserver | null = null + return [ + async function run(): Promise<void> { + const els = await findElementByXPath({ + xpath, + nodeType: 'UNORDERED_NODE_ITERATOR_TYPE', + }) + const ancestor = findAncestor(els) ?? defaultAncestor + + const mountFn = debounce(async () => { + await unmount?.() + if (!_observer) return + mount() + }, 100) + mountFn() + _observer?.disconnect() + _observer = new MutationObserver(mountFn) + if (ancestor) + _observer.observe(ancestor, { childList: true, subtree: true }) + }, + () => { + _observer?.disconnect() + _observer = null + unmount?.() + }, + ] +} + +export const customEventDispatch: CustomEventDispatch = (eventName, data?) => { + const event = new CustomEvent(eventName, { detail: data }) + window.dispatchEvent(event) +} + +export function getPageName(): PageName | undefined { + if (location.pathname === '/') { + // 首页 + return 'homePage' + } + const paths = location.pathname.split('/').filter(Boolean) + if (paths[0] === 'problem-list') { + // 题单页 + return 'problemListPage' + } else if (paths[0] === 'problems') { + // if (paths[2] === 'solutions' && paths[3]) { + // // 新版题解 solutions + // // 旧版题解 solution + // return 'solutionsPage' + // } + // 答题页 + return 'problemsPage' + } else if (paths[0] === 'contest') { + if (paths[2] === 'problems') { + // 比赛答题页 + return 'contestProblemsPage' + } else if (paths[2] === 'ranking') { + // 比赛排名页 + return 'contestRankingPage' + } + } else if (paths[0] === 'problemset') { + // 题库页 + return 'problemsetPage' + } +} + +export function gkey(region: string, username: string): string { + return `${region.toLocaleLowerCase()}:${username.toLocaleLowerCase()}` +} diff --git a/src/index.tsx b/src/index.tsx deleted file mode 100644 index f7736b1..0000000 --- a/src/index.tsx +++ /dev/null @@ -1,57 +0,0 @@ -import { StrictMode } from 'react' -import { render } from 'react-dom' -import minimatch from 'minimatch' - -import Download from './page/submissions-detail/Download' -import Clock from './page/problems/Clock' -import { getElement } from './utils' - -function loadDownload(parent: Element) { - if (parent && parent instanceof HTMLElement) { - parent.style.display = 'flex' - parent.style.justifyContent = 'space-between' - const root = document.createElement('div') - parent.append(root) - - render( - <StrictMode> - <Download /> - </StrictMode>, - root - ) - } -} - -if (minimatch(location.href, 'https://leetcode-cn.com/submissions/detail/**')) { - window.onload = async () => { - const main = await getElement('.css-smuvek-Main') - loadDownload(main[0]?.children?.[0]) - } -} - -if (minimatch(location.href, 'https://leetcode.com/submissions/detail/**')) { - window.onload = async () => { - const parent = await getElement('#submission-app>.row>div:first-child') - loadDownload(parent[0]) - } -} - -if (minimatch(location.href, 'https://leetcode-cn.com/problems/**')) { - window.onload = async () => { - const parent = (await getElement('.container__Kjnx>.action__KaAP'))[0] - if (parent && parent instanceof HTMLElement) { - const root = document.createElement('div') - parent.prepend(root) - root.style.display = 'flex' - root.style.alignItems = 'center' - root.style.flexShrink = '0' - - render( - <StrictMode> - <Clock /> - </StrictMode>, - root - ) - } - } -} diff --git a/src/leetcode-api/index.ts b/src/leetcode-api/index.ts deleted file mode 100644 index f116973..0000000 --- a/src/leetcode-api/index.ts +++ /dev/null @@ -1,465 +0,0 @@ -import { baseApi, globalGetStatusText, graphqlApi } from './utils' - -interface GlobalSubmissionDetail { - submissionData: { - status_code: number - runtime: string - memory: string - total_correct: string - total_testcases: string - compare_result: string - input_formatted: string - input: string - expected_output: string - code_output: string - last_testcase: string - } - questionId: string - submissionId: string - sessionId: string - getLangDisplay: string - submissionCode: string - editCodeUrl: string - checkUrl: string - runtimeDistributionFormatted: string - memoryDistributionFormatted: string - langs: [] - runtime: string - memory: string - enableMemoryDistribution: string - nonSufficientMsg: string -} - -export type SuccessCheckReturnType = { - status_code: number - lang: string - run_success: boolean - status_runtime: string - memory: number - question_id: string - elapsed_time: number - compare_result: string - code_output: string - std_output: string - last_testcase: string - expected_output: string - task_finish_time: number - task_name: string - finished: boolean - state: 'SUCCESS' - fast_submit: boolean - total_correct: number - total_testcases: number - submission_id: string - status_memory: string - memory_percentile: number - pretty_lang: string -} & ( - | { - status_msg: 'Accepted' - runtime_percentile: number - memory_percentile: number - } - | { - status_msg: 'Wrong Answer' - runtime_percentile: null - memory_percentile: null - input_formatted: string - input: string - } -) - -type CheckReturnType = - | { state: 'STARTED' } - | { state: 'PENDING' } - | SuccessCheckReturnType - -class LeetCodeApi { - public graphqlApi: ( - { method, body }: { method?: string; body?: unknown }, - retry?: number - ) => Promise<any> - public baseApi: ( - url: string, - method?: string | undefined, - body?: object | null | undefined, - retry?: number | undefined - ) => Promise<any> - public REGION_URL: string - - public constructor(REGION_URL: string) { - this.REGION_URL = REGION_URL - this.graphqlApi = graphqlApi.bind(null, REGION_URL) - this.baseApi = baseApi.bind(null, REGION_URL) - } - - public async getAllQuestions(): Promise< - { - translatedTitle: string - title: string - questionFrontendId: string - titleSlug: string - questionId: string - categoryTitle: string - isPaidOnly: boolean - status: string - difficulty: string - __typename: string - }[] - > { - const cache = localStorage.getItem('lc-extend:allQuestions') - if (cache) { - try { - const res = JSON.parse(cache) - return res - } catch (error) { - console.log('解析缓存失败') - } - } - const body = { - operationName: 'allQuestions', - variables: {}, - query: /* GraphQL */ ` - query allQuestions { - allQuestions { - title - titleSlug - translatedTitle - questionId - questionFrontendId - status - difficulty - isPaidOnly - categoryTitle - __typename - } - } - `, - } - - return this.graphqlApi({ body }).then(data => { - const res = data?.data?.allQuestions - if (res) { - localStorage.setItem('lc-extend:allQuestions', JSON.stringify(res)) - return res - } - throw new Error('获取题目列表失败,返回结果为: ' + JSON.stringify(data)) - }) - } - - public async getSubmissions( - questionSlug: string, - limit = 40, - offset = 0 - ): Promise<{ - lastKey: string - hasNext: boolean - submissions: { - id: string - statusDisplay: string - lang: string - runtime: string - timestamp: string - url: string - isPending: string - memory: string - submissionComment: { - comment: string - flagType: string - __typename: string - } - __typename: string - }[] - __typename: string - }> { - const body = { - operationName: 'submissions', - variables: { - offset, - limit, - lastKey: null, - questionSlug, - }, - query: /* GraphQL */ ` - query submissions( - $offset: Int! - $limit: Int! - $lastKey: String - $questionSlug: String! - ) { - submissionList( - offset: $offset - limit: $limit - lastKey: $lastKey - questionSlug: $questionSlug - ) { - lastKey - hasNext - submissions { - id - statusDisplay - lang - runtime - timestamp - url - isPending - memory - __typename - } - __typename - } - } - `, - } - return this.graphqlApi({ body }).then(({ data }) => data.submissionList) - } - - private async getSubmissionDetailByLocal(submissionId: string): Promise<{ - id: string - code: string - runtime: string - memory: string - rawMemory: string - statusDisplay: string - timestamp: number - lang: string - passedTestCaseCnt: number - totalTestCaseCnt: number - sourceUrl: string - question: { - titleSlug: string - title: string - translatedTitle: string - questionId: string - __typename: string - } - outputDetail: { - codeOutput: string - expectedOutput: string - input: string - compileError: string - runtimeError: string - lastTestcase: string - __typename: string - } - __typename: string - submissionComment: null - }> { - const body = { - operationName: 'mySubmissionDetail', - variables: { id: submissionId }, - query: /* GraphQL */ ` - query mySubmissionDetail($id: ID!) { - submissionDetail(submissionId: $id) { - id - code - runtime - memory - rawMemory - statusDisplay - timestamp - lang - passedTestCaseCnt - totalTestCaseCnt - sourceUrl - question { - titleSlug - title - translatedTitle - questionId - __typename - } - ... on GeneralSubmissionNode { - outputDetail { - codeOutput - expectedOutput - input - compileError - runtimeError - lastTestcase - __typename - } - __typename - } - submissionComment { - comment - flagType - __typename - } - __typename - } - } - `, - } - - return this.graphqlApi({ body }).then(({ data }) => data.submissionDetail) - } - private async getDistributionLocal(submissionId: string): Promise<{ - runtimeDistribution: { - lang: string - distribution: [string, number][] - } | null - memoryDistribution: { - lang: string - distribution: [string, number][] - } | null - }> { - const runtimeApi = `/submissions/api/runtime_distribution/${submissionId}/` - const runtimeDistribution = await this.baseApi(runtimeApi).then( - ({ runtime_distribution_formatted }) => - runtime_distribution_formatted - ? JSON.parse(runtime_distribution_formatted) - : null - ) - const memoryApi = `/submissions/api/memory_distribution/${submissionId}/` - const memoryDistribution = await this.baseApi(memoryApi).then( - ({ memory_distribution_formatted }) => - memory_distribution_formatted - ? JSON.parse(memory_distribution_formatted) - : null - ) - - return { runtimeDistribution, memoryDistribution } - } - - private async getSubmissionDetailByGlobal( - submissionId: string - ): Promise<GlobalSubmissionDetail> { - const text = await fetch( - `https://leetcode.com/submissions/detail/${submissionId}/`, - { - headers: { - accept: - 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9', - }, - referrer: 'https://leetcode.com/', - referrerPolicy: 'strict-origin-when-cross-origin', - body: null, - method: 'GET', - mode: 'cors', - credentials: 'include', - } - ).then(res => res.text()) - - const dataText = text.match(/var pageData = ([\d\D]+?});/)?.[1] - - const data = eval(`(function (){return ${dataText}})()`) - - return data - } - - public async getSubmissionDetail(submissionId: string): Promise<{ - id: string // submissionId - code: string // submissionCode - runtime: string // runtime - memory: string // submissionData.memory - rawMemory: string // memory - statusDisplay: string // status_code - // timestamp: string - lang: string // getLangDisplay - passedTestCaseCnt: number // submissionData.total_correct - totalTestCaseCnt: number // submissionData.total_testcases - sourceUrl: string // editCodeUrl - questionId: string - runtimeDistribution?: { lang: string; distribution: [string, number][] } - memoryDistribution?: { lang: string; distribution: [string, number][] } - }> { - if (/leetcode-cn\.com/.test(this.REGION_URL)) { - const data = await this.getSubmissionDetailByLocal(submissionId) - const { runtimeDistribution, memoryDistribution } = - await this.getDistributionLocal(submissionId) - return { - ...data, - questionId: data.question.questionId, - runtimeDistribution: runtimeDistribution - ? runtimeDistribution - : { lang: data.lang, distribution: [] }, - memoryDistribution: memoryDistribution - ? memoryDistribution - : { - lang: data.lang, - distribution: [], - }, - } - } else { - const data = await this.getSubmissionDetailByGlobal(submissionId) - return { - id: data.submissionId, - code: data.submissionCode, - runtime: data.runtime, - memory: data.submissionData.memory, - rawMemory: data.memory, - statusDisplay: globalGetStatusText(data.submissionData.status_code), - lang: data.getLangDisplay, - passedTestCaseCnt: Number(data.submissionData.total_correct), - totalTestCaseCnt: Number(data.submissionData.total_testcases), - sourceUrl: data.editCodeUrl, - questionId: data.questionId, - runtimeDistribution: JSON.parse(data.runtimeDistributionFormatted), - memoryDistribution: JSON.parse(data.memoryDistributionFormatted), - } - } - } - - public getCodeByTime( - lang: string, - questionId: string, - time: string - ): Promise<string> { - const api = `/submissions/api/detail/${questionId}/${lang}/${time}/` - - return this.baseApi(api).then(data => data.code) - } - - public getCodeByMemory( - lang: string, - questionId: string, - memory: string - ): Promise<string> { - const api = `/submissions/api/detail/${questionId}/${lang}/memory/${memory}/` - - return this.baseApi(api).then(data => data.code) - } - - public check(submissionId: string): Promise<CheckReturnType> { - const api = `/submissions/detail/${submissionId}/check/` - return this.baseApi(api) - } - - public submissionCreateOrUpdateSubmissionComment( - submissionId: string, - flagType: 'BLUE' | 'ORANGE' | 'GREEN' | 'PURPLE' | 'RED', - comment: string - ): Promise<{ ok: boolean; __typename: string }> { - const body = { - operationName: 'submissionCreateOrUpdateSubmissionComment', - variables: { - submissionId: submissionId, - flagType: flagType, - comment: comment, - }, - query: /* GraphQL */ ` - mutation submissionCreateOrUpdateSubmissionComment( - $submissionId: ID! - $flagType: SubmissionFlagTypeEnum! - $comment: String! - ) { - submissionCreateOrUpdateSubmissionComment( - comment: $comment - flagType: $flagType - submissionId: $submissionId - ) { - ok - __typename - } - } - `, - } - - return this.graphqlApi({ body }).then( - ({ data }) => data.submissionCreateOrUpdateSubmissionComment - ) - } -} - -export { LeetCodeApi } diff --git a/src/leetcode-api/utils.ts b/src/leetcode-api/utils.ts deleted file mode 100644 index 85a6b3a..0000000 --- a/src/leetcode-api/utils.ts +++ /dev/null @@ -1,135 +0,0 @@ -/** - * 延时函数 - * - * @param time 时间 - * @returns - */ -function sleep(time: number): Promise<void> { - return new Promise(function (resolve) { - setTimeout(resolve, time) - }) -} - -function graphqlApi( - REGION_URL: string, - { method, body }: { method?: string; body?: unknown }, - retry = 1 -): Promise<unknown> { - method = method || 'POST' - const RETRY_TIME = 3000, - RETRY_COUNT = 5 - return fetch(`${REGION_URL}/graphql/`, { - headers: { - 'content-type': 'application/json', - }, - referrer: `${REGION_URL}/`, - referrerPolicy: 'strict-origin-when-cross-origin', - body: JSON.stringify(body), - method, - mode: 'cors', - credentials: 'include', - }).then(res => { - if (res.status === 200) { - return res.json() - } - - if (res.status === 429) { - console.log(`超出接口限制,休息一下,等待第${retry}次重试...`) - if (retry > RETRY_COUNT) { - throw new Error( - `已重试 ${RETRY_COUNT} 次,仍然无法获取,可能力扣君生气了,晚点在试试吧...` - ) - } - // 触发限制之后,等一会儿在进行请求 - return sleep(RETRY_TIME).then(() => - graphqlApi(REGION_URL, { method, body }, retry + 1) - ) - } - - throw new Error(`未知状态: ${res.status}`) - }) -} - -function isObject(obj: any): obj is object { - return typeof obj === 'object' && obj !== null -} - -function baseApi( - REGION_URL: string, - url: string, - method = 'GET', - body: null | object = null, - retry = 1 -): Promise<any> { - const RETRY_TIME = 20000, - RETRY_COUNT = 10 - - method = method.toUpperCase() - let bodyStr: null | string - - if (method === 'GET') { - bodyStr = null - } else { - bodyStr = isObject(body) ? JSON.stringify(body) : body - } - - return fetch(REGION_URL + url, { - headers: { - accept: 'application/json, text/plain, */*', - }, - referrer: `REGION_URL`, - referrerPolicy: 'strict-origin-when-cross-origin', - body: bodyStr, - method, - mode: 'cors', - credentials: 'include', - }).then(res => { - if (res.status === 200) { - return res.json() - } - - if (res.status === 429) { - console.log(`超出接口限制,休息一下,等待第${retry}次重试...`) - if (retry > RETRY_COUNT) { - throw new Error( - `已重试 ${RETRY_COUNT} 次,仍然无法获取,可能力扣君生气了,晚点在试试吧...` - ) - } - // 触发限制之后,等一会儿在进行请求 - return sleep(RETRY_TIME).then(() => - baseApi(REGION_URL, url, method, body, retry + 1) - ) - } - - throw new Error(`未知状态: ${res.status}`) - }) -} - -function globalGetStatusText(e: number): string { - switch (e) { - case 10: - return 'Accepted' - case 11: - return 'Wrong Answer' - case 12: - return 'Memory Limit Exceeded' - case 13: - return 'Output Limit Exceeded' - case 14: - return 'Time Limit Exceeded' - case 15: - return 'Runtime Error' - case 16: - return 'Internal Error' - case 20: - return 'Compile Error' - case 21: - return 'Unknown Error' - case 30: - return 'Timeout' - default: - return 'Invalid Error Code' - } -} - -export { sleep, graphqlApi, baseApi, globalGetStatusText } diff --git a/src/options/App.tsx b/src/options/App.tsx new file mode 100644 index 0000000..f73b405 --- /dev/null +++ b/src/options/App.tsx @@ -0,0 +1,21 @@ +import React, { FC } from 'react' +import { css } from 'styled-components/macro' +import Option from './Option' + +const App: FC = () => { + return ( + <div + css={css` + height: 100vh; + background: #191919; + display: flex; + align-items: center; + justify-content: center; + `} + > + <Option /> + </div> + ) +} + +export default App diff --git a/src/options/Option.tsx b/src/options/Option.tsx new file mode 100644 index 0000000..65a59ef --- /dev/null +++ b/src/options/Option.tsx @@ -0,0 +1,187 @@ +import Checkbox from '@/components/Checkbox' +import Switch from '@/components/Switch' +import React, { FC, useEffect, useState } from 'react' +import { css } from 'styled-components/macro' + +import { defaultOptions, labelMap, OptionsType } from './options' + +const storage = chrome.storage.local + +const mergeOptions = ( + options?: OptionsType +): [[string, [string, boolean][]][], boolean, boolean] => { + const res: [string, [string, boolean][]][] = [] + let allItem = 0, + enableItem = 0 + for (const page of Reflect.ownKeys(defaultOptions)) { + const ans: [string, [string, boolean][]] = [page as string, []] + for (const key of Reflect.ownKeys((defaultOptions as any)[page])) { + allItem++ + const enable = + (options as any)?.[page]?.[key] ?? (defaultOptions as any)[page][key] + if (enable) enableItem++ + ans[1].push([key as string, enable]) + } + res.push(ans) + } + return [res, !!enableItem, enableItem > 0 && enableItem < allItem] +} + +const Option: FC = () => { + const [state, setOptions] = + useState<[[string, [string, boolean][]][], boolean, boolean]>() + useEffect(() => { + storage.get('options').then(({ options }) => { + setOptions(mergeOptions(options)) + }) + }, []) + useEffect(() => { + const handle = (e: { [key: string]: chrome.storage.StorageChange }) => { + if ('options' in e) { + const options = e.options.newValue + setOptions(mergeOptions(options)) + } + } + chrome.storage.onChanged.addListener(handle) + return () => { + chrome.storage.onChanged.removeListener(handle) + } + }, []) + const handleChange = (args: string[][], enable?: boolean) => () => { + storage.get('options').then(({ options }) => { + for (const [page, key] of args) { + if (enable !== undefined) { + options[page][key] = enable + } else { + options[page][key] = !options[page][key] + } + } + setOptions(mergeOptions(options)) + storage.set({ options }) + }) + } + if (!state) return null + const [options, hasEnable, indeterminate] = state + + return ( + <div + css={css` + width: 200px; + padding: 3px; + background: #191919; + `} + > + <div + css={css` + padding: 10px; + border-radius: 5px; + background: #282828; + color: #eff2f6ba; + box-shadow: 0 1px 2px #0000004c, 0 4px 4px #0000003f; + `} + > + <div + css={css` + display: flex; + align-items: center; + justify-content: flex-end; + `} + > + <label + htmlFor="selectAll" + css={css` + cursor: pointer; + `} + > + {hasEnable ? '全部禁用' : '全部启用'} + </label> + <Checkbox + id="selectAll" + checked={hasEnable} + indeterminate={indeterminate} + onChange={() => + handleChange( + options + .map(([page, features]) => + features.map(([key]) => [page, key]) + ) + .flat(), + !hasEnable + )() + } + size={20} + color={hasEnable ? 'rgb(144, 202, 249)' : ''} + /> + </div> + {options?.map(([page, features], i) => { + const enableItems = features.filter(([, e]) => e) + const hasEnable = + enableItems.length > 0 && enableItems.length < features.length + return ( + <div + key={page} + css={css` + border-bottom: ${i < options.length - 1 + ? '2px solid #6f6f6fb0' + : ''}; + `} + > + <div + css={css` + display: flex; + align-items: center; + margin-top: 5px; + `} + > + <h2 + css={css` + font-size: 16px; + margin: 0; + `} + > + {labelMap[page]} + </h2> + <Checkbox + checked={!!enableItems.length} + indeterminate={hasEnable} + onChange={handleChange( + features.map(([key]) => [page, key]), + !enableItems.length + )} + size={20} + color={enableItems.length ? 'rgb(144, 202, 249)' : ''} + /> + </div> + {features.map( + ([key, enable]) => + labelMap[key] && ( + <div + key={key} + css={css` + margin-left: 10px; + `} + > + <div + onClick={handleChange([[page, key]])} + css={css` + display: flex; + justify-content: space-between; + align-items: center; + cursor: pointer; + `} + > + <div>{labelMap[key]}</div> + <Switch enable={enable} /> + </div> + </div> + ) + )} + </div> + ) + })} + </div> + </div> + ) +} + +export default Option diff --git a/src/options/index.tsx b/src/options/index.tsx new file mode 100644 index 0000000..c2f7cb1 --- /dev/null +++ b/src/options/index.tsx @@ -0,0 +1,21 @@ +import { StrictMode } from 'react' +import { render } from 'react-dom' +import { createGlobalStyle } from 'styled-components/macro' + +import App from './App' + +__webpack_public_path__ = chrome.runtime.getURL('.') + '/' + +const GlobalStyle = createGlobalStyle` + body { + margin: 0; + } +` + +render( + <StrictMode> + <GlobalStyle /> + <App /> + </StrictMode>, + document.getElementById('root') +) diff --git a/src/options/options.ts b/src/options/options.ts new file mode 100644 index 0000000..a6048ec --- /dev/null +++ b/src/options/options.ts @@ -0,0 +1,62 @@ +export const defaultOptions = { + homePage: { + block: true, + }, + problemsetPage: { + problemList: true, + problemRating: false, + }, + problemListPage: { + problemList: true, + problemRating: false, + }, + problemsPage: { + timer: true, + }, + contestProblemsPage: { + disableShortcutkey: false, + modifyPageLayout: false, + reverseLayout: false, + problemViewWidth: '40%', + }, + contestRankingPage: { + languageIcon: false, + showPredict: true, + realTimePredict: false, + showOldRating: false, + ratingPredictor: true, + showNewRating: true, + expectingRanking: false, + }, +} + +type Child<T extends object> = { [K in keyof T]: T[K] }[keyof T] + +export type PageName = keyof typeof defaultOptions | 'solutionsPage' + +export type OptionsType = typeof defaultOptions + +export type ItemType = Child<OptionsType> + +export const labelMap: { [key: string]: string } = { + homePage: '首页', + problemsetPage: '题库页', + problemListPage: '题单页', + problemsPage: '答题页', + contestProblemsPage: '竞赛答题页', + contestRankingPage: '竞赛排名页', + block: '黑名单', + problemList: '题单列表', + problemRating: '题目评分', + timer: '计时器', + disableShortcutkey: '禁用快捷键', + modifyPageLayout: '修改页面布局', + reverseLayout: '题面居于右侧', + languageIcon: '语言图标', + showOldRating: '显示旧分数', + ratingPredictor: '显示预测分数', + showNewRating: '显示新分数', + showPredict: '显示预测', + realTimePredict: '显示实时预测', + expectingRanking: '期望全球排名', +} diff --git a/src/page/problems/Clock.tsx b/src/page/problems/Clock.tsx deleted file mode 100644 index 77a564d..0000000 --- a/src/page/problems/Clock.tsx +++ /dev/null @@ -1,148 +0,0 @@ -import React, { FC, useEffect, useState } from 'react' -import styled from 'styled-components/macro' - -import { LeetCodeApi, SuccessCheckReturnType } from '../../leetcode-api' -import { sleep } from '../../leetcode-api/utils' -import { getElement, submissionOnMarkChange } from '../../utils' -import { useTimer } from './useTimer' - -const Container = styled.div` - display: flex; - justify-content: center; - align-items: center; - font-size: 14px; -` - -const Content = styled.div` - border-radius: 3px 0 0 3px; - border: 1px solid palevioletred; - border-right-width: 0; - margin-left: 15px; - padding: 6px 15px; -` - -const Button = styled.button<{ primary?: boolean }>` - background: transparent; - border-radius: 0 3px 3px 0; - border: 1px solid palevioletred; - color: palevioletred; - margin-right: 15px; - padding: 6px 15px; - width: 100px; - text-align: center; - cursor: pointer; -` - -const Clock: FC = () => { - const pathnames = location.pathname.split('/').filter(Boolean) - - const slug = pathnames[1] - const [leetCodeApi] = useState(new LeetCodeApi(location.origin)) - const [hidden, setHidden] = useState(false) - - const { time, isDone, done, restart } = useTimer() - - const handleHidden = () => { - setHidden(hidden => !hidden) - } - - async function getSubmissionId( - retry = 1, - time = new Date() - ): Promise<string> { - if (retry > 10) throw new Error('获取 SubmissionId 失败') - - await sleep(500) - const { submissions } = await leetCodeApi.getSubmissions(slug) - const pendingSubmission = submissions.find( - ({ timestamp, isPending }) => - isPending === 'Pending' || - new Date((Number(timestamp) + 2) * 1000) >= time - ) - - if (!pendingSubmission) { - return getSubmissionId(retry + 1, time) - } else { - return pendingSubmission.id - } - } - - async function check( - submissionId: string, - retry = 1 - ): Promise<SuccessCheckReturnType> { - if (retry > 10) throw new Error('获取提交状态结果超时') - - await sleep(1000 + retry * 500) - const state = await leetCodeApi.check(submissionId) - - if (state.state === 'SUCCESS') { - return state - } else { - return await check(submissionId, retry + 1) - } - } - - useEffect(() => { - let cancel: (() => void) | null = null - - void (async function () { - const submitBtn = (await getElement('.submit__-6u9'))[0] - const handleClick: EventListenerOrEventListenerObject = async () => { - const submissionId = await getSubmissionId() - const state = await check(submissionId) - - if (state.status_msg === 'Accepted') { - // 提交成功 - done(async time => { - // 对当前提交添加备注 - await leetCodeApi.submissionCreateOrUpdateSubmissionComment( - submissionId, - 'RED', - time.map(t => t.toString().padStart(2, '0')).join(' : ') - ) - - await sleep(1000) - submissionOnMarkChange(submissionId) - }) - - setHidden(false) - } - } - - submitBtn.addEventListener('click', handleClick) - cancel = () => { - submitBtn.removeEventListener('click', handleClick) - } - })() - return () => { - if (cancel) cancel() - } - }, []) - - return ( - <Container> - {!hidden && ( - <Content> - {`${isDone ? '本次耗时: ' : ''}${time - .map(t => t.toString().padStart(2, '0')) - .join(' : ')}`} - </Content> - )} - {!isDone ? ( - <Button - onClick={handleHidden} - style={ - hidden ? { borderTopLeftRadius: 3, borderBottomLeftRadius: 3 } : {} - } - > - {hidden ? '显示计时' : '隐藏'} - </Button> - ) : ( - <Button onClick={restart}>重新开始</Button> - )} - </Container> - ) -} - -export default Clock diff --git a/src/page/problems/useTimer.ts b/src/page/problems/useTimer.ts deleted file mode 100644 index d918d33..0000000 --- a/src/page/problems/useTimer.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { useEffect, useRef, useState } from 'react' - -function formatTime(time: number) { - time = time / 1000 - const house = Math.floor(time / 3600) - const minute = Math.floor((time / 60) % 60) - const second = Math.floor(time % 60) - return [house, minute, second] -} - -type UseTimeReturn = { - time: number[] - isDone: boolean - done: (fn?: (time: number[]) => void) => void - restart: () => void -} - -const useTimer = (): UseTimeReturn => { - const [start, setStart] = useState(new Date()) - const [isDone, setIsDone] = useState(false) - const [time, setTime] = useState(formatTime(0)) - const cacheTime = useRef(time) - cacheTime.current = time - useEffect(() => { - let timer: ReturnType<typeof setInterval> - if (!isDone) { - timer = setInterval(async () => { - setTime(formatTime(new Date().valueOf() - start.valueOf())) - }, 1000) - } - - return () => { - if (timer) { - clearInterval(timer) - } - } - }, [isDone]) - - const restart = () => { - setIsDone(false) - setStart(new Date()) - setTime(formatTime(0)) - } - - const done = (fn?: (time: number[]) => void) => { - setIsDone(true) - - if (fn) { - fn(cacheTime.current) - } - } - - return { time, isDone, done, restart } -} - -export { useTimer } diff --git a/src/page/submissions-detail/Download.tsx b/src/page/submissions-detail/Download.tsx deleted file mode 100644 index 3d1e8f9..0000000 --- a/src/page/submissions-detail/Download.tsx +++ /dev/null @@ -1,128 +0,0 @@ -import React, { FC, useState } from 'react' -import styled, { css } from 'styled-components/macro' - -import { LeetCodeApi } from '../../leetcode-api' -import { download } from '../../utils' - -const Container = styled.div` - display: flex; - justify-content: center; - align-items: center; - font-size: 14px; -` - -const Button = styled.a<{ primary?: boolean }>` - background: transparent; - border-radius: 3px; - border: 2px solid palevioletred; - color: palevioletred; - margin: 0.5em 1em; - padding: 0.25em 1em; - width: 150px; - text-align: center; - - ${props => - props.primary && - css` - background: palevioletred; - color: white; - `} -` - -const Download: FC = () => { - const [option, setOption] = useState({ runtime: true, memory: false }) - const [isDownloading, setDownloading] = useState(false) - const [progress, setProgress] = useState(0) - - const handleChange: React.ChangeEventHandler<HTMLInputElement> = e => { - const key = e.target.id as 'runtime' | 'memory' - setOption(option => ({ ...option, [key]: !option[key] })) - } - const handleClick = async function () { - setDownloading(true) - const pathnames = location.pathname.split('/').filter(Boolean) - const leetCodeApi = new LeetCodeApi(location.origin) - const data = await leetCodeApi.getSubmissionDetail( - pathnames[pathnames.length - 1] - ) - const allQuestions = await leetCodeApi.getAllQuestions() - const { questionId, lang } = data - const question = allQuestions.find(q => q.questionId === questionId) - let res = `# ${question?.title} - ${lang}\n\n` - const cache = new Set<string>() - - const total = - (option.runtime - ? data.runtimeDistribution?.distribution.length ?? 0 - : 0) + - (option.memory ? data.memoryDistribution?.distribution.length ?? 0 : 0) - - let progress = 0 - if (option.runtime) { - const time = data.runtimeDistribution - res += `## 用时分布代码\n\n` - if (time) { - const { lang, distribution } = time - for (const [t] of distribution) { - const code = await leetCodeApi.getCodeByTime(lang, questionId, t) - - res += `### ${t}ms\n\n` - res += `\`\`\`${lang}\n${code}\n\`\`\`\n\n` - cache.add(code) - progress++ - setProgress(progress / total) - } - } - } - if (option.memory) { - const memory = data.memoryDistribution - res += `## 小号内存分布分布代码\n\n` - if (memory) { - const { lang, distribution } = memory - for (const [m] of distribution) { - const code = await leetCodeApi.getCodeByMemory(lang, questionId, m) - if (cache.has(code)) continue - - res += `### ${m}kb\n\n` - res += `\`\`\`${lang}\n${code}\n\`\`\`\n\n` - - progress++ - setProgress(progress / total) - } - } - } - download(res, `${question?.titleSlug}-${lang}.md`) - setDownloading(false) - setProgress(0) - } - - return ( - <Container> - <div> - <input - type="checkbox" - name="runtime" - id="runtime" - onChange={handleChange} - checked={option.runtime} - /> - <label htmlFor="runtime">运行时间</label> - </div> - <div> - <input - type="checkbox" - name="memory" - id="memory" - onChange={handleChange} - checked={option.memory} - /> - <label htmlFor="memory">运行内存</label> - </div> - <Button onClick={isDownloading ? undefined : handleClick}> - {isDownloading ? `下载中... | ${(progress * 100) >>> 0}%` : '下载'} - </Button> - </Container> - ) -} - -export default Download diff --git a/src/popup/App.tsx b/src/popup/App.tsx new file mode 100644 index 0000000..2b70cd9 --- /dev/null +++ b/src/popup/App.tsx @@ -0,0 +1,8 @@ +import React, { FC } from 'react' +import Option from '../options/Option' + +const App: FC = () => { + return <Option /> +} + +export default App diff --git a/src/popup/index.tsx b/src/popup/index.tsx new file mode 100644 index 0000000..c2f7cb1 --- /dev/null +++ b/src/popup/index.tsx @@ -0,0 +1,21 @@ +import { StrictMode } from 'react' +import { render } from 'react-dom' +import { createGlobalStyle } from 'styled-components/macro' + +import App from './App' + +__webpack_public_path__ = chrome.runtime.getURL('.') + '/' + +const GlobalStyle = createGlobalStyle` + body { + margin: 0; + } +` + +render( + <StrictMode> + <GlobalStyle /> + <App /> + </StrictMode>, + document.getElementById('root') +) diff --git a/src/test b/src/test new file mode 100644 index 0000000..e69de29 diff --git a/src/userscriptPlugin.js b/src/userscriptPlugin.js deleted file mode 100644 index 5c216a9..0000000 --- a/src/userscriptPlugin.js +++ /dev/null @@ -1,83 +0,0 @@ -/* eslint-disable @typescript-eslint/no-var-requires */ -const packageData = require('../package.json') - -class UserscriptPlugin { - /** - * - * @param {import('webpack').Compiler} compiler - */ - apply(compiler) { - const { webpack, options } = compiler - let mode = 'development' - if ( - options.mode !== 'development' || - (process.env.NODE_ENV && process.env.NODE_ENV === 'production') - ) { - mode = 'production' - } - - const pluginName = UserscriptPlugin.name - const { ConcatSource, RawSource } = webpack.sources - - let HEADER = '' - if (mode === 'development') { - HEADER = `// ==UserScript== -// @name leetcode-extend-dev -// @namespace https://github.com/xyshaokang/leetcode-extend -// @version ${packageData.version} -// @description 力扣扩展 -// @author XYShaoKang -// @match https://leetcode-cn.com/* -// @match https://leetcode.com/* -// ==/UserScript== - -` - } else { - HEADER = `// ==UserScript== -// @name leetcode-extend -// @namespace https://github.com/xyshaokang/leetcode-extend -// @version ${packageData.version} -// @description 力扣扩展 -// @author XYShaoKang -// @match https://leetcode-cn.com/* -// @match https://leetcode.com/* -// @require https://unpkg.com/react@17/umd/react.production.min.js -// @require https://unpkg.com/react-dom@17/umd/react-dom.production.min.js -// ==/UserScript== - -` - } - - compiler.hooks.thisCompilation.tap(pluginName, compilation => { - compilation.hooks.processAssets.tap( - { - name: 'generater-image-plugin', - stage: webpack.Compilation.PROCESS_ASSETS_STAGE_SUMMARIZE, - }, - () => { - const filename = 'main.user.js' - if (mode === 'development') { - const newFile = 'main.js' - const content = `const script = document.createElement('script') -script.src = 'http://localhost:9000/${newFile}' -document.body.append(script) -` - compilation.emitAsset(newFile, compilation.assets[filename]) - - compilation.updateAsset( - filename, - () => new RawSource(HEADER + content) - ) - } else { - compilation.updateAsset( - filename, - file => new ConcatSource(HEADER, file) - ) - } - } - ) - }) - } -} - -module.exports = UserscriptPlugin diff --git a/src/utils/index.ts b/src/utils/index.ts new file mode 100644 index 0000000..874f591 --- /dev/null +++ b/src/utils/index.ts @@ -0,0 +1,2 @@ +export { default as logger } from './logger' +export * from './utils' diff --git a/src/utils/logger.ts b/src/utils/logger.ts new file mode 100644 index 0000000..7ef932d --- /dev/null +++ b/src/utils/logger.ts @@ -0,0 +1,92 @@ +import { format } from 'date-fns' +import pino from 'pino' + +const MSG_TYPE: { + [key: number]: 'trace' | 'debug' | 'info' | 'warn' | 'error' +} = { + 10: 'trace', + 20: 'debug', + 30: 'info', + 40: 'warn', + 50: 'error', +} + +const colored: { [key: number | string]: string } = { + default: 'white', + 50: 'red', + 40: 'yellow', + 30: 'green', + 20: 'cornflowerblue', + 10: 'gray', + message: 'white', + gray: 'gray', + background: '#202124', +} + +const levelMap = new Map([ + ['trace', 10], + ['debug', 20], + ['info', 30], + ['warn', 40], + ['error', 50], + ['silent', Infinity], +]) + +// REFINED_LEETCODE_LOG_LEVEL 的值由 webpack.DefinePlugin 提供 +const logLevel = + levelMap.get( + (typeof REFINED_LEETCODE_LOG_LEVEL === undefined + ? 'silent' + : REFINED_LEETCODE_LOG_LEVEL + ).toLocaleLowerCase() + ) ?? Infinity + +const logger = pino({ + level: 'debug', + browser: { + write: ((o: { + time: number + level: number + msg: string + prefix: string | undefined + }) => { + if (o.level < logLevel) return + + const type = MSG_TYPE[o.level] ?? 'unknown' + + const time = `[${format( + new Date(o.time), + 'yyyy-MM-dd HH:mm:ss.SSS xxxx' + )}]` + const msgType = type.toUpperCase().padStart(7, ' ') + const prefix = o.prefix ? `(${o.prefix}) ` : '' + const msgContext = o.msg + + const msg = `%c${time} %c${msgType} %c${prefix}: %c${msgContext}` + + // [时间] 类型 (前缀); 内容 + // [2022-05-03 20:00:00.000 +0800] INFO (fun): text + let styles = [ + `color: ${colored.gray}`, // 时间 + `color: ${o.level in MSG_TYPE ? colored[o.level] : colored.gray}`, // 类型 + `color: ${colored.gray}`, // 前缀 + `color: ${colored.message}`, // 内容 + ] + + styles = styles.map( + (str, i) => + `background:${colored.background};padding:5px ${ + i === styles.length - 1 ? 5 : 0 + }px 5px ${i === 0 ? 5 : 0}px;${str}` + ) + + if (o.level in MSG_TYPE) { + console[type](msg, ...styles) + } else { + console.log(msg, ...styles) + } + }) as (o: any) => void, + }, +}) + +export default logger diff --git a/src/utils/utils.ts b/src/utils/utils.ts new file mode 100644 index 0000000..a015a7e --- /dev/null +++ b/src/utils/utils.ts @@ -0,0 +1,50 @@ +/** 限流 + * + * @param fn 要执行的函数,如果函数返回 true 时,则表示不去限制下一个函数的执行 + * @param interval 间隔时间 + * + * + */ +export function throttle< + T extends (...args: any) => Promise<boolean | void> | boolean | void, + R = (...args: Parameters<T>) => Promise<void> +>(fn: T, interval = 0): R { + let pre: number | null = null, + next = false + return (async (...args: any) => { + const cur = new Date().valueOf() + if (!pre || cur - pre >= interval || next) { + pre = cur + next = false + if (await fn(...args)) next = true + } + }) as R +} + +/** 防抖 + * + * @param fn 要执行的函数 + * @param delay 延迟时间 + */ +export function debounce< + T extends (...args: any) => void, + R extends T & { cancel: () => void; destroy: () => void } +>(fn: T, delay = 0): R { + let timer: ReturnType<typeof setTimeout>, + destroy = false + const debounced: R = ((...args: any) => { + if (timer) clearTimeout(timer) + if (destroy) return + timer = setTimeout(() => { + fn(...args) + }, delay) + }) as any + debounced.cancel = () => { + if (timer) clearTimeout(timer) + } + debounced.destroy = () => { + destroy = true + if (timer) clearTimeout(timer) + } + return debounced +} diff --git a/tsconfig.json b/tsconfig.json index cee33b0..9ca5952 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -14,7 +14,12 @@ "isolatedModules": true, "noEmit": true, "jsx": "preserve", - "downlevelIteration": true + "downlevelIteration": true, + "baseUrl": "./", + "paths": { + "@/*": ["src/content/*"], + "src/*": ["src/*"] + } }, "include": ["src", "config"] } diff --git a/webpack.config.js b/webpack.config.js index 64059b6..e66d5f3 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -4,12 +4,12 @@ const { common } = require('./config/common.js') const { development } = require('./config/development.js') const { production } = require('./config/production.js') -module.exports = (_env, _args) => { +module.exports = (env, _args) => { switch (process.env.NODE_ENV) { case 'development': - return merge(common, development) + return merge(common, development(env)) case 'production': - return merge(common, production) + return merge(common, production(env)) default: throw new Error('No matching configuration was found!') }