From a1a4192b8153ed9f89bb60547b8fca5521f94af4 Mon Sep 17 00:00:00 2001 From: harytfw Date: Sat, 27 Aug 2022 14:38:13 +0800 Subject: [PATCH] improve and add options page --- Makefile | 32 +- README.zh_cn.md | 53 - package.json | 33 +- pnpm-lock.yaml | 1505 ++++++++++------- rollup.config.js | 73 +- scripts/copy_simplecss.mjs | 23 + src/_locales/en/messages.json | 278 +++ src/_locales/zh_CN/messages.json | 278 +++ src/background/context.test.ts | 17 +- src/background/context.ts | 129 +- src/background/executor.test.ts | 6 +- src/background/executor.ts | 96 +- src/background/helper.test.ts | 18 +- src/background/main.ts | 39 +- src/background/menu.ts | 79 + src/background/resolver.ts | 21 +- src/background/search.ts | 12 +- src/background/utils.test.ts | 12 +- src/background/utils.ts | 30 +- src/background/volatile_state.ts | 22 +- src/build_info.ts | 1 - src/components/helper.ts | 37 + src/components/indicator/indicator.svelte | 12 +- src/components/indicator/indicator.test.ts | 11 - src/components/indicator/indicator.ts | 35 +- src/components/indicator/indicator_proxy.ts | 28 +- src/components/main.ts | 8 +- src/components/menu/menu.svelte | 78 +- src/components/menu/menu.test.ts | 27 +- src/components/menu/menu.ts | 54 +- src/components/menu/menu_proxy.ts | 34 +- src/components/prompt/prompt.svelte | 23 + src/components/prompt/prompt.ts | 29 + src/components/prompt/prompt_proxy.ts | 25 + src/components/status/status.svelte | 15 - src/components/status/status.ts | 17 - src/components/status/status_proxy.ts | 5 - src/components/{message.ts => types.ts} | 36 +- src/config/config.ts | 280 ++- src/content_scripts/content_script.css | 2 +- src/content_scripts/drag.ts | 512 +----- src/content_scripts/drag_utils.ts | 105 +- src/content_scripts/features/auxclose.ts | 37 + .../features/middle_button_selector.ts | 5 +- src/content_scripts/label_chain.ts | 51 +- src/content_scripts/main.ts | 74 +- src/content_scripts/op.ts | 507 ++++++ src/content_scripts/op_source.ts | 140 ++ src/content_scripts/script.ts | 2 +- src/content_scripts/state_man.ts | 12 +- src/content_scripts/utils.ts | 103 +- src/localization/helper.ts | 20 + src/manifest_chromium.json | 16 +- src/manifest_firefox.json | 18 +- src/message/message.ts | 53 +- src/options/actions.svelte | 1172 +++++++++++++ src/options/assets.svelte | 294 ++++ src/options/cfg_utils.ts | 170 ++ src/options/common.svelte | 80 + src/options/common.ts | 91 + src/options/confirm_dialog.svelte | 41 + src/options/nav.svelte | 31 + src/options/options.html | 45 +- src/options/options.svelte | 127 +- src/options/requests.svelte | 363 ++++ src/options/scripts.svelte | 216 +++ src/options/search_engines.ts | 26 + src/options/store.ts | 73 + src/options/utils.ts | 49 + src/types.ts | 12 +- src/utils/log.ts | 12 +- src/utils/url.ts | 1 - src/utils/var_substitute.ts | 4 + src/utils/vendor.ts | 7 +- 74 files changed, 6087 insertions(+), 1895 deletions(-) delete mode 100644 README.zh_cn.md create mode 100644 scripts/copy_simplecss.mjs create mode 100644 src/_locales/en/messages.json create mode 100644 src/_locales/zh_CN/messages.json create mode 100644 src/background/menu.ts create mode 100644 src/components/helper.ts create mode 100644 src/components/prompt/prompt.svelte create mode 100644 src/components/prompt/prompt.ts create mode 100644 src/components/prompt/prompt_proxy.ts delete mode 100644 src/components/status/status.svelte delete mode 100644 src/components/status/status.ts delete mode 100644 src/components/status/status_proxy.ts rename src/components/{message.ts => types.ts} (55%) create mode 100644 src/content_scripts/features/auxclose.ts create mode 100644 src/content_scripts/op.ts create mode 100644 src/content_scripts/op_source.ts create mode 100644 src/localization/helper.ts create mode 100644 src/options/actions.svelte create mode 100644 src/options/assets.svelte create mode 100644 src/options/cfg_utils.ts create mode 100644 src/options/common.svelte create mode 100644 src/options/common.ts create mode 100644 src/options/confirm_dialog.svelte create mode 100644 src/options/nav.svelte create mode 100644 src/options/requests.svelte create mode 100644 src/options/scripts.svelte create mode 100644 src/options/search_engines.ts create mode 100644 src/options/store.ts create mode 100644 src/options/utils.ts diff --git a/Makefile b/Makefile index c348cc1..bf421e5 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,9 @@ -SRC = ./src -DIST = ./dist -BROWSER ?= $(shell which firefox-developer-edition) -NODE_MODULES = ./node_modules - +export SRC = ./src +export DIST = ./dist +export BROWSER ?= $(shell which firefox-developer-edition) +export NODE_MODULES = ./node_modules +export WEB_EXT_ARTIFACTS = ./web-ext-artifacts export BUILD_PROFILE ?= debug export BUILD_COMMIT_ID = $(shell git rev-parse --short HEAD) export BUILD_DATE = $(shell date --rfc-3339=seconds) @@ -16,13 +16,17 @@ $(shell [ ! -d $(DIST) ] && mkdir $(DIST)) entryPoints = background content_scripts options components assets = ./content_scripts/content_script.css \ ./icon/drag.png \ - ./options/options.html + ./options/options.html \ + ./_locales + +.PHONY: extension +extension: extension-firefox extension-chromium .PHONY: extension-firefox -extension-firefox: manifest-firefox compile lint package +extension-firefox: clean manifest-firefox compile lint package-firefox .PHONY: extension-chromium -extension-chromium: manifest-chromium compile package +extension-chromium: clean manifest-chromium compile package-chromium .PHONY: manifest-firefox manifest-firefox: @@ -32,18 +36,24 @@ manifest-firefox: manifest-chromium: @cp $(SRC)/manifest_chromium.json $(DIST)/manifest.json -.PHONY: package -package: - @web-ext build -s $(DIST) --overwrite-dest +.PHONY: package-firefox +package-firefox: + @web-ext build -s $(DIST) -a $(WEB_EXT_ARTIFACTS)/firefox --overwrite-dest + +.PHONY: packagec-chromium +package-chromium: + @web-ext build -s $(DIST) -a $(WEB_EXT_ARTIFACTS)/chromium --overwrite-dest .PHONY: clean clean: @rm -rf $(DIST) + @mkdir $(DIST) .PHONY: compile compile: @entryPoints="$(entryPoints)" src=$(SRC) dist=$(DIST) npx rollup -c; @echo $(assets) | tr " " "\n" | rsync --files-from=- -r $(SRC) $(DIST) + @node scripts/copy_simplecss.mjs .PHONY: lint lint: diff --git a/README.zh_cn.md b/README.zh_cn.md deleted file mode 100644 index ce2826c..0000000 --- a/README.zh_cn.md +++ /dev/null @@ -1,53 +0,0 @@ -# 闪耀拖拽 v2 - -## v2 特性 - -- 支持 Firefox 浏览器以及基于 Chromium 的浏览器 -- 兼容 Manifest V3 -- 允许自定义个人的喜欢拖拽命令 -- 主要支持的命令:打开链接,搜索文本,下载图片,执行脚本 - -## 跟 v1 对比 - -### 暂时移除的功能 - -- 支持外部拖拽的内容 -- 自定义样式 -- 图片搜索 -- 内置的搜索引擎 -- 翻译命令 -- 超时功能 -- 不启用站点的规则 - -### 重做/重新设计 - -- 项目代码和库的优化,使用 typescript + svelte + rollup + mocha -- 重新设计了动作以及动作的执行条件,并且允许多种条件的进行组合 -- 执行条件新增多个方向的链式组合,类似鼠标手势的操作行为。 -- 重新设计面板 -- 优化字符串模板 - -## 浏览器版本支持情况 - -目前只在 Firefox 104 和 Chromium 104 下经过测试. 其他版本或许可以使用,但没有经过测试. 后续可能会根据测试情况降低版本限制 - -## 如何构建 - -我个人的开发环境是 Arch, 其他环境暂未测试. - -依赖的程序: - -- make -- pnpm - -构建步骤: - -```shell -pnpm install -# 构建适配 firefox 的扩展 -make extension-firefox -# 或者 -make extension-chromium -``` - -编译后的文件存在放 `/dist`, 打包后的文件存放在 `web-ext-artifacts` diff --git a/package.json b/package.json index f52714f..6587131 100644 --- a/package.json +++ b/package.json @@ -3,30 +3,33 @@ "description": "An drag extension for Firefox Browser.", "type": "module", "devDependencies": { - "@rollup/plugin-commonjs": "^22.0.0", - "@rollup/plugin-node-resolve": "^13.3.0", - "@rollup/plugin-replace": "^4.0.0", - "@rollup/plugin-typescript": "^8.3.2", + "@rollup/plugin-commonjs": "^23.0.2", + "@rollup/plugin-node-resolve": "^15.0.1", + "@rollup/plugin-replace": "^5.0.1", + "@rollup/plugin-typescript": "^9.0.2", "@tsconfig/svelte": "^3.0.0", - "@types/chai": "^4.3.1", + "@types/chai": "^4.3.3", "@types/lodash-es": "^4.17.6", - "@types/mocha": "^9.1.1", - "@types/node": "^18.0.0", - "@types/webextension-polyfill": "^0.9.0", + "@types/mocha": "^10.0.0", + "@types/node": "^18.11.9", + "@types/uuid": "^8.3.4", + "@types/webextension-polyfill": "^0.9.1", "lodash": "^4.17.21", "lodash-core": "^4.17.19", "lodash-es": "^4.17.21", - "mocha": "^10.0.0", - "rollup": "^2.75.7", + "mocha": "^10.1.0", + "rollup": "^3.2.5", "rollup-plugin-svelte": "^7.1.0", "rollup-plugin-terser": "^7.0.2", - "svelte": "^3.48.0", + "simpledotcss": "^2.1.1", + "svelte": "^3.52.0", "svelte-preprocess": "^4.10.7", - "tldts": "^5.7.84", + "tldts": "^5.7.97", "tslib": "*", - "typescript": "^4.7.4", - "web-ext": "7.1.0", - "webextension-polyfill": "^0.9.0" + "typescript": "^4.8.4", + "uuid": "^9.0.0", + "web-ext": "7.3.1", + "webextension-polyfill": "^0.10.0" }, "license": "MIT" } \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bdf2545..79994ad 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,66 +1,65 @@ lockfileVersion: 5.4 specifiers: - '@rollup/plugin-commonjs': ^22.0.0 - '@rollup/plugin-node-resolve': ^13.3.0 - '@rollup/plugin-replace': ^4.0.0 - '@rollup/plugin-typescript': ^8.3.2 + '@rollup/plugin-commonjs': ^23.0.2 + '@rollup/plugin-node-resolve': ^15.0.1 + '@rollup/plugin-replace': ^5.0.1 + '@rollup/plugin-typescript': ^9.0.2 '@tsconfig/svelte': ^3.0.0 - '@types/chai': ^4.3.1 + '@types/chai': ^4.3.3 '@types/lodash-es': ^4.17.6 - '@types/mocha': ^9.1.1 - '@types/node': ^18.0.0 - '@types/webextension-polyfill': ^0.9.0 + '@types/mocha': ^10.0.0 + '@types/node': ^18.11.9 + '@types/uuid': ^8.3.4 + '@types/webextension-polyfill': ^0.9.1 lodash: ^4.17.21 lodash-core: ^4.17.19 lodash-es: ^4.17.21 - mocha: ^10.0.0 - rollup: ^2.75.7 + mocha: ^10.1.0 + rollup: ^3.2.5 rollup-plugin-svelte: ^7.1.0 rollup-plugin-terser: ^7.0.2 - svelte: ^3.48.0 + simpledotcss: ^2.1.1 + svelte: ^3.52.0 svelte-preprocess: ^4.10.7 - tldts: ^5.7.84 + tldts: ^5.7.97 tslib: '*' - typescript: ^4.7.4 - web-ext: 7.1.0 - webextension-polyfill: ^0.9.0 + typescript: ^4.8.4 + uuid: ^9.0.0 + web-ext: 7.3.1 + webextension-polyfill: ^0.10.0 devDependencies: - '@rollup/plugin-commonjs': 22.0.0_rollup@2.75.7 - '@rollup/plugin-node-resolve': 13.3.0_rollup@2.75.7 - '@rollup/plugin-replace': 4.0.0_rollup@2.75.7 - '@rollup/plugin-typescript': 8.3.2_g4qkabtmybowem44p7ts7jnbqm + '@rollup/plugin-commonjs': 23.0.2_rollup@3.2.5 + '@rollup/plugin-node-resolve': 15.0.1_rollup@3.2.5 + '@rollup/plugin-replace': 5.0.1_rollup@3.2.5 + '@rollup/plugin-typescript': 9.0.2_skqhbvp355vci76ty3pdffvjrq '@tsconfig/svelte': 3.0.0 - '@types/chai': 4.3.1 + '@types/chai': 4.3.3 '@types/lodash-es': 4.17.6 - '@types/mocha': 9.1.1 - '@types/node': 18.0.0 - '@types/webextension-polyfill': 0.9.0 + '@types/mocha': 10.0.0 + '@types/node': 18.11.9 + '@types/uuid': 8.3.4 + '@types/webextension-polyfill': 0.9.1 lodash: 4.17.21 lodash-core: 4.17.19 lodash-es: 4.17.21 - mocha: 10.0.0 - rollup: 2.75.7 - rollup-plugin-svelte: 7.1.0_oqvu6r7na5sdokb6fyq7tyqy6i - rollup-plugin-terser: 7.0.2_rollup@2.75.7 - svelte: 3.48.0 - svelte-preprocess: 4.10.7_lvfi2wesz6u4l5rfbnetbucfmm - tldts: 5.7.84 - tslib: 2.4.0 - typescript: 4.7.4 - web-ext: 7.1.0 - webextension-polyfill: 0.9.0 + mocha: 10.1.0 + rollup: 3.2.5 + rollup-plugin-svelte: 7.1.0_rollup@3.2.5+svelte@3.52.0 + rollup-plugin-terser: 7.0.2_rollup@3.2.5 + simpledotcss: 2.1.1 + svelte: 3.52.0 + svelte-preprocess: 4.10.7_besnmoibwkhwtentvwuriss7pa + tldts: 5.7.97 + tslib: 2.4.1 + typescript: 4.8.4 + uuid: 9.0.0 + web-ext: 7.3.1 + webextension-polyfill: 0.10.0 packages: - /@babel/code-frame/7.16.7: - resolution: {integrity: sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/highlight': 7.17.9 - dev: true - /@babel/code-frame/7.18.6: resolution: {integrity: sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==} engines: {node: '>=6.9.0'} @@ -68,39 +67,25 @@ packages: '@babel/highlight': 7.18.6 dev: true - /@babel/helper-validator-identifier/7.16.7: - resolution: {integrity: sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==} + /@babel/helper-validator-identifier/7.19.1: + resolution: {integrity: sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==} engines: {node: '>=6.9.0'} dev: true - /@babel/helper-validator-identifier/7.18.6: - resolution: {integrity: sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/highlight/7.17.9: - resolution: {integrity: sha512-J9PfEKCbFIv2X5bjTMiZu6Vf341N05QIY+d6FvVKynkG1S7G0j3I0QoRtWIrXhZ+/Nlb5Q0MzqL7TokEJ5BNHg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-validator-identifier': 7.16.7 - chalk: 2.4.2 - js-tokens: 4.0.0 - dev: true - /@babel/highlight/7.18.6: resolution: {integrity: sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==} engines: {node: '>=6.9.0'} dependencies: - '@babel/helper-validator-identifier': 7.18.6 + '@babel/helper-validator-identifier': 7.19.1 chalk: 2.4.2 js-tokens: 4.0.0 dev: true - /@babel/runtime/7.18.3: - resolution: {integrity: sha512-38Y8f7YUhce/K7RMwTp7m0uCumpv9hZkitCbBClqQIow1qSbCvGkcegKOXpEWCQLfWmevgRiWokZ1GkpfhbZug==} + /@babel/runtime/7.19.4: + resolution: {integrity: sha512-EXpLCrk55f+cYqmHsSR+yD/0gAIMxxA9QK9lnQWzhMCvt+YmoBN7Zx94s++Kv0+unHk39vxNO8t+CMA2WSS3wA==} engines: {node: '>=6.9.0'} dependencies: - regenerator-runtime: 0.13.9 + regenerator-runtime: 0.13.10 dev: true /@devicefarmer/adbkit-logcat/2.1.2: @@ -121,7 +106,7 @@ packages: '@devicefarmer/adbkit-logcat': 2.1.2 '@devicefarmer/adbkit-monkey': 1.2.1 bluebird: 3.7.2 - commander: 9.3.0 + commander: 9.4.1 debug: 4.3.4 node-forge: 1.3.1 split: 1.0.1 @@ -129,14 +114,14 @@ packages: - supports-color dev: true - /@eslint/eslintrc/1.3.0: - resolution: {integrity: sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw==} + /@eslint/eslintrc/1.3.3: + resolution: {integrity: sha512-uj3pT6Mg+3t39fvLrj8iuCIJ38zKO9FpGtJ4BBJebJhEwjoT+KLVNCcHT5QC9NGRIEi7fZ0ZR8YRb884auB4Lg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: ajv: 6.12.6 debug: 4.3.4 - espree: 9.3.2 - globals: 13.15.0 + espree: 9.4.0 + globals: 13.17.0 ignore: 5.2.0 import-fresh: 3.3.0 js-yaml: 4.1.0 @@ -146,8 +131,8 @@ packages: - supports-color dev: true - /@humanwhocodes/config-array/0.9.5: - resolution: {integrity: sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==} + /@humanwhocodes/config-array/0.10.7: + resolution: {integrity: sha512-MDl6D6sBsaV452/QSdX+4CXIjZhIcI0PELsxUjk4U828yd58vk3bTIvk/6w5FY+4hIy9sLW0sfrV7K7Kc++j/w==} engines: {node: '>=10.10.0'} dependencies: '@humanwhocodes/object-schema': 1.2.1 @@ -157,266 +142,316 @@ packages: - supports-color dev: true + /@humanwhocodes/module-importer/1.0.1: + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + dev: true + /@humanwhocodes/object-schema/1.2.1: resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==} dev: true - /@jridgewell/gen-mapping/0.3.1: - resolution: {integrity: sha512-GcHwniMlA2z+WFPWuY8lp3fsza0I8xPFMWL5+n8LYyP6PSvPrXf4+n8stDHZY2DM0zy9sVkRDy1jDI4XGzYVqg==} + /@jridgewell/gen-mapping/0.3.2: + resolution: {integrity: sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==} engines: {node: '>=6.0.0'} dependencies: - '@jridgewell/set-array': 1.1.1 - '@jridgewell/sourcemap-codec': 1.4.13 - '@jridgewell/trace-mapping': 0.3.13 + '@jridgewell/set-array': 1.1.2 + '@jridgewell/sourcemap-codec': 1.4.14 + '@jridgewell/trace-mapping': 0.3.17 dev: true - /@jridgewell/resolve-uri/3.0.7: - resolution: {integrity: sha512-8cXDaBBHOr2pQ7j77Y6Vp5VDT2sIqWyWQ56TjEq4ih/a4iST3dItRe8Q9fp0rrIl9DoKhWQtUQz/YpOxLkXbNA==} + /@jridgewell/resolve-uri/3.1.0: + resolution: {integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==} engines: {node: '>=6.0.0'} dev: true - /@jridgewell/set-array/1.1.1: - resolution: {integrity: sha512-Ct5MqZkLGEXTVmQYbGtx9SVqD2fqwvdubdps5D3djjAkgkKwT918VNOz65pEHFaYTeWcukmJmH5SwsA9Tn2ObQ==} + /@jridgewell/set-array/1.1.2: + resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==} engines: {node: '>=6.0.0'} dev: true /@jridgewell/source-map/0.3.2: resolution: {integrity: sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==} dependencies: - '@jridgewell/gen-mapping': 0.3.1 - '@jridgewell/trace-mapping': 0.3.13 + '@jridgewell/gen-mapping': 0.3.2 + '@jridgewell/trace-mapping': 0.3.17 dev: true - /@jridgewell/sourcemap-codec/1.4.13: - resolution: {integrity: sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w==} + /@jridgewell/sourcemap-codec/1.4.14: + resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==} dev: true - /@jridgewell/trace-mapping/0.3.13: - resolution: {integrity: sha512-o1xbKhp9qnIAoHJSWd6KlCZfqslL4valSF81H8ImioOAxluWYWOpWkpyktY2vnt4tbrX9XYaxovq6cgowaJp2w==} + /@jridgewell/trace-mapping/0.3.17: + resolution: {integrity: sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==} dependencies: - '@jridgewell/resolve-uri': 3.0.7 - '@jridgewell/sourcemap-codec': 1.4.13 + '@jridgewell/resolve-uri': 3.1.0 + '@jridgewell/sourcemap-codec': 1.4.14 + dev: true + + /@mdn/browser-compat-data/5.2.6: + resolution: {integrity: sha512-KJfP6iTcVX+R5OSC4NOIF4V9fTyifcjwmdkOk7UzsaWxkF21rc6KhGlohqiSRVEynidGO1EEyyYf/PD3jsM1gA==} dev: true - /@mdn/browser-compat-data/5.1.1: - resolution: {integrity: sha512-odIvtuAoXePQL4UcPrhy3MSXMvz2vefTe5uQQoLzKHQ6+f6vAhVlZEbs92d6cz8oSjylF+KL3Z/G2eLCMFl7qw==} + /@nodelib/fs.scandir/2.1.5: + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + dev: true + + /@nodelib/fs.stat/2.0.5: + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} dev: true - /@rollup/plugin-commonjs/22.0.0_rollup@2.75.7: - resolution: {integrity: sha512-Ktvf2j+bAO+30awhbYoCaXpBcyPmJbaEUYClQns/+6SNCYFURbvBiNbWgHITEsIgDDWCDUclWRKEuf8cwZCFoQ==} - engines: {node: '>= 12.0.0'} + /@nodelib/fs.walk/1.2.8: + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.13.0 + dev: true + + /@pnpm/network.ca-file/1.0.1: + resolution: {integrity: sha512-gkINruT2KUhZLTaiHxwCOh1O4NVnFT0wLjWFBHmTz9vpKag/C/noIMJXBxFe4F0mYpUVX2puLwAieLYFg2NvoA==} + engines: {node: '>=12.22.0'} + dependencies: + graceful-fs: 4.2.10 + dev: true + + /@pnpm/npm-conf/1.0.5: + resolution: {integrity: sha512-hD8ml183638O3R6/Txrh0L8VzGOrFXgRtRDG4qQC4tONdZ5Z1M+tlUUDUvrjYdmK6G+JTBTeaCLMna11cXzi8A==} + engines: {node: '>=12'} + dependencies: + '@pnpm/network.ca-file': 1.0.1 + config-chain: 1.1.13 + dev: true + + /@rollup/plugin-commonjs/23.0.2_rollup@3.2.5: + resolution: {integrity: sha512-e9ThuiRf93YlVxc4qNIurvv+Hp9dnD+4PjOqQs5vAYfcZ3+AXSrcdzXnVjWxcGQOa6KGJFcRZyUI3ktWLavFjg==} + engines: {node: '>=14.0.0'} peerDependencies: - rollup: ^2.68.0 + rollup: ^2.68.0||^3.0.0 + peerDependenciesMeta: + rollup: + optional: true dependencies: - '@rollup/pluginutils': 3.1.0_rollup@2.75.7 + '@rollup/pluginutils': 5.0.2_rollup@3.2.5 commondir: 1.0.1 estree-walker: 2.0.2 - glob: 7.2.0 + glob: 8.0.3 is-reference: 1.2.1 - magic-string: 0.25.9 - resolve: 1.22.0 - rollup: 2.75.7 + magic-string: 0.26.7 + rollup: 3.2.5 dev: true - /@rollup/plugin-node-resolve/13.3.0_rollup@2.75.7: - resolution: {integrity: sha512-Lus8rbUo1eEcnS4yTFKLZrVumLPY+YayBdWXgFSHYhTT2iJbMhoaaBL3xl5NCdeRytErGr8tZ0L71BMRmnlwSw==} - engines: {node: '>= 10.0.0'} + /@rollup/plugin-node-resolve/15.0.1_rollup@3.2.5: + resolution: {integrity: sha512-ReY88T7JhJjeRVbfCyNj+NXAG3IIsVMsX9b5/9jC98dRP8/yxlZdz7mHZbHk5zHr24wZZICS5AcXsFZAXYUQEg==} + engines: {node: '>=14.0.0'} peerDependencies: - rollup: ^2.42.0 + rollup: ^2.78.0||^3.0.0 + peerDependenciesMeta: + rollup: + optional: true dependencies: - '@rollup/pluginutils': 3.1.0_rollup@2.75.7 - '@types/resolve': 1.17.1 + '@rollup/pluginutils': 5.0.2_rollup@3.2.5 + '@types/resolve': 1.20.2 deepmerge: 4.2.2 - is-builtin-module: 3.1.0 + is-builtin-module: 3.2.0 is-module: 1.0.0 - resolve: 1.22.0 - rollup: 2.75.7 + resolve: 1.22.1 + rollup: 3.2.5 dev: true - /@rollup/plugin-replace/4.0.0_rollup@2.75.7: - resolution: {integrity: sha512-+rumQFiaNac9y64OHtkHGmdjm7us9bo1PlbgQfdihQtuNxzjpaB064HbRnewUOggLQxVCCyINfStkgmBeQpv1g==} + /@rollup/plugin-replace/5.0.1_rollup@3.2.5: + resolution: {integrity: sha512-Z3MfsJ4CK17BfGrZgvrcp/l6WXoKb0kokULO+zt/7bmcyayokDaQ2K3eDJcRLCTAlp5FPI4/gz9MHAsosz4Rag==} + engines: {node: '>=14.0.0'} peerDependencies: - rollup: ^1.20.0 || ^2.0.0 + rollup: ^1.20.0||^2.0.0||^3.0.0 + peerDependenciesMeta: + rollup: + optional: true dependencies: - '@rollup/pluginutils': 3.1.0_rollup@2.75.7 - magic-string: 0.25.9 - rollup: 2.75.7 + '@rollup/pluginutils': 5.0.2_rollup@3.2.5 + magic-string: 0.26.7 + rollup: 3.2.5 dev: true - /@rollup/plugin-typescript/8.3.2_g4qkabtmybowem44p7ts7jnbqm: - resolution: {integrity: sha512-MtgyR5LNHZr3GyN0tM7gNO9D0CS+Y+vflS4v/PHmrX17JCkHUYKvQ5jN5o3cz1YKllM3duXUqu3yOHwMPUxhDg==} - engines: {node: '>=8.0.0'} + /@rollup/plugin-typescript/9.0.2_skqhbvp355vci76ty3pdffvjrq: + resolution: {integrity: sha512-/sS93vmHUMjzDUsl5scNQr1mUlNE1QjBBvOhmRwJCH8k2RRhDIm3c977B3wdu3t3Ap17W6dDeXP3hj1P1Un1bA==} + engines: {node: '>=14.0.0'} peerDependencies: - rollup: ^2.14.0 + rollup: ^2.14.0||^3.0.0 tslib: '*' typescript: '>=3.7.0' + peerDependenciesMeta: + rollup: + optional: true + tslib: + optional: true dependencies: - '@rollup/pluginutils': 3.1.0_rollup@2.75.7 - resolve: 1.22.0 - rollup: 2.75.7 - tslib: 2.4.0 - typescript: 4.7.4 + '@rollup/pluginutils': 5.0.2_rollup@3.2.5 + resolve: 1.22.1 + rollup: 3.2.5 + tslib: 2.4.1 + typescript: 4.8.4 dev: true - /@rollup/pluginutils/3.1.0_rollup@2.75.7: - resolution: {integrity: sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==} - engines: {node: '>= 8.0.0'} + /@rollup/pluginutils/5.0.2_rollup@3.2.5: + resolution: {integrity: sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==} + engines: {node: '>=14.0.0'} peerDependencies: - rollup: ^1.20.0||^2.0.0 + rollup: ^1.20.0||^2.0.0||^3.0.0 + peerDependenciesMeta: + rollup: + optional: true dependencies: - '@types/estree': 0.0.39 - estree-walker: 1.0.1 + '@types/estree': 1.0.0 + estree-walker: 2.0.2 picomatch: 2.3.1 - rollup: 2.75.7 + rollup: 3.2.5 dev: true - /@sindresorhus/is/0.14.0: - resolution: {integrity: sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==} - engines: {node: '>=6'} + /@sindresorhus/is/5.3.0: + resolution: {integrity: sha512-CX6t4SYQ37lzxicAqsBtxA3OseeoVrh9cSJ5PFYam0GksYlupRfy1A+Q4aYD3zvcfECLc0zO2u+ZnR2UYKvCrw==} + engines: {node: '>=14.16'} dev: true - /@szmarczak/http-timer/1.1.2: - resolution: {integrity: sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==} - engines: {node: '>=6'} + /@szmarczak/http-timer/5.0.1: + resolution: {integrity: sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==} + engines: {node: '>=14.16'} dependencies: - defer-to-connect: 1.1.3 + defer-to-connect: 2.0.1 dev: true /@tsconfig/svelte/3.0.0: resolution: {integrity: sha512-pYrtLtOwku/7r1i9AMONsJMVYAtk3hzOfiGNekhtq5tYBGA7unMve8RvUclKLMT3PrihvJqUmzsRGh0RP84hKg==} dev: true - /@types/chai/4.3.1: - resolution: {integrity: sha512-/zPMqDkzSZ8t3VtxOa4KPq7uzzW978M9Tvh+j7GHKuo6k6GTLxPJ4J5gE5cjfJ26pnXst0N5Hax8Sr0T2Mi9zQ==} + /@types/chai/4.3.3: + resolution: {integrity: sha512-hC7OMnszpxhZPduX+m+nrx+uFoLkWOMiR4oa/AZF3MuSETYTZmFfJAHqZEM8MVlvfG7BEUcgvtwoCTxBp6hm3g==} dev: true - /@types/estree/0.0.39: - resolution: {integrity: sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==} + /@types/estree/1.0.0: + resolution: {integrity: sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==} dev: true - /@types/keyv/3.1.4: - resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==} - dependencies: - '@types/node': 18.0.1 + /@types/http-cache-semantics/4.0.1: + resolution: {integrity: sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==} dev: true /@types/lodash-es/4.17.6: resolution: {integrity: sha512-R+zTeVUKDdfoRxpAryaQNRKk3105Rrgx2CFRClIgRGaqDTdjsm8h6IYA8ir584W3ePzkZfst5xIgDwYrlh9HLg==} dependencies: - '@types/lodash': 4.14.182 + '@types/lodash': 4.14.187 dev: true - /@types/lodash/4.14.182: - resolution: {integrity: sha512-/THyiqyQAP9AfARo4pF+aCGcyiQ94tX/Is2I7HofNRqoYLgN1PBoOWu2/zTA5zMxzP5EFutMtWtGAFRKUe961Q==} + /@types/lodash/4.14.187: + resolution: {integrity: sha512-MrO/xLXCaUgZy3y96C/iOsaIqZSeupyTImKClHunL5GrmaiII2VwvWmLBu2hwa0Kp0sV19CsyjtrTc/Fx8rg/A==} dev: true /@types/minimatch/3.0.5: resolution: {integrity: sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==} dev: true - /@types/mocha/9.1.1: - resolution: {integrity: sha512-Z61JK7DKDtdKTWwLeElSEBcWGRLY8g95ic5FoQqI9CMx0ns/Ghep3B4DfcEimiKMvtamNVULVNKEsiwV3aQmXw==} - dev: true - - /@types/node/18.0.0: - resolution: {integrity: sha512-cHlGmko4gWLVI27cGJntjs/Sj8th9aYwplmZFwmmgYQQvL5NUsgVJG7OddLvNfLqYS31KFN0s3qlaD9qCaxACA==} + /@types/mocha/10.0.0: + resolution: {integrity: sha512-rADY+HtTOA52l9VZWtgQfn4p+UDVM2eDVkMZT1I6syp0YKxW2F9v+0pbRZLsvskhQv/vMb6ZfCay81GHbz5SHg==} dev: true - /@types/node/18.0.1: - resolution: {integrity: sha512-CmR8+Tsy95hhwtZBKJBs0/FFq4XX7sDZHlGGf+0q+BRZfMbOTkzkj0AFAuTyXbObDIoanaBBW0+KEW+m3N16Wg==} + /@types/node/18.11.9: + resolution: {integrity: sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg==} dev: true /@types/pug/2.0.6: resolution: {integrity: sha512-SnHmG9wN1UVmagJOnyo/qkk0Z7gejYxOYYmaAwr5u2yFYfsupN3sg10kyzN8Hep/2zbHxCnsumxOoRIRMBwKCg==} dev: true - /@types/resolve/1.17.1: - resolution: {integrity: sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==} - dependencies: - '@types/node': 18.0.0 - dev: true - - /@types/responselike/1.0.0: - resolution: {integrity: sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==} - dependencies: - '@types/node': 18.0.1 + /@types/resolve/1.20.2: + resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} dev: true /@types/sass/1.43.1: resolution: {integrity: sha512-BPdoIt1lfJ6B7rw35ncdwBZrAssjcwzI5LByIrYs+tpXlj/CAkuVdRsgZDdP4lq5EjyWzwxZCqAoFyHKFwp32g==} dependencies: - '@types/node': 18.0.0 + '@types/node': 18.11.9 + dev: true + + /@types/uuid/8.3.4: + resolution: {integrity: sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==} dev: true - /@types/webextension-polyfill/0.9.0: - resolution: {integrity: sha512-HG1y1o2hK8ag6Y7dfkrAbfKmMIP+B0E6SwAzUfmQ1dDxEIdLTtMyrStY26suHBPrAL7Xw/chlDW02ugc3uXWtQ==} + /@types/webextension-polyfill/0.9.1: + resolution: {integrity: sha512-6aNzPIhqKlAV9t06nwSH3/veAceYE2dS2RVFZI8V1+UXHqsFNB6cRwxNmheiBvEGRc45E/gyZNzH0xAYIC27KA==} dev: true - /@types/yauzl/2.9.2: - resolution: {integrity: sha512-8uALY5LTvSuHgloDVUvWP3pIauILm+8/0pDMokuDYIoNsOkSwd5AiHBTSEJjKTDcZr5z8UpgOWZkxBF4iJftoA==} + /@types/yauzl/2.10.0: + resolution: {integrity: sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==} dependencies: - '@types/node': 18.0.1 + '@types/node': 18.11.9 dev: true - /@ungap/promise-all-settled/1.1.2: - resolution: {integrity: sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==} + /abort-controller/3.0.0: + resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} + engines: {node: '>=6.5'} + dependencies: + event-target-shim: 5.0.1 dev: true - /acorn-jsx/5.3.2_acorn@8.7.1: + /acorn-jsx/5.3.2_acorn@8.8.1: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 dependencies: - acorn: 8.7.1 + acorn: 8.8.1 dev: true - /acorn/8.7.1: - resolution: {integrity: sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==} + /acorn/8.8.1: + resolution: {integrity: sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==} engines: {node: '>=0.4.0'} hasBin: true dev: true - /addons-linter/5.9.0: - resolution: {integrity: sha512-ACvBvkO8WtupOT42S3ln801/Ek7X1Yss59aYlI5JPc+dEBfEyEtkUa23UEQmALqdDEoHk0i+3NkKHdiXbhqp/g==} + /addons-linter/5.18.0_node-fetch@3.2.10: + resolution: {integrity: sha512-pce7nSuf/fNesDTmiD077auB15gcWZVHSVFmmAU/mm4BpzDPJBYp5rBYVMDaLjTAsYxR6Qq1ICBN8zryso2UxQ==} engines: {node: '>=12.21.0'} hasBin: true dependencies: - '@mdn/browser-compat-data': 5.1.1 + '@mdn/browser-compat-data': 5.2.6 addons-moz-compare: 1.2.0 - addons-scanner-utils: 7.0.0 + addons-scanner-utils: 8.1.0_node-fetch@3.2.10 ajv: 8.11.0 ajv-merge-patch: 5.0.1_ajv@8.11.0 chalk: 4.1.2 - cheerio: 1.0.0-rc.11 + cheerio: 1.0.0-rc.12 columnify: 1.6.0 common-tags: 1.8.2 deepmerge: 4.2.2 - eslint: 8.18.0 - eslint-plugin-no-unsanitized: 4.0.1_eslint@8.18.0 + eslint: 8.25.0 + eslint-plugin-no-unsanitized: 4.0.1_eslint@8.25.0 eslint-visitor-keys: 3.3.0 - espree: 9.3.2 + espree: 9.4.0 esprima: 4.0.1 fluent-syntax: 0.13.0 glob: 8.0.3 - image-size: 1.0.1 + image-size: 1.0.2 is-mergeable-object: 1.1.1 jed: 1.1.1 os-locale: 5.0.0 - pino: 8.0.0 - postcss: 8.4.14 + pino: 8.6.1 + postcss: 8.4.18 relaxed-json: 1.0.3 - semver: 7.3.7 + semver: 7.3.8 sha.js: 2.4.11 source-map-support: 0.5.21 tosource: 1.0.0 upath: 2.0.1 - yargs: 17.5.1 + yargs: 17.6.0 yauzl: 2.10.0 transitivePeerDependencies: - - '@types/download' - body-parser - - download - express + - node-fetch - safe-compare - supports-color dev: true @@ -425,18 +460,27 @@ packages: resolution: {integrity: sha512-COG8qk2/dubPqabfcoJW4E7pm2EQDI43iMrHnhlobvq/uRMEzx/PYJ1KaUZ97Vgg44R3QdRG5CvDsTRbMUHcDw==} dev: true - /addons-scanner-utils/7.0.0: - resolution: {integrity: sha512-5j/qMzL13uGSiaFKvUNiMwyWMYD2YtEeY477q7Ahan3c90wLCwXIGCdpCfstgT3hpl44r+d6lqTIo2j2FW6uJQ==} + /addons-scanner-utils/8.1.0_node-fetch@3.2.10: + resolution: {integrity: sha512-wxqnmmrzZXjz4B4GZbFcR4HJxTP+pGu+C6iOjMJdmL6mgZZey/UEVJlU6XTxu8GdGv0bUoJxyIioH8XEDxy91Q==} peerDependencies: - '@types/download': 8.0.1 - body-parser: 1.19.2 - download: 8.0.0 - express: 4.17.3 + body-parser: 1.20.1 + express: 4.18.2 + node-fetch: 2.6.7 safe-compare: 1.1.4 + peerDependenciesMeta: + body-parser: + optional: true + express: + optional: true + node-fetch: + optional: true + safe-compare: + optional: true dependencies: - '@types/yauzl': 2.9.2 + '@types/yauzl': 2.10.0 common-tags: 1.8.2 first-chunk-stream: 3.0.0 + node-fetch: 3.2.10 strip-bom-stream: 4.0.0 upath: 2.0.1 yauzl: 2.10.0 @@ -491,6 +535,11 @@ packages: engines: {node: '>=8'} dev: true + /ansi-regex/6.0.1: + resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} + engines: {node: '>=12'} + dev: true + /ansi-styles/3.2.1: resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} engines: {node: '>=4'} @@ -505,6 +554,11 @@ packages: color-convert: 2.0.1 dev: true + /ansi-styles/6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + dev: true + /any-promise/1.3.0: resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} dev: true @@ -526,6 +580,11 @@ packages: engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} dev: true + /array-union/2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + dev: true + /array-union/3.0.1: resolution: {integrity: sha512-1OvF9IbWwaeiM9VhzYXVQacMibxpXOMYVNIvMtKRyX9SImBXpKcFr8XvFDeEslCyuH/t6KRt7HEO94AlP8Iatw==} engines: {node: '>=12'} @@ -572,6 +631,10 @@ packages: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} dev: true + /base64-js/1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + dev: true + /bcrypt-pbkdf/1.0.2: resolution: {integrity: sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==} dependencies: @@ -591,18 +654,18 @@ packages: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} dev: true - /boxen/5.1.2: - resolution: {integrity: sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==} - engines: {node: '>=10'} + /boxen/7.0.0: + resolution: {integrity: sha512-j//dBVuyacJbvW+tvZ9HuH03fZ46QcaKvvhZickZqtB271DxJ7SNRSNxrV/dZX0085m7hISRZWbzWlJvx/rHSg==} + engines: {node: '>=14.16'} dependencies: ansi-align: 3.0.1 - camelcase: 6.3.0 - chalk: 4.1.2 - cli-boxes: 2.2.1 - string-width: 4.2.3 - type-fest: 0.20.2 - widest-line: 3.1.0 - wrap-ansi: 7.0.0 + camelcase: 7.0.0 + chalk: 5.1.2 + cli-boxes: 3.0.0 + string-width: 5.1.2 + type-fest: 2.19.0 + widest-line: 4.0.1 + wrap-ansi: 8.0.1 dev: true /brace-expansion/1.1.11: @@ -630,7 +693,7 @@ packages: dev: true /buffer-crc32/0.2.13: - resolution: {integrity: sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=} + resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} dev: true /buffer-equal-constant-time/1.0.1: @@ -641,8 +704,15 @@ packages: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} dev: true - /builtin-modules/3.2.0: - resolution: {integrity: sha512-lGzLKcioL90C7wMczpkY0n/oART3MbBa8R9OFGE1rJxoVI86u4WAGfEk8Wjv10eKSyTHVGkSo3bvBylCEtk7LA==} + /buffer/6.0.3: + resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + dev: true + + /builtin-modules/3.3.0: + resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} engines: {node: '>=6'} dev: true @@ -657,17 +727,22 @@ packages: safe-json-stringify: 1.2.0 dev: true - /cacheable-request/6.1.0: - resolution: {integrity: sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==} - engines: {node: '>=8'} + /cacheable-lookup/7.0.0: + resolution: {integrity: sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==} + engines: {node: '>=14.16'} + dev: true + + /cacheable-request/10.2.2: + resolution: {integrity: sha512-KxjQZM3UIo7/J6W4sLpwFvu1GB3Whv8NtZ8ZrUL284eiQjiXeeqWTdhixNrp/NLZ/JNuFBo6BD4ZaO8ZJ5BN8Q==} + engines: {node: '>=14.16'} dependencies: - clone-response: 1.0.2 - get-stream: 5.2.0 + '@types/http-cache-semantics': 4.0.1 + get-stream: 6.0.1 http-cache-semantics: 4.1.0 - keyv: 3.1.0 - lowercase-keys: 2.0.0 - normalize-url: 4.5.1 - responselike: 1.0.2 + keyv: 4.5.0 + mimic-response: 4.0.0 + normalize-url: 7.2.0 + responselike: 3.0.0 dev: true /callsites/3.1.0: @@ -675,11 +750,6 @@ packages: engines: {node: '>=6'} dev: true - /camelcase/6.2.0: - resolution: {integrity: sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==} - engines: {node: '>=10'} - dev: true - /camelcase/6.3.0: resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} engines: {node: '>=10'} @@ -711,6 +781,11 @@ packages: supports-color: 7.2.0 dev: true + /chalk/5.1.2: + resolution: {integrity: sha512-E5CkT4jWURs1Vy5qGJye+XwCkNj7Od3Af7CP6SujMetSMkLs8Do2RWJK5yx1wamHV/op8Rz+9rltjaTQWDnEFQ==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + dev: true + /cheerio-select/2.1.0: resolution: {integrity: sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==} dependencies: @@ -722,8 +797,8 @@ packages: domutils: 3.0.1 dev: true - /cheerio/1.0.0-rc.11: - resolution: {integrity: sha512-bQwNaDIBKID5ts/DsdhxrjqFXYfLw4ste+wMKqWA8DyKcS4qwsPP4Bk8ZNaTJjvpiX/qW3BT4sU7d6Bh5i+dag==} + /cheerio/1.0.0-rc.12: + resolution: {integrity: sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==} engines: {node: '>= 6'} dependencies: cheerio-select: 2.1.0 @@ -731,9 +806,8 @@ packages: domhandler: 5.0.3 domutils: 3.0.1 htmlparser2: 8.0.1 - parse5: 7.0.0 + parse5: 7.1.1 parse5-htmlparser2-tree-adapter: 7.0.0 - tslib: 2.4.0 dev: true /chokidar/3.5.3: @@ -756,7 +830,7 @@ packages: engines: {node: '>=12.13.0'} hasBin: true dependencies: - '@types/node': 18.0.1 + '@types/node': 18.11.9 escape-string-regexp: 4.0.0 is-wsl: 2.2.0 lighthouse-logger: 1.3.0 @@ -764,13 +838,13 @@ packages: - supports-color dev: true - /ci-info/2.0.0: - resolution: {integrity: sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==} + /ci-info/3.5.0: + resolution: {integrity: sha512-yH4RezKOGlOhxkmhbeNuC4eYZKAUsEaGtBuBzDDP1eFUKiccDWzBABxBfOx31IDwDIXMTxWuwAxUGModvkbuVw==} dev: true - /cli-boxes/2.2.1: - resolution: {integrity: sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==} - engines: {node: '>=6'} + /cli-boxes/3.0.0: + resolution: {integrity: sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==} + engines: {node: '>=10'} dev: true /cliui/7.0.4: @@ -781,10 +855,13 @@ packages: wrap-ansi: 7.0.0 dev: true - /clone-response/1.0.2: - resolution: {integrity: sha512-yjLXh88P599UOyPTFX0POsd7WxnbsVsGohcwzHOLspIhhpalPw1BcqED8NblyZLKcGrL8dTgMlcaZxV2jAD41Q==} + /cliui/8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} dependencies: - mimic-response: 1.0.1 + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 dev: true /clone/1.0.4: @@ -806,7 +883,7 @@ packages: dev: true /color-name/1.1.3: - resolution: {integrity: sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=} + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} dev: true /color-name/1.1.4: @@ -839,8 +916,8 @@ packages: graceful-readlink: 1.0.1 dev: true - /commander/9.3.0: - resolution: {integrity: sha512-hv95iU5uXPbK83mjrJKuZyFM/LBAoCV/XhVGkS5Je6tl7sxr6A0ITMw5WoRV46/UaJ46Nllm3Xt7IaJhXTIkzw==} + /commander/9.4.1: + resolution: {integrity: sha512-5EEkTNyHNGFPD2H+c/dXXfQZYa/scCKasxWcXJaWnNJ99pnQN9Vnmqow+p+PlFPE63Q6mThaZws1T+HxfpgtPw==} engines: {node: ^12.20.0 || >=14} dev: true @@ -867,21 +944,26 @@ packages: typedarray: 0.0.6 dev: true - /configstore/5.0.1: - resolution: {integrity: sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==} - engines: {node: '>=8'} + /config-chain/1.1.13: + resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==} dependencies: - dot-prop: 5.3.0 + ini: 1.3.8 + proto-list: 1.2.4 + dev: true + + /configstore/6.0.0: + resolution: {integrity: sha512-cD31W1v3GqUlQvbBCGcXmd2Nj9SvLDOP1oQ0YFuLETufzSPaKp11rYBsSOm7rCsW3OnIRAFM3OxRhceaXNYHkA==} + engines: {node: '>=12'} + dependencies: + dot-prop: 6.0.1 graceful-fs: 4.2.10 - make-dir: 3.1.0 - unique-string: 2.0.0 + unique-string: 3.0.0 write-file-atomic: 3.0.3 - xdg-basedir: 4.0.0 + xdg-basedir: 5.1.0 dev: true - /core-js/3.22.8: - resolution: {integrity: sha512-UoGQ/cfzGYIuiq6Z7vWL1HfkE9U9IZ4Ub+0XSiJTCzvbZzgPA69oDF2f+lgJ6dFFLEdjW5O6svvoKzXX23xFkA==} - deprecated: core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js. + /core-js/3.25.3: + resolution: {integrity: sha512-y1hvKXmPHvm5B7w4ln1S4uc9eV/O5+iFExSRUimnvIph11uaizFR8LFMdONN8hG3P2pipUfX4Y/fR8rAEtcHcQ==} requiresBuild: true dev: true @@ -902,9 +984,11 @@ packages: which: 2.0.2 dev: true - /crypto-random-string/2.0.0: - resolution: {integrity: sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==} - engines: {node: '>=8'} + /crypto-random-string/4.0.0: + resolution: {integrity: sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==} + engines: {node: '>=12'} + dependencies: + type-fest: 1.4.0 dev: true /css-select/5.1.0: @@ -929,6 +1013,11 @@ packages: assert-plus: 1.0.0 dev: true + /data-uri-to-buffer/4.0.0: + resolution: {integrity: sha512-Vr3mLBA8qWmcuschSLAOogKgQ/Jwxulv3RNE4FXnYWRGujzrRWQI4m12fQqRkwX06C0KanhLr4hK+GydchZsaA==} + engines: {node: '>= 12'} + dev: true + /debounce/1.2.1: resolution: {integrity: sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==} dev: true @@ -979,11 +1068,11 @@ packages: engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} dev: true - /decompress-response/3.3.0: - resolution: {integrity: sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==} - engines: {node: '>=4'} + /decompress-response/6.0.0: + resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} + engines: {node: '>=10'} dependencies: - mimic-response: 1.0.1 + mimic-response: 3.1.0 dev: true /deep-extend/0.6.0: @@ -1006,14 +1095,15 @@ packages: engines: {node: '>=0.10.0'} dev: true - /defaults/1.0.3: - resolution: {integrity: sha512-s82itHOnYrN0Ib8r+z7laQz3sdE+4FP3d9Q7VLO7U+KRT+CR0GsWuyHxzdAY82I7cXv0G/twrqomTJLOssO5HA==} + /defaults/1.0.4: + resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} dependencies: clone: 1.0.4 dev: true - /defer-to-connect/1.1.3: - resolution: {integrity: sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==} + /defer-to-connect/2.0.1: + resolution: {integrity: sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==} + engines: {node: '>=10'} dev: true /define-lazy-prop/2.0.0: @@ -1036,6 +1126,13 @@ packages: engines: {node: '>=0.3.1'} dev: true + /dir-glob/3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + dependencies: + path-type: 4.0.0 + dev: true + /doctrine/3.0.0: resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} engines: {node: '>=6.0.0'} @@ -1048,7 +1145,7 @@ packages: dependencies: domelementtype: 2.3.0 domhandler: 5.0.3 - entities: 4.3.1 + entities: 4.4.0 dev: true /domelementtype/2.3.0: @@ -1070,9 +1167,9 @@ packages: domhandler: 5.0.3 dev: true - /dot-prop/5.3.0: - resolution: {integrity: sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==} - engines: {node: '>=8'} + /dot-prop/6.0.1: + resolution: {integrity: sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==} + engines: {node: '>=10'} dependencies: is-obj: 2.0.0 dev: true @@ -1082,21 +1179,12 @@ packages: engines: {node: '>=0.10'} requiresBuild: true dependencies: - nan: 2.16.0 + nan: 2.17.0 dev: true optional: true - /duplexer3/0.1.4: - resolution: {integrity: sha512-CEj8FwwNA4cVH2uFCoHUrmojhYh1vmCdOaneKJXwkeY1i9jnlslVo9dx+hQ5Hl9GnH/Bwy/IjxAyOePyPKYnzA==} - 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 + /eastasianwidth/0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} dev: true /ecc-jsbn/0.1.2: @@ -1116,14 +1204,18 @@ packages: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} dev: true + /emoji-regex/9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + dev: true + /end-of-stream/1.4.4: resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} dependencies: once: 1.4.0 dev: true - /entities/4.3.1: - resolution: {integrity: sha512-o4q/dYJlmyjP2zfnaWDUC6A3BQFmVTX+tZPezK7k0GLSU9QYCauscf5Y+qcEPzKL+EixVouYDgLQK5H9GrLpkg==} + /entities/4.4.0: + resolution: {integrity: sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==} engines: {node: '>=0.12'} dev: true @@ -1151,13 +1243,13 @@ packages: engines: {node: '>=6'} dev: true - /escape-goat/2.1.1: - resolution: {integrity: sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==} - engines: {node: '>=8'} + /escape-goat/4.0.0: + resolution: {integrity: sha512-2Sd4ShcWxbx6OY1IHyla/CVNwvg7XwZVoXZHcSu9w9SReNP1EzzD5T8NWKIR38fIqEns9kDWKUQTXXAmlDrdPg==} + engines: {node: '>=12'} dev: true /escape-string-regexp/1.0.5: - resolution: {integrity: sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=} + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} engines: {node: '>=0.8.0'} dev: true @@ -1166,12 +1258,12 @@ packages: engines: {node: '>=10'} dev: true - /eslint-plugin-no-unsanitized/4.0.1_eslint@8.18.0: + /eslint-plugin-no-unsanitized/4.0.1_eslint@8.25.0: resolution: {integrity: sha512-y/lAMWnPPC7RYuUdxlEL/XiCL8FehN9h9s3Kjqbp/Kv0i9NZs+IXSC2kS546Fa4Bumwy31HlVS/OdWX0Kxb5Xg==} peerDependencies: eslint: ^6 || ^7 || ^8 dependencies: - eslint: 8.18.0 + eslint: 8.25.0 dev: true /eslint-scope/7.1.1: @@ -1182,13 +1274,13 @@ packages: estraverse: 5.3.0 dev: true - /eslint-utils/3.0.0_eslint@8.18.0: + /eslint-utils/3.0.0_eslint@8.25.0: resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==} engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0} peerDependencies: eslint: '>=5' dependencies: - eslint: 8.18.0 + eslint: 8.25.0 eslint-visitor-keys: 2.1.0 dev: true @@ -1202,13 +1294,14 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true - /eslint/8.18.0: - resolution: {integrity: sha512-As1EfFMVk7Xc6/CvhssHUjsAQSkpfXvUGMFC3ce8JDe6WvqCgRrLOBQbVpsBFr1X1V+RACOadnzVvcUS5ni2bA==} + /eslint/8.25.0: + resolution: {integrity: sha512-DVlJOZ4Pn50zcKW5bYH7GQK/9MsoQG2d5eDH0ebEkE8PbgzTTmtt/VTH9GGJ4BfeZCpBLqFfvsjX35UacUL83A==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} hasBin: true dependencies: - '@eslint/eslintrc': 1.3.0 - '@humanwhocodes/config-array': 0.9.5 + '@eslint/eslintrc': 1.3.3 + '@humanwhocodes/config-array': 0.10.7 + '@humanwhocodes/module-importer': 1.0.1 ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.3 @@ -1216,20 +1309,23 @@ packages: doctrine: 3.0.0 escape-string-regexp: 4.0.0 eslint-scope: 7.1.1 - eslint-utils: 3.0.0_eslint@8.18.0 + eslint-utils: 3.0.0_eslint@8.25.0 eslint-visitor-keys: 3.3.0 - espree: 9.3.2 + espree: 9.4.0 esquery: 1.4.0 esutils: 2.0.3 fast-deep-equal: 3.1.3 file-entry-cache: 6.0.1 - functional-red-black-tree: 1.0.1 + find-up: 5.0.0 glob-parent: 6.0.2 - globals: 13.15.0 + globals: 13.17.0 + globby: 11.1.0 + grapheme-splitter: 1.0.4 ignore: 5.2.0 import-fresh: 3.3.0 imurmurhash: 0.1.4 is-glob: 4.0.3 + js-sdsl: 4.1.5 js-yaml: 4.1.0 json-stable-stringify-without-jsonify: 1.0.1 levn: 0.4.1 @@ -1241,17 +1337,16 @@ packages: strip-ansi: 6.0.1 strip-json-comments: 3.1.1 text-table: 0.2.0 - v8-compile-cache: 2.3.0 transitivePeerDependencies: - supports-color dev: true - /espree/9.3.2: - resolution: {integrity: sha512-D211tC7ZwouTIuY5x9XnS0E9sWNChB7IYKX/Xp5eQj3nFXhqmiUDB9q27y76oFl8jTg3pXcQx/bpxMfs3CIZbA==} + /espree/9.4.0: + resolution: {integrity: sha512-DQmnRpLj7f6TgN/NYb0MTzJXL+vJF9h3pHy4JhCIs3zwcgez8xmGg3sXHcEO97BrmO2OSvCwMdfdlyl+E9KjOw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: - acorn: 8.7.1 - acorn-jsx: 5.3.2_acorn@8.7.1 + acorn: 8.8.1 + acorn-jsx: 5.3.2_acorn@8.8.1 eslint-visitor-keys: 3.3.0 dev: true @@ -1284,10 +1379,6 @@ packages: resolution: {integrity: sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==} dev: true - /estree-walker/1.0.1: - resolution: {integrity: sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==} - dev: true - /estree-walker/2.0.2: resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} dev: true @@ -1297,6 +1388,16 @@ packages: engines: {node: '>=0.10.0'} dev: true + /event-target-shim/5.0.1: + resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} + engines: {node: '>=6'} + dev: true + + /events/3.3.0: + resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} + engines: {node: '>=0.8.x'} + dev: true + /execa/4.1.0: resolution: {integrity: sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==} engines: {node: '>=10'} @@ -1317,7 +1418,7 @@ packages: dev: true /extsprintf/1.3.0: - resolution: {integrity: sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=} + resolution: {integrity: sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==} engines: {'0': node >=0.6.0} dev: true @@ -1329,6 +1430,17 @@ packages: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} 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.5 + dev: true + /fast-json-patch/2.2.1: resolution: {integrity: sha512-4j5uBaTnsYAV5ebkidvxiLUYOwjQ+JSFljeqfTxCrH9bDmlCQaOJFS84oDJ2rAXZq2yskmk3ORfoP9DCwqFNig==} engines: {node: '>= 0.4.0'} @@ -1341,20 +1453,34 @@ packages: dev: true /fast-levenshtein/2.0.6: - resolution: {integrity: sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=} + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} dev: true - /fast-redact/3.1.1: - resolution: {integrity: sha512-odVmjC8x8jNeMZ3C+rPMESzXVSEU8tSWSHv9HFxP2mm89G/1WwqhrerJDQm9Zus8X6aoRgQDThKqptdNA6bt+A==} + /fast-redact/3.1.2: + resolution: {integrity: sha512-+0em+Iya9fKGfEQGcd62Yv6onjBmmhV1uh86XVfOU8VwAe6kaFdQCWI9s0/Nnugx5Vd9tdbZ7e6gE2tR9dzXdw==} engines: {node: '>=6'} dev: true + /fastq/1.13.0: + resolution: {integrity: sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==} + dependencies: + reusify: 1.0.4 + dev: true + /fd-slicer/1.1.0: resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==} dependencies: pend: 1.2.0 dev: true + /fetch-blob/3.2.0: + resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==} + engines: {node: ^12.20 || >= 14.13} + dependencies: + node-domexception: 1.0.0 + web-streams-polyfill: 3.2.1 + dev: true + /file-entry-cache/6.0.1: resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} engines: {node: ^10.12.0 || >=12.0.0} @@ -1384,7 +1510,7 @@ packages: adm-zip: 0.5.9 fs-extra: 9.0.1 ini: 2.0.0 - minimist: 1.2.6 + minimist: 1.2.7 xml2js: 0.4.23 dev: true @@ -1397,7 +1523,7 @@ packages: resolution: {integrity: sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==} engines: {node: ^10.12.0 || >=12.0.0} dependencies: - flatted: 3.2.5 + flatted: 3.2.7 rimraf: 3.0.2 dev: true @@ -1406,8 +1532,8 @@ packages: hasBin: true dev: true - /flatted/3.2.5: - resolution: {integrity: sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==} + /flatted/3.2.7: + resolution: {integrity: sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==} dev: true /fluent-syntax/0.13.0: @@ -1419,6 +1545,11 @@ packages: resolution: {integrity: sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==} dev: true + /form-data-encoder/2.1.3: + resolution: {integrity: sha512-KqU0nnPMgIJcCOFTNJFEA8epcseEaoox4XZffTgy8jlI6pL/5EFyR54NRG7CnCJN0biY7q52DO3MH6/sJ/TKlQ==} + engines: {node: '>= 14.17'} + dev: true + /form-data/2.3.3: resolution: {integrity: sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==} engines: {node: '>= 0.12'} @@ -1428,6 +1559,13 @@ packages: mime-types: 2.1.35 dev: true + /formdata-polyfill/4.0.10: + resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==} + engines: {node: '>=12.20.0'} + dependencies: + fetch-blob: 3.2.0 + dev: true + /fs-extra/10.1.0: resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} engines: {node: '>=12'} @@ -1463,12 +1601,8 @@ packages: resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} dev: true - /functional-red-black-tree/1.0.1: - resolution: {integrity: sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=} - dev: true - - /fx-runner/1.2.0: - resolution: {integrity: sha512-/zR9BmHF8h4OaVJ+fHHJBv/5FdPV9mjOAPIscQZbAijm7Aa15Ls/P8UBHD5OKU5jwu2niTxkkzzHKITE7oCMoQ==} + /fx-runner/1.3.0: + resolution: {integrity: sha512-5b37H4GCyhF+Nf8xk9mylXoDq4wb7pbGAXxlCXp/631UTeeZomWSYcEGXumY4wk8g2QAqjPMGdWW+RbNt8PUcA==} hasBin: true dependencies: commander: 2.9.0 @@ -1484,13 +1618,6 @@ packages: engines: {node: 6.* || 8.* || >= 10.*} 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'} @@ -1498,6 +1625,11 @@ packages: pump: 3.0.0 dev: true + /get-stream/6.0.1: + resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} + engines: {node: '>=10'} + dev: true + /getpass/0.1.7: resolution: {integrity: sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==} dependencies: @@ -1544,6 +1676,17 @@ packages: path-is-absolute: 1.0.1 dev: true + /glob/7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: true + /glob/8.0.3: resolution: {integrity: sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==} engines: {node: '>=12'} @@ -1562,30 +1705,40 @@ packages: ini: 2.0.0 dev: true - /globals/13.15.0: - resolution: {integrity: sha512-bpzcOlgDhMG070Av0Vy5Owklpv1I6+j96GhUI7Rh7IzDCKLzboflLrrfqMu8NquDbiR4EOQk7XzJwqVJxicxog==} + /globals/13.17.0: + resolution: {integrity: sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==} engines: {node: '>=8'} dependencies: type-fest: 0.20.2 dev: true - /got/9.6.0: - resolution: {integrity: sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==} - engines: {node: '>=8.6'} + /globby/11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} 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 + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.2.12 + ignore: 5.2.0 + merge2: 1.4.1 + slash: 3.0.0 + dev: true + + /got/12.5.2: + resolution: {integrity: sha512-guHGMSEcsA5m1oPRweXUJnug0vuvlkX9wx5hzOka+ZBrBUOJHU0Z1JcNu3QE5IPGnA5aXUsQHdWOD4eJg9/v3A==} + engines: {node: '>=14.16'} + dependencies: + '@sindresorhus/is': 5.3.0 + '@szmarczak/http-timer': 5.0.1 + cacheable-lookup: 7.0.0 + cacheable-request: 10.2.2 + decompress-response: 6.0.0 + form-data-encoder: 2.1.3 + get-stream: 6.0.1 + http2-wrapper: 2.1.11 + lowercase-keys: 3.0.0 + p-cancelable: 3.0.0 + responselike: 3.0.0 dev: true /graceful-fs/4.2.10: @@ -1596,6 +1749,10 @@ packages: resolution: {integrity: sha512-8tLu60LgxF6XpdbK8OW3FA+IfTNBn1ZHGHKF4KQbEeSkajYw5PlYJcKluntgegDPTg8UkHjpet1T82vk6TQ68w==} dev: true + /grapheme-splitter/1.0.4: + resolution: {integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==} + dev: true + /growly/1.3.0: resolution: {integrity: sha512-+xGQY0YyAWCnqy7Cd++hc2JqMYzlm0dG30Jd0beaA64sROr8C4nt8Yc9V5Ro3avlSUDTN0ulqP/VBKi1/lLygw==} dev: true @@ -1615,7 +1772,7 @@ packages: dev: true /has-flag/3.0.0: - resolution: {integrity: sha1-tdRU3CGZriJWmfNGfloH87lVuv0=} + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} engines: {node: '>=4'} dev: true @@ -1624,9 +1781,9 @@ packages: engines: {node: '>=8'} dev: true - /has-yarn/2.1.0: - resolution: {integrity: sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==} - engines: {node: '>=8'} + /has-yarn/3.0.0: + resolution: {integrity: sha512-IrsVwUHhEULx3R8f/aA8AHuEzAorplsab/v8HBzEiIukwq5i/EC+xmOW+HfP1OaDP+2JkgT1yILHN2O3UFIbcA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} dev: true /has/1.0.3: @@ -1647,7 +1804,7 @@ packages: domelementtype: 2.3.0 domhandler: 5.0.3 domutils: 3.0.1 - entities: 4.3.1 + entities: 4.4.0 dev: true /http-cache-semantics/4.1.0: @@ -1663,19 +1820,31 @@ packages: sshpk: 1.17.0 dev: true + /http2-wrapper/2.1.11: + resolution: {integrity: sha512-aNAk5JzLturWEUiuhAN73Jcbq96R7rTitAoXV54FYMatvihnpD2+6PUgU4ce3D/m5VDbw+F5CsyKSF176ptitQ==} + engines: {node: '>=10.19.0'} + dependencies: + quick-lru: 5.1.1 + resolve-alpn: 1.2.1 + dev: true + /human-signals/1.1.1: resolution: {integrity: sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==} engines: {node: '>=8.12.0'} dev: true + /ieee754/1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + dev: true + /ignore/5.2.0: resolution: {integrity: sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==} engines: {node: '>= 4'} dev: true - /image-size/1.0.1: - resolution: {integrity: sha512-VAwkvNSNGClRw9mDHhc5Efax8PLlsOGcUTh0T/LIriC8vPA3U5PdqXWqkz406MoYHMKW8Uf9gWr05T/rYB44kQ==} - engines: {node: '>=12.0.0'} + /image-size/1.0.2: + resolution: {integrity: sha512-xfOoWjceHntRb3qFCrh5ZFORYH8XCdYpASltMhZ/Q0KZiOwjdE/Yl2QCiWdwD+lygV5bMCvauzgu5PxBX/Yerg==} + engines: {node: '>=14.0.0'} hasBin: true dependencies: queue: 6.0.2 @@ -1693,13 +1862,13 @@ packages: resolve-from: 4.0.0 dev: true - /import-lazy/2.1.0: - resolution: {integrity: sha512-m7ZEHgtw69qOGw+jwxXkHlrlIPdTGkyh66zXZ1ajZbxkDBNjSY/LGbmjc7h0s2ELsUDTAhFr55TrPSSqJGPG0A==} - engines: {node: '>=4'} + /import-lazy/4.0.0: + resolution: {integrity: sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==} + engines: {node: '>=8'} dev: true /imurmurhash/0.1.4: - resolution: {integrity: sha1-khi5srkoojixPcT7a21XbyMUU+o=} + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} dev: true @@ -1746,22 +1915,22 @@ packages: binary-extensions: 2.2.0 dev: true - /is-builtin-module/3.1.0: - resolution: {integrity: sha512-OV7JjAgOTfAFJmHZLvpSTb4qi0nIILDV1gWPYDnDJUTNFM5aGlRAhk4QcT8i7TuAleeEV5Fdkqn3t4mS+Q11fg==} + /is-builtin-module/3.2.0: + resolution: {integrity: sha512-phDA4oSGt7vl1n5tJvTWooWWAsXLY+2xCnxNqvKhGEzujg+A43wPlPOyDg3C8XQHN+6k/JTQWJ/j0dQh/qr+Hw==} engines: {node: '>=6'} dependencies: - builtin-modules: 3.2.0 + builtin-modules: 3.3.0 dev: true - /is-ci/2.0.0: - resolution: {integrity: sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==} + /is-ci/3.0.1: + resolution: {integrity: sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==} hasBin: true dependencies: - ci-info: 2.0.0 + ci-info: 3.5.0 dev: true - /is-core-module/2.9.0: - resolution: {integrity: sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==} + /is-core-module/2.11.0: + resolution: {integrity: sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==} dependencies: has: 1.0.3 dev: true @@ -1773,7 +1942,7 @@ packages: dev: true /is-extglob/2.1.1: - resolution: {integrity: sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=} + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} dev: true @@ -1802,12 +1971,12 @@ packages: dev: true /is-module/1.0.0: - resolution: {integrity: sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=} + resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==} dev: true - /is-npm/5.0.0: - resolution: {integrity: sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA==} - engines: {node: '>=10'} + /is-npm/6.0.0: + resolution: {integrity: sha512-JEjxbSmtPSt1c8XTkVrlujcXdKV1/tvuQ7GwKcAlyiVLeYFQ2VHat8xfrDJsIkhCdF/tZ7CiIR3sy141c6+gPQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} dev: true /is-number/7.0.0: @@ -1833,7 +2002,7 @@ packages: /is-reference/1.2.1: resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==} dependencies: - '@types/estree': 0.0.39 + '@types/estree': 1.0.0 dev: true /is-relative/0.1.3: @@ -1866,8 +2035,9 @@ packages: is-docker: 2.2.1 dev: true - /is-yarn-global/0.3.0: - resolution: {integrity: sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==} + /is-yarn-global/0.4.0: + resolution: {integrity: sha512-HneQBCrXGBy15QnaDfcn6OLoU8AQPAa0Qn0IeJR/QCo4E8dNZaGGwxpCwWyEBQC5QvFonP8d6t60iGpAHVAfNA==} + engines: {node: '>=12'} dev: true /isarray/1.0.0: @@ -1879,7 +2049,7 @@ packages: dev: true /isexe/2.0.0: - resolution: {integrity: sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=} + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} dev: true /isstream/0.1.2: @@ -1894,11 +2064,19 @@ packages: resolution: {integrity: sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==} engines: {node: '>= 10.13.0'} dependencies: - '@types/node': 18.0.0 + '@types/node': 18.11.9 merge-stream: 2.0.0 supports-color: 7.2.0 dev: true + /jose/4.10.0: + resolution: {integrity: sha512-KEhB/eLGLomWGPTb+/RNbYsTjIyx03JmbqAyIyiXBuNSa7CmNrJd5ysFhblayzs/e/vbOPMUaLnjHUMhGp4yLw==} + dev: true + + /js-sdsl/4.1.5: + resolution: {integrity: sha512-08bOAKweV2NUC1wqTtf3qZlnpOX/R2DU9ikpjOHs0H+ibQv3zpncVQg6um4uYtRtrwIX8M4Nh3ytK4HGlYAq7Q==} + dev: true + /js-tokens/4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} dev: true @@ -1914,8 +2092,8 @@ packages: resolution: {integrity: sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==} dev: true - /json-buffer/3.0.0: - resolution: {integrity: sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=} + /json-buffer/3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} dev: true /json-merge-patch/1.0.2: @@ -1941,7 +2119,7 @@ packages: dev: true /json-stable-stringify-without-jsonify/1.0.1: - resolution: {integrity: sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=} + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} dev: true /json-stringify-safe/5.0.1: @@ -1982,8 +2160,8 @@ packages: verror: 1.10.0 dev: true - /jszip/3.10.0: - resolution: {integrity: sha512-LDfVtOLtOxb9RXkYOwPyNBTQDL4eUbqahtoY6x07GiDJHwSYvn8sHHIw8wINImV3MqbMNve2gSuM1DDqEKk09Q==} + /jszip/3.10.1: + resolution: {integrity: sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==} dependencies: lie: 3.3.0 pako: 1.0.11 @@ -2006,17 +2184,17 @@ packages: safe-buffer: 5.2.1 dev: true - /keyv/3.1.0: - resolution: {integrity: sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==} + /keyv/4.5.0: + resolution: {integrity: sha512-2YvuMsA+jnFGtBareKqgANOEKe1mk3HKiXu2fRmAfyxG0MJAywNhi5ttWA3PMjl4NmpyjZNbFifR2vNjW1znfA==} dependencies: - json-buffer: 3.0.0 + json-buffer: 3.0.1 dev: true - /latest-version/5.1.0: - resolution: {integrity: sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==} - engines: {node: '>=8'} + /latest-version/7.0.0: + resolution: {integrity: sha512-KvNT4XqAMzdcL6ka6Tl3i2lYeFDgXNCuIX+xNx6ZMVR1dFq+idXd9FLKNMOIx0t9mJ9/HudyX4oZWXZQ0UJHeg==} + engines: {node: '>=14.16'} dependencies: - package-json: 6.5.0 + package-json: 8.1.0 dev: true /lcid/3.1.1: @@ -2044,7 +2222,7 @@ packages: resolution: {integrity: sha512-BbqAKApLb9ywUli+0a+PcV04SyJ/N1q/8qgCNe6U97KbPCS1BTksEuHFLYdvc8DltuhfxIUBqDZsC0bBGtl3lA==} dependencies: debug: 2.6.9 - marky: 1.2.4 + marky: 1.2.5 transitivePeerDependencies: - supports-color dev: true @@ -2113,14 +2291,9 @@ packages: is-unicode-supported: 0.1.0 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'} + /lowercase-keys/3.0.0: + resolution: {integrity: sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} dev: true /lru-cache/6.0.0: @@ -2136,11 +2309,11 @@ packages: sourcemap-codec: 1.4.8 dev: true - /make-dir/3.1.0: - resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} - engines: {node: '>=8'} + /magic-string/0.26.7: + resolution: {integrity: sha512-hX9XH3ziStPoPhJxLq1syWuZMxbDvGNbVchfrdCtanC7D13888bMFow61x8axrx+GfHLtVeAx2kxL7tTGRl+Ow==} + engines: {node: '>=12'} dependencies: - semver: 6.3.0 + sourcemap-codec: 1.4.8 dev: true /make-error/1.3.6: @@ -2154,8 +2327,8 @@ packages: p-defer: 1.0.0 dev: true - /marky/1.2.4: - resolution: {integrity: sha512-zd2/GiSn6U3/jeFVZ0J9CA1LzQ8RfIVvXkb/U0swFHF/zT+dVohTAWjmo2DcIuofmIIIROlwTbd+shSeXmxr0w==} + /marky/1.2.5: + resolution: {integrity: sha512-q9JtQJKjpsVxCRVgQ+WapguSbKC3SQ5HEzFGPAJMStgh3QjCawp00UKv3MTTAArTmGmmPUvllHZoNbZ3gs0I+Q==} dev: true /mem/5.1.1: @@ -2171,6 +2344,19 @@ packages: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} dev: true + /merge2/1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + dev: true + + /micromatch/4.0.5: + resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + engines: {node: '>=8.6'} + dependencies: + braces: 3.0.2 + picomatch: 2.3.1 + dev: true + /mime-db/1.52.0: resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} engines: {node: '>= 0.6'} @@ -2188,9 +2374,14 @@ packages: engines: {node: '>=6'} dev: true - /mimic-response/1.0.1: - resolution: {integrity: sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==} - engines: {node: '>=4'} + /mimic-response/3.1.0: + resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} + engines: {node: '>=10'} + dev: true + + /mimic-response/4.0.0: + resolution: {integrity: sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} dev: true /min-indent/1.0.1: @@ -2218,15 +2409,15 @@ packages: brace-expansion: 2.0.1 dev: true - /minimist/1.2.6: - resolution: {integrity: sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==} + /minimist/1.2.7: + resolution: {integrity: sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==} dev: true /mkdirp/0.5.6: resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} hasBin: true dependencies: - minimist: 1.2.6 + minimist: 1.2.7 dev: true /mkdirp/1.0.4: @@ -2235,12 +2426,11 @@ packages: hasBin: true dev: true - /mocha/10.0.0: - resolution: {integrity: sha512-0Wl+elVUD43Y0BqPZBzZt8Tnkw9CMUdNYnUsTfOM1vuhJVZL+kiesFYsqwBkEEuEixaiPe5ZQdqDgX2jddhmoA==} + /mocha/10.1.0: + resolution: {integrity: sha512-vUF7IYxEoN7XhQpFLxQAEMtE4W91acW4B6En9l97MwE9stL1A9gusXfoHZCLVHDUJ/7V5+lbCM6yMqzo5vNymg==} engines: {node: '>= 14.0.0'} hasBin: true dependencies: - '@ungap/promise-all-settled': 1.1.2 ansi-colors: 4.1.1 browser-stdout: 1.3.1 chokidar: 3.5.3 @@ -2311,8 +2501,8 @@ packages: thenify-all: 1.6.0 dev: true - /nan/2.16.0: - resolution: {integrity: sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==} + /nan/2.17.0: + resolution: {integrity: sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==} dev: true optional: true @@ -2329,7 +2519,7 @@ packages: dev: true /natural-compare/1.4.0: - resolution: {integrity: sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=} + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} dev: true /ncp/2.0.0: @@ -2338,6 +2528,20 @@ packages: dev: true optional: true + /node-domexception/1.0.0: + resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} + engines: {node: '>=10.5.0'} + dev: true + + /node-fetch/3.2.10: + resolution: {integrity: sha512-MhuzNwdURnZ1Cp4XTazr69K0BTizsBroX7Zx3UgDSVcZYKF/6p0CBe4EUb/hLqmzVhl0UpYfgRljQ4yxE+iCxA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + data-uri-to-buffer: 4.0.0 + fetch-blob: 3.2.0 + formdata-polyfill: 4.0.10 + dev: true + /node-forge/1.3.1: resolution: {integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==} engines: {node: '>= 6.13.0'} @@ -2348,7 +2552,7 @@ packages: dependencies: growly: 1.3.0 is-wsl: 2.2.0 - semver: 7.3.7 + semver: 7.3.8 shellwords: 0.1.1 uuid: 8.3.2 which: 2.0.2 @@ -2359,9 +2563,9 @@ packages: engines: {node: '>=0.10.0'} dev: true - /normalize-url/4.5.1: - resolution: {integrity: sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==} - engines: {node: '>=8'} + /normalize-url/7.2.0: + resolution: {integrity: sha512-uhXOdZry0L6M2UIo9BTt7FdpBDiAGN/7oItedQwPKh8jh31ZlvC8U9Xl/EJ3aijDHaywXTW3QbZ6LuCocur1YA==} + engines: {node: '>=12.20'} dev: true /npm-run-path/4.0.1: @@ -2386,12 +2590,12 @@ packages: engines: {node: '>=0.10.0'} dev: true - /on-exit-leak-free/1.0.0: - resolution: {integrity: sha512-Ve8ubhrXRdnuCJ5bQSQpP3uaV43K1PMcOfSRC1pqHgRZommXCgsXwh08jVC5NpjwScE23BPDwDvVg4cov3mwjw==} + /on-exit-leak-free/2.1.0: + resolution: {integrity: sha512-VuCaZZAjReZ3vUwgOB8LxAosIurDiAW0s13rI1YwmaP++jvcxP77AWoQvenZebpCA2m8WC1/EosPYPMjnRAp/w==} dev: true /once/1.4.0: - resolution: {integrity: sha1-WDsap3WWHUsROsF9nFC6753Xa9E=} + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} dependencies: wrappy: 1.0.2 dev: true @@ -2438,9 +2642,9 @@ packages: engines: {node: '>= 0.4.0'} dev: true - /p-cancelable/1.1.0: - resolution: {integrity: sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==} - engines: {node: '>=6'} + /p-cancelable/3.0.0: + resolution: {integrity: sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==} + engines: {node: '>=12.20'} dev: true /p-defer/1.0.0: @@ -2467,14 +2671,14 @@ packages: p-limit: 3.1.0 dev: true - /package-json/6.5.0: - resolution: {integrity: sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==} - engines: {node: '>=8'} + /package-json/8.1.0: + resolution: {integrity: sha512-hySwcV8RAWeAfPsXb9/HGSPn8lwDnv6fabH+obUZKX169QknRkRhPxd1yMubpKDskLFATkl3jHpNtVtDPFA0Wg==} + engines: {node: '>=14.16'} dependencies: - got: 9.6.0 - registry-auth-token: 4.2.2 - registry-url: 5.1.0 - semver: 6.3.0 + got: 12.5.2 + registry-auth-token: 5.0.1 + registry-url: 6.0.1 + semver: 7.3.8 dev: true /pako/1.0.11: @@ -2502,13 +2706,13 @@ packages: resolution: {integrity: sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==} dependencies: domhandler: 5.0.3 - parse5: 7.0.0 + parse5: 7.1.1 dev: true - /parse5/7.0.0: - resolution: {integrity: sha512-y/t8IXSPWTuRZqXc0ajH/UwDj4mnqLEbSttNbThcFhGrZuOyoyvNBO85PBp2jQa55wY9d07PBNjsK8ZP3K5U6g==} + /parse5/7.1.1: + resolution: {integrity: sha512-kwpuwzB+px5WUg9pyK0IcK/shltJN5/OVhQagxhCQNtT9Y9QRZqNY2e1cmbu/paRh5LMnz/oVTVLBpjFmMZhSg==} dependencies: - entities: 4.3.1 + entities: 4.4.0 dev: true /path-exists/4.0.0: @@ -2530,6 +2734,11 @@ packages: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} dev: true + /path-type/4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + dev: true + /pend/1.2.0: resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} dev: true @@ -2547,36 +2756,36 @@ packages: engines: {node: '>=8.6'} dev: true - /pino-abstract-transport/0.5.0: - resolution: {integrity: sha512-+KAgmVeqXYbTtU2FScx1XS3kNyfZ5TrXY07V96QnUSFqo2gAqlvmaxH67Lj7SWazqsMabf+58ctdTcBgnOLUOQ==} + /pino-abstract-transport/1.0.0: + resolution: {integrity: sha512-c7vo5OpW4wIS42hUVcT5REsL8ZljsUfBjqV/e2sFxmFEFZiq1XLUp5EYLtuDH6PEHq9W1egWqRbnLUP5FuZmOA==} dependencies: - duplexify: 4.1.2 + readable-stream: 4.2.0 split2: 4.1.0 dev: true - /pino-std-serializers/5.6.0: - resolution: {integrity: sha512-VdUXCw8gO+xhir7sFuoYSjTnzB+TMDGxhAC/ph3YS3sdHnXNdsK0wMtADNUltfeGkn2KDxEM21fnjF3RwXyC8A==} + /pino-std-serializers/6.0.0: + resolution: {integrity: sha512-mMMOwSKrmyl+Y12Ri2xhH1lbzQxwwpuru9VjyJpgFIH4asSj88F2csdMwN6+M5g1Ll4rmsYghHLQJw81tgZ7LQ==} dev: true - /pino/8.0.0: - resolution: {integrity: sha512-EvZh9ZUoLGkrhqhoF9UBxw2/ZiAhXHUKlGrI4WUT/wLu0sfu8Wr3NJaZ6lxcy/S51W0PMSon5KE7ujPAhc/G6g==} + /pino/8.6.1: + resolution: {integrity: sha512-fi+V2K98eMZjQ/uEHHSiMALNrz7HaFdKNYuyA3ZUrbH0f1e8sPFDmeRGzg7ZH2q4QDxGnJPOswmqlEaTAZeDPA==} hasBin: true dependencies: atomic-sleep: 1.0.0 - fast-redact: 3.1.1 - on-exit-leak-free: 1.0.0 - pino-abstract-transport: 0.5.0 - pino-std-serializers: 5.6.0 + fast-redact: 3.1.2 + on-exit-leak-free: 2.1.0 + pino-abstract-transport: 1.0.0 + pino-std-serializers: 6.0.0 process-warning: 2.0.0 quick-format-unescaped: 4.0.4 - real-require: 0.1.0 - safe-stable-stringify: 2.3.1 - sonic-boom: 3.0.0 - thread-stream: 1.0.1 + real-require: 0.2.0 + safe-stable-stringify: 2.4.1 + sonic-boom: 3.2.0 + thread-stream: 2.2.0 dev: true - /postcss/8.4.14: - resolution: {integrity: sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==} + /postcss/8.4.18: + resolution: {integrity: sha512-Wi8mWhncLJm11GATDaQKobXSNEYGUHeQLiQqDFG1qQ5UTDPTEvKw0Xt5NsTpktGTwLps3ByrWsBrG0rB8YQ9oA==} engines: {node: ^10 || ^12 || >=14} dependencies: nanoid: 3.3.4 @@ -2589,11 +2798,6 @@ packages: engines: {node: '>= 0.8.0'} dev: true - /prepend-http/2.0.0: - resolution: {integrity: sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==} - engines: {node: '>=4'} - dev: true - /process-nextick-args/2.0.1: resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} dev: true @@ -2602,6 +2806,11 @@ packages: resolution: {integrity: sha512-+MmoAXoUX+VTHAlwns0h+kFUWFs/3FZy+ZuchkgjyOu3oioLAo2LB5aCfKPh2+P9O18i3m43tUEv3YqttSy0Ww==} dev: true + /process/0.11.10: + resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} + engines: {node: '>= 0.6.0'} + dev: true + /promise-toolbox/0.21.0: resolution: {integrity: sha512-NV8aTmpwrZv+Iys54sSFOBx3tuVaOBvvrft5PNppnxy9xpU/akHbaWIril22AB22zaPgrgwKdD0KsrM0ptUtpg==} engines: {node: '>=6'} @@ -2609,6 +2818,10 @@ packages: make-error: 1.3.6 dev: true + /proto-list/1.2.4: + resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==} + dev: true + /psl/1.9.0: resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==} dev: true @@ -2625,11 +2838,11 @@ packages: engines: {node: '>=6'} dev: true - /pupa/2.1.1: - resolution: {integrity: sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==} - engines: {node: '>=8'} + /pupa/3.1.0: + resolution: {integrity: sha512-FLpr4flz5xZTSJxSeaheeMKN/EDzMdK7b8PTOC6a5PYFKTucWbdqjgqaEyH0shFiSJrVB1+Qqi4Tk19ccU6Aug==} + engines: {node: '>=12.20'} dependencies: - escape-goat: 2.1.1 + escape-goat: 4.0.0 dev: true /qs/6.5.3: @@ -2637,6 +2850,10 @@ packages: engines: {node: '>=0.6'} dev: true + /queue-microtask/1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + dev: true + /queue/6.0.2: resolution: {integrity: sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==} dependencies: @@ -2647,6 +2864,11 @@ packages: resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==} dev: true + /quick-lru/5.1.1: + resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} + engines: {node: '>=10'} + dev: true + /randombytes/2.1.0: resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} dependencies: @@ -2659,7 +2881,7 @@ packages: dependencies: deep-extend: 0.6.0 ini: 1.3.8 - minimist: 1.2.6 + minimist: 1.2.7 strip-json-comments: 2.0.1 dev: true @@ -2675,13 +2897,14 @@ packages: util-deprecate: 1.0.2 dev: true - /readable-stream/3.6.0: - resolution: {integrity: sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==} - engines: {node: '>= 6'} + /readable-stream/4.2.0: + resolution: {integrity: sha512-gJrBHsaI3lgBoGMW/jHZsQ/o/TIWiu5ENCJG1BB7fuCKzpFM8GaS2UoBVt9NO+oI+3FcrBNbUkl3ilDe09aY4A==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: - inherits: 2.0.4 - string_decoder: 1.3.0 - util-deprecate: 1.0.2 + abort-controller: 3.0.0 + buffer: 6.0.3 + events: 3.3.0 + process: 0.11.10 dev: true /readdirp/3.6.0: @@ -2691,13 +2914,13 @@ packages: picomatch: 2.3.1 dev: true - /real-require/0.1.0: - resolution: {integrity: sha512-r/H9MzAWtrv8aSVjPCMFpDMl5q66GqtmmRkRjpHTsp4zBAa+snZyiQNlMONiUmEJcsnaw0wCauJ2GWODr/aFkg==} + /real-require/0.2.0: + resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==} engines: {node: '>= 12.13.0'} dev: true - /regenerator-runtime/0.13.9: - resolution: {integrity: sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==} + /regenerator-runtime/0.13.10: + resolution: {integrity: sha512-KepLsg4dU12hryUO7bp/axHAKvwGOCV0sGloQtpagJ12ai+ojVDqkeGSiRX1zlq+kjIMZ1t7gpze+26QqtdGqw==} dev: true /regexpp/3.2.0: @@ -2705,16 +2928,16 @@ packages: engines: {node: '>=8'} dev: true - /registry-auth-token/4.2.2: - resolution: {integrity: sha512-PC5ZysNb42zpFME6D/XlIgtNGdTl8bBOCw90xQLVMpzuuubJKYDWFAEuUNc+Cn8Z8724tg2SDhDRrkVEsqfDMg==} - engines: {node: '>=6.0.0'} + /registry-auth-token/5.0.1: + resolution: {integrity: sha512-UfxVOj8seK1yaIOiieV4FIP01vfBDLsY0H9sQzi9EbbUdJiuuBjJgLa1DpImXMNPnVkBD4eVxTEXcrZA6kfpJA==} + engines: {node: '>=14'} dependencies: - rc: 1.2.8 + '@pnpm/npm-conf': 1.0.5 dev: true - /registry-url/5.1.0: - resolution: {integrity: sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==} - engines: {node: '>=8'} + /registry-url/6.0.1: + resolution: {integrity: sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q==} + engines: {node: '>=12'} dependencies: rc: 1.2.8 dev: true @@ -2756,7 +2979,7 @@ packages: dev: true /require-directory/2.1.1: - resolution: {integrity: sha1-jGStX9MNqxyXbiNE/+f3kqam30I=} + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} dev: true @@ -2766,7 +2989,11 @@ packages: dev: true /require-relative/0.8.7: - resolution: {integrity: sha1-eZlTn8ngR6N5KPoZb44VY9q9Nt4=} + resolution: {integrity: sha512-AKGr4qvHiryxRb19m3PsLRGuKVAbJLUD7E6eOaHkfKhwc+vSgVOCY5xNvm9EkolBKTOf0GrQAZKLimOCz81Khg==} + dev: true + + /resolve-alpn/1.2.1: + resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==} dev: true /resolve-from/4.0.0: @@ -2774,19 +3001,25 @@ packages: engines: {node: '>=4'} dev: true - /resolve/1.22.0: - resolution: {integrity: sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==} + /resolve/1.22.1: + resolution: {integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==} hasBin: true dependencies: - is-core-module: 2.9.0 + is-core-module: 2.11.0 path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 dev: true - /responselike/1.0.2: - resolution: {integrity: sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ==} + /responselike/3.0.0: + resolution: {integrity: sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==} + engines: {node: '>=14.16'} dependencies: - lowercase-keys: 1.0.1 + lowercase-keys: 3.0.0 + dev: true + + /reusify/1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} dev: true /rimraf/2.4.5: @@ -2801,17 +3034,17 @@ packages: resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==} hasBin: true dependencies: - glob: 7.2.0 + glob: 7.2.3 dev: true /rimraf/3.0.2: resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} hasBin: true dependencies: - glob: 7.2.0 + glob: 7.2.3 dev: true - /rollup-plugin-svelte/7.1.0_oqvu6r7na5sdokb6fyq7tyqy6i: + /rollup-plugin-svelte/7.1.0_rollup@3.2.5+svelte@3.52.0: resolution: {integrity: sha512-vopCUq3G+25sKjwF5VilIbiY6KCuMNHP1PFvx2Vr3REBNMDllKHFZN2B9jwwC+MqNc3UPKkjXnceLPEjTjXGXg==} engines: {node: '>=10'} peerDependencies: @@ -2819,21 +3052,21 @@ packages: svelte: '>=3.5.0' dependencies: require-relative: 0.8.7 - rollup: 2.75.7 + rollup: 3.2.5 rollup-pluginutils: 2.8.2 - svelte: 3.48.0 + svelte: 3.52.0 dev: true - /rollup-plugin-terser/7.0.2_rollup@2.75.7: + /rollup-plugin-terser/7.0.2_rollup@3.2.5: resolution: {integrity: sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==} peerDependencies: rollup: ^2.0.0 dependencies: - '@babel/code-frame': 7.16.7 + '@babel/code-frame': 7.18.6 jest-worker: 26.6.2 - rollup: 2.75.7 + rollup: 3.2.5 serialize-javascript: 4.0.0 - terser: 5.14.1 + terser: 5.15.1 dev: true /rollup-pluginutils/2.8.2: @@ -2842,14 +3075,20 @@ packages: estree-walker: 0.6.1 dev: true - /rollup/2.75.7: - resolution: {integrity: sha512-VSE1iy0eaAYNCxEXaleThdFXqZJ42qDBatAwrfnPlENEZ8erQ+0LYX4JXOLPceWfZpV1VtZwZ3dFCuOZiSyFtQ==} - engines: {node: '>=10.0.0'} + /rollup/3.2.5: + resolution: {integrity: sha512-/Ha7HhVVofduy+RKWOQJrxe4Qb3xyZo+chcpYiD8SoQa4AG7llhupUtyfKSSrdBM2mWJjhM8wZwmbY23NmlIYw==} + engines: {node: '>=14.18.0', npm: '>=8.0.0'} hasBin: true optionalDependencies: fsevents: 2.3.2 dev: true + /run-parallel/1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + dependencies: + queue-microtask: 1.2.3 + dev: true + /safe-buffer/5.1.2: resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} dev: true @@ -2864,8 +3103,8 @@ packages: dev: true optional: true - /safe-stable-stringify/2.3.1: - resolution: {integrity: sha512-kYBSfT+troD9cDA85VDnHZ1rpHC50O0g1e6WlGHVCz/g+JS+9WKLj+XwFYyR8UbrZN8ll9HUpDAAddY58MGisg==} + /safe-stable-stringify/2.4.1: + resolution: {integrity: sha512-dVHE6bMtS/bnL2mwualjc6IxEv1F+OCUpA46pKUj6F8uDbUM0jCCulPqRNPSnWwGNKx5etqMjZYdXtrm5KJZGA==} engines: {node: '>=10'} dev: true @@ -2886,11 +3125,11 @@ packages: resolution: {integrity: sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==} dev: true - /semver-diff/3.1.1: - resolution: {integrity: sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==} - engines: {node: '>=8'} + /semver-diff/4.0.0: + resolution: {integrity: sha512-0Ju4+6A8iOnpL/Thra7dZsSlOHYAHIeMxfhWQRI1/VLcT3WDBZKKtQt/QkBOsiIN9ZpuvHE6cGZ0x4glCMmfiA==} + engines: {node: '>=12'} dependencies: - semver: 6.3.0 + semver: 7.3.8 dev: true /semver/5.7.1: @@ -2898,13 +3137,8 @@ packages: hasBin: true dev: true - /semver/6.3.0: - resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==} - hasBin: true - dev: true - - /semver/7.3.7: - resolution: {integrity: sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==} + /semver/7.3.8: + resolution: {integrity: sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==} engines: {node: '>=10'} hasBin: true dependencies: @@ -2955,11 +3189,11 @@ packages: resolution: {integrity: sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==} dev: true - /sign-addon/5.0.0: - resolution: {integrity: sha512-qO3YYs8/kV7SyY8Kqmk1TW30FAVnvxTxUvncnK82H1+k4AkhVw33owReKyzoiHfNpgv1ugmgxA9jEsAIWqVCCg==} + /sign-addon/5.1.0: + resolution: {integrity: sha512-fag/csbsw25WpW+G+uWE6rRImSjlfwQNjuP28fFhvXpfW+kXccxl/o1QEW+hXtTidwpysksb7Y0B8UCeMkYkSA==} dependencies: common-tags: 1.8.2 - core-js: 3.22.8 + core-js: 3.25.3 deepcopy: 2.1.0 es6-error: 4.1.1 es6-promisify: 7.0.0 @@ -2974,8 +3208,17 @@ packages: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} dev: true - /sonic-boom/3.0.0: - resolution: {integrity: sha512-p5DiZOZHbJ2ZO5MADczp5qrfOd3W5Vr2vHxfCpe7G4AzPwVOweIjbfgku8wSQUuk+Y5Yuo8W7JqRe6XKmKistg==} + /simpledotcss/2.1.1: + resolution: {integrity: sha512-BhqPaXVd8yGiZucZzn8rRV+1q19iVUvkv4mVXvtc4KMuf8H7/FrreTqzDcTfOl8X44DftHdn/laMkAKtX/itcw==} + dev: true + + /slash/3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + dev: true + + /sonic-boom/3.2.0: + resolution: {integrity: sha512-SbbZ+Kqj/XIunvIAgUZRlqd6CGQYq71tRRbXR92Za8J/R3Yh4Av+TWENiSiEgnlwckYLyP0YZQWVfyNC0dzLaA==} dependencies: atomic-sleep: 1.0.0 dev: true @@ -2985,7 +3228,7 @@ packages: hasBin: true dependencies: buffer-crc32: 0.2.13 - minimist: 1.2.6 + minimist: 1.2.7 sander: 0.5.1 sourcemap-codec: 1.4.8 dev: true @@ -3046,10 +3289,6 @@ packages: tweetnacl: 0.14.5 dev: true - /stream-shift/1.0.1: - resolution: {integrity: sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==} - dev: true - /stream-to-array/2.3.0: resolution: {integrity: sha512-UsZtOYEn4tWU2RGLOXr/o/xjRBftZRlG3dEWoaHr8j4GuypJ3isitGbVyjQKAuMu+xbiop8q224TjiZWc4XTZA==} dependencies: @@ -3074,16 +3313,19 @@ packages: strip-ansi: 6.0.1 dev: true - /string_decoder/1.1.1: - resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} + /string-width/5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} dependencies: - safe-buffer: 5.1.2 + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.0.1 dev: true - /string_decoder/1.3.0: - resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + /string_decoder/1.1.1: + resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} dependencies: - safe-buffer: 5.2.1 + safe-buffer: 5.1.2 dev: true /strip-ansi/6.0.1: @@ -3093,6 +3335,13 @@ packages: ansi-regex: 5.0.1 dev: true + /strip-ansi/7.0.1: + resolution: {integrity: sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==} + engines: {node: '>=12'} + dependencies: + ansi-regex: 6.0.1 + dev: true + /strip-bom-buf/2.0.0: resolution: {integrity: sha512-gLFNHucd6gzb8jMsl5QmZ3QgnUJmp7qn4uUSHNwEXumAp7YizoGYw19ZUVfuq4aBOQUtyn2k8X/CwzWB73W2lQ==} engines: {node: '>=8'} @@ -3135,9 +3384,9 @@ packages: engines: {node: '>=8'} dev: true - /strip-json-comments/4.0.0: - resolution: {integrity: sha512-LzWcbfMbAsEDTRmhjWIioe8GcDRl0fa35YMXFoJKDdiD/quGFmjJjdgPjFJJNwCMaLyQqFIDqCdHD2V4HfLgYA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + /strip-json-comments/5.0.0: + resolution: {integrity: sha512-V1LGY4UUo0jgwC+ELQ2BNWfPa17TIuwBLg+j1AA/9RPzKINl1lhxVEu2r+ZTTO8aetIsUzE5Qj6LMSBkoGYKKw==} + engines: {node: '>=14.16'} dev: true /supports-color/5.5.0: @@ -3166,7 +3415,7 @@ packages: engines: {node: '>= 0.4'} dev: true - /svelte-preprocess/4.10.7_lvfi2wesz6u4l5rfbnetbucfmm: + /svelte-preprocess/4.10.7_besnmoibwkhwtentvwuriss7pa: resolution: {integrity: sha512-sNPBnqYD6FnmdBrUmBCaqS00RyCsCpj2BG58A1JBswNF7b0OKviwxqVrOL/CKyJrLSClrSeqQv5BXNg2RUbPOw==} engines: {node: '>= 9.11.2'} requiresBuild: true @@ -3213,28 +3462,28 @@ packages: magic-string: 0.25.9 sorcery: 0.10.0 strip-indent: 3.0.0 - svelte: 3.48.0 - typescript: 4.7.4 + svelte: 3.52.0 + typescript: 4.8.4 dev: true - /svelte/3.48.0: - resolution: {integrity: sha512-fN2YRm/bGumvjUpu6yI3BpvZnpIm9I6A7HR4oUNYd7ggYyIwSA/BX7DJ+UXXffLp6XNcUijyLvttbPVCYa/3xQ==} + /svelte/3.52.0: + resolution: {integrity: sha512-FxcnEUOAVfr10vDU5dVgJN19IvqeHQCS1zfe8vayTfis9A2t5Fhx+JDe5uv/C3j//bB1umpLJ6quhgs9xyUbCQ==} engines: {node: '>= 8'} dev: true - /terser/5.14.1: - resolution: {integrity: sha512-+ahUAE+iheqBTDxXhTisdA8hgvbEG1hHOQ9xmNjeUJSoi6DU/gMrKNcfZjHkyY6Alnuyc+ikYJaxxfHkT3+WuQ==} + /terser/5.15.1: + resolution: {integrity: sha512-K1faMUvpm/FBxjBXud0LWVAGxmvoPbZbfTCYbSgaaYQaIXI3/TdI7a7ZGA73Zrou6Q8Zmz3oeUTsp/dj+ag2Xw==} engines: {node: '>=10'} hasBin: true dependencies: '@jridgewell/source-map': 0.3.2 - acorn: 8.7.1 + acorn: 8.8.1 commander: 2.20.3 source-map-support: 0.5.21 dev: true /text-table/0.2.0: - resolution: {integrity: sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=} + resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} dev: true /thenify-all/1.6.0: @@ -3250,25 +3499,25 @@ packages: any-promise: 1.3.0 dev: true - /thread-stream/1.0.1: - resolution: {integrity: sha512-JuZyfzx81e5MBk8uIr8ZH76bXyjEQvbRDEkSdlV1JFBdq/rbby2RuvzBYlTBd/xCljxy6lPxrTLXzB9Jl1bNrw==} + /thread-stream/2.2.0: + resolution: {integrity: sha512-rUkv4/fnb4rqy/gGy7VuqK6wE1+1DOCOWy4RMeaV69ZHMP11tQKZvZSip1yTgrKCMZzEMcCL/bKfHvSfDHx+iQ==} dependencies: - real-require: 0.1.0 + real-require: 0.2.0 dev: true /through/2.3.8: resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} dev: true - /tldts-core/5.7.84: - resolution: {integrity: sha512-1qKxwSDjmWdqG81cnXGvKI+FHPiVRT6w5DORjp2+YVqDdzFUZO0oQoWu0zbDtWA6HXVk+B15yY9DKbVKZ6fRLg==} + /tldts-core/5.7.97: + resolution: {integrity: sha512-qxcuOSdlpee8rjH0gxbV26iONL91Foqe5nB/Gv/4Dh14cAX4DDhGGhpJnXbNP/7nxa8Nmvwx8k9/Wvr9IhUJRA==} dev: true - /tldts/5.7.84: - resolution: {integrity: sha512-PGkhyObqEEntI/xUDJdagtvNW+O7+5j8vbXSOXL+563At8gH/4LHxHjdPNv7qrahYuL6y6ZgjBxcvWdut7/LtA==} + /tldts/5.7.97: + resolution: {integrity: sha512-0A9BMNpg2RyzmOkEQRTRVfHUr1j7e2RxL2SgH/E/rLq//Fl8TNQ6D8NloCV66wOt3NeTzONrCDYFhBlN+SGRGg==} hasBin: true dependencies: - tldts-core: 5.7.84 + tldts-core: 5.7.97 dev: true /tmp/0.2.1: @@ -3278,11 +3527,6 @@ packages: rimraf: 3.0.2 dev: true - /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'} @@ -3303,8 +3547,8 @@ packages: punycode: 2.1.1 dev: true - /tslib/2.4.0: - resolution: {integrity: sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==} + /tslib/2.4.1: + resolution: {integrity: sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==} dev: true /tunnel-agent/0.6.0: @@ -3334,6 +3578,16 @@ packages: engines: {node: '>=10'} dev: true + /type-fest/1.4.0: + resolution: {integrity: sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==} + engines: {node: '>=10'} + dev: true + + /type-fest/2.19.0: + resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} + engines: {node: '>=12.20'} + dev: true + /typedarray-to-buffer/3.1.5: resolution: {integrity: sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==} dependencies: @@ -3344,17 +3598,17 @@ packages: resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} dev: true - /typescript/4.7.4: - resolution: {integrity: sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==} + /typescript/4.8.4: + resolution: {integrity: sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==} engines: {node: '>=4.2.0'} hasBin: true dev: true - /unique-string/2.0.0: - resolution: {integrity: sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==} - engines: {node: '>=8'} + /unique-string/3.0.0: + resolution: {integrity: sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==} + engines: {node: '>=12'} dependencies: - crypto-random-string: 2.0.0 + crypto-random-string: 4.0.0 dev: true /universalify/1.0.0: @@ -3372,24 +3626,24 @@ packages: engines: {node: '>=4'} dev: true - /update-notifier/5.1.0: - resolution: {integrity: sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw==} - engines: {node: '>=10'} + /update-notifier/6.0.2: + resolution: {integrity: sha512-EDxhTEVPZZRLWYcJ4ZXjGFN0oP7qYvbXWzEgRm/Yql4dHX5wDbvh89YHP6PK1lzZJYrMtXUuZZz8XGK+U6U1og==} + engines: {node: '>=14.16'} dependencies: - boxen: 5.1.2 - chalk: 4.1.2 - configstore: 5.0.1 - has-yarn: 2.1.0 - import-lazy: 2.1.0 - is-ci: 2.0.0 + boxen: 7.0.0 + chalk: 5.1.2 + configstore: 6.0.0 + has-yarn: 3.0.0 + import-lazy: 4.0.0 + is-ci: 3.0.1 is-installed-globally: 0.4.0 - is-npm: 5.0.0 - is-yarn-global: 0.3.0 - latest-version: 5.1.0 - pupa: 2.1.1 - semver: 7.3.7 - semver-diff: 3.1.1 - xdg-basedir: 4.0.0 + is-npm: 6.0.0 + is-yarn-global: 0.4.0 + latest-version: 7.0.0 + pupa: 3.1.0 + semver: 7.3.8 + semver-diff: 4.0.0 + xdg-basedir: 5.1.0 dev: true /uri-js/4.4.1: @@ -3398,13 +3652,6 @@ packages: punycode: 2.1.1 dev: true - /url-parse-lax/3.0.0: - resolution: {integrity: sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ==} - engines: {node: '>=4'} - dependencies: - prepend-http: 2.0.0 - dev: true - /util-deprecate/1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} dev: true @@ -3420,8 +3667,9 @@ packages: hasBin: true dev: true - /v8-compile-cache/2.3.0: - resolution: {integrity: sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==} + /uuid/9.0.0: + resolution: {integrity: sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==} + hasBin: true dev: true /verror/1.10.0: @@ -3444,17 +3692,17 @@ packages: /wcwidth/1.0.1: resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} dependencies: - defaults: 1.0.3 + defaults: 1.0.4 dev: true - /web-ext/7.1.0: - resolution: {integrity: sha512-wrEU9uIieKwkqQaa2NESuaypIvtJWEvMzPh3LSfI3C6R7DMMTmtxHchVLJnupeWjQ1FJzc3TszfcVRIwXk8DfQ==} + /web-ext/7.3.1: + resolution: {integrity: sha512-ZTfktd1zcQpWaFAM3U+IQW674G89d1IW/Oh0Ncw9LwFvKvAcW/nA5EB4pwqB8LiW/6OSYQhHBP4x2XUTBu1SKg==} engines: {node: '>=14.0.0', npm: '>=6.9.0'} hasBin: true dependencies: - '@babel/runtime': 7.18.3 + '@babel/runtime': 7.19.4 '@devicefarmer/adbkit': 3.2.3 - addons-linter: 5.9.0 + addons-linter: 5.18.0_node-fetch@3.2.10 bunyan: 1.8.15 camelcase: 7.0.0 chrome-launcher: 0.15.1 @@ -3463,38 +3711,43 @@ packages: es6-error: 4.1.1 firefox-profile: 4.2.2 fs-extra: 10.1.0 - fx-runner: 1.2.0 + fx-runner: 1.3.0 import-fresh: 3.3.0 + jose: 4.10.0 mkdirp: 1.0.4 multimatch: 6.0.0 mz: 2.7.0 + node-fetch: 3.2.10 node-notifier: 10.0.1 open: 8.4.0 parse-json: 6.0.2 promise-toolbox: 0.21.0 - sign-addon: 5.0.0 + sign-addon: 5.1.0 source-map-support: 0.5.21 strip-bom: 5.0.0 - strip-json-comments: 4.0.0 + strip-json-comments: 5.0.0 tmp: 0.2.1 - update-notifier: 5.1.0 + update-notifier: 6.0.2 watchpack: 2.4.0 - ws: 8.8.0 - yargs: 17.5.1 + ws: 8.9.0 + yargs: 17.6.0 zip-dir: 2.0.0 transitivePeerDependencies: - - '@types/download' - body-parser - bufferutil - - download - express - safe-compare - supports-color - utf-8-validate dev: true - /webextension-polyfill/0.9.0: - resolution: {integrity: sha512-LTtHb0yR49xa9irkstDxba4GATDAcDw3ncnFH9RImoFwDlW47U95ME5sn5IiQX2ghfaECaf6xyXM8yvClIBkkw==} + /web-streams-polyfill/3.2.1: + resolution: {integrity: sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==} + engines: {node: '>= 8'} + dev: true + + /webextension-polyfill/0.10.0: + resolution: {integrity: sha512-c5s35LgVa5tFaHhrZDnr3FpQpjj1BB+RXhLTYUxGqBVN460HkbM8TBtEqdXWbpTKfzwCcjAZVF7zXCYSKtcp9g==} dev: true /when/3.7.7: @@ -3502,7 +3755,7 @@ packages: dev: true /which/1.2.4: - resolution: {integrity: sha1-FVf5YIBgTlsRs1meufRbUKnv1yI=} + resolution: {integrity: sha512-zDRAqDSBudazdfM9zpiI30Fu9ve47htYXcGi3ln0wfKu2a7SmrT6F3VDoYONu//48V8Vz4TdCRNPjtvyRO3yBA==} hasBin: true dependencies: is-absolute: 0.1.7 @@ -3517,11 +3770,11 @@ packages: isexe: 2.0.0 dev: true - /widest-line/3.1.0: - resolution: {integrity: sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==} - engines: {node: '>=8'} + /widest-line/4.0.1: + resolution: {integrity: sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==} + engines: {node: '>=12'} dependencies: - string-width: 4.2.3 + string-width: 5.1.2 dev: true /winreg/0.0.12: @@ -3546,8 +3799,17 @@ packages: strip-ansi: 6.0.1 dev: true + /wrap-ansi/8.0.1: + resolution: {integrity: sha512-QFF+ufAqhoYHvoHdajT/Po7KoXVBPXS2bgjIam5isfWJPfIOnQZ50JtUiVvCv/sjgacf3yRrt2ZKUZ/V4itN4g==} + engines: {node: '>=12'} + dependencies: + ansi-styles: 6.2.1 + string-width: 5.1.2 + strip-ansi: 7.0.1 + dev: true + /wrappy/1.0.2: - resolution: {integrity: sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=} + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} dev: true /write-file-atomic/3.0.3: @@ -3559,8 +3821,8 @@ packages: typedarray-to-buffer: 3.1.5 dev: true - /ws/8.8.0: - resolution: {integrity: sha512-JDAgSYQ1ksuwqfChJusw1LSJ8BizJ2e/vVu5Lxjq3YvNJNlROv1ui4i+c/kUUrPheBvQl4c5UbERhTwKa6QBJQ==} + /ws/8.9.0: + resolution: {integrity: sha512-Ja7nszREasGaYUYCI2k4lCKIRTt+y7XuqVoHR44YpI49TtryyqbqvDMn5eqfW7e6HzTukDRIsXqzVHScqRcafg==} engines: {node: '>=10.0.0'} peerDependencies: bufferutil: ^4.0.1 @@ -3572,9 +3834,9 @@ packages: optional: true dev: true - /xdg-basedir/4.0.0: - resolution: {integrity: sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==} - engines: {node: '>=8'} + /xdg-basedir/5.1.0: + resolution: {integrity: sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ==} + engines: {node: '>=12'} dev: true /xml2js/0.4.23: @@ -3604,13 +3866,8 @@ packages: engines: {node: '>=10'} dev: true - /yargs-parser/20.2.9: - resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} - engines: {node: '>=10'} - dev: true - - /yargs-parser/21.0.1: - resolution: {integrity: sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==} + /yargs-parser/21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} engines: {node: '>=12'} dev: true @@ -3618,7 +3875,7 @@ packages: resolution: {integrity: sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==} engines: {node: '>=10'} dependencies: - camelcase: 6.2.0 + camelcase: 6.3.0 decamelize: 4.0.0 flat: 5.0.2 is-plain-obj: 2.1.0 @@ -3634,20 +3891,20 @@ packages: require-directory: 2.1.1 string-width: 4.2.3 y18n: 5.0.8 - yargs-parser: 20.2.9 + yargs-parser: 20.2.4 dev: true - /yargs/17.5.1: - resolution: {integrity: sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA==} + /yargs/17.6.0: + resolution: {integrity: sha512-8H/wTDqlSwoSnScvV2N/JHfLWOKuh5MVla9hqLjK3nsfyy6Y4kDSYSvkU5YCUEPOSnRXfIyx3Sq+B/IWudTo4g==} engines: {node: '>=12'} dependencies: - cliui: 7.0.4 + cliui: 8.0.1 escalade: 3.1.1 get-caller-file: 2.0.5 require-directory: 2.1.1 string-width: 4.2.3 y18n: 5.0.8 - yargs-parser: 21.0.1 + yargs-parser: 21.1.1 dev: true /yauzl/2.10.0: @@ -3666,5 +3923,5 @@ packages: resolution: {integrity: sha512-uhlsJZWz26FLYXOD6WVuq+fIcZ3aBPGo/cFdiLlv3KNwpa52IF3ISV8fLhQLiqVu5No3VhlqlgthN6gehil1Dg==} dependencies: async: 3.2.4 - jszip: 3.10.0 + jszip: 3.10.1 dev: true diff --git a/rollup.config.js b/rollup.config.js index f15c5d0..4e5e52b 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -8,56 +8,61 @@ import commonjs from '@rollup/plugin-commonjs'; import pathLib from 'path' const PROD = process.env.BUILD_ENV === 'prod'; -const src = process.env.src -const dist = process.env.dist; -const entryPoints = process.env.entryPoints.split(" ") +const SRC = process.env.src +const DIST = process.env.dist; +const ENTRYPOINT_LIST = process.env.entryPoints.split(" ") const safeEnvVar = Object.fromEntries(Object.entries(process.env).filter((entry) => entry[0].startsWith("BUILD"))) -const plugins = [ - commonjs(), - replace({ - values: { - // avoid "Function constructor" warning - "Function('return this')()": "globalThis", - }, - delimiters: ["", ""], - preventAssignment: true - }), - replace({ - __ENV: JSON.stringify(safeEnvVar), - __BUILD_PROFILE: JSON.stringify(process.env.BUILD_PROFILE), - preventAssignment: true - }), - svelte({ +const useCustomElement = ["components"] - preprocess: autoPreprocess(), +function getPlugins(entrypoint) { + const plugins = [ + commonjs(), + replace({ + values: { + // avoid "Function constructor" warning + "Function('return this')()": "globalThis", + }, + delimiters: ["", ""], + preventAssignment: true + }), + replace({ + __ENV: JSON.stringify(safeEnvVar), + __BUILD_PROFILE: JSON.stringify(process.env.BUILD_PROFILE), + preventAssignment: true + }), + svelte({ - compilerOptions: { - customElement: true - } - }), - typescript({ sourceMap: false }), - resolve({ browser: true }), -] + preprocess: autoPreprocess(), -if (PROD) { - plugins.push(terser()) -} + compilerOptions: { + customElement: useCustomElement.includes(entrypoint) + } + }), + typescript({ sourceMap: false }), + resolve({ browser: true }), + ] + if (PROD) { + plugins.push(terser()) + } + + return plugins +} const output = [] -for (const e of entryPoints) { +for (const e of ENTRYPOINT_LIST) { output.push({ - input: pathLib.join(src, e, "main.ts"), + input: pathLib.join(SRC, e, "main.ts"), output: { sourcemap: !PROD, - file: pathLib.join(dist, e, "main.js"), + file: pathLib.join(DIST, e, "main.js"), format: 'iife' }, - plugins: plugins + plugins: getPlugins(e) }) } diff --git a/scripts/copy_simplecss.mjs b/scripts/copy_simplecss.mjs new file mode 100644 index 0000000..7ec68c9 --- /dev/null +++ b/scripts/copy_simplecss.mjs @@ -0,0 +1,23 @@ +import { copyFile, mkdir, } from 'node:fs/promises'; +import { join as joinPath, dirname } from 'node:path'; + +function requireEnv(name) { + const value = process.env[name] + if (!value) { + console.error("require env: " + name) + process.exit(1) + } + return value +} + +const node_modules = requireEnv("NODE_MODULES") +const dist = requireEnv("DIST") + +const src = joinPath(node_modules, "simpledotcss", "simple.min.css") +const dest = joinPath(dist, "res", "simple.min.css") + +try { + await mkdir(dirname(dest)) +} catch (_e) {} + +await copyFile(src, dest) \ No newline at end of file diff --git a/src/_locales/en/messages.json b/src/_locales/en/messages.json new file mode 100644 index 0000000..13e5acd --- /dev/null +++ b/src/_locales/en/messages.json @@ -0,0 +1,278 @@ +{ + "extensionName": { + "message": "Glitter Drag Pro", + "description": "extension name." + }, + "extensionDescription": { + "message": "A good drag and drop extension that improve your browsing experience" + }, + "tabTitleActions": { + "message": "Actions" + }, + "tabTitleScripts": { + "message": "Scripts" + }, + "tabTitleAssets": { + "message": "Assets" + }, + "tabTitleRequests": { + "message": "Search Requests" + }, + "requestUrl": { + "message": "Request url" + }, + "requestQuery": { + "message": "Request query" + }, + "edit": { + "message": "Edit" + }, + "command": { + "message": "Command" + }, + "commandInvalid": { + "message": "Invalid" + }, + "commandOpen": { + "message": "Open" + }, + "commandCopy": { + "message": "Copy" + }, + "commandDownload": { + "message": "Download" + }, + "commandRequest": { + "message": "Search Request" + }, + "commandDump": { + "message": "Dump" + }, + "commandScript": { + "message": "Execute Script" + }, + "contextType": { + "message": "Context" + }, + "contextTypeSelection": { + "message": "Selection" + }, + "contextTypeLink": { + "message": "Link" + }, + "contextTypeImage": { + "message": "Image" + }, + "direction": { + "message": "Direction" + }, + "directionLeft": { + "message": "Left" + }, + "directionRight": { + "message": "Right" + }, + "directionUp": { + "message": "Up" + }, + "directionDown": { + "message": "Down" + }, + "tabPosition": { + "message": "Tab Position" + }, + "tabPositionStart": { + "message": "Start" + }, + "tabPositionEnd": { + "message": "End" + }, + "tabPositionPrev": { + "message": "Previous" + }, + "tabPositionNext": { + "message": "Next" + }, + "tabPositionCurrent": { + "message": "Current" + }, + "tabPositionNewWindow": { + "message": "New Window" + }, + "tabPositionPrivateWindow": { + "message": "Private Window" + }, + "activeTab": { + "message": "Activate Tab" + }, + "downloadDirectory": { + "message": "Download Directory" + }, + "showSaveAsDialog": { + "message": "Show SaveAs Dialog" + }, + "requests": { + "message": "Request" + }, + "name": { + "message": "Name" + }, + "prompt": { + "message": "Prompt" + }, + "operationMode": { + "message": "Operation Mode" + }, + "modeChain": { + "message": "Chain" + }, + "modeNormal": { + "message": "Normal" + }, + "modeLeftRightUpDown": { + "message": "Left Right Up Down" + }, + "modeCircleMenu": { + "message": "Circle Menu" + }, + "modeGridMenu": { + "message": "Grid Menu" + }, + "modeContextMenu": { + "message": "Context Menu" + }, + "assetData": { + "message": "Asset Data" + }, + "add": { + "message": "Add" + }, + "save": { + "message": "Save" + }, + "operation": { + "message": "Operation" + }, + "scriptText": { + "message": "Script" + }, + "actionIcon": { + "message": "Icon of Actions" + }, + "minimumDistance": { + "message": "Minimum Distance" + }, + "tabTitleCommon": { + "message": "Common" + }, + "cancel": { + "message": "Cancel" + }, + "confirm": { + "message": "Confirm" + }, + "close": { + "message": "Close" + }, + "delete": { + "message": "Delete" + }, + "confirmDelete": { + "message": "Confirm Delete \"$name$\"?", + "placeholders": { + "name": { + "content": "$1" + } + } + }, + "pickImage": { + "message": "Pick Image" + }, + "duplicate": { + "message": "Duplicate" + }, + "preferContextDataType": { + "message": "Prefer Data Type" + }, + "contextDataTypeSelection": { + "message": "Selection" + }, + "contextDataTypeLink": { + "message": "Link" + }, + "contextDataTypeLinkText": { + "message": "Text Of Link" + }, + "contextDataTypeImageSource": { + "message": "Source of Image" + }, + "reset": { + "message": "Reset" + }, + "container": { + "message": "Container" + }, + "inheritContainer": { + "message": "[Inherit Container]" + }, + "helpActionName": { + "message": "the name of action" + }, + "helpActionCommand": { + "message": "the command of action. \"Open\" will open a tab and use selected content as url; \"Copy\" writes the selected content into clipboard; \"Search Request\" will open a tab with url base on this request template; \"Download\" let browser download selected content; \"Script\" inject script into web page" + }, + "helpActionContextType": { + "message": "context type to use action" + }, + "helpActionPrompt": { + "message": "the text to show up when action will be performed. if this field left blank, the name of action will show up" + }, + "helpActionOperationMode": { + "message": "the operation mode of this action. \"direction chain\" allows multiple direction to pick actions. \"normal\" allows one direction to pick actions. \"circle menu\" shows a menu which you can pick actions。\"context menu\" will register a context menu item associating this action" + }, + "helpActionDirection": { + "message": "use one direction to match this action" + }, + "helpActionDirectionChain": { + "message": "use multiple directions to match this action" + }, + "helpActionPreferDataType": { + "message": "decide which data you prefer to processed when performing action." + }, + "helpCommandRequest": { + "message": "open a new tab with the url that is based on request template" + }, + "helpScript": { + "message": "select the script" + }, + "helpActionIcon": { + "message": "the icon of action that showed under menu operation mode" + }, + "helpActionContainer": { + "message": "specific how to deal with container when open new tab. you can use \"[Inherit Container]\" to let new tab inherit the container of opener tab, or specific another container" + }, + "organizeActionOrder": { + "message": "Organize action order" + }, + "editConfig": { + "message": "Edit Config" + }, + "filterActions": { + "message": "Filter" + }, + "manageActions": { + "message": "Manage" + }, + "noFilter": { + "message": "No" + }, + "importSearchEngineFromBrowser": { + "message": "Import Search Engine From Browser " + }, + "importSearchEngineFromExtension": { + "message": "Import Search Engine From Extension" + }, + "tabTitleEditor": { + "message": "Editor" + } +} \ No newline at end of file diff --git a/src/_locales/zh_CN/messages.json b/src/_locales/zh_CN/messages.json new file mode 100644 index 0000000..f6dbc1c --- /dev/null +++ b/src/_locales/zh_CN/messages.json @@ -0,0 +1,278 @@ +{ + "extensionName": { + "message": "闪耀拖拽 Pro", + "description": "extension name." + }, + "extensionDescription": { + "message": "提升浏览体验的网页拖拽扩展" + }, + "tabTitleActions": { + "message": "动作" + }, + "tabTitleScripts": { + "message": "脚本" + }, + "tabTitleAssets": { + "message": "资源素材" + }, + "tabTitleRequests": { + "message": "搜索请求" + }, + "requestUrl": { + "message": "请求链接" + }, + "requestQuery": { + "message": "请求参数" + }, + "edit": { + "message": "编辑" + }, + "command": { + "message": "命令" + }, + "commandInvalid": { + "message": "无效" + }, + "commandOpen": { + "message": "打开" + }, + "commandCopy": { + "message": "复制" + }, + "commandDownload": { + "message": "下载" + }, + "commandRequest": { + "message": "搜索请求" + }, + "commandDump": { + "message": "导出信息" + }, + "commandScript": { + "message": "执行脚本" + }, + "contextType": { + "message": "应用场景" + }, + "contextTypeSelection": { + "message": "文本" + }, + "contextTypeLink": { + "message": "链接" + }, + "contextTypeImage": { + "message": "图片" + }, + "direction": { + "message": "方向标签" + }, + "directionLeft": { + "message": "左" + }, + "directionRight": { + "message": "右" + }, + "directionUp": { + "message": "上" + }, + "directionDown": { + "message": "下" + }, + "tabPosition": { + "message": "标签页位置" + }, + "tabPositionStart": { + "message": "开头" + }, + "tabPositionEnd": { + "message": "末尾" + }, + "tabPositionPrev": { + "message": "上一个" + }, + "tabPositionNext": { + "message": "下一个" + }, + "tabPositionCurrent": { + "message": "当前" + }, + "tabPositionNewWindow": { + "message": "新窗口" + }, + "tabPositionPrivateWindow": { + "message": "隐私窗口" + }, + "activeTab": { + "message": "激活标签页" + }, + "downloadDirectory": { + "message": "下载目录" + }, + "showSaveAsDialog": { + "message": "显示下载目录" + }, + "requests": { + "message": "请求" + }, + "name": { + "message": "名称" + }, + "prompt": { + "message": "提示" + }, + "operationMode": { + "message": "操作方式" + }, + "modeChain": { + "message": "方向链" + }, + "modeNormal": { + "message": "普通" + }, + "modeLeftRightUpDown": { + "message": "上下左右" + }, + "modeCircleMenu": { + "message": "环型菜单" + }, + "modeGridMenu": { + "message": "方格菜单" + }, + "modeContextMenu": { + "message": "右键菜单" + }, + "assetData": { + "message": "素材数据" + }, + "add": { + "message": "添加" + }, + "save": { + "message": "保存" + }, + "operation": { + "message": "操作" + }, + "scriptText": { + "message": "脚本内容" + }, + "actionIcon": { + "message": "动作图标" + }, + "minimumDistance": { + "message": "最小距离" + }, + "tabTitleCommon": { + "message": "通用" + }, + "cancel": { + "message": "取消" + }, + "confirm": { + "message": "确定" + }, + "close": { + "message": "关闭" + }, + "delete": { + "message": "删除" + }, + "confirmDelete": { + "message": "确定删除 \"$name$\"?", + "placeholders": { + "name": { + "content": "$1" + } + } + }, + "pickImage": { + "message": "选择图片" + }, + "duplicate": { + "message": "复制" + }, + "preferContextDataType": { + "message": "优先的数据类型" + }, + "contextDataTypeSelection": { + "message": "选中文本" + }, + "contextDataTypeLink": { + "message": "链接" + }, + "contextDataTypeLinkText": { + "message": "链接文本" + }, + "contextDataTypeImageSource": { + "message": "图片链接" + }, + "reset": { + "message": "重置" + }, + "container": { + "message": "容器" + }, + "inheritContainer": { + "message": "[继承当前的容器]" + }, + "helpActionName": { + "message": "动作名称" + }, + "helpActionCommand": { + "message": "动作执行的命令。“打开”使用当前的选择内容作为URL在新标签页打开; “复制” 将选择的内容写入剪切板; “搜索请求” 使用URL请求模板构建URL并在新标签页打开; “下载” 用浏览器下载选中的内容; “执行脚本” 用于执行预配置的脚本;" + }, + "helpActionContextType": { + "message": "让动作的生效的网页元素" + }, + "helpActionPrompt": { + "message": "执行动作时显示的提示文本,如果留空,则使用动作名称作为提示文本" + }, + "helpActionOperationMode": { + "message": "限定当前动作只能在指定的操作模式下生效。“方向链”允许用方向组合选择动作。“普通”则只使用一个方向选择动作。“环形菜单”使用菜单+图标的选择动作。“右键菜单”支持将动作注册到右键菜单中使用" + }, + "helpActionDirection": { + "message": "只使用一个方向匹配该动作" + }, + "helpActionDirectionChain": { + "message": "使用方向组合匹配该动作" + }, + "helpActionPreferDataType": { + "message": "在动作的执行时候,可以指定要优先使用哪种数据. 不选择或多选则使用第一种数据" + }, + "helpCommandRequest": { + "message": "根据预先配置的URL请求模板构建URL,并在指定的标签页打开该URL" + }, + "helpScript": { + "message": "选择需要执行自定义的脚本" + }, + "helpActionIcon": { + "message": "配置在 “菜单”操作模式下展示的图标" + }, + "helpActionContainer": { + "message": "指定新建标签页时处理容器的行为。默认是“[继承当前容器]”,即新创建的标签页跟当前标签页具有相同的容器,也可以用其他容器创建标签页" + }, + "organizeActionOrder": { + "message": "管理动作顺序" + }, + "editConfig": { + "message": "编辑配置" + }, + "filterActions": { + "message": "过滤器" + }, + "manageActions": { + "message": "管理" + }, + "noFilter": { + "message": "无" + }, + "importSearchEngineFromBrowser": { + "message": "从浏览器导入搜索引擎" + }, + "importSearchEngineFromExtension": { + "message": "从扩展导入搜索引擎" + }, + "tabTitleEditor": { + "message": "编辑器" + } +} \ No newline at end of file diff --git a/src/background/context.test.ts b/src/background/context.test.ts index 07428f0..1191d73 100644 --- a/src/background/context.test.ts +++ b/src/background/context.test.ts @@ -1,20 +1,21 @@ -import { assertEqual, assertFail } from "../utils/test_helper" -import { primaryType } from "./context" +import { ContextType } from "../config/config" +import { assertEqual } from "../utils/test_helper" +import { primaryContextType } from "./context" import { blankExecuteContext } from "./helper.test" describe("test context", () => { it("primary type",async () => { let ctx = await blankExecuteContext() - ctx.text = "hello" - assertEqual(primaryType(ctx), "text") + ctx.data.selection = "hello" + assertEqual(primaryContextType(ctx), ContextType.selection) ctx = await blankExecuteContext() - ctx.link = "http://example.com/" - assertEqual(primaryType(ctx), "link") + ctx.data.link = "http://example.com/" + assertEqual(primaryContextType(ctx), ContextType.link) ctx = await blankExecuteContext() - ctx.image = "http://example.com/a.jpg" - assertEqual(primaryType(ctx), "image") + ctx.data.imageSource = "http://example.com/a.jpg" + assertEqual(primaryContextType(ctx), ContextType.image) }) }) \ No newline at end of file diff --git a/src/background/context.ts b/src/background/context.ts index 2ed69f8..bccc8a9 100644 --- a/src/background/context.ts +++ b/src/background/context.ts @@ -1,89 +1,106 @@ import browser from 'webextension-polyfill'; -import { ActionConfig, Configuration, TypeConstraint, TypePriority } from "../config/config"; +import { ActionConfig, Configuration, ContextType, ContextDataType, TabPosition } from "../config/config"; import type { ExecuteArgs } from "../message/message"; -import type { ExtensionStorage } from '../types'; -import { defaultVolatileState } from './volatile_state'; - -export interface ExecuteContext extends ExecuteArgs { - readonly action: ActionConfig - readonly windowId: number - readonly tabId: number, - readonly tabIndex: number, - readonly tabURL: string, - readonly frameId: number, - readonly config: Readonly, - readonly backgroundTabCounter: number, - readonly hostname: string, +import { ExtensionStorageKey, type ExtensionStorage } from '../types'; +import { defaultVolatileState, type VolatileState } from './volatile_state'; + +export type ExecuteContext = Readonly, + hostname: string, + tab: browser.Tabs.Tab, + state: VolatileState +}> + + +export async function buildExecuteContextFromMessageSender(args: ExecuteArgs, sender: browser.Runtime.MessageSender): Promise> { + return buildExecuteContext(args, sender.tab, sender.frameId) } -export async function buildExecuteContext(args: ExecuteArgs, sender: browser.Runtime.MessageSender): Promise> { - const storage = (await browser.storage.local.get('userConfig')) as ExtensionStorage +export async function buildExecuteContext(args: ExecuteArgs, tab: browser.Tabs.Tab, frameId: number): Promise> { + const storage = (await browser.storage.local.get(ExtensionStorageKey.userConfig)) as ExtensionStorage + const permissions = (await browser.permissions.getAll()) const state = await defaultVolatileState() const config = new Configuration(storage.userConfig) const urlObj = new URL(args.url) - return Object.assign({}, { - backgroundTabCounter: state.backgroundTabCounter, - windowId: sender.tab.windowId, - tabId: sender.tab.id, - tabIndex: sender.tab.index, - frameId: sender.frameId, - tabURL: sender.tab.url, + return { + data: args.data, + url: args.url, + title: args.title, + modifierKey: args.modifierKey, + startPosition: args.startPosition, + endPosition: args.endPosition, action: new ActionConfig(args.action), + frameId: frameId, + tabURL: tab.url, hostname: urlObj.hostname, - config, - }, args) + config: config, + tab, + state, + } } +export function primaryContextType(ctx: ExecuteContext): ContextType { -export function primaryType(ctx: ExecuteContext): "text" | "link" | "image" { - - for (const p of ctx.action.config.priorities) { - if (TypePriority.text === p && ctx.text) { - return TypePriority.text - } - if (TypePriority.link === p && ctx.link) { - return TypePriority.link - } - if (TypePriority.image === p && ctx.image) { - return TypePriority.image - } - } - - for (const t of ctx.action.condition.types) { + for (const t of ctx.action.condition.contextTypes) { - if (TypeConstraint.text === t && ctx.text) { - return TypeConstraint.text + if (ContextType.selection === t && ctx.data.selection) { + return ContextType.selection } - if (TypeConstraint.link === t && ctx.link) { - return TypeConstraint.link + if (ContextType.link === t && ctx.data.link) { + return ContextType.link } - if (TypeConstraint.image === t && ctx.image) { - return TypeConstraint.image + if (ContextType.image === t && ctx.data.imageSource) { + return ContextType.image } } - if (ctx.image) { - return "image" + if (ctx.data.imageSource) { + return ContextType.image } - if (ctx.link) { - return "link" + if (ctx.data.link) { + return ContextType.link } - return "text" + return ContextType.selection } -export function primarySelection(ctx: ExecuteContext): string { - const t = primaryType(ctx) +export function primaryContextData(ctx: ExecuteContext): string { + const t = primaryContextType(ctx) switch (t) { - case "text": return ctx.text - case "link": return ctx.link - case "image": return ctx.image + case ContextType.selection: return ctx.data.selection + case ContextType.link: { + for (const p of ctx.action.config.preferDataTypes) { + if (p == ContextDataType.linkText) { + return ctx.data.linkText + } else if (p === ContextDataType.link) { + return ctx.data.link + } + } + return ctx.data.link + } + case ContextType.image: return ctx.data.imageSource default: throw new Error("unreachable") } } +export function getTabIndex(ctx: ExecuteContext, tabsLength = 0): number { + + let index = 0; + switch (ctx.action.config.tabPosition) { + case TabPosition.prev: index = ctx.tab.index; break; + case TabPosition.next: index = ctx.tab.index + ctx.state.backgroundTabCounter + 1; break; + case TabPosition.start: index = 0; break; + case TabPosition.end: index = tabsLength; break; + default: throw new Error("unknown tab position: " + ctx.action.config.tabPosition); + } + + return index; +} diff --git a/src/background/executor.test.ts b/src/background/executor.test.ts index 92f9ab7..21bb740 100644 --- a/src/background/executor.test.ts +++ b/src/background/executor.test.ts @@ -31,14 +31,14 @@ describe("test executor", async () => { it("copy text", async () => { const ctx = await blankExecuteContext(new ActionConfig({ "command": "copy" })) - ctx.text = "copy demo" + ctx.data.selection = "copy demo" await executor.copyHandler(ctx) }) it("copy image", async () => { const ctx = await blankExecuteContext(new ActionConfig({ "command": "copy" })) - ctx.image = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAA8UlEQVQYlY3QoaqDYACG4dd5ysDgQBwz+QdZWFBYsTnwHryek3cVZi1isngHljVBUNAi/Ay3MIaWnXhY88tP+HiVqqo+rNhmDQL4aZoGx3FI05RpmhBCcDweKYoCXdeJooh5nlEty/rd7/ecTifatsV1XWzbZpomwjDkfr+TJAnK9Xr9qKpKEAR0XUdVVXieh2EY7Ha7/4/b7ZbX6wWAEAJN0+j7/gsBbN7vN5qmAfB8PjFNk3EcGYbhGw7DgOM4PB4Pbrcb5/OZy+VCWZZIKQFYloWN7/scDgfyPKeua6SU1HXNsixkWYaUkjiOUdYG/wONbmSLuq2dcQAAAABJRU5ErkJggg==" + ctx.data.imageSource = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAA8UlEQVQYlY3QoaqDYACG4dd5ysDgQBwz+QdZWFBYsTnwHryek3cVZi1isngHljVBUNAi/Ay3MIaWnXhY88tP+HiVqqo+rNhmDQL4aZoGx3FI05RpmhBCcDweKYoCXdeJooh5nlEty/rd7/ecTifatsV1XWzbZpomwjDkfr+TJAnK9Xr9qKpKEAR0XUdVVXieh2EY7Ha7/4/b7ZbX6wWAEAJN0+j7/gsBbN7vN5qmAfB8PjFNk3EcGYbhGw7DgOM4PB4Pbrcb5/OZy+VCWZZIKQFYloWN7/scDgfyPKeua6SU1HXNsixkWYaUkjiOUdYG/wONbmSLuq2dcQAAAABJRU5ErkJggg==" await executor.copyHandler(ctx) }) @@ -46,7 +46,7 @@ describe("test executor", async () => { const ctx = await blankExecuteContext(buildActionConfig(CommandKind.download)) - ctx.text = "hello world" + ctx.data.selection = "hello world" let downloadId: number | undefined try { diff --git a/src/background/executor.ts b/src/background/executor.ts index 7aa7275..d082ef3 100644 --- a/src/background/executor.ts +++ b/src/background/executor.ts @@ -1,10 +1,11 @@ import trimStart from 'lodash-es/trimStart'; import browser from 'webextension-polyfill'; -import { CommandKind, LogLevel, TabPosition } from '../config/config'; -import { buildRuntimeMessage } from '../message/message'; +import { CommandKind, ContextType, LogLevel, TabPosition } from '../config/config'; +import { buildRuntimeMessage, RuntimeMessageName as RuntimeMessageName } from '../message/message'; import { rootLog } from '../utils/log'; import { VarSubstituteTemplate } from '../utils/var_substitute'; -import { primarySelection, primaryType, type ExecuteContext } from './context'; +import { isFirefox } from '../utils/vendor'; +import { getTabIndex, primaryContextData, primaryContextType, type ExecuteContext } from './context'; import { Protocol, RequestResolver } from './resolver'; import { searchText as searchTextViaBrowser } from './search'; import { buildDownloadableURL, buildVars, dumpFunc, generatedDownloadFileName, guessImageType, isOpenableURL, urlToArrayBuffer } from './utils'; @@ -48,27 +49,27 @@ export class Executor { } async openHandler(ctx: ExecuteContext) { - this.openTab(ctx, primarySelection(ctx)) + this.openTab(ctx, primaryContextData(ctx)) } async copyHandler(ctx: ExecuteContext) { - const type = primaryType(ctx) + const type = primaryContextType(ctx) switch (type) { - case "text": - case "link": - browser.tabs.sendMessage(ctx.tabId, buildRuntimeMessage("copy", primarySelection(ctx)), { - frameId: ctx.frameId - }) - return - case "image": + case ContextType.image: { // TODO: chrome - const buf = await urlToArrayBuffer(new URL(primarySelection(ctx))) + const buf = await urlToArrayBuffer(new URL(primaryContextData(ctx))) const imageType = guessImageType(buf) if (imageType === "jpeg" || imageType === "png") { browser.clipboard.setImageData(buf, imageType) } else { log.E("unknown image type", buf.slice(0, 4)) } + return + } + default: { + browser.tabs.sendMessage(ctx.tab.id, buildRuntimeMessage(RuntimeMessageName.copy, primaryContextData(ctx))) + return + } } } @@ -89,12 +90,12 @@ export class Executor { const resolver = new RequestResolver(ctx, request) switch (resolver.protocol) { - case Protocol.search: + case Protocol.browserSearch: { const tabHoldingSearch = await this.openTab(ctx, 'about:blank') await new Promise(r => setTimeout(r, 50)) - const query = primarySelection(ctx) + const query = primaryContextData(ctx) const engine = resolver.resolveEngine() log.VV("search: ", query, "with: ", engine) @@ -161,7 +162,7 @@ export class Executor { let arg1 = { ctx: plainCtx, - backgroundTabCounter: ctx.backgroundTabCounter, + backgroundTabCounter: ctx.state.backgroundTabCounter, localStorage: await browser.storage.local.get() } @@ -182,13 +183,14 @@ export class Executor { return } - await browser.tabs.sendMessage(ctx.tabId, buildRuntimeMessage("doScript", { + await browser.tabs.sendMessage(ctx.tab.id, buildRuntimeMessage(RuntimeMessageName.executeScript, { text: script.text, - selection: { - text: ctx.text, - link: ctx.link, - image: ctx.image, - primary: primarySelection(ctx), + data: { + text: ctx.data.selection, + link: ctx.data.link, + linkText: ctx.data.linkText, + imageSource: ctx.data.imageSource, + primary: primaryContextData(ctx), } }), { frameId: ctx.frameId @@ -196,28 +198,6 @@ export class Executor { return } - private getTabIndex(ctx: ExecuteContext, tabsLength = 0, currentTabIndex = 0): number { - - let index = 0; - switch (ctx.action.config.tabPosition) { - case TabPosition.before: index = currentTabIndex; break; - case TabPosition.next: index = currentTabIndex + ctx.backgroundTabCounter + 1; break; - case TabPosition.start: index = 0; break; - case TabPosition.end: index = tabsLength; break; - default: throw new Error("unknown tab position:" + ctx.action.config.tabPosition); - } - - log.VVV({ - tabsLength, - currentTabIndex, - activeTab: ctx.action.config.activeTab, - tabPosition: ctx.action.config.tabPosition, - childTabCount: ctx.backgroundTabCounter, - index - }); - - return index; - } async openTab(ctx: ExecuteContext, urlArg: string | URL) { @@ -227,7 +207,7 @@ export class Executor { log.V(urlArg, "is not openable") } - if ([TabPosition.window, TabPosition.privateWindow].includes(ctx.action.config.tabPosition!)) { + if ([TabPosition.newWindow, TabPosition.privateWindow].includes(ctx.action.config.tabPosition!)) { const incognito = ctx.action.config.tabPosition === TabPosition.privateWindow @@ -245,21 +225,37 @@ export class Executor { if (ctx.action.config.tabPosition === TabPosition.current) { log.VVV('update current active tab with url', url) - return browser.tabs.update(ctx.tabId, { url }); + return browser.tabs.update(ctx.tab.id, { url }); } const tabsOfCurrentWindow = await browser.tabs.query({ - windowId: ctx.windowId, + windowId: ctx.tab.windowId, }); + const option: browser.Tabs.CreateCreatePropertiesType = { active: Boolean(ctx.action.config.activeTab), - index: this.getTabIndex(ctx, tabsOfCurrentWindow.length, ctx.tabIndex), + index: getTabIndex(ctx, tabsOfCurrentWindow.length), url, - windowId: ctx.windowId, - openerTabId: ctx.tabId + windowId: ctx.tab.windowId, + openerTabId: ctx.tab.id, }; + if (isFirefox()) { + let cookieStoreId = ctx.tab.cookieStoreId + + if (ctx.action.config.container) { + const arr = await browser.contextualIdentities.query({ name: ctx.action.config.container }) + for (const c of arr) { + cookieStoreId = c.cookieStoreId + break + } + } + + option.cookieStoreId = cookieStoreId + } + + log.VVV('create new tab with option', option) if (!ctx.action.config.activeTab && ctx.action.config.tabPosition === TabPosition.next) { diff --git a/src/background/helper.test.ts b/src/background/helper.test.ts index ab3eee6..7e11153 100644 --- a/src/background/helper.test.ts +++ b/src/background/helper.test.ts @@ -2,28 +2,30 @@ import browser from 'webextension-polyfill' import { ActionConfig, Configuration } from "../config/config" import { ModifierKey } from "../types" import type { ExecuteContext } from "./context" +import { defaultVolatileState } from './volatile_state' export async function blankExecuteContext(action?: ActionConfig): Promise { - const tabs = await browser.tabs.query({title: "*Mocha*"}) + const tabs = await browser.tabs.query({ title: "*Mocha*" }) const tab = tabs[0] if (!tab) { throw new Error("no active tab") } return { - windowId: tab.windowId, - tabId: tab.id, - tabIndex: tab.index, + tab: {} as browser.Tabs.Tab, + state: await defaultVolatileState(), action: action ? action : new ActionConfig({}), config: new Configuration({}), - text: "", - image: "", - link: "", + data: { + selection: "", + imageSource: "", + link: "", + linkText: "", + }, url: "", title: "", modifierKey: ModifierKey.none, startPosition: { x: 0, y: 0 }, endPosition: { x: 0, y: 0 }, - backgroundTabCounter: 0, frameId: 0, tabURL: "http://example.com", hostname: "example.com" diff --git a/src/background/main.ts b/src/background/main.ts index d9b99b9..41ed3e0 100644 --- a/src/background/main.ts +++ b/src/background/main.ts @@ -1,18 +1,20 @@ -import browser from 'webextension-polyfill' +import browser from 'webextension-polyfill'; import buildInfo from "../build_info"; import { Configuration } from "../config/config"; -import { type RuntimeMessage, type RuntimeMessageArgs } from "../message/message"; -import type { ExtensionStorage } from "../types"; +import { RuntimeMessageName, type RuntimeMessage, type RuntimeMessageArgsMap } from "../message/message"; +import { ExtensionStorageKey, type ExtensionStorage } from "../types"; import { captureError } from '../utils/error'; import { configureRootLog, rootLog } from '../utils/log'; -import { buildExecuteContext } from './context'; +import { buildExecuteContextFromMessageSender } from './context'; import { Executor } from "./executor"; +import { onMenuItemClick, registerContextMenuActions } from './menu'; import { defaultVolatileState } from './volatile_state'; captureError() async function onLoadConfiguration(config: Configuration) { configureRootLog(config) + registerContextMenuActions(config) } async function onContentScriptLoaded(tabId: number, frameId?: number) { @@ -29,7 +31,7 @@ async function onContentScriptLoaded(tabId: number, frameId?: number) { }) } -browser.tabs.onRemoved.addListener(async () => { +browser.tabs.onRemoved.addListener(async (tabId,) => { rootLog.VVV("a tab is remove, reset tab counter") const state = await defaultVolatileState() state.backgroundTabCounter = 0; @@ -47,24 +49,25 @@ browser.runtime.onSuspend.addListener(async () => { await state.save() }); -browser.runtime.onMessage.addListener(async (m: RuntimeMessage, sender: browser.Runtime.MessageSender) => { +browser.runtime.onMessage.addListener(async (m: any, sender: browser.Runtime.MessageSender) => { rootLog.VVV("cmd: ", m.cmd, "sender tabId: ", sender.tab) - - switch (m.cmd) { - case "execute": { + const cmd = m.cmd as string + switch (cmd) { + case RuntimeMessageName.execute: { + const args = (m as RuntimeMessage).args const executor = new Executor(); - let ctx = await buildExecuteContext(m.args, sender) + let ctx = await buildExecuteContextFromMessageSender(args, sender) executor.execute(ctx) return } - case "contentScriptLoaded": { + case RuntimeMessageName.contextScriptLoaded: { if (sender.tab) { return onContentScriptLoaded(sender.tab.id, sender.frameId) } return } - case "closeCurrentTab": { + case RuntimeMessageName.closeCurrentTab: { await browser.tabs.remove(sender.tab.id) return } @@ -76,16 +79,20 @@ browser.runtime.onMessage.addListener(async (m: RuntimeMessage { - onLoadConfiguration(new Configuration(storage.userConfig)) + const config = new Configuration(storage[ExtensionStorageKey.userConfig]) + onLoadConfiguration(config) }) browser.storage.local.onChanged.addListener(async () => { - const storage = (await browser.storage.local.get('userConfig')) as ExtensionStorage + const storage = (await browser.storage.local.get(ExtensionStorageKey.userConfig)) as ExtensionStorage onLoadConfiguration(new Configuration(storage.userConfig)) }) -rootLog.V("background script executed.") -rootLog.V(buildInfo) +browser.contextMenus.onClicked.addListener(onMenuItemClick) + + +console.log("background script executed.") +console.log(buildInfo) if (__BUILD_PROFILE === "test") { const url = new URL(browser.runtime.getURL("test/mocha.html")) diff --git a/src/background/menu.ts b/src/background/menu.ts new file mode 100644 index 0000000..6136fcb --- /dev/null +++ b/src/background/menu.ts @@ -0,0 +1,79 @@ +import defaultTo from 'lodash-es/defaultTo'; +import browser from 'webextension-polyfill' +import { Configuration, OperationMode, ContextType } from "../config/config"; +import type { ExecuteArgs } from '../message/message'; +import { buildExecuteContext } from './context'; +import { Executor } from './executor'; +import { ExtensionStorageKey, ModifierKey } from '../types'; +import { rootLog } from '../utils/log'; + +type BrowserContextType = browser.Menus.ContextType + +function actionTypeToContextType(tc: ContextType[]): BrowserContextType[] { + const result: BrowserContextType[] = [] + for (const t of tc) { + result.push(t) + } + return result +} + +export async function registerContextMenuActions(config: Configuration) { + browser.contextMenus.removeAll() + + for (const action of config.actions) { + if (!action.condition.modes.includes(OperationMode.contextMenu)) { + continue + } + const contexts: BrowserContextType[] = actionTypeToContextType(action.condition.contextTypes) + contexts.push("frame") + browser.contextMenus.create( + { + id: action.id, + title: action.name, + contexts: contexts, + } + ) + rootLog.V("add context menu: ", action.id) + } +} + +const defaultPosition: Readonly<{ x: number, y: number }> = { x: 0, y: 0 } + +export async function onMenuItemClick(info: browser.Menus.OnClickData, tab: browser.Tabs.Tab) { + + const config = await browser.storage.local.get(ExtensionStorageKey.userConfig).then((storage) => { + return new Configuration(storage.userConfig) + }) + + const action = config.actions.find(action => action.id === info.menuItemId); + + if (!action) { + rootLog.E("action with menu id %s not found", info.menuItemId) + return + } + + let text = info.selectionText + if (!text) { + text = defaultTo(info.linkText, "") + } + + const args: ExecuteArgs = { + action: action, + data: { + selection: text, + imageSource: defaultTo(info.srcUrl, ""), + link: defaultTo(info.linkUrl, ""), + linkText: defaultTo(info.linkText, ""), + }, + url: defaultTo(tab.url, ""), + title: defaultTo(tab.title, ""), + modifierKey: ModifierKey.none, + + startPosition: defaultPosition, + endPosition: defaultPosition, + } + + const ctx = await buildExecuteContext(args, tab, info.frameId) + const executor = new Executor(); + executor.execute(ctx) +} \ No newline at end of file diff --git a/src/background/resolver.ts b/src/background/resolver.ts index fe20e33..dce4c85 100644 --- a/src/background/resolver.ts +++ b/src/background/resolver.ts @@ -2,7 +2,7 @@ import { CommandRequest } from "../config/config" import type { KVRecord } from "../types" import { VarSubstituteTemplate } from "../utils/var_substitute" -import { primarySelection, type ExecuteContext } from "./context" +import { primaryContextData, type ExecuteContext } from "./context" export type RequestParameterResolver = (key: string, value: string | string[]) => string | string[] @@ -15,7 +15,7 @@ function requestFunc(rawReq: KVRecord) { export enum Protocol { http = "http:", https = "https:", - search = "search:", + browserSearch = "browser:", extension = "extension:", } @@ -38,17 +38,24 @@ export class RequestResolver { } resolveEngine(): string | undefined { - if (!this.req.url.searchParams.has("engine")) { + const url = this.resolveURL() + const engine = url.searchParams.get("engine") + if (!engine) { return undefined } - return this.req.url.searchParams.get("engine") + return engine } resolveURL(): URL { + // TODO: CACHE const vars = this.buildVars() const url = new URL(this.req.url) + + const pathTemplate = new VarSubstituteTemplate(this.req.url.pathname) + url.pathname = pathTemplate.substitute(vars) + for (let [k, v] of Object.entries(this.req.query)) { url.searchParams.set(k, v) } @@ -64,7 +71,7 @@ export class RequestResolver { resolveMessage(): KVRecord { let msg = { - "content": primarySelection(this.ctx) + "content": primaryContextData(this.ctx) } return msg } @@ -82,12 +89,12 @@ export class RequestResolver { } return new Map([ - ["s", primarySelection(this.ctx)], + ["s", primaryContextData(this.ctx)], ["o", this.req.url.protocol], ["d", this.req.url.hostname], ["h", mainHost], ["p", this.req.url.pathname.substring(1) + this.req.url.search], - ["x", `site:${this.req.url.hostname} ${primarySelection(this.ctx)}`], + ["x", `site:${this.req.url.hostname} ${primaryContextData(this.ctx)}`], ]) } diff --git a/src/background/search.ts b/src/background/search.ts index 7a5759d..a245a18 100644 --- a/src/background/search.ts +++ b/src/background/search.ts @@ -14,11 +14,11 @@ export async function searchText(opt: SearchTextOption): Promise { engine: opt.engine, tabId: opt.tabId, }) - } else { - // https://developer.chrome.com/docs/extensions/reference/search/ - return chrome.search.query({ - text: opt.query, - tabId: opt.tabId, - }) } + + // https://developer.chrome.com/docs/extensions/reference/search/ + return chrome.search.query({ + text: opt.query, + tabId: opt.tabId, + }) } \ No newline at end of file diff --git a/src/background/utils.test.ts b/src/background/utils.test.ts index 6a0d318..ea38872 100644 --- a/src/background/utils.test.ts +++ b/src/background/utils.test.ts @@ -8,19 +8,19 @@ describe("background utils", () => { describe("resolve download filename", () => { it("text", async () => { const ctx = await blankExecuteContext() - ctx.text = "hello world" + ctx.data.selection = "hello world" assertOk(generatedDownloadFileName(ctx, await buildDownloadableURL(ctx))) }) it("image", async () => { const ctx = await blankExecuteContext() - ctx.image = "http://example.com/a.jpg" + ctx.data.imageSource = "http://example.com/a.jpg" assertOk(generatedDownloadFileName(ctx, await buildDownloadableURL(ctx))) }) it("link", async () => { const ctx = await blankExecuteContext() - ctx.link = "http://example.com/" + ctx.data.link = "http://example.com/" assertOk(generatedDownloadFileName(ctx, await buildDownloadableURL(ctx))) }) @@ -39,19 +39,19 @@ describe("background utils", () => { it("build url for text", async () => { let ctx = await blankExecuteContext() - ctx.text = "hello" + ctx.data.selection = "hello" assertOk(buildDownloadableURL(ctx)) }) it("build url for image", async () => { let ctx = await blankExecuteContext() - ctx.image = browser.runtime.getURL("icon/drag.png") + ctx.data.imageSource = browser.runtime.getURL("icon/drag.png") assertOk(buildDownloadableURL(ctx)) }) it("build url for link", async () => { let ctx = await blankExecuteContext() - ctx.link = "http://www.example.com" + ctx.data.link = "http://www.example.com" assertOk(buildDownloadableURL(ctx)) }) diff --git a/src/background/utils.ts b/src/background/utils.ts index 0ff9e1b..a6d94ef 100644 --- a/src/background/utils.ts +++ b/src/background/utils.ts @@ -1,4 +1,6 @@ -import { primarySelection, primaryType, type ExecuteContext } from "./context"; +import browser from 'webextension-polyfill'; +import { ContextType } from "../config/config"; +import { primaryContextData, primaryContextType, type ExecuteContext } from "./context"; export function createObjectURL(blob = new Blob(), revokeTime = 1000 * 60 * 3) { const url = window.URL.createObjectURL(blob); @@ -103,14 +105,14 @@ export function dateTimeAsFileName(date: Date): string { export async function buildDownloadableURL(ctx: ExecuteContext): Promise { - const type = primaryType(ctx) + const type = primaryContextType(ctx) switch (type) { - case "text": + case ContextType.selection: const encoder = new TextEncoder() - const buf = encoder.encode(primarySelection(ctx)) + const buf = encoder.encode(primaryContextData(ctx)) return bufferToObjectURL(buf) - case "image": - const url = new URL(primarySelection(ctx)) + case ContextType.image: + const url = new URL(primaryContextData(ctx)) switch (url.protocol) { case "data:": const buf = await urlToArrayBuffer(url) @@ -119,8 +121,8 @@ export async function buildDownloadableURL(ctx: ExecuteContext): Promise { case "https:": return url } - case "link": - return new URL(primarySelection(ctx)) + case ContextType.link: + return new URL(primaryContextData(ctx)) } } @@ -137,13 +139,13 @@ export function guessFilenameFromURL(url: URL): string | null { } export function generatedDownloadFileName(ctx: ExecuteContext, url: URL): string | null { - const type = primaryType(ctx) + const type = primaryContextType(ctx) switch (type) { - case "text": { + case ContextType.selection: { return dateTimeAsFileName(new Date()) + ".txt" } - case "image": { - const sel = primarySelection(ctx) + case ContextType.image: { + const sel = primaryContextData(ctx) if (sel.startsWith("data:")) { const type = guessImageTypeFromBase64(sel) if (type === "png" || type === "jpeg") { @@ -154,7 +156,7 @@ export function generatedDownloadFileName(ctx: ExecuteContext, url: URL): string const filename = guessFilenameFromURL(url) return filename } - case "link": { + case ContextType.link: { const filename = guessFilenameFromURL(url) return filename } @@ -170,4 +172,4 @@ export function buildVars(ctx: ExecuteContext): Map { ["title", ctx.title], ["url", ctx.url], ]) -} \ No newline at end of file +} diff --git a/src/background/volatile_state.ts b/src/background/volatile_state.ts index 374a612..ffcd15f 100644 --- a/src/background/volatile_state.ts +++ b/src/background/volatile_state.ts @@ -1,16 +1,17 @@ import defaultTo from 'lodash-es/defaultTo' import browser from 'webextension-polyfill' +import type { KVRecord, Position } from '../types' -const enum States { - backgroundTabCounter = "backgroundTabCounter" +const enum State { + backgroundTabCounter = "backgroundTabCounter", } - export interface VolatileState { backgroundTabCounter: number load(): Promise save(): Promise + reset(): Promise } @@ -24,23 +25,30 @@ class localStorageBackend implements VolatileState { if (state.loaded) { return } + state.loaded = true + const storageData = await browser.storage.local.get(localStorageBackend.storageKey) state.data = new Map(defaultTo<[]>(storageData[localStorageBackend.storageKey], [])) - state.loaded = true } async save() { const obj = {} - obj[localStorageBackend.storageKey] = this.data + obj[localStorageBackend.storageKey] = Array.from(this.data.entries()) return browser.storage.local.set(obj) } + async reset() { + this.data = new Map() + await this.save() + return + } + get backgroundTabCounter() { - return Number(defaultTo(this.data.get(States.backgroundTabCounter), 0)) + return Number(defaultTo(this.data.get(State.backgroundTabCounter), 0)) } set backgroundTabCounter(val) { - this.data.set(States.backgroundTabCounter, val) + this.data.set(State.backgroundTabCounter, val) } } diff --git a/src/build_info.ts b/src/build_info.ts index e306451..25fad92 100644 --- a/src/build_info.ts +++ b/src/build_info.ts @@ -9,5 +9,4 @@ export default { os: env["BUILD_OS"], mochaFilter: env["BUILD_MOCHA_FILTER"], profile: env["BUILD_PROFILE"], - targetBrowser: env["BUILD_TARGET_BROWSER"] } as const diff --git a/src/components/helper.ts b/src/components/helper.ts new file mode 100644 index 0000000..4015230 --- /dev/null +++ b/src/components/helper.ts @@ -0,0 +1,37 @@ +import { rootLog } from "../utils/log"; +import type { GenericFunction } from "./types"; + +export class Stub { + + eventName: string + + constructor(eventName: string) { + this.eventName = eventName + } + + forwardMessage(msg: GenericFunction) { + window.dispatchEvent(new CustomEvent(this.eventName, { detail: JSON.stringify(msg) })) + } +} + +export class MessageTarget { + + event: string + + constructor(event: string) { + this.event = event + + globalThis.addEventListener(this.event, (event: CustomEvent) => { + this.onMessage(JSON.parse(event.detail) as any as GenericFunction) + }) + } + + onMessage(msg: GenericFunction) { + const fn = this[msg.name as any] as any + if (typeof fn !== 'function') { + rootLog.E("method %s not found", msg.name) + return + } + fn.apply(this, msg.args); + } +} \ No newline at end of file diff --git a/src/components/indicator/indicator.svelte b/src/components/indicator/indicator.svelte index bfca6d5..9fe2828 100644 --- a/src/components/indicator/indicator.svelte +++ b/src/components/indicator/indicator.svelte @@ -2,7 +2,7 @@
diff --git a/src/components/indicator/indicator.test.ts b/src/components/indicator/indicator.test.ts index c7153ca..74846fb 100644 --- a/src/components/indicator/indicator.test.ts +++ b/src/components/indicator/indicator.test.ts @@ -1,13 +1,2 @@ -import { updateIndicator } from "./indicator"; import { onDocumentLoaded } from "../../content_scripts/utils"; -onDocumentLoaded(()=>{ - updateIndicator({ - type: "show", - radius: 100, - center: { - x: 500, - y: 500 - } - }) -}) \ No newline at end of file diff --git a/src/components/indicator/indicator.ts b/src/components/indicator/indicator.ts index c211f0b..3a60e47 100644 --- a/src/components/indicator/indicator.ts +++ b/src/components/indicator/indicator.ts @@ -1,18 +1,31 @@ import App from './indicator.svelte'; -import { EventType, type IndicatorMessage } from '../message'; +import { ProxyEventType, type Indicator } from '../types'; +import type { Position } from '../../types'; +import { MessageTarget } from '../helper'; -const indicatorApp = new App({ target: undefined }) as any as HTMLElement; -export function updateIndicator(msg: IndicatorMessage) { - if (msg.type === "hide") { - indicatorApp.remove() - } else { - indicatorApp.dispatchEvent(new CustomEvent(EventType.Indicator, { detail: msg })) - !indicatorApp.parentElement && document.body.append(indicatorApp) +interface IndicatorElement extends HTMLElement { + update(radius: number, position: Position) +} + +const indicatorElem = new App({ target: undefined }) as any as IndicatorElement; + +class IndicatorImpl extends MessageTarget implements Indicator { + + constructor() { + super(ProxyEventType.Indicator) + } + + show(radius: number, pos: Position) { + indicatorElem.update(radius, pos); + !indicatorElem.parentElement && document.body.append(indicatorElem) + } + + hide() { + indicatorElem.remove() } } -globalThis.addEventListener("indicator-proxy", (event: CustomEvent) => { - updateIndicator(JSON.parse(event.detail) as IndicatorMessage) -}) +export const indicatorImpl = new IndicatorImpl() + diff --git a/src/components/indicator/indicator_proxy.ts b/src/components/indicator/indicator_proxy.ts index a723793..7123a35 100644 --- a/src/components/indicator/indicator_proxy.ts +++ b/src/components/indicator/indicator_proxy.ts @@ -1,5 +1,27 @@ -import { EventType, type IndicatorMessage } from "../message"; +import type { Position } from "../../types"; +import { Stub } from "../helper"; +import { ProxyEventType, type Indicator } from "../types"; -export function updateIndicatorProxy(msg: IndicatorMessage) { - globalThis.dispatchEvent(new CustomEvent(EventType.IndicatorProxy, {detail: JSON.stringify(msg)})) + +export class IndicatorProxy extends Stub implements Indicator { + + constructor() { + super(ProxyEventType.Indicator) + } + + show(radius: number, center: Position) { + this.forwardMessage({ + name: "show", + args: [radius, center] + }) + } + + hide() { + this.forwardMessage({ + name: "hide", + args: [] + }) + } } + +export const indicatorProxy = new IndicatorProxy() diff --git a/src/components/main.ts b/src/components/main.ts index 0a8f780..b814305 100644 --- a/src/components/main.ts +++ b/src/components/main.ts @@ -1,3 +1,7 @@ import './indicator/indicator' -import './status/status' -import './menu/menu' \ No newline at end of file +import './prompt/prompt' +import './menu/menu' +import { rootLog } from '../utils/log' +import { LogLevel } from '../config/config' + +rootLog.setLevel(__BUILD_PROFILE === 'debug' ? LogLevel.VVV : LogLevel.S) \ No newline at end of file diff --git a/src/components/menu/menu.svelte b/src/components/menu/menu.svelte index e5fdbbd..e60cd11 100644 --- a/src/components/menu/menu.svelte +++ b/src/components/menu/menu.svelte @@ -6,8 +6,8 @@ import { get_current_component } from "svelte/internal"; import { MenuLayout } from "../../config/config"; import type { Position } from "../../types"; - import { updateStatus } from "../status/status"; - import { EventType, type MenuItem, type MenuMessage } from "../message"; + import { rootLog } from "../../utils/log"; + import { EventType, type MenuItem, type ShowMenuOptions } from "../types"; let component = get_current_component() as HTMLElement; let items: MenuItem[] = []; @@ -35,21 +35,6 @@ }deg) translateY(${-distance}px) rotate(${i * angle * -1}deg`; }; - const cb = (msg: CustomEvent) => { - if (msg.detail.type === "reset") { - selectedMenuId = "" - return - } - center = msg.detail.center; - layout = msg.detail.layout; - items = cloneDeep(msg.detail.items); - if (layout === MenuLayout.circle) { - items = items.slice(0, 12); - } else { - items = items.slice(0, 16); - } - }; - const closestMenuItem = (target: EventTarget): HTMLElement | null => { if (!(target instanceof Element)) { return null; @@ -64,17 +49,18 @@ return closest; }; - component.addEventListener(EventType.Menu, cb); - const updateSelectedId = (id: string) => { selectedMenuId = id; component.dataset["id"] = id; + rootLog.VVV("update selected id: ", id); + window.top.dispatchEvent( + new CustomEvent(EventType.MenuSelectedId, { detail: id }) + ); }; - const dragover = (event: DragEvent) => { + const dragover = (event: MouseEvent) => { const closest = closestMenuItem(event.target); - if (!(closest instanceof HTMLElement)) { return; } @@ -84,22 +70,58 @@ if (selectedMenuId !== id) { updateSelectedId(id); - updateStatus({ - type: "show", - text: items[idx].title, - }); } }; - const dragleave = (event: DragEvent) => { + const dragleave = (event: MouseEvent) => { const closest = closestMenuItem(event.target); if (closest === event.target) { updateSelectedId(""); } }; + + component["update"] = (opts: ShowMenuOptions) => { + const docRect = document.documentElement.getBoundingClientRect(); + + let x = opts.position.x; + let y = opts.position.y; + + const len = distance + containerOffset; + + const right = x + len; + const left = x - len; + const top = y - len; + const bottom = y + len; + + if (right > docRect.width) { + x = docRect.width - len; + } else if (left < 0) { + x = len; + } + + if (bottom > docRect.height) { + y = docRect.height - len; + } else if (top < 0) { + y = len; + } + + center = { x, y }; + layout = cloneDeep(opts.layout); + items = cloneDeep(opts.items); + if (layout === MenuLayout.circle) { + items = items.slice(0, 12); + } else { + items = items.slice(0, 16); + } + }; + + component["reset"] = () => { + updateSelectedId(""); + }; +
- {@html item.htmlContent} + {@html item.html}
{/each}
@@ -131,6 +153,6 @@ border-radius: 18px; border-style: solid; border-width: 2px; - border-color: #777; + border-color: #ccc; } diff --git a/src/components/menu/menu.test.ts b/src/components/menu/menu.test.ts index eba755d..e3e3558 100644 --- a/src/components/menu/menu.test.ts +++ b/src/components/menu/menu.test.ts @@ -1,28 +1,5 @@ -import { MenuLayout } from "../../config/config"; import { onDocumentLoaded } from "../../content_scripts/utils"; -import { updateMenu } from "./menu"; -onDocumentLoaded(()=>{ - updateMenu({ - type: "show", - layout: MenuLayout.circle, - center: {x: 100, y: 100}, - items: [ - { - id: "1", - title: "1", - htmlContent: "" - }, - { - id: "2", - title: "2", - htmlContent: "" - }, - { - id: "3", - title: "3", - htmlContent: "" - }, - ] - }) +onDocumentLoaded(() => { + }) diff --git a/src/components/menu/menu.ts b/src/components/menu/menu.ts index 6854cca..a37182f 100644 --- a/src/components/menu/menu.ts +++ b/src/components/menu/menu.ts @@ -1,36 +1,38 @@ import App from './menu.svelte'; -import { EventType, type MenuItem, type MenuMessage } from '../message'; +import { ProxyEventType, type Menu, type ShowMenuOptions } from '../types'; +import { MessageTarget } from '../helper'; +import { rootLog } from '../../utils/log'; +import { LogLevel } from '../../config/config'; -export const menuApp = new App({ target: undefined }) as any as HTMLElement; +const log = rootLog.subLogger(LogLevel.VVV, "menu") -export function updateMenu(msg: MenuMessage) { - if (msg.type === "hide") { - menuApp.dispatchEvent(new CustomEvent(EventType.Menu, { - detail: { - type: "reset" - } - })) - menuApp.remove() - return +interface MenuElement extends HTMLElement { + update(opts: ShowMenuOptions) + reset() +} + +const menuApp = new App({ target: undefined }) as any as MenuElement; + +class MenuImpl extends MessageTarget implements Menu { + constructor() { + super(ProxyEventType.Menu) } - menuApp.dispatchEvent(new CustomEvent(EventType.Menu, { detail: msg })) - !menuApp.parentElement && document.body.append(menuApp) -} + hide() { + if (!menuApp.parentElement) { + return + } + log.V("hide menu") + menuApp.reset() + menuApp.remove() + } -export function getMenuSelectedId(): string { - if ('id' in menuApp.dataset) { - return menuApp.dataset['id'] + show(opts: ShowMenuOptions) { + log.V("show menu: ", opts) + menuApp.update(opts) + !menuApp.parentElement && document.body.append(menuApp) } - return "" } -globalThis.addEventListener(EventType.MenuProxy, (event: CustomEvent) => { - updateMenu(JSON.parse(event.detail) as MenuMessage) -}) - -globalThis.addEventListener(EventType.MenuSelectedIDProxy, (event: CustomEvent) => { - const id = getMenuSelectedId() - document.head.setAttribute("gd-menu-selected-id", id) -}) \ No newline at end of file +export const menuImpl = new MenuImpl() \ No newline at end of file diff --git a/src/components/menu/menu_proxy.ts b/src/components/menu/menu_proxy.ts index a130876..cd8ebcf 100644 --- a/src/components/menu/menu_proxy.ts +++ b/src/components/menu/menu_proxy.ts @@ -1,11 +1,29 @@ -import { EventType, type MenuMessage, } from "../message"; +import { rootLog } from "../../utils/log"; +import { Stub } from "../helper"; +import { EventType, ProxyEventType, type Menu, type ShowMenuOptions, } from "../types"; -export function updateMenuProxy(msg: MenuMessage) { - globalThis.dispatchEvent(new CustomEvent(EventType.MenuProxy, {detail: JSON.stringify(msg)})) -} -export function getMenuSelectedIdProxy(): string { - globalThis.dispatchEvent(new CustomEvent(EventType.MenuSelectedIDProxy)) - const id = document.head.getAttribute("gd-menu-selected-id") - return id ? id : "" + +// TODO: test menu under iframe +export class MenuProxy extends Stub implements Menu { + + constructor() { + super(ProxyEventType.Menu) + } + + show(opts: ShowMenuOptions) { + this.forwardMessage({ + name: "show", + args: [opts], + }) + } + + hide() { + this.forwardMessage({ + name: "hide", + args: [] + }) + } } + +export const menuProxy = new MenuProxy() diff --git a/src/components/prompt/prompt.svelte b/src/components/prompt/prompt.svelte new file mode 100644 index 0000000..5630189 --- /dev/null +++ b/src/components/prompt/prompt.svelte @@ -0,0 +1,23 @@ + + + + +
{content}
diff --git a/src/components/prompt/prompt.ts b/src/components/prompt/prompt.ts new file mode 100644 index 0000000..bb72779 --- /dev/null +++ b/src/components/prompt/prompt.ts @@ -0,0 +1,29 @@ +import { MessageTarget } from '../helper'; +import { ProxyEventType, type Prompt } from '../types'; +import App from './prompt.svelte'; + + +interface PromptElement extends HTMLElement { + update(text: string) +} + +export const promptApp = new App({ target: undefined }) as any as PromptElement; + + +export class PromptImpl extends MessageTarget implements Prompt { + + constructor() { + super(ProxyEventType.Status) + } + + show(text: string) { + promptApp.update(text) + !promptApp.parentElement && document.body.append(promptApp) + } + + hide() { + promptApp.remove() + } +} + +export const promptImpl = new PromptImpl() diff --git a/src/components/prompt/prompt_proxy.ts b/src/components/prompt/prompt_proxy.ts new file mode 100644 index 0000000..3301408 --- /dev/null +++ b/src/components/prompt/prompt_proxy.ts @@ -0,0 +1,25 @@ +import { Stub } from "../helper"; +import { ProxyEventType, type Prompt } from "../types"; + +export class PromptProxy extends Stub implements Prompt { + + constructor() { + super(ProxyEventType.Status) + } + + show(text: string) { + this.forwardMessage({ + name: "show", + args: [text], + }) + } + + hide() { + this.forwardMessage({ + name: "hide", + args: [], + }) + } +} + +export const promptProxy = new PromptProxy() diff --git a/src/components/status/status.svelte b/src/components/status/status.svelte deleted file mode 100644 index 8ea1a4e..0000000 --- a/src/components/status/status.svelte +++ /dev/null @@ -1,15 +0,0 @@ - - - - -
{content}
diff --git a/src/components/status/status.ts b/src/components/status/status.ts deleted file mode 100644 index cda4f77..0000000 --- a/src/components/status/status.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { EventType, type StatusMessage } from '../message'; -import App from './status.svelte'; - -export const statusApp = new App({ target: undefined }) as any as HTMLElement; - -export function updateStatus(msg: StatusMessage) { - if (msg.type === 'hide') { - statusApp.remove() - } else { - statusApp.dispatchEvent(new CustomEvent(EventType.Status, { detail: { content: msg.text } })) - !statusApp.parentElement && document.body.append(statusApp) - } -} - -globalThis.addEventListener(EventType.StatusProxy, (event: CustomEvent) => { - updateStatus(JSON.parse(event.detail) as StatusMessage) -}) diff --git a/src/components/status/status_proxy.ts b/src/components/status/status_proxy.ts deleted file mode 100644 index 5e58c1b..0000000 --- a/src/components/status/status_proxy.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { EventType, type StatusMessage } from "../message"; - -export function updateStatusProxy(msg: StatusMessage) { - globalThis.dispatchEvent(new CustomEvent(EventType.StatusProxy, {detail: JSON.stringify(msg)})) -} \ No newline at end of file diff --git a/src/components/message.ts b/src/components/types.ts similarity index 55% rename from src/components/message.ts rename to src/components/types.ts index 3ca5551..bb4c629 100644 --- a/src/components/message.ts +++ b/src/components/types.ts @@ -10,7 +10,13 @@ export enum EventType { IndicatorProxy = "gd-indicator-proxy", Menu = "gd-menu", MenuProxy = "gd-menu-proxy", - MenuSelectedIDProxy = "gd-menu-selected-id", + MenuSelectedId = "gd-menu-id" +} + +export enum ProxyEventType { + Menu = "gd-proxy:menu", + Status = "gd-proxy:status", + Indicator = "gd-proxy:indicator", } export interface IndicatorMessage { @@ -29,7 +35,7 @@ export interface StatusMessage { export interface MenuItem { id: string, title: string, - htmlContent: string + html: string style?: "" } @@ -39,3 +45,29 @@ export interface MenuMessage { layout?: MenuLayout items?: MenuItem[] } + +export interface ShowMenuOptions { + position: Position, + layout: MenuLayout, + items: MenuItem[] +} + +export interface GenericFunction { + name: string + args: unknown[] +} + +export interface Indicator { + show(radius: number, pos: Position) + hide() +} + +export interface Prompt { + show(text: string) + hide() +} + +export interface Menu { + show(opts: ShowMenuOptions): void + hide(): void +} \ No newline at end of file diff --git a/src/config/config.ts b/src/config/config.ts index 941ed21..02b1060 100644 --- a/src/config/config.ts +++ b/src/config/config.ts @@ -3,7 +3,7 @@ import cloneDeep from 'lodash-es/cloneDeep' import type { KVRecord } from "../types"; -export const enum LogLevel { +export enum LogLevel { Silent = 0, S = 0, V = 1, @@ -12,7 +12,7 @@ export const enum LogLevel { } -export const enum CommandKind { +export enum CommandKind { invalid = 'invalid', copy = 'copy', request = 'request', @@ -22,10 +22,10 @@ export const enum CommandKind { script = "script", } -export const enum OperationMode { +export enum OperationMode { chain = 'chain', normal = 'normal', - leftRightUpDown = 'normal', + leftRightUpDown = 'leftRightUpDown', upDown = 'upDown', leftRight = 'leftRight', diagonal = 'diagonal', @@ -33,29 +33,24 @@ export const enum OperationMode { upperRightLowerLeft = 'upperRightLowerLeft', full = 'full', any = 'any', - circle = 'circle', - grid = 'grid', + circleMenu = 'circleMenu', + gridMenu = 'gridMenu', + contextMenu = 'contextMenu', } -// 类型优先级 -export enum TypePriority { - image = 'image', - link = 'link', - text = 'text', -} -export const enum TabPosition { +export enum TabPosition { start = 'start', end = 'end', - before = 'before', + prev = 'prev', next = 'next', current = 'current', - window = 'newWindow', + newWindow = 'newWindow', privateWindow = 'privateWindow' } -export enum DirectionLabel { +export enum Direction { any = 'any', left = 'left', right = 'right', @@ -67,15 +62,27 @@ export enum DirectionLabel { lowerRight = 'lowerRight', } -export enum TypeConstraint { - text = 'text', +export enum ContextType { + selection = 'selection', image = 'image', link = 'link', } +export enum ContextDataType { + selection = 'selection', + imageSource = 'imageSource', + link = 'link', + linkText = 'linkText', +} + +export type ContextData = { + [k in ContextDataType]: string; +}; export enum Feature { - middleButtonSelector = "middleButtonSelector" + middleButtonSelector = "middleButtonSelector", + retainComponent = "retainComponent", + auxClose = "auxClose", } export class LogConfig { @@ -91,6 +98,10 @@ export class LogConfig { } } +export interface PlainLogConfig { + level: number +} + export class SmartURLConfig { cfg: KVRecord @@ -99,15 +110,41 @@ export class SmartURLConfig { } } -export class ExtensionConfig { - private _allow: string[] = []; - private _disallow: string[] = []; - cfg: KVRecord + +export class ModeConfig { + + private cfg: KVRecord + + constructor(cfg: KVRecord) { + this.cfg = cfg + } + + get link(): OperationMode { + return defaultTo(this.cfg['link'], OperationMode.normal) + } + + get selection(): OperationMode { + return defaultTo(this.cfg['selection'], OperationMode.normal) + } + + get image(): OperationMode { + return defaultTo(this.cfg['image'], OperationMode.normal) + } + +} + +export class CommonConfig { + private cfg: KVRecord + private _mode: ModeConfig constructor(cfg: KVRecord) { this.cfg = cfg + this._mode = new ModeConfig(defaultTo(this.cfg['mode'], {})) } + get mode(): ModeConfig { + return this._mode + } get allow(): string[] { return defaultTo(this.cfg['allow'], []) @@ -126,13 +163,20 @@ export class ExtensionConfig { } } +export interface PlainCommonConfig { + mode?: string + allowHost?: string[] + disallowHost?: string[] + minDistance?: number + maxDistance?: number +} export enum MenuLayout { circle = "circle", grid = "grid" } -export class MenuModeConfig { +export class MenuConfig { cfg: KVRecord constructor(cfg: KVRecord) { @@ -141,6 +185,10 @@ export class MenuModeConfig { } +export interface PlainMenuConfig { + +} + export class ListModeConfig { cfg: KVRecord @@ -153,7 +201,7 @@ export class Script { private cfg: KVRecord - constructor (cfg: KVRecord) { + constructor(cfg: KVRecord) { this.cfg = cfg } @@ -171,8 +219,20 @@ export class Script { get text() { return defaultTo(this.cfg['text'], "") } + + get name() { + return defaultTo(this.cfg['name'], this.id) + } } +export interface PlainScript { + id?: string + text?: string + name?: string +} + + + export class CommandRequest { private _url: URL @@ -184,11 +244,15 @@ export class CommandRequest { this.cfg = cfg this._url = new URL(cfg['url']) this._query = defaultTo(cfg['query'], {}) + for (const [k, v] of this._url.searchParams) { + this._query[k] = cloneDeep(v) + } } - toPlainObject() { + toPlainObject(): PlainCommandRequest { return { "id": this.id, + "name": this.name, "url": this.url.toString(), "query": this.query } @@ -202,6 +266,10 @@ export class CommandRequest { return defaultTo(this.cfg['id'], '') } + get name() { + return defaultTo(this.cfg["name"], this.id) + } + get method() { return "GET" } @@ -215,6 +283,15 @@ export class CommandRequest { } } + + +export interface PlainCommandRequest { + id?: string + name?: string + url?: string + query?: KVRecord +} + export const enum AssetType { html = "html", } @@ -226,10 +303,14 @@ export class Asset { this.cfg = cfg } - get id() { + get id(): string { return defaultTo(this.cfg["id"], "") } + get name(): string { + return defaultTo(this.cfg["name"], this.id) + } + get type(): AssetType { return defaultTo(this.cfg["type"], AssetType.html) } @@ -239,6 +320,13 @@ export class Asset { } } +export interface PlainAsset { + id?: string + name?: string + type?: string + data?: string +} + export class CommandConfig { private cfg: KVRecord @@ -247,7 +335,7 @@ export class CommandConfig { this.cfg = cfg } - toPlainObject(): KVRecord { + toPlainObject(): PlainCommandConfig { return { activeTab: cloneDeep(this.activeTab), tabPosition: cloneDeep(this.tabPosition), @@ -255,7 +343,7 @@ export class CommandConfig { directory: cloneDeep(this.directory), showSaveAsDialog: cloneDeep(this.showSaveAsDialog), scriptId: cloneDeep(this.scriptId), - priorities: cloneDeep(this.priorities), + preferDataTypes: cloneDeep(this.preferDataTypes), container: cloneDeep(this.container), } } @@ -284,8 +372,8 @@ export class CommandConfig { return defaultTo(this.cfg['showSaveAsDialog'], false) } - get priorities(): TypePriority[] { - return defaultTo(this.cfg['priorities'], []) + get preferDataTypes(): ContextDataType[] { + return defaultTo(this.cfg['preferDataTypes'], []) } get container(): string { @@ -293,27 +381,17 @@ export class CommandConfig { } } -export class ActionStyleConfig { - - private cfg: KVRecord - - constructor(cfg: KVRecord) { - this.cfg = cfg - } - - toPlainObject(): KVRecord { - return { - menuIcon: cloneDeep(this.menuIconId), - } - } - - get menuIconId(): string { - return defaultTo(this.cfg['menuIconId'], "") - } - +export interface PlainCommandConfig { + activeTab?: boolean + tabPosition?: string + requestId?: string + scriptId?: string + directory?: string + showSaveAsDialog?: boolean + preferDataTypes?: string[] + container?: string } - export class ConditionConfig { private cfg: KVRecord @@ -321,10 +399,10 @@ export class ConditionConfig { this.cfg = cfg } - toPlainObject(): KVRecord { + toPlainObject(): PlainConditionConfig { return { - types: cloneDeep(this.types), - labels: cloneDeep(this.labels), + contextTypes: cloneDeep(this.contextTypes), + directions: cloneDeep(this.directions), modes: cloneDeep(this.modes), } } @@ -333,56 +411,63 @@ export class ConditionConfig { return defaultTo(this.cfg['modes'], []) } - get types(): TypeConstraint[] { - return defaultTo(this.cfg['types'], []) + get contextTypes(): ContextType[] { + return defaultTo(this.cfg['contextTypes'], []) } - get labels(): DirectionLabel[] { - return defaultTo(this.cfg['labels'], []) + get directions(): Direction[] { + return defaultTo(this.cfg['directions'], []) } - get extra(): TypeConstraint[] { - return defaultTo(this.cfg['extra'], []) + get extra(): ContextType[] { + return defaultTo(this.cfg['extra'], []) } } +export interface PlainConditionConfig { + modes?: string[] + contextTypes?: string[], + directions?: string[], + extra?: string[] +} + export class ActionConfig { private cfg: KVRecord private _conditionConfig: ConditionConfig private _config: CommandConfig - private _style: ActionStyleConfig constructor(cfg: KVRecord) { this.cfg = cfg this._conditionConfig = new ConditionConfig(defaultTo(cfg['condition'], {})) this._config = new CommandConfig(defaultTo(cfg['config'], {})) - this._style = new ActionStyleConfig(defaultTo(cfg['style'], {})) } - toPlainObject(): KVRecord { + toPlainObject(): PlainActionConfig { return { id: cloneDeep(this.id), command: cloneDeep(this.command), condition: this.condition.toPlainObject(), config: this.config.toPlainObject(), - style: this.style.toPlainObject(), + icon: this.icon, + iconAssetId: this.iconAssetId, + prompt: this.prompt } } - toJSON() { - return this.toPlainObject() - } - get id(): string { return defaultTo(this.cfg['id'], "") } - get title(): string { - return defaultTo(this.cfg['title'], this.id) + get name(): string { + return defaultTo(this.cfg['name'], this.id) + } + + get prompt(): string { + return defaultTo(this.cfg['prompt'], "") } - get condition(): ConditionConfig { + get condition(): Readonly { return this._conditionConfig } @@ -394,22 +479,34 @@ export class ActionConfig { return this._config } - get style(): ActionStyleConfig { - return this._style + get icon(): string { + return defaultTo(this.cfg['icon'], "") } + get iconAssetId(): string { + return defaultTo(this.cfg['iconAssetId'], "") + } } +export interface PlainActionConfig { + id?: string + name?: string + condition?: PlainConditionConfig + command?: string + config?: PlainCommandConfig + icon?: string + iconAssetId?: string + prompt?: string +} export class Configuration { - private _features: Set = new Set(); - private _mode: OperationMode; + private _features: Set = new Set(); private _actions: ActionConfig[] = []; private _log: LogConfig private _smartURL: SmartURLConfig - private _extension: ExtensionConfig - private _menu: MenuModeConfig + private _common: CommonConfig + private _menu: MenuConfig private _requests: CommandRequest[] private _assets: Asset[] private _scripts: Script[] @@ -417,11 +514,10 @@ export class Configuration { constructor(data?: KVRecord) { data = defaultTo(data, {}) - this._mode = defaultTo(data['mode'], OperationMode.chain) this._log = new LogConfig(defaultTo(data['log'], {})) this._smartURL = new SmartURLConfig(defaultTo(data['smartURL'], {})) - this._extension = new ExtensionConfig(defaultTo(data['extension'], {})) - this._menu = new MenuModeConfig(defaultTo(data['grid'], {})) + this._common = new CommonConfig(defaultTo(data['common'], {})) + this._menu = new MenuConfig(defaultTo(data['grid'], {})) this._actions = defaultTo(data['actions'], []).map((c: KVRecord) => new ActionConfig(c)) this._features = new Set(defaultTo(data['features'], [])) this._requests = defaultTo(data['requests'], []).map((r: KVRecord) => new CommandRequest(r)) @@ -441,18 +537,14 @@ export class Configuration { return this._smartURL } - get extension(): ExtensionConfig { - return this._extension + get common(): CommonConfig { + return this._common } - get menu(): MenuModeConfig { + get menu(): MenuConfig { return this._menu } - get mode(): OperationMode { - return this._mode - } - get actions(): readonly ActionConfig[] { return this._actions } @@ -468,6 +560,20 @@ export class Configuration { get scripts(): readonly Script[] { return this._scripts } + + Enabled(f: Feature): boolean { + return this._features.has(f) + } } -export type ReadonlyConfiguration = Readonly \ No newline at end of file +export type ReadonlyConfiguration = Readonly + +export interface PlainConfiguration { + log?: PlainLogConfig + common?: PlainCommonConfig + menu?: PlainMenuConfig, + actions?: PlainActionConfig[], + requests?: PlainCommandRequest[], + assets?: PlainAsset[], + scripts?: PlainScript[], +} \ No newline at end of file diff --git a/src/content_scripts/content_script.css b/src/content_scripts/content_script.css index 3873c4a..13f9443 100644 --- a/src/content_scripts/content_script.css +++ b/src/content_scripts/content_script.css @@ -6,7 +6,7 @@ glitter-drag-status { color: white !important; pointer-events: none; z-index: 2147483647; - font-size: 16px; + font-size: 14px; } glitter-drag-indicator { diff --git a/src/content_scripts/drag.ts b/src/content_scripts/drag.ts index 692cff0..1dec755 100644 --- a/src/content_scripts/drag.ts +++ b/src/content_scripts/drag.ts @@ -1,19 +1,9 @@ -import isEqual from 'lodash-es/isEqual' -import browser from 'webextension-polyfill' -import { ActionConfig, DirectionLabel, LogLevel, MenuLayout, OperationMode, type ReadonlyConfiguration } from '../config/config' -import { buildRuntimeMessage } from '../message/message' -import { ModifierKey, type Position } from '../types' +import { LogLevel } from '../config/config' import { rootLog } from '../utils/log' -import { updateIndicatorProxy } from '../components/indicator/indicator_proxy' -import { getMenuSelectedIdProxy, updateMenuProxy } from '../components/menu/menu_proxy' -import { updateStatusProxy } from '../components/status/status_proxy' -import { buildDataTransferStorage, canDestinationAcceptDrop, EventPhase, guessDragContent, isEditableAndDraggable, isInputArea, isInstance, modifierKey, objectifyDataTransfer, stringifyEventPhase, type Guess } from './drag_utils' -import { LabelChain } from './label_chain' -import { StateMan, States } from './state_man' -import { directionLabelMapping, getAngle, transformMenuItem, type RangeMapping } from './utils' -import { VarSubstituteTemplate } from '../utils/var_substitute' - +import { EventPhase, isEditableAndDraggable, isInstance } from './drag_utils' +import { buildOpPosition, Op, OpExecutor, OpType } from './op' +import { OpSource } from './op_source' enum TriggerSource { unknown = 'unknown', @@ -23,32 +13,31 @@ enum TriggerSource { const log = rootLog.subLogger(LogLevel.VVV, 'drag') -export class Controller { - state: StateMan - dragTriggerSource: TriggerSource - sourceTarget: EventTarget | null - destTarget: EventTarget | null +export class DragController { - startPos: Position = { x: 0, y: 0 } - endPos: Position = { x: 0, y: 0 } + dragTriggerSource: TriggerSource - eventSource: GlobalEventHandlers - config: ReadonlyConfiguration | null = null + sourceTarget: Node | null + destTarget: Node | null - tmpStorage: Map = new Map() - titleTemplateCache: Map = new Map() + eventSource: GlobalEventHandlers + c: OpExecutor + frameX: number + frameY: number - labelChain: LabelChain = new LabelChain() + opQueue: Op[] - constructor(eventSource: GlobalEventHandlers) { - this.state = new StateMan() + constructor(eventSource: GlobalEventHandlers, opExecutor: OpExecutor) { this.dragTriggerSource = TriggerSource.unknown this.sourceTarget = null this.destTarget = null this.dragHandler = this.dragHandler.bind(this) this.eventSource = eventSource + this.c = opExecutor + this.frameX = 0 + this.frameY = 0 } start() { @@ -65,79 +54,22 @@ export class Controller { } } - async updateStorage(config: ReadonlyConfiguration) { - this.config = config - this.titleTemplateCache.clear() - this.config.actions.forEach(a => { - try { - const t = new VarSubstituteTemplate(a.title) - this.titleTemplateCache.set(a.title, t) - } catch (e) { - log.E(e) - } - }) - log.VVV("new config", this.config) - } - - private dragHandler(event: DragEvent): boolean { - this.preCheckEvent(event) - this.checkEvent(event) - this.postCheckEvent(event) - return true - } - - private get distance(): number { - return Math.hypot(this.startPos.x - this.endPos.x, this.startPos.y - this.endPos.y); - } - - private preCheckEvent(e: DragEvent) { - - // TODO: more readable code - if (this.tmpStorage.size === 0 && e.dataTransfer.items.length > 0) { - this.tmpStorage = buildDataTransferStorage(e.dataTransfer) - } - - // TODO: no magic number - if (this.distance > 3) { - const label = this.angleToLabel(getAngle(this.startPos, this.endPos)) - if (label) { - if (this.config.mode === OperationMode.chain) { - this.labelChain.push(label) - } else { - this.labelChain.overwrite(label) - } - } else { - log.V("no label available") - } - } - - } - - private checkEvent(e: DragEvent) { - - log.VVV( - 'check event', - { - 'type': e.type, - 'distance': this.distance.toFixed(2), - 'source': this.dragTriggerSource, - 'phase': stringifyEventPhase(e.eventPhase), - 'labels': this.labelChain.labels, - target: e.target, - }, - e, - ) - - log.VVV('before state: ', this.state.toString()) + private dragHandler(e: DragEvent) { + log.VV(e) switch (e.type) { case 'dragstart': this.checkDragStart(e) + if (this.sourceTarget != null) { + this.initFramePosition() + this.c.applyOp(this.makeOp(OpType.start, this.sourceTarget, e)) + } break case 'dragend': this.checkDragEnd(e) break case 'dragenter': + this.initFramePosition() this.checkDragEnter(e) break case 'dragover': @@ -152,104 +84,24 @@ export class Controller { default: throw new Error("unhandled event type: " + e.type) } - log.VVV('after state: ', this.state.toString()) - - } - - private postCheckEvent(e: DragEvent) { - this.updateUI(e) - } - - private updateUI(e: DragEvent) { - - - const g = guessDragContent( - this.sourceTarget, - this.tmpStorage - ) - - const actions = this.filterAction(g, this.labelChain.labels) - - if (e.type === 'dragstart' && this.state.test(States.running)) { - if (this.config.extension.minDistance > 0) { - updateIndicatorProxy({ - type: "show", - radius: this.config.extension.minDistance, - center: { - x: e.pageX, - y: e.pageY, - } - }) - } - - if (actions.length) { - updateMenuProxy({ - center: { - x: e.pageX, - y: e.pageY, - }, - type: "show", - layout: MenuLayout.circle, - items: transformMenuItem(actions, this.config.assets), - }) - } - } - - if (this.state.test(States.running)) { - if (actions.length) { - const title = actions[0].title - // TODO: prevent render same "title" multiple times - const tmpl = this.titleTemplateCache.get(title) - if (tmpl) { - // TODO: determine what vars should be - const text = tmpl.substitute(new Map()) - updateStatusProxy({ type: 'show', text: text }) - } else { - log.V(`missing template instance of title: "${title}"`) - } - } else if (this.state.test(States.exceedDistance)) { - updateStatusProxy({ type: 'hide' }) - } - } else { - updateStatusProxy({ type: 'hide' }) - } - } - - - private reset() { - this.state.reset() - this.labelChain.reset() - this.tmpStorage.clear() - this.resetUI() - } - - private resetUI() { - this.state.clear() - updateIndicatorProxy({ type: 'hide' }) - updateStatusProxy({ type: 'hide' }) - updateMenuProxy({ type: 'hide' }) + return true } private checkDragStart(event: DragEvent) { - - if (event.eventPhase != EventPhase.capturing) { + if (event.eventPhase !== EventPhase.capturing) { return } - this.reset() - - this.startPos.x = event.pageX - this.startPos.y = event.pageY - - this.endPos.x = event.pageX - this.endPos.y = event.pageY + if (!(event.target instanceof Node)) { + return + } let target = event.target if (event.composed) { log.VV("composed event, check composed path") const paths = event.composedPath() - if (paths.length) { + if (paths.length && paths[0] instanceof Node) { target = paths[0] log.VV("use target of first composed path value:", target) } @@ -280,22 +132,14 @@ export class Controller { log.VV('target\'s href starts with javascript, do extra check ') const firstChild = target.firstElementChild if (isInstance(firstChild, window.HTMLImageElement)) { - log.VV('first child is image element') this.sourceTarget = firstChild - this.state.set(States.running) - this.dragTriggerSource = TriggerSource.document - return; } log.VV('not support anchor with javascript:') - this.state.set(States.skip) return } - this.sourceTarget = target - this.state.set(States.running) - this.dragTriggerSource = TriggerSource.document return } @@ -306,15 +150,11 @@ export class Controller { } else { this.sourceTarget = target } - this.state.set(States.running) - this.dragTriggerSource = TriggerSource.document return } if (isInstance(target, window.Text)) { this.sourceTarget = target - this.state.set(States.running) - this.dragTriggerSource = TriggerSource.document return } @@ -322,8 +162,6 @@ export class Controller { log.VV('target is input element, input type: ', target.type) if (["text", "number", "url"].includes(target.type.toLowerCase())) { this.sourceTarget = target - this.state.set(States.running) - this.dragTriggerSource = TriggerSource.document return } } @@ -331,8 +169,6 @@ export class Controller { if (isInstance(target, window.HTMLTextAreaElement)) { log.VV('target is text area') this.sourceTarget = target - this.state.set(States.running) - this.dragTriggerSource = TriggerSource.document return } @@ -342,114 +178,52 @@ export class Controller { } private checkDragEnter(event: DragEvent) { - - // always clear 'interfere' flag when DragEnter event occur. - this.state.clear(States.interfere) - - const target = event.target! - - if (!canDestinationAcceptDrop(target)) { - log.VV('destination target can not accept drop') + if (event.eventPhase !== EventPhase.bubbling) { return } - - if (this.state.test(States.skip)) { + if (!(event.target instanceof Node)) { return } - - if (this.state.test_not(States.running)) { - log.VV('drag enter is happened without running flag, do extra check') - this.reset() - if (event.dataTransfer) { - this.state.set(States.running) - log.VV('set trigger source to \'external\'') - this.dragTriggerSource = TriggerSource.external - } - } - - if (this.state.test_not(States.running)) { - return - } - - log.VV('current dest target:', target) - this.destTarget = target + this.c.applyOp(this.makeOp(OpType.running, event.target, event)) + this.destTarget = event.target + event.preventDefault() } private checkDragOver(event: DragEvent) { - - this.endPos.x = event.pageX - this.endPos.y = event.pageY - - - const target = event.target! - - if (!this.state.test(States.running)) { - log.VV('drag over event is happened without running flag, skip!') + if (event.eventPhase !== EventPhase.bubbling) { return } - if (this.checkDistance()) { - this.state.clear(States.exceedDistance) - } else { - this.state.set(States.exceedDistance) - } - - if (!canDestinationAcceptDrop(target)) { - log.VV('drag over target can not accept drop') + if (!(event.target instanceof Node)) { return } - if (event.eventPhase === EventPhase.capturing) { // capture - - } else if (event.eventPhase === EventPhase.bubbling) { // bubble - if (event.defaultPrevented) { - log.VV('defaultPrevented is true, set \'interfere\' flag') - this.state.set(States.interfere) - } - event.preventDefault() - } + this.c.applyOp(this.makeOp(OpType.running, event.target, event)) + event.preventDefault() } - private checkDrop(event: DragEvent) { - const target = event.target! - - if (!this.state.test(States.running)) { + if (event.eventPhase !== EventPhase.bubbling) { return } - if (!canDestinationAcceptDrop(target)) { - log.VV('event target can not accept drop') - this.state.set(States.resolved, States.skip) + if (!(event.target instanceof Node)) { return } - if (isInputArea(target)) { - log.VV('event target is input area') - this.state.set(States.resolved, States.skip) + if (event.defaultPrevented) { + this.c.applyOp(this.makeOp(OpType.reset, event.target, event)) return } - if (this.dragTriggerSource === TriggerSource.external) { - this.state.set(States.resolved) - this.doDrop(event) - } else if (this.dragTriggerSource === TriggerSource.document) { + const r = this.c.applyOp(this.makeOp(OpType.end, event.target, event)) + if (r.cancelDrop) { log.VV("cancel drop event") event.preventDefault() - this.state.set(States.resolved) - } else { - throw new Error("unknown trigger source") - } - } - - private doDrop(event: DragEvent) { - if (this.dragTriggerSource !== TriggerSource.external) { - return } - this.reset() } - private checkDragLeave(event: DragEvent) { + private checkDragLeave(_event: DragEvent) { return } @@ -459,191 +233,33 @@ export class Controller { return } - if (this.state.test(States.skip)) { - return - } - - if (!this.state.test(States.resolved)) { - log.VV("state is not resolved, maybe 'checkDrop' was not called, try re-evaluate") - - const b = [ - this.state.test(States.running), - this.dragTriggerSource === TriggerSource.document, - canDestinationAcceptDrop(event.target), - ] - - if (b.every(v => v)) { - log.VV("re-evaluate pass") - this.state.set(States.resolved) - } else { - log.VV("re-evaluate failed") - this.reset() - return - } - } - - if (this.dragTriggerSource !== TriggerSource.document) { - this.reset() - throw new Error("trigger source is not document") - } - - if (this.state.test(States.skip)) { - log.VV("skip handle") - this.reset() - return - } - - if (this.state.test(States.interfere)) { - log.VV("interfere") - this.reset() + if (!(event.target instanceof Node)) { return } - - try { - this.doDragEnd(event) - } catch (e) { - log.E(e) - } finally { - this.reset() - } + event.preventDefault() + // this.c.applyOp(this.makeOp(OpType.end, event.target, event)) } - private doDragEnd(event: DragEvent) { - if (!this.sourceTarget) { - log.V("missing sourceTarget") - return - } - - const guess = guessDragContent( - this.sourceTarget, - this.tmpStorage, - ) - - log.VV('dragEnd', { - sourceTarget: this.sourceTarget, - types: guess.types, - key: modifierKey(event), - textSel: guess.textSel, - linkSel: guess.linkSel, - imageSel: guess.imageSel, - dt: new Map(this.tmpStorage), - distance: this.distance, - labels: this.labelChain.labels, - mode: this.config.mode, + private makeOp(type: OpType, target: Node, e: DragEvent): Op { + return Op.make({ + type: type, + source: OpSource.fromNode(target), + position: buildOpPosition(e, this.frameX, this.frameY), + dt: e.dataTransfer }) - - this.postCommand(guess) } - private postCommand(g: Guess) { - - if (!this.config) { - return - } - - let action: ActionConfig | null = null - - if (this.config.mode === OperationMode.circle) { - const id = getMenuSelectedIdProxy() - log.VV("menu id: ", id) - action = this.config.actions.find(c => c.id === id) + private initFramePosition(): boolean { + let cur: Window = window.self + this.frameX = this.frameY = 0 + const frame = cur.frameElement + if (frame) { + const rect = frame.getBoundingClientRect() + this.frameX = rect.x + this.frameY = rect.y + return true } else { - - const actions = this.filterAction(g, this.labelChain.labels) - log.VV("labels: ", this.labelChain.labels) - if (actions.length) { - action = actions[0] - } - } - - if (!action) { - log.VVV("not found candidate action") - return - } - - log.VVV("use action:", action) - - let cmd = buildRuntimeMessage("execute", { - action: action.toPlainObject(), - text: g.textSel, - link: g.linkSel, - image: g.imageSel, - url: location.href, - title: document.title, - modifierKey: ModifierKey.none, - startPosition: this.startPos, - endPosition: this.endPos, - }) - - log.VVV("cmd", cmd) - browser.runtime.sendMessage(cmd); - } - - angleToLabel(angle: number): DirectionLabel | null { - - const rangeMapping = this.getAngleRangeMapping() - - if (!rangeMapping) { - return null - } - - for (const obj of rangeMapping) { - if (obj.range[0] <= angle && angle < obj.range[1]) { - return obj.label; - } - } - - return null - } - - getAngleRangeMapping(): RangeMapping[] | null { - if (!this.config) { - return null - } - if (directionLabelMapping[this.config.mode]) { - return directionLabelMapping[this.config.mode] - } - log.VVV("missing mapping of mode: ", this.config.mode) - return null - } - - filterAction(g: Guess, labels: readonly string[]): ActionConfig[] { - if (!this.config) { - return - } - return this.config.actions - .filter((action) => { - return action.condition.modes.length === 0 - // contains any of - || action.condition.modes.includes(this.config.mode) - }) - .filter((action) => { - return action.condition.types.length === 0 - // subset - || action.condition.types.every((t) => g.types.has(t)) - }) - .filter((action) => { - return action.condition.labels.length === 0 - // equal - || isEqual(action.condition.labels, labels) - }) - .filter((action) => { - return action.condition.extra.length === 0 - || action.condition.extra.every((label) => g.types.has(label)) - }) - } - - - checkDistance(): boolean { - - if (this.config.extension.maxDistance != 0 && this.distance > this.config.extension.maxDistance) { return false } - - if (this.config.extension.minDistance != 0 && this.distance < this.config.extension.minDistance) { - return false - } - - return true } } diff --git a/src/content_scripts/drag_utils.ts b/src/content_scripts/drag_utils.ts index cdd46bd..292b350 100644 --- a/src/content_scripts/drag_utils.ts +++ b/src/content_scripts/drag_utils.ts @@ -1,85 +1,5 @@ -import { TypeConstraint } from "../config/config" import { ModifierKey } from "../types" -import { URLFixer } from "../utils/url" - - -export interface Guess { - types: Set - extra: Set - textSel: string - linkSel: string - imageSel: string -} - -function tryGetLink(dataTransferLike: Map): string { - let link = dataTransferLike.get("text/plain") || "" - if (!link) { - const data = dataTransferLike.get("text/uri-list") || "" - if (data) { - const arr = data.split("\n").map(line => line.trim()) - if (arr.length) { - link = arr[0] - } - } - } - return link -} - -export function guessDragContent(sourceTarget: EventTarget, dataTransferStorage: Map): Guess { - - let actionTypes: Set = new Set() - let textSel = '' - let linkSel = '' - let imageSel = '' - let labels: Set = new Set() - - if (isInstance(sourceTarget, window.Text)) { - actionTypes.add(TypeConstraint.text) - textSel = dataTransferStorage.get("text/plain") || "" - - const url = new URLFixer().fix(textSel) - if (url) { - actionTypes.add(TypeConstraint.link) - linkSel = url.toString() - labels.add("protocol:" + url.protocol.substring(0, url.protocol.length - 1)) - } - - } else if (isInstance(sourceTarget, window.HTMLAnchorElement)) { - actionTypes.add(TypeConstraint.link) - const descentImageElement = sourceTarget.querySelector("img") - if (descentImageElement) { - actionTypes.add(TypeConstraint.image) - textSel = sourceTarget.textContent || "" - linkSel = tryGetLink(dataTransferStorage) - imageSel = descentImageElement.src - } else { - actionTypes.add(TypeConstraint.link) - actionTypes.add(TypeConstraint.text) - textSel = sourceTarget.textContent || "" - linkSel = tryGetLink(dataTransferStorage) - } - - } else if (isInstance(sourceTarget, window.HTMLImageElement) || isInstance(sourceTarget, window.HTMLPictureElement)) { - actionTypes.add(TypeConstraint.image) - //workaround #79 - if (isInstance(sourceTarget, window.HTMLImageElement)) { - imageSel = sourceTarget.src - linkSel = imageSel - } else if (isInstance(sourceTarget, window.HTMLPictureElement)) { - throw new Error("TODO: to support Picture Element") - } - } else { - // TODO: handle web component with closed shadow root. - } - - return { - types: actionTypes, - textSel, - linkSel, - imageSel, - extra: new Set() - } -} +import { OpSource } from "./op_source" export function modifierKey(event: MouseEvent): ModifierKey { @@ -106,32 +26,29 @@ export function isEditableAndDraggable(elem: HTMLElement): boolean { return true } -export function canDestinationAcceptDrop(target?: EventTarget) { +export function canDestinationAcceptDropFix(s: OpSource) { - if (isInstance(target, window.Text)) { - return true + if (s.isContentEditable) { + return false } - if (isInputArea(target)) { + if (s.targetNodeName == "TEXT") { return true } - if (isInstance(target, window.HTMLElement)) { - if (target.getAttribute && target.getAttribute("contenteditable") === null) { - return true - } - return false + if (isInputArea(s)) { + return true } - return false + return true } -export function isInputArea(target: EventTarget): boolean { - if (isInstance(target, window.HTMLInputElement)) { +export function isInputArea(s: OpSource): boolean { + if (s.targetNodeName === "INPUT") { return true } - if (isInstance(target, window.HTMLTextAreaElement)) { + if (s.targetNodeName === "TEXTAREA") { return true } diff --git a/src/content_scripts/features/auxclose.ts b/src/content_scripts/features/auxclose.ts new file mode 100644 index 0000000..db5a5c9 --- /dev/null +++ b/src/content_scripts/features/auxclose.ts @@ -0,0 +1,37 @@ +import browser from 'webextension-polyfill'; +import { buildRuntimeMessage, RuntimeMessageName } from '../../message/message'; + +export class MiddleButtonClose { + target: HTMLElement + constructor(target: HTMLElement) { + this.target = target + this.auxclick = this.auxclick.bind(this); + } + + async start() { + this.target.addEventListener("auxclick", this.auxclick); + } + + async stop() { + this.target.removeEventListener("mouseup", this.auxclick) + } + + auxclick(e: MouseEvent) { + const target = e.target + if (target instanceof HTMLElement) { + if (target.closest("a")) { + return + } + if (e.defaultPrevented) { + return + } + // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button + if (e.button != 1) { + return + } + e.preventDefault() + browser.runtime.sendMessage(buildRuntimeMessage(RuntimeMessageName.closeCurrentTab, null)) + } + } +}; + diff --git a/src/content_scripts/features/middle_button_selector.ts b/src/content_scripts/features/middle_button_selector.ts index 7bbc206..be639a5 100644 --- a/src/content_scripts/features/middle_button_selector.ts +++ b/src/content_scripts/features/middle_button_selector.ts @@ -1,4 +1,3 @@ - const MINIUM_MOVEMENT = 10 const LEFT_BUTTON = 0 const MIDDLE_BUTTON = 1 @@ -54,14 +53,14 @@ export class MiddleButtonSelector { this.target = target } - start() { + async start() { this.target.addEventListener("mouseup", this.mouseup); this.target.addEventListener("mousedown", this.mousedown); this.target.addEventListener("mousemove", this.mousemove); this.target.addEventListener("auxclick", this.auxclick); } - stop() { + async stop() { this.target.removeEventListener("mouseup", this.mouseup) this.target.removeEventListener("mousedown", this.mousedown) this.target.removeEventListener("mousemove", this.mousemove) diff --git a/src/content_scripts/label_chain.ts b/src/content_scripts/label_chain.ts index 9c921b1..a643803 100644 --- a/src/content_scripts/label_chain.ts +++ b/src/content_scripts/label_chain.ts @@ -1,7 +1,22 @@ -import { DirectionLabel } from "../config/config"; +import { Direction } from "../config/config"; +import type { Position } from "../types"; -export class LabelChain { - private s: DirectionLabel[] = [] + + +export class ChainItem { + dir: Direction + start: Position + end: Position + + constructor(dir: Direction, start: Position, end: Position) { + this.dir = dir + this.start = { x: start.x, y: start.y } + this.end = { x: end.x, y: end.y } + } +} + +export class DirectionChain { + private s: ChainItem[] = [] constructor() { @@ -11,29 +26,33 @@ export class LabelChain { return JSON.stringify(this.s) } - overwrite(l: DirectionLabel) { - while (this.s.length !== 0) { - this.s.pop() + overwrite(item: ChainItem) { + if (this.s.length != 0) { + this.s = [] } - this.s.push(l); + this.s.push(item); } - push(l: DirectionLabel) { + push(item: ChainItem) { + this.s.push(item) + } + + pop(): ChainItem | null { if (this.s.length == 0) { - this.s.push(l) - return - } - if (this.s[this.s.length - 1] != l) { - this.s.push(l) - return + return null } + return this.s.pop() + } + + empty(): boolean { + return this.s.length == 0 } reset() { this.s = [] } - get labels(): readonly string[] { - return this.s + get directions(): readonly Direction[] { + return this.s.map(item => item.dir) } } diff --git a/src/content_scripts/main.ts b/src/content_scripts/main.ts index 6386156..50ec274 100644 --- a/src/content_scripts/main.ts +++ b/src/content_scripts/main.ts @@ -1,24 +1,23 @@ import browser from 'webextension-polyfill'; import { Configuration, Feature, type ReadonlyConfiguration } from '../config/config'; -import { buildRuntimeMessage, type FetchURLReply, type RuntimeMessage, type RuntimeMessageArgs } from '../message/message'; +import { buildRuntimeMessage, RuntimeMessageName, type FetchURLReply, type RuntimeMessage, type RuntimeMessageArg, type RuntimeMessageArgsMap } from '../message/message'; import type { ExtensionStorage } from '../types'; import { configureRootLog, rootLog } from '../utils/log'; -import { Controller } from "./drag"; +import { DragController } from "./drag"; +import { MiddleButtonClose } from './features/auxclose'; import { MiddleButtonSelector } from './features/middle_button_selector'; +import { OpExecutor } from './op'; import { ScriptWrapper as UserScriptWrapper } from './script'; import { onDocumentLoaded } from './utils'; -async function dispatcher(message: RuntimeMessage) { - rootLog.V("content script dispatcher:", message) - - switch (message.cmd) { - case "fetchURL": - return onFetchURLMessage(message as any) - case "ping": - return "pong" - case "copy": +async function dispatcher(m: any) { + rootLog.V("content script dispatcher:", m) + const cmd = m.cmd as RuntimeMessageName; + switch (cmd) { + case RuntimeMessageName.copy: { + const args = (m as RuntimeMessage).args const storage = document.createElement("textarea"); - storage.value = message.args; + storage.value = args; storage.setAttribute('readonly', ''); storage.style.position = 'absolute'; storage.style.width = '0px'; @@ -28,52 +27,40 @@ async function dispatcher(message: RuntimeMessage) { document.execCommand("copy"); storage.remove(); return - case "doScript": { - const wrapper = new UserScriptWrapper(message.args) + } + case RuntimeMessageName.executeScript: { + const args = (m as RuntimeMessage).args + const wrapper = new UserScriptWrapper(args) wrapper.do() + return } default: return } } -async function onFetchURLMessage(message: RuntimeMessage<"fetchURL">) { - - const controller = new AbortController(); - const signal = controller.signal; - - setTimeout(() => { controller.abort("timeout: " + message.args.timeoutMs + " ms") }, message.args.timeoutMs) - - return window.fetch(message.args.url, { signal }).then((resp) => { - return resp.arrayBuffer() - }).then(content => { - let fetchURLResp: FetchURLReply = { - data: String.fromCharCode(...new Uint8Array(content)) - } - if ("base64" === message.args.encoding) { - fetchURLResp.data = btoa(fetchURLResp.data); - } - return fetchURLResp - }) -} - function setupComponents() { const s = document.createElement("script") s.src = browser.runtime.getURL("components/main.js") document.body.appendChild(s) } -let controller: Controller | null = null +let controller: DragController | null = null +let opExecutor: OpExecutor | null = null async function setup() { browser.storage.onChanged.addListener(onConfigChange) browser.runtime.onMessage.addListener(dispatcher as any) - controller = new Controller(document.documentElement); + + opExecutor = new OpExecutor() + opExecutor.reset() + + controller = new DragController(document.documentElement, opExecutor); controller.start() onDocumentLoaded(async () => { - await browser.runtime.sendMessage(buildRuntimeMessage("contentScriptLoaded", null)) + await browser.runtime.sendMessage(buildRuntimeMessage(RuntimeMessageName.contextScriptLoaded, null)) onConfigChange() setupComponents() }) @@ -92,7 +79,11 @@ async function manageFeatures(config: ReadonlyConfiguration) { featureManagedFlag = true if (config.features.has(Feature.middleButtonSelector)) { const f = new MiddleButtonSelector(document.getSelection(), document.documentElement) - f.start() + await f.start() + } + if (config.features.has(Feature.auxClose)) { + const f = new MiddleButtonClose(document.documentElement) + await f.start() } } @@ -103,8 +94,8 @@ async function onConfigChange() { configureRootLog(config) manageFeatures(config) - if (controller) { - controller.updateStorage(config) + if (opExecutor) { + opExecutor.updateConfig(config) } else { throw new Error("controller is null") } @@ -116,8 +107,9 @@ async function main() { await setup() } catch (error) { - rootLog.E("failed to setup glitter drag extension"); + rootLog.E("failed to setup glitter drag extension: ", window.self); rootLog.E(error); + rootLog.E(error.stack) } } diff --git a/src/content_scripts/op.ts b/src/content_scripts/op.ts new file mode 100644 index 0000000..766cf69 --- /dev/null +++ b/src/content_scripts/op.ts @@ -0,0 +1,507 @@ + +import cloneDeep from 'lodash-es/cloneDeep' +import isEqual from 'lodash-es/isEqual' +import browser from 'webextension-polyfill' +import { indicatorProxy } from '../components/indicator/indicator_proxy' +import { menuProxy } from '../components/menu/menu_proxy' +import { promptProxy } from '../components/prompt/prompt_proxy' +import { EventType } from '../components/types' +import { ActionConfig, ContextType, Feature, LogLevel, MenuLayout, OperationMode, type ReadonlyConfiguration } from '../config/config' +import { buildRuntimeMessage, RuntimeMessageName } from '../message/message' +import { ModifierKey, type KVRecord, type Position } from '../types' +import { rootLog } from '../utils/log' +import { VarSubstituteTemplate } from '../utils/var_substitute' +import { buildDataTransferStorage, canDestinationAcceptDropFix as canDestinationAcceptDrop, isInputArea } from './drag_utils' +import { ChainItem, DirectionChain } from './label_chain' +import { OpSource } from './op_source' +import { StateManager, States } from './state_man' +import { angleToDirection, getAngle, transformMenuItem } from './utils' + +const log = rootLog.subLogger(LogLevel.VVV, 'op') + +export enum OpType { + start, + running, + end, + reset, +} + +export interface OpPositions { + page: Position, + screen: Position, + client: Position, + real: Position, +} + +export function buildOpPosition(e: DragEvent, frameX: number = 0, frameY: number = 0): OpPositions { + return { + page: { x: e.pageX, y: e.pageY }, + client: { x: e.clientX, y: e.clientY }, + screen: { x: e.screenX, y: e.screenY }, + real: { x: e.clientX + frameX, y: e.clientY + frameY } + } +} + +export class Op { + type: OpType + source: OpSource + positions: OpPositions + data: Map + modifierKeys: Set + + private constructor() { } + + static make(opt: { type: OpType, source: OpSource, position: OpPositions, dt: DataTransfer }): Op { + const op = new Op + op.type = opt.type + op.source = opt.source + op.positions = opt.position + op.data = buildDataTransferStorage(opt.dt) + op.modifierKeys = new Set() + return op + } + + toPlainObject(): KVRecord { + return { + type: this.type, + source: this.source.toPlainObject(), + position: this.positions, + data: Array.from(this.data.entries()), + modifierKeys: Array.from(this.modifierKeys.entries()) + } + } + + static fromPlainObject(obj: KVRecord): Op { + const op = new Op + op.type = obj.type + op.source = OpSource.fromPlainObject(obj.source) + op.positions = obj.position + op.data = new Map(obj.data) + op.modifierKeys = new Set(obj.modifierKeys) + return op + } + +} + + +export interface OpResult { + cancelDrop: boolean +} + +const defaultOpResult: OpResult = { cancelDrop: false } + +export interface OpSummary { + contextTypes: readonly ContextType[] + selection: string + link: string + linkText: string + imgSrc: string +} + +const forwardOpEventName = "gdp-forward-op" + +export class OpExecutor { + state: StateManager + source: OpSource | null + startPos: Position = { x: 0, y: 0 } + endPos: Position = { x: 0, y: 0 } + config: ReadonlyConfiguration | null = null + data: Map = new Map() + titleTemplateCache: Map = new Map() + dirChain: DirectionChain = new DirectionChain() + selectedMenuId = "" + + constructor() { + this.state = new StateManager() + this.source = null + window.addEventListener(forwardOpEventName, (event: CustomEvent) => { + this.applyOp(Op.fromPlainObject(JSON.parse(event.detail))) + }) + window.addEventListener(EventType.MenuSelectedId, (e: CustomEvent) => { + this.selectedMenuId = e.detail + log.VVV("menu id: ", this.selectedMenuId) + }) + } + + async updateConfig(config: ReadonlyConfiguration) { + this.config = config + this.titleTemplateCache.clear() + this.config.actions.forEach(a => { + try { + const t = new VarSubstituteTemplate(a.prompt ? a.prompt : a.name) + log.V("new template: ", t.template) + this.titleTemplateCache.set(t.template, t) + } catch (e) { + log.E(e) + } + }) + log.VVV("new config", this.config) + } + + private get distance(): number { + return Math.hypot(this.startPos.x - this.endPos.x, this.startPos.y - this.endPos.y); + } + + public applyOp(op: Op): OpResult { + if (window.top != window.self) { + if (window.frameElement) { + window.top.dispatchEvent(new CustomEvent(forwardOpEventName, { detail: JSON.stringify(op.toPlainObject()) })) + return defaultOpResult + } + + log.VVV("detect cross origin drag operation") + return defaultOpResult + } + + log.VVV('apply op: ', op) + log.VVV('apply op, position: ', JSON.stringify(op.positions), JSON.stringify(this.data), JSON.stringify(this.dirChain)) + + + switch (op.type) { + case OpType.start: + this.reset() + this.onStart(op) + this.updateUI(op) + this.data = new Map(op.data.entries()) + return defaultOpResult + case OpType.running: { + this.onRunning(op) + this.updateUI(op) + return defaultOpResult + } + case OpType.end: + const r = this.onEnd(op) + this.updateUI(op) + return r + case OpType.reset: + this.reset() + return defaultOpResult + default: + throw new Error("unknown op type: " + op.type) + } + } + + private updateUI(op: Op) { + log.VVV("update ui:", op) + + if (!this.state.test(States.running)) { + return + } + + const g = this.source.summary() + const mode = this.currentMode() + const actions = this.filterActionConfig(g) + + if (op.type === OpType.start) { + if (this.config.common.minDistance > 0) { + indicatorProxy.show( + this.config.common.minDistance, + op.positions.page, + ) + } + + if (actions.length && (mode === OperationMode.circleMenu || mode === OperationMode.gridMenu)) { + let layout = MenuLayout.circle + if (mode === OperationMode.gridMenu) { + layout = MenuLayout.grid + } + menuProxy.show({ + position: op.positions.page, + layout: layout, + items: transformMenuItem(actions, this.config.assets), + }) + } + return + } + + if (op.type === OpType.running) { + let action: ActionConfig | null = null + + if (mode === OperationMode.circleMenu || mode === OperationMode.gridMenu) { + if (this.selectedMenuId.length > 0) { + action = this.config.actions.find(a => a.id === this.selectedMenuId) + } + } else if (actions.length > 0) { + action = actions[0] + } + + if (action) { + const template = action.prompt ? action.prompt : action.name + const tmpl = this.titleTemplateCache.get(template) + if (tmpl) { + const text = tmpl.substitute(new Map()) + promptProxy.show(text) + } else { + log.V(`missing template instance: "${prompt}"`) + promptProxy.hide() + } + } else { + promptProxy.hide() + } + + + return + } + } + + + reset() { + this.state.reset() + this.dirChain.reset() + this.data.clear() + this.source = null + this.selectedMenuId = "" + this.resetUI() + } + + private resetUI() { + if (this.config && !this.config.Enabled(Feature.retainComponent)) { + indicatorProxy.hide() + menuProxy.hide() + promptProxy.hide() + } + } + + private updateDirChain() { + // TODO: no magic number + if (this.distance < 3) { + return + } + + const mode = this.currentMode() + + if (mode != OperationMode.chain) { + const dir = angleToDirection(mode, getAngle(this.startPos, this.endPos)) + const latest = new ChainItem(dir, this.startPos, this.endPos) + this.dirChain.overwrite(latest) + return + } + + let latest = this.dirChain.pop() + let newChain: ChainItem | null = null + + if (!latest) { + const dir = angleToDirection(mode, getAngle(this.startPos, this.endPos)) + latest = new ChainItem(dir, this.startPos, this.endPos) + } + + if (Math.hypot(latest.end.x - this.endPos.x, latest.end.y - this.endPos.y) > 3) { + const nextDir = angleToDirection(mode, getAngle(latest.end, this.endPos)) + if (latest.dir == nextDir) { + latest.end = cloneDeep(this.endPos) + } else { + newChain = new ChainItem(nextDir, latest.end, this.endPos) + } + } + + this.dirChain.push(latest) + if (newChain) { + this.dirChain.push(newChain) + } + } + + private onStart(op: Op) { + + this.reset() + + this.startPos = op.positions.real + this.endPos = op.positions.real + + this.source = op.source + this.state.set(States.running) + } + + private onRunning(op: Op) { + + if (!this.state.test(States.running)) { + return + } + + this.updateDirChain() + + this.endPos = op.positions.real + + if (this.checkDistance()) { + this.state.set(States.distanceOk) + } else { + this.state.clear(States.distanceOk) + } + } + + private onEnd(op: Op): OpResult { + + if (!this.state.test(States.running)) { + log.VV("not running") + return { cancelDrop: false } + } + + if (!canDestinationAcceptDrop(op.source)) { + log.VV('event target can not accept drop') + this.state.set(States.resolved, States.skip) + return { cancelDrop: false } + } + + if (isInputArea(op.source)) { + log.VV('event target is input area') + this.state.set(States.resolved, States.skip) + return { cancelDrop: false } + } + + if (this.state.test(States.skip)) { + log.VV("ski p") + this.reset() + return { cancelDrop: false } + } + + if (this.state.test_not(States.distanceOk)) { + log.VV("out of distance") + this.reset() + return { cancelDrop: true } + } + + try { + + const g = this.source.summary() + + log.VV('before post command', { + sourceTarget: this.source, + contextTypes: g.contextTypes, + key: Array.from(op.modifierKeys)[0], + text: g.selection, + link: g.link, + image: g.imgSrc, + dt: new Map(this.data), + distance: this.distance, + labels: this.dirChain.directions, + mode: this.currentMode(), + }) + this.postCommand(g) + } catch (e) { + log.E(e) + } finally { + this.reset() + } + return { cancelDrop: true } + } + + private postCommand(g: OpSummary) { + + if (!this.config) { + log.VV("no config") + return + } + + if (g.contextTypes.length === 0) { + throw new Error("missing context types") + } + + let action: ActionConfig | null = null + const mode = this.currentMode() + if (mode === OperationMode.circleMenu || mode === OperationMode.gridMenu) { + const id = this.selectedMenuId + action = this.config.actions.find(c => c.id === id) + } else { + const actions = this.filterActionConfig(g) + if (actions.length) { + action = actions[0] + } + } + + if (!action) { + log.VVV("not found candidate action") + return + } + + log.VVV("use action:", action) + + let cmd = buildRuntimeMessage(RuntimeMessageName.execute, { + action: action.toPlainObject(), + data: { + selection: g.selection, + link: g.link, + linkText: g.linkText, + imageSource: g.imgSrc, + }, + url: location.href, + title: document.title, + modifierKey: ModifierKey.none, + startPosition: this.startPos, + endPosition: this.endPos, + }) + + log.VVV("cmd", cmd) + browser.runtime.sendMessage(cmd); + } + + + + filterActionConfig(g: OpSummary): ActionConfig[] { + if (!this.config) { + throw new Error("missing config") + } + const mode = this.currentMode() + const dirs = this.dirChain.directions + return this.config.actions + .filter((action) => { + return action.condition.modes.length === 0 + // contains any of + || action.condition.modes.includes(mode) + }) + .filter((action) => { + return action.condition.contextTypes.length === 0 + // subset + || action.condition.contextTypes.every((t) => g.contextTypes.includes(t)) + }) + .filter((action) => { + return action.condition.directions.length === 0 + // equal + || isEqual(action.condition.directions, dirs) + }) + .filter((action) => { + return action.condition.extra.length === 0 + || action.condition.extra.every((label) => g.contextTypes.includes(label)) + }) + } + + + checkDistance(): boolean { + + if (this.config.common.maxDistance > 0 && this.distance > this.config.common.maxDistance) { + return false + } + + if (this.config.common.minDistance > 0 && this.distance < this.config.common.minDistance) { + return false + } + + return true + } + + currentMode(): OperationMode { + + if (!this.config) { + throw new Error("require config") + } + + const g = this.source.summary() + log.V("D", g) + + if (!g.contextTypes.length) { + throw new Error("require context type") + } + + let contextType = g.contextTypes[0] + + switch (contextType) { + case ContextType.selection: + return this.config.common.mode.selection + case ContextType.link: + return this.config.common.mode.link + case ContextType.image: + return this.config.common.mode.image + default: + throw new Error("unreachable: " + contextType) + } + } +} + diff --git a/src/content_scripts/op_source.ts b/src/content_scripts/op_source.ts new file mode 100644 index 0000000..0bef508 --- /dev/null +++ b/src/content_scripts/op_source.ts @@ -0,0 +1,140 @@ +import { ContextType } from "../config/config" +import type { KVRecord } from "../types" +import { URLFixer } from "../utils/url" +import type { OpSummary } from "./op" + +export class OpSource { + private _isContentEditable: boolean = false + private _isDraggable: boolean = false + private _type: ContextType | null = null + private _src: string = "" + private _imgSrc: string = "" + private _link: string = "" + private _linkText: string = "" + private _text: string = "" + private _nodeName: string = "" + private _url: string = "" + + private constructor() { + + } + + toPlainObject(): KVRecord { + return JSON.parse(JSON.stringify(this)) + } + + static fromPlainObject(obj: KVRecord): OpSource { + const os = new OpSource() + Object.assign(os, obj) + return os + } + + static fromNode(target: Node): OpSource { + const os = new OpSource() + const win = target.ownerDocument.defaultView + + if (target instanceof win.HTMLAnchorElement) { + os._type = ContextType.link + os._link = new URL(target.href).toString() + os._linkText = target.textContent + } else if (target instanceof win.HTMLImageElement) { + os._type = ContextType.image + os._src = target.src + os._imgSrc = os._src + os._text = target.title + } else if (win.getSelection().toString().length > 0) { + os._type = ContextType.selection + os._text = win.getSelection().toString() + } else if (target instanceof win.Text) { + os._type = ContextType.selection + os._text = target.textContent + } else { + os._type = null + } + + if (target instanceof win.Node) { + os._nodeName = target.nodeName + } + + if (target instanceof HTMLElement) { + os._isContentEditable = target.isContentEditable + os._isDraggable = target.draggable + const img = target.querySelector("img") + if (img) { + os._imgSrc = img.src + } + } + + if (os.type === ContextType.selection) { + const url = new URLFixer().fix(os.text) + if (url) { + os._link = url.toString() + os._linkText = os.text + os._type = ContextType.link + } + } + + return os + } + + get text(): string { + return this._text + } + + get src(): string { + return this._src + } + + get imgSrc(): string { + return this._imgSrc + } + + get link(): string { + return this._link + } + + get linkText(): string { + return this._linkText + } + + get targetNodeName(): string { + return this._nodeName + } + + get type(): ContextType | null { + return this._type + } + + get isContentEditable(): boolean { + return this._isContentEditable + } + + get isDraggable(): boolean { + return this._isDraggable + } + + summary(): OpSummary { + + // TODO: cache types variable + let types: ContextType[] = [] + + if (this.type == ContextType.selection) { + types.push(ContextType.selection) + } else if (this.type == ContextType.link) { + types.push(ContextType.link) + if (this.imgSrc.length > 0) { + types.push(ContextType.image) + } + } else if (this.type == ContextType.image) { + types.push(ContextType.image) + } + + return { + contextTypes: types, + selection: this.text, + link: this.link, + imgSrc: this.imgSrc, + linkText: this.linkText, + } + } +} diff --git a/src/content_scripts/script.ts b/src/content_scripts/script.ts index 84894c1..d3473f1 100644 --- a/src/content_scripts/script.ts +++ b/src/content_scripts/script.ts @@ -13,7 +13,7 @@ export class ScriptWrapper { do() { const text = ` { - const selection = ${JSON.stringify(this.args.selection)}; + const selection = ${JSON.stringify(this.args.data)}; !(function() { ${this.args.text} }).apply(selection) diff --git a/src/content_scripts/state_man.ts b/src/content_scripts/state_man.ts index 1552867..349166a 100644 --- a/src/content_scripts/state_man.ts +++ b/src/content_scripts/state_man.ts @@ -3,12 +3,11 @@ export enum States { initial = 0, running = 1 << 1, resolved = 1 << 3, - exceedDistance = 1 << 4, - interfere = 1 << 9, + distanceOk = 1 << 4, skip = 1 << 10, } -export class StateMan { +export class StateManager { private cur: States constructor() { @@ -70,9 +69,6 @@ export class StateMan { if ((s & States.running) !== 0) { a.push('running') } - if ((s & States.interfere) !== 0) { - a.push('interfere') - } if ((s & States.resolved) !== 0) { a.push('resolved') } @@ -80,8 +76,8 @@ export class StateMan { a.push('skip') } - if ((s & States.exceedDistance) !== 0) { - a.push("badDistance") + if ((s & States.distanceOk) !== 0) { + a.push("distanceOk") } return a.join("|") } diff --git a/src/content_scripts/utils.ts b/src/content_scripts/utils.ts index e516249..af2a506 100644 --- a/src/content_scripts/utils.ts +++ b/src/content_scripts/utils.ts @@ -1,6 +1,6 @@ -import { ActionConfig, Asset, AssetType, DirectionLabel, OperationMode } from "../config/config"; +import { ActionConfig, Asset, AssetType, Configuration, Direction, OperationMode } from "../config/config"; import type { Position } from "../types"; -import type { MenuItem } from "../components/message"; +import type { MenuItem } from "../components/types"; export function getAngle(a: Position, b: Position) { @@ -18,70 +18,93 @@ export function onDocumentLoaded(cb: Function) { export type RangeMapping = { range: [number, number], - label: DirectionLabel + label: Direction } -export const directionLabelMapping: Record = { +export const directionMapping: Record = { any: [ - { range: [0, 360], label: DirectionLabel.any, } + { range: [0, 360], label: Direction.any, } ], normal: [ - { range: [45, 135], label: DirectionLabel.up, }, - { range: [135, 225], label: DirectionLabel.left, }, - { range: [225, 315], label: DirectionLabel.down, }, - { range: [315, 360], label: DirectionLabel.right, }, - { range: [0, 45], label: DirectionLabel.right, } + { range: [45, 135], label: Direction.up, }, + { range: [135, 225], label: Direction.left, }, + { range: [225, 315], label: Direction.down, }, + { range: [315, 360], label: Direction.right, }, + { range: [0, 45], label: Direction.right, } ], upDown: [ - { range: [0, 180], label: DirectionLabel.up, }, - { range: [180, 360], label: DirectionLabel.down, }, + { range: [0, 180], label: Direction.up, }, + { range: [180, 360], label: Direction.down, }, ], leftRight: [ - { range: [90, 270], label: DirectionLabel.left, }, - { range: [270, 360], label: DirectionLabel.right, }, - { range: [0, 90], label: DirectionLabel.right, } + { range: [90, 270], label: Direction.left, }, + { range: [270, 360], label: Direction.right, }, + { range: [0, 90], label: Direction.right, } ], upperLeftLowerRight: [ - { range: [45, 225], label: DirectionLabel.upperLeft, }, - { range: [225, 360], label: DirectionLabel.lowerRight, }, - { range: [0, 45], label: DirectionLabel.upperLeft, }, + { range: [45, 225], label: Direction.upperLeft, }, + { range: [225, 360], label: Direction.lowerRight, }, + { range: [0, 45], label: Direction.upperLeft, }, ], upperRightLowerLeft: [ - { range: [135, 275], label: DirectionLabel.lowerLeft, }, - { range: [275, 360], label: DirectionLabel.upperRight, }, - { range: [0, 135], label: DirectionLabel.upperRight, }, + { range: [135, 275], label: Direction.lowerLeft, }, + { range: [275, 360], label: Direction.upperRight, }, + { range: [0, 135], label: Direction.upperRight, }, ], diagonal: [ - { range: [0, 90], label: DirectionLabel.upperRight, }, - { range: [90, 180], label: DirectionLabel.upperLeft, }, - { range: [180, 270], label: DirectionLabel.lowerLeft, }, - { range: [270, 360], label: DirectionLabel.lowerRight, },], + { range: [0, 90], label: Direction.upperRight, }, + { range: [90, 180], label: Direction.upperLeft, }, + { range: [180, 270], label: Direction.lowerLeft, }, + { range: [270, 360], label: Direction.lowerRight, }, + ], full: [ - { range: [22.5, 22.5 * 3], label: DirectionLabel.upperRight, }, - { range: [22.5 * 3, 22.5 * 5], label: DirectionLabel.up, }, - { range: [22.5 * 5, 22.5 * 7], label: DirectionLabel.upperLeft, }, - { range: [22.5 * 7, 22.5 * 9], label: DirectionLabel.left, }, - { range: [22.5 * 9, 22.5 * 11], label: DirectionLabel.lowerLeft, }, - { range: [22.5 * 11, 22.5 * 13], label: DirectionLabel.down, }, - { range: [22.5 * 13, 22.5 * 15], label: DirectionLabel.lowerRight, }, - { range: [22.5 * 15, 360], label: DirectionLabel.right, }, - { range: [0, 22.5], label: DirectionLabel.right, } + { range: [22.5, 22.5 * 3], label: Direction.upperRight, }, + { range: [22.5 * 3, 22.5 * 5], label: Direction.up, }, + { range: [22.5 * 5, 22.5 * 7], label: Direction.upperLeft, }, + { range: [22.5 * 7, 22.5 * 9], label: Direction.left, }, + { range: [22.5 * 9, 22.5 * 11], label: Direction.lowerLeft, }, + { range: [22.5 * 11, 22.5 * 13], label: Direction.down, }, + { range: [22.5 * 13, 22.5 * 15], label: Direction.lowerRight, }, + { range: [22.5 * 15, 360], label: Direction.right, }, + { range: [0, 22.5], label: Direction.right, } ], chain: [], - circle: [], - grid: [] + circleMenu: [], + gridMenu: [], + contextMenu: [], + leftRightUpDown: [] }; -directionLabelMapping.chain = directionLabelMapping.full +directionMapping.chain = directionMapping.normal + + +export function angleToDirection(mode: OperationMode, angle: number): Direction | null { + let rangeMapping: RangeMapping[] + if (directionMapping[mode]) { + rangeMapping = directionMapping[mode] + } + + if (!rangeMapping) { + return null + } + + for (const obj of rangeMapping) { + if (obj.range[0] <= angle && angle < obj.range[1]) { + return obj.label; + } + } + + return null +} export function transformMenuItem(actions: readonly ActionConfig[], assets: readonly Asset[]): MenuItem[] { return actions.map(c => { - const asset = assets.find(a => a.id === c.style.menuIconId) + const asset = assets.find(a => a.id === c.iconAssetId) return { id: c.id, - title: c.title, - htmlContent: asset && asset.type === AssetType.html ? asset.data : "" + title: c.name, + html: asset && asset.type === AssetType.html ? asset.data : "" } }) } \ No newline at end of file diff --git a/src/localization/helper.ts b/src/localization/helper.ts new file mode 100644 index 0000000..a24ab4d --- /dev/null +++ b/src/localization/helper.ts @@ -0,0 +1,20 @@ +import browser from 'webextension-polyfill'; +import { Direction } from '../config/config'; + +export interface LocaleMessage { + [key: string]: string +} + + +export const defaultLocaleMessage = new Proxy({}, { + get(_target, p) { + if (typeof p === 'string') { + const m = browser.i18n.getMessage(p) + if (!m) { + return p + } + return m + } + return p + } +}) as LocaleMessage diff --git a/src/manifest_chromium.json b/src/manifest_chromium.json index d53efdf..fa63c3f 100644 --- a/src/manifest_chromium.json +++ b/src/manifest_chromium.json @@ -1,7 +1,7 @@ { - "description": "A good drag and drop tool", "manifest_version": 3, - "name": "Glitter Drag Pro", + "name": "__MSG_extensionName__", + "description": "__MSG_extensionDescription__", "version": "2.1.0.0", "version_name": "2.1.0.0 alpha", "homepage_url": "https://github.com/harytfw/GlitterDrag", @@ -16,7 +16,8 @@ "clipboardWrite", "downloads", "search", - "scripting" + "scripting", + "contextMenus" ], "host_permissions": [ "*://*/*" @@ -41,12 +42,6 @@ "browser_style": true, "open_in_tab": true }, - "browser_specific_settings": { - "gecko": { - "id": "glitterdrag@harytfw", - "strict_min_version": "63.0" - } - }, "web_accessible_resources": [ { "resources": [ @@ -56,5 +51,6 @@ "*://*/*" ] } - ] + ], + "default_locale": "en" } \ No newline at end of file diff --git a/src/manifest_firefox.json b/src/manifest_firefox.json index 6a99611..f79b0bb 100644 --- a/src/manifest_firefox.json +++ b/src/manifest_firefox.json @@ -1,7 +1,7 @@ { - "description": "A good drag and drop tool", "manifest_version": 2, - "name": "Glitter Drag Pro", + "name": "__MSG_extensionName__", + "description": "__MSG_extensionDescription__", "version": "2.1.0.0", "homepage_url": "https://github.com/harytfw/GlitterDrag", "icons": { @@ -12,11 +12,16 @@ "activeTab", "storage", "tabs", - "clipboardWrite", "downloads", "search", "scripting", - "" + "", + "contextualIdentities", + "cookies", + "contextMenus" + ], + "optional_permissions": [ + "clipboardWrite" ], "background": { "scripts": [ @@ -43,10 +48,11 @@ "browser_specific_settings": { "gecko": { "id": "glitterdrag@harytfw", - "strict_min_version": "63.0" + "strict_min_version": "106.0" } }, "web_accessible_resources": [ "components/main.js" - ] + ], + "default_locale": "en" } \ No newline at end of file diff --git a/src/message/message.ts b/src/message/message.ts index 15402f8..53d6449 100644 --- a/src/message/message.ts +++ b/src/message/message.ts @@ -1,19 +1,14 @@ -import { CommandRequest, Script } from "../config/config" +import { type ContextData } from "../config/config" import type { ModifierKey, Position, KVRecord } from "../types" -export interface ExecuteArgs { +export type ExecuteArgs = { action: KVRecord, - - text: string - image: string - link: string - + data: ContextData, url: string title: string modifierKey: ModifierKey - startPosition: Position endPosition: Position } @@ -32,39 +27,53 @@ export interface FetchURLReply { data: string } -export interface openTabArgs { - url: string, -} - export interface ScriptArgs { text: string - selection: { + data: { text: string, - image: string + imageSource: string + linkText: string, link: string primary: string } } -export interface RuntimeMessageArgs { +export enum RuntimeMessageName { + execute = "execute", + contextScriptLoaded = "contentScriptLoaded", + ping = "ping", + fetchURL = "fetchURL", + closeCurrentTab = "closeCurrentTab", + copy = "copy", + executeScript = "doScript" +} + +export interface RuntimeMessageArgsMap { "execute": ExecuteArgs - "contentScriptLoaded": any - "ping": any "fetchURL": FetchURLArgs "closeCurrentTab": null + "contentScriptLoaded": null + "ping": null "copy": string "doScript": ScriptArgs + } -export interface RuntimeMessage { +export type RuntimeMessageArg = + K extends RuntimeMessageName.execute ? ExecuteArgs + : K extends RuntimeMessageName.executeScript ? ScriptArgs + : K extends RuntimeMessageName.fetchURL ? FetchURLArgs + : K extends RuntimeMessageName.copy ? string + : null + +export interface RuntimeMessage { cmd: K, - args: RuntimeMessageArgs[K] + args: RuntimeMessageArg } - -export function buildRuntimeMessage(cmd: K, args: RuntimeMessageArgs[K]): RuntimeMessage { +export function buildRuntimeMessage(cmd: K, args: RuntimeMessageArg): RuntimeMessage { return { cmd, args } -} \ No newline at end of file +} diff --git a/src/options/actions.svelte b/src/options/actions.svelte new file mode 100644 index 0000000..d6acaee --- /dev/null +++ b/src/options/actions.svelte @@ -0,0 +1,1172 @@ + + + + +
+
+
{}} + on:change={onOperationModeChange} + > +
+ {locale.operationMode} +
+ + + + + + +
+
+
+
{}}> +
+ + {locale.manageActions} + +
+ + + +
+
+
+ +
{}} + > +
+ {locale.filterActions} +
+ + + + + + + + + +
+
+
+
+
+
+
+ {#each transformedActions as action} +
+
+ + {action.name} +

+ + +

+

+ + 0 + ? locale[ + "contextType" + + titleCase( + action.condition.contextTypes[0] + ) + ] + : ""} + /> +

+

+ + +

+
+ + + +
+
+
+ {/each} +
+ +
+

+ {locale.add} +

+

+ + +

+

+ + +

+

+ + +

+

+ + +

+ +
+
+ +
+

+ + +

+

+ +

+
+ {#each contextTypeOptions as t} + + {/each} +
+

+ + +

+

+ + +

+

+ + +

+ + {#if editAction.condition.modes.includes(OperationMode.normal)} +

+ +

+
+ {#each directionOptions as m} + + {/each} +
+ {:else if editAction.condition.modes.includes(OperationMode.chain)} + +

+ +

+
+
+ ≡ +
+
+

+ + {directionEditorEditFlag + ? directionEditorText + : "[" + + editAction.condition.directions + .map( + (l) => locale["direction" + titleCase(l)] + ) + .join(", ") + + "]"} + +

+ {/if} + + {#if editAction.condition.contextTypes.includes(ContextType.link)} +

+ +

+
+ {#each contextDataTypeOptionsForLink as t} + + {/each} +
+ {/if} + {#if [CommandKind.request, CommandKind.open].includes(editAction.command)} +

+ +

+

+ + +

+ {/if} + {#if editAction.command === CommandKind.request} +

+ + +

+ {/if} + {#if editAction.command === CommandKind.script} +

+ + +

+ {/if} + {#if [OperationMode.gridMenu, OperationMode.circleMenu].some( (target) => editAction.condition.modes.includes(target) )} +

+ + +

+ {/if} + {#if editAction.command === CommandKind.download} +

+ + +

+ +

+ +

+ {/if} + + {#if isFirefox()} +

+ + +

+ {/if} + +
+
+ +

+ +

+
    +
+ +
diff --git a/src/options/assets.svelte b/src/options/assets.svelte new file mode 100644 index 0000000..6fcc1e9 --- /dev/null +++ b/src/options/assets.svelte @@ -0,0 +1,294 @@ + + + + +
+
+ + + + + + + + + + {#each transformed as asset, i} + + + + + {/each} + +
{locale.name}{locale.operation}
{asset.name} + + +
+
+
+ +
+

+ {locale.edit} +

+

+ + +

+

+ + +

+

Preview

+
+

+ +