summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortoasted-nutbread <toasted-nutbread@users.noreply.github.com>2024-02-08 06:52:06 -0500
committerGitHub <noreply@github.com>2024-02-08 11:52:06 +0000
commitd4381831209dfbbbddd6d238c68461c9601573e2 (patch)
tree87839d80f838464ff92ebc7fa652029b9329cc96
parent725a90dd6570044a3df6631051aaab8b026ca6c2 (diff)
Update eslint (#638)
* Add json test * Update vscode settings to better handle json * Collapse eslint rules for easier readability * Reorganize * Update no-multi-spaces rule for JSON * Rules updates * Switch to @stylistic/eslint-plugin * Update deprecated stylistic rules * Group stylistic rules * Simplify rules * Move eslint env overrides to end of file * Add test * Move promiseAnimationFrame to separate file * Remove unneeded eslint disable * Remove unneeded
-rw-r--r--.eslintrc.json710
-rw-r--r--.vscode/settings.json6
-rw-r--r--ext/js/app/frontend.js10
-rw-r--r--ext/js/app/popup-factory.js4
-rw-r--r--ext/js/application.js4
-rw-r--r--ext/js/background/backend.js4
-rw-r--r--ext/js/background/offscreen.js5
-rw-r--r--ext/js/core/promise-animation-frame.js62
-rw-r--r--ext/js/core/utilities.js45
-rw-r--r--ext/js/data/options-util.js6
-rw-r--r--ext/js/display/display-anki.js4
-rw-r--r--ext/js/display/display-audio.js4
-rw-r--r--ext/js/display/display.js4
-rw-r--r--ext/js/pages/settings/keyboard-shortcuts-controller.js4
-rw-r--r--ext/js/pages/settings/popup-preview-frame.js4
-rw-r--r--ext/js/pages/settings/profile-conditions-ui.js4
-rw-r--r--ext/js/templates/sandbox/anki-template-renderer.js4
-rw-r--r--package-lock.json529
-rw-r--r--package.json3
-rw-r--r--playwright.config.js2
-rw-r--r--test/cache-map.test.js4
-rw-r--r--test/data/dictionaries/valid-dictionary1/term_bank_1.json8
-rw-r--r--test/eslint-config.test.js172
-rw-r--r--test/hotkey-util.test.js8
-rw-r--r--test/json-schema.test.js8
-rw-r--r--test/language-transformer.test.js4
-rw-r--r--test/options-util.test.js4
-rw-r--r--test/playwright/playwright-util.js3
-rw-r--r--test/playwright/visual.spec.js4
-rw-r--r--test/profile-conditions-util.test.js4
-rw-r--r--types/ext/dictionary-database.d.ts4
31 files changed, 1000 insertions, 641 deletions
diff --git a/.eslintrc.json b/.eslintrc.json
index 3557f83a..440fe53b 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -33,175 +33,26 @@
"jsonc",
"unused-imports",
"@typescript-eslint",
- "@stylistic/ts"
+ "@stylistic"
],
"ignorePatterns": [
"/ext/lib/",
"/dev/lib/handlebars/"
],
"rules": {
- "arrow-parens": [
- "error",
- "always"
- ],
- "comma-dangle": [
- "error",
- "never"
- ],
- "curly": [
- "error",
- "all"
- ],
+ "curly": ["error", "all"],
"dot-notation": "error",
"eqeqeq": "error",
- "func-names": [
- "error",
- "always"
- ],
+ "func-names": ["error", "always"],
"guard-for-in": "error",
- "new-parens": "error",
"no-case-declarations": "error",
"no-const-assign": "error",
"no-constant-condition": "off",
- "no-multiple-empty-lines": [
- "error",
- {
- "max": 2
- }
- ],
"no-global-assign": "error",
+ "no-implicit-globals": "error",
"no-new": "error",
"no-param-reassign": "off",
"no-prototype-builtins": "error",
- "no-shadow": [
- "off",
- {
- "builtinGlobals": false
- }
- ],
- "no-undef": "error",
- "no-undefined": "error",
- "no-underscore-dangle": [
- "error",
- {
- "allowAfterThis": true,
- "allowAfterSuper": false,
- "allowAfterThisConstructor": false
- }
- ],
- "no-unexpected-multiline": "error",
- "no-unneeded-ternary": "error",
- "no-unused-vars": [
- "error",
- {
- "vars": "local",
- "args": "after-used",
- "argsIgnorePattern": "^_",
- "caughtErrors": "none"
- }
- ],
- "no-unused-expressions": "error",
- "no-var": "error",
- "prefer-const": [
- "error",
- {
- "destructuring": "all"
- }
- ],
- "quote-props": [
- "error",
- "consistent"
- ],
- "quotes": [
- "error",
- "single",
- "avoid-escape"
- ],
- "require-atomic-updates": "off",
- "semi": "error",
- "wrap-iife": [
- "error",
- "inside"
- ],
- "brace-style": [
- "error",
- "1tbs",
- {
- "allowSingleLine": true
- }
- ],
- "indent": [
- "error",
- 4,
- {
- "SwitchCase": 1,
- "MemberExpression": 1,
- "flatTernaryExpressions": true,
- "ignoredNodes": [
- "ConditionalExpression"
- ]
- }
- ],
- "object-curly-newline": "error",
- "padded-blocks": [
- "error",
- "never"
- ],
- "array-bracket-spacing": [
- "error",
- "never"
- ],
- "arrow-spacing": [
- "error",
- {
- "before": true,
- "after": true
- }
- ],
- "block-spacing": [
- "error",
- "always"
- ],
- "comma-spacing": [
- "error",
- {
- "before": false,
- "after": true
- }
- ],
- "computed-property-spacing": [
- "error",
- "never"
- ],
- "func-call-spacing": [
- "error",
- "never"
- ],
- "function-paren-newline": [
- "error",
- "multiline-arguments"
- ],
- "generator-star-spacing": [
- "error",
- "before"
- ],
- "key-spacing": [
- "error",
- {
- "beforeColon": false,
- "afterColon": true,
- "mode": "strict"
- }
- ],
- "keyword-spacing": [
- "error",
- {
- "before": true,
- "after": true
- }
- ],
- "no-implicit-globals": "error",
- "no-multi-spaces": "error",
"no-restricted-syntax": [
"error",
{
@@ -213,92 +64,76 @@
"selector": "MemberExpression[property.name=json]"
}
],
- "no-trailing-spaces": "error",
- "no-whitespace-before-property": "error",
- "object-curly-spacing": [
- "error",
- "never"
- ],
- "rest-spread-spacing": [
- "error",
- "never"
- ],
- "semi-spacing": [
- "error",
- {
- "before": false,
- "after": true
- }
- ],
- "space-before-blocks": [
- "error",
- "always"
- ],
- "space-before-function-paren": [
- "error",
- {
- "anonymous": "never",
- "named": "never",
- "asyncArrow": "always"
- }
- ],
- "space-in-parens": [
- "error",
- "never"
- ],
- "space-infix-ops": [
- "error",
- {
- "int32Hint": false
- }
- ],
- "space-unary-ops": "error",
- "spaced-comment": [
- "error",
- "always"
- ],
- "switch-colon-spacing": [
- "error",
- {
- "after": true,
- "before": false
- }
- ],
- "template-curly-spacing": [
- "error",
- "never"
- ],
- "template-tag-spacing": [
- "error",
- "never"
- ],
+ "no-shadow": ["off", {"builtinGlobals": false}],
+ "no-undef": "error",
+ "no-undefined": "error",
+ "no-underscore-dangle": ["error", {"allowAfterThis": true, "allowAfterSuper": false, "allowAfterThisConstructor": false}],
+ "no-unexpected-multiline": "error",
+ "no-unneeded-ternary": "error",
+ "no-unused-vars": ["error", {"vars": "local", "args": "after-used", "argsIgnorePattern": "^_", "caughtErrors": "none"}],
+ "no-unused-expressions": "error",
+ "no-var": "error",
+ "prefer-const": ["error", {"destructuring": "all"}],
+ "require-atomic-updates": "off",
+
+ "@stylistic/array-bracket-spacing": ["error", "never"],
+ "@stylistic/arrow-parens": ["error", "always"],
+ "@stylistic/arrow-spacing": ["error", {"before": true, "after": true}],
+ "@stylistic/block-spacing": ["error", "always"],
+ "@stylistic/brace-style": ["error", "1tbs", {"allowSingleLine": true}],
+ "@stylistic/comma-dangle": ["error", "never"],
+ "@stylistic/comma-spacing": ["error", {"before": false, "after": true}],
+ "@stylistic/computed-property-spacing": ["error", "never"],
+ "@stylistic/func-call-spacing": ["error", "never"],
+ "@stylistic/function-paren-newline": ["error", "multiline-arguments"],
+ "@stylistic/generator-star-spacing": ["error", "before"],
+ "@stylistic/indent": ["error", 4, {"SwitchCase": 1, "MemberExpression": 1, "flatTernaryExpressions": true, "ignoredNodes": ["ConditionalExpression"]}],
+ "@stylistic/key-spacing": ["error", {"beforeColon": false, "afterColon": true, "mode": "strict"}],
+ "@stylistic/keyword-spacing": ["error", {"before": true, "after": true}],
+ "@stylistic/new-parens": "error",
+ "@stylistic/no-multi-spaces": "error",
+ "@stylistic/no-multiple-empty-lines": ["error", {"max": 2}],
+ "@stylistic/no-trailing-spaces": "error",
+ "@stylistic/no-whitespace-before-property": "error",
+ "@stylistic/object-curly-newline": "error",
+ "@stylistic/object-curly-spacing": ["error", "never"],
+ "@stylistic/padded-blocks": ["error", "never"],
+ "@stylistic/quote-props": ["error", "consistent"],
+ "@stylistic/quotes": ["error", "single", "avoid-escape"],
+ "@stylistic/rest-spread-spacing": ["error", "never"],
+ "@stylistic/semi": "error",
+ "@stylistic/semi-spacing": ["error", {"before": false, "after": true}],
+ "@stylistic/space-before-blocks": ["error", "always"],
+ "@stylistic/space-before-function-paren": ["error", {"anonymous": "never", "named": "never", "asyncArrow": "always"}],
+ "@stylistic/space-in-parens": ["error", "never"],
+ "@stylistic/space-infix-ops": ["error", {"int32Hint": false}],
+ "@stylistic/space-unary-ops": "error",
+ "@stylistic/spaced-comment": ["error", "always"],
+ "@stylistic/switch-colon-spacing": ["error", {"after": true, "before": false}],
+ "@stylistic/template-curly-spacing": ["error", "never"],
+ "@stylistic/template-tag-spacing": ["error", "never"],
+ "@stylistic/wrap-iife": ["error", "inside"],
+
"no-unsanitized/method": "error",
"no-unsanitized/property": "error",
+
"jsdoc/check-access": "error",
"jsdoc/check-alignment": "error",
- "jsdoc/check-line-alignment": [
- "error",
- "never",
- {
- "wrapIndent": " "
- }
- ],
+ "jsdoc/check-line-alignment": ["error", "never", {"wrapIndent": " "}],
"jsdoc/check-param-names": "error",
"jsdoc/check-property-names": "error",
"jsdoc/check-tag-names": "error",
+ "jsdoc/empty-tags": "error",
"jsdoc/check-types": "error",
"jsdoc/check-values": "error",
- "jsdoc/empty-tags": "error",
"jsdoc/implements-on-classes": "error",
"jsdoc/multiline-blocks": "error",
"jsdoc/no-bad-blocks": "error",
"jsdoc/no-multi-asterisks": "error",
"jsdoc/no-undefined-types": "error",
"jsdoc/require-asterisk-prefix": "error",
- "jsdoc/require-hyphen-before-param-description": [
- "error",
- "never"
- ],
+ "jsdoc/require-description": "off",
+ "jsdoc/require-hyphen-before-param-description": ["error", "never"],
"jsdoc/require-jsdoc": [
"error",
{
@@ -317,7 +152,6 @@
"checkSetters": "no-getter"
}
],
- "jsdoc/require-description": "off",
"jsdoc/require-param": "error",
"jsdoc/require-param-description": "off",
"jsdoc/require-param-name": "error",
@@ -335,77 +169,27 @@
"jsdoc/require-yields-check": "error",
"jsdoc/tag-lines": ["error", "never", {"startLines": 0}],
"jsdoc/valid-types": "error",
- "jsonc/indent": [
- "error",
- 4
- ],
- "jsonc/array-bracket-newline": [
- "error",
- "consistent"
- ],
- "jsonc/array-bracket-spacing": [
- "error",
- "never"
- ],
- "jsonc/array-element-newline": [
- "error",
- "consistent"
- ],
- "jsonc/comma-style": [
- "error",
- "last"
- ],
- "jsonc/key-spacing": [
- "error",
- {
- "beforeColon": false,
- "afterColon": true,
- "mode": "strict"
- }
- ],
+
+ "jsonc/indent": ["error", 4],
+ "jsonc/array-bracket-newline": ["error", "consistent"],
+ "jsonc/array-bracket-spacing": ["error", "never"],
+ "jsonc/array-element-newline": ["error", "consistent"],
+ "jsonc/comma-style": ["error", "last"],
+ "jsonc/key-spacing": ["error", {"beforeColon": false, "afterColon": true, "mode": "strict"}],
"jsonc/no-octal-escape": "error",
- "jsonc/object-curly-newline": [
- "error",
- {
- "consistent": true
- }
- ],
- "jsonc/object-curly-spacing": [
- "error",
- "never"
- ],
- "jsonc/object-property-newline": [
- "error",
- {
- "allowAllPropertiesOnSameLine": true
- }
- ],
+ "jsonc/object-curly-newline": ["error", {"consistent": true}],
+ "jsonc/object-curly-spacing": ["error", "never"],
+ "jsonc/object-property-newline": ["error", {"allowAllPropertiesOnSameLine": true}],
+
"eslint-comments/no-unused-disable": "error",
- "@typescript-eslint/ban-ts-comment": [
- "error",
- {
- "ts-expect-error": {
- "descriptionFormat": "^ - .+$"
- }
- }
- ],
- "@typescript-eslint/ban-types": [
- "error",
- {
- "types": {
- "object": true
- },
- "extendDefaults": true
- }
- ],
+
+ "unused-imports/no-unused-imports": "error",
+
+ "@typescript-eslint/ban-ts-comment": ["error", {"ts-expect-error": {"descriptionFormat": "^ - .+$"}}],
+ "@typescript-eslint/ban-types": ["error", {"types": {"object": true}, "extendDefaults": true}],
"@typescript-eslint/consistent-type-exports": "off",
"@typescript-eslint/no-explicit-any": "error",
- "@typescript-eslint/no-shadow": [
- "error",
- {
- "builtinGlobals": false
- }
- ],
+ "@typescript-eslint/no-shadow": ["error", {"builtinGlobals": false}],
"@typescript-eslint/no-this-alias": "error",
"@typescript-eslint/no-unused-vars": "off",
"@typescript-eslint/no-var-requires": "off"
@@ -416,47 +200,13 @@
"*.ts"
],
"rules": {
- "no-multiple-empty-lines": [
- "error",
- {
- "max": 1,
- "maxEOF": 0
- }
- ],
"no-undef": "off",
- "unused-imports/no-unused-imports": "error",
- "@typescript-eslint/no-unused-vars": [
- "error",
- {
- "vars": "local",
- "args": "after-used",
- "argsIgnorePattern": "^_",
- "caughtErrors": "none"
- }
- ],
- "comma-dangle": "off",
- "@typescript-eslint/comma-dangle": [
- "error",
- {
- "arrays": "always-multiline",
- "objects": "always-multiline",
- "imports": "always-multiline",
- "exports": "always-multiline",
- "functions": "always-multiline",
- "enums": "always-multiline",
- "generics": "always-multiline",
- "tuples": "always-multiline"
- }
- ],
- "@stylistic/ts/block-spacing": "off",
- "@stylistic/ts/brace-style": [
- "error",
- "1tbs",
- {
- "allowSingleLine": true
- }
- ],
- "@stylistic/ts/comma-dangle": [
+
+ "@typescript-eslint/no-unused-vars": ["error", {"vars": "local", "args": "after-used", "argsIgnorePattern": "^_", "caughtErrors": "none"}],
+
+ "@stylistic/block-spacing": "off",
+ "@stylistic/brace-style": ["error", "1tbs", {"allowSingleLine": true}],
+ "@stylistic/comma-dangle": [
"error",
{
"arrays": "always-multiline",
@@ -469,94 +219,46 @@
"tuples": "always-multiline"
}
],
- "@stylistic/ts/comma-spacing": [
- "error",
- {
- "before": false,
- "after": true
- }
- ],
- "@stylistic/ts/function-call-spacing": [
- "error",
- "never"
- ],
- "@stylistic/ts/indent": [
- "error",
- 4
- ],
- "@stylistic/ts/key-spacing": [
- "error",
- {
- "beforeColon": false,
- "afterColon": true,
- "mode": "strict"
- }
- ],
- "@stylistic/ts/keyword-spacing": [
+ "@stylistic/comma-spacing": ["error", {"before": false, "after": true}],
+ "@stylistic/function-call-spacing": ["error", "never"],
+ "@stylistic/indent": ["error", 4],
+ "@stylistic/key-spacing": ["error", {"beforeColon": false, "afterColon": true, "mode": "strict"}],
+ "@stylistic/keyword-spacing": ["error", {"before": true, "after": true}],
+ "@stylistic/lines-around-comment": "off",
+ "@stylistic/lines-between-class-members": ["error", "always"],
+ "@stylistic/member-delimiter-style": [
"error",
{
- "before": true,
- "after": true
- }
- ],
- "@stylistic/ts/lines-around-comment": "off",
- "@stylistic/ts/lines-between-class-members": [
- "error",
- "always"
- ],
- "@stylistic/ts/member-delimiter-style": [
- "error",
- {
- "multiline": {
- "delimiter": "semi",
- "requireLast": true
- },
- "singleline": {
- "delimiter": "comma",
- "requireLast": false
- },
+ "multiline": {"delimiter": "semi", "requireLast": true},
+ "singleline": {"delimiter": "comma", "requireLast": false},
"multilineDetection": "brackets"
}
],
- "@stylistic/ts/no-extra-parens": [
- "error",
- "all"
- ],
- "@stylistic/ts/no-extra-semi": "error",
- "@stylistic/ts/object-curly-spacing": [
- "error",
- "never"
- ],
- "@stylistic/ts/padding-line-between-statements": "off",
- "@stylistic/ts/quotes": [
- "error",
- "single",
- "avoid-escape"
- ],
- "@stylistic/ts/semi": "error",
- "@stylistic/ts/space-before-blocks": [
- "error",
- "always"
- ],
- "@stylistic/ts/space-before-function-paren": [
- "error",
- {
- "anonymous": "never",
- "named": "never",
- "asyncArrow": "always"
- }
- ],
- "@stylistic/ts/space-infix-ops": "error",
- "@stylistic/ts/type-annotation-spacing": "error"
+ "@stylistic/no-multiple-empty-lines": ["error", {"max": 1, "maxEOF": 0}],
+ "@stylistic/no-extra-parens": ["error", "all"],
+ "@stylistic/no-extra-semi": "error",
+ "@stylistic/object-curly-spacing": ["error", "never"],
+ "@stylistic/padding-line-between-statements": "off",
+ "@stylistic/quotes": ["error", "single", "avoid-escape"],
+ "@stylistic/semi": "error",
+ "@stylistic/space-before-blocks": ["error", "always"],
+ "@stylistic/space-before-function-paren": ["error", {"anonymous": "never", "named": "never", "asyncArrow": "always"}],
+ "@stylistic/space-infix-ops": "error",
+ "@stylistic/type-annotation-spacing": "error"
}
},
{
"files": [
"*.json"
],
- "parser": "jsonc-eslint-parser",
+ "parser": "jsonc-eslint-parser"
+ },
+ {
+ "files": [
+ "ext/data/schemas/options-schema.json"
+ ],
"rules": {
- "no-multi-spaces": "off"
+ "@stylistic/no-multi-spaces": "off"
}
},
{
@@ -567,10 +269,7 @@
"test/data/translator-test-results.json"
],
"rules": {
- "jsonc/indent": [
- "error",
- 2
- ]
+ "jsonc/indent": ["error", 2]
}
},
{
@@ -579,12 +278,8 @@
"test/data/dictionaries/valid-dictionary1/term_bank_2.json"
],
"rules": {
- "jsonc/array-element-newline": [
- "off"
- ],
- "jsonc/object-property-newline": [
- "off"
- ]
+ "jsonc/array-element-newline": "off",
+ "jsonc/object-property-newline": "off"
}
},
{
@@ -612,20 +307,12 @@
},
{
"files": [
- "ext/js/core.js",
- "ext/js/core/extension-error.js",
- "ext/js/**/sandbox/**/*.js",
- "ext/js/language/ja/japanese.js",
- "ext/js/language/ja/japanese-wanakana.js"
- ],
- "env": {
- "webextensions": false
- }
- },
- {
- "files": [
"test/**/*.js",
- "dev/**/*.js"
+ "dev/**/*.js",
+ "integration.spec.js",
+ "playwright.config.js",
+ "playwright-util.js",
+ "visual.spec.js"
],
"env": {
"browser": false,
@@ -659,11 +346,74 @@
},
{
"files": [
+ "test/**/*.test.js"
+ ],
+ "plugins": [
+ "vitest"
+ ],
+ "extends": [
+ "plugin:vitest/recommended"
+ ],
+ "rules": {
+ "vitest/prefer-to-be": "off"
+ }
+ },
+ {
+ "files": [
+ "dev/lib/**/*.js"
+ ],
+ "extends": [
+ "plugin:@typescript-eslint/disable-type-checked"
+ ]
+ },
+ {
+ "files": [
+ "ext/js/core/api-map.js",
+ "ext/js/core/extension-error.js",
+ "ext/js/core/json.js",
+ "ext/js/data/sandbox/anki-note-data-creator.js",
+ "ext/js/dictionary/dictionary-data-util.js",
+ "ext/js/display/sandbox/pronunciation-generator.js",
+ "ext/js/display/sandbox/structured-content-generator.js",
+ "ext/js/dom/sandbox/css-style-applier.js",
+ "ext/js/language/ja/japanese.js",
+ "ext/js/templates/sandbox/anki-template-renderer-content-manager.js",
+ "ext/js/templates/sandbox/anki-template-renderer.js",
+ "ext/js/templates/sandbox/template-renderer-frame-api.js",
+ "ext/js/templates/sandbox/template-renderer-frame-main.js",
+ "ext/js/templates/sandbox/template-renderer-media-provider.js",
+ "ext/js/templates/sandbox/template-renderer.js"
+ ],
+ "env": {
+ "webextensions": false
+ }
+ },
+ {
+ "files": [
+ "ext/js/core/event-dispatcher.js",
"ext/js/core/extension-error.js",
- "ext/js/application.js",
+ "ext/js/core/json.js",
+ "ext/js/core/logger.js",
+ "ext/js/core/to-error.js",
+ "ext/js/core/utilities.js",
+ "ext/js/data/database.js",
+ "ext/js/dictionary/dictionary-database.js",
+ "ext/js/dictionary/dictionary-importer.js",
+ "ext/js/dictionary/dictionary-worker-handler.js",
+ "ext/js/dictionary/dictionary-worker-main.js",
+ "ext/js/dictionary/dictionary-worker-media-loader.js",
+ "ext/js/media/media-util.js"
+ ],
+ "env": {
+ "browser": false,
+ "worker": true
+ }
+ },
+ {
+ "files": [
"ext/js/accessibility/accessibility-controller.js",
"ext/js/background/backend.js",
- "ext/js/background/offscreen.js",
+ "ext/js/background/background-main.js",
"ext/js/background/offscreen-proxy.js",
"ext/js/background/profile-conditions-util.js",
"ext/js/background/request-builder.js",
@@ -672,32 +422,41 @@
"ext/js/comm/clipboard-monitor.js",
"ext/js/comm/clipboard-reader.js",
"ext/js/comm/mecab.js",
+ "ext/js/core/api-map.js",
+ "ext/js/core/event-dispatcher.js",
+ "ext/js/core/event-listener-collection.js",
+ "ext/js/core/extension-error.js",
+ "ext/js/core/fetch-utilities.js",
+ "ext/js/core/json.js",
+ "ext/js/core/logger.js",
+ "ext/js/core/to-error.js",
+ "ext/js/core/utilities.js",
"ext/js/data/anki-util.js",
"ext/js/data/database.js",
"ext/js/data/json-schema.js",
"ext/js/data/options-util.js",
"ext/js/data/permissions-util.js",
"ext/js/data/sandbox/array-buffer-util.js",
+ "ext/js/dictionary/dictionary-database.js",
+ "ext/js/dom/native-simple-dom-parser.js",
"ext/js/dom/simple-dom-parser.js",
"ext/js/extension/environment.js",
+ "ext/js/extension/web-extension.js",
"ext/js/general/cache-map.js",
"ext/js/general/object-property-accessor.js",
"ext/js/general/regex-util.js",
"ext/js/general/text-source-map.js",
+ "ext/js/language/ja/japanese-wanakana.js",
+ "ext/js/language/ja/japanese.js",
"ext/js/language/language-transformer.js",
- "ext/js/dictionary/dictionary-database.js",
- "ext/js/dictionary/dictionary-data-util.js",
- "ext/js/language/sandbox/japanese-util.js",
"ext/js/language/translator.js",
"ext/js/media/audio-downloader.js",
"ext/js/media/media-util.js",
- "ext/js/templates/template-patcher.js",
- "ext/js/background/background-main.js"
+ "ext/js/templates/template-patcher.js"
],
"env": {
"browser": false,
- "serviceworker": true,
- "webextensions": true
+ "serviceworker": true
},
"globals": {
"FileReader": "readonly",
@@ -705,77 +464,6 @@
"crypto": "readonly",
"AbortController": "readonly"
}
- },
- {
- "files": [
- "ext/js/core.js",
- "ext/js/core/extension-error.js",
- "ext/js/data/database.js",
- "ext/js/data/json-schema.js",
- "ext/js/general/cache-map.js",
- "ext/js/dictionary/dictionary-database.js",
- "ext/js/dictionary/dictionary-importer.js",
- "ext/js/dictionary/dictionary-worker-handler.js",
- "ext/js/dictionary/dictionary-worker-media-loader.js",
- "ext/js/media/media-util.js"
- ],
- "env": {
- "browser": false,
- "worker": true,
- "webextensions": true
- }
- },
- {
- "files": [
- "playwright.config.js"
- ],
- "env": {
- "browser": false,
- "node": true,
- "webextensions": false
- },
- "rules": {
- "no-undefined": "off"
- }
- },
- {
- "files": [
- "integration.spec.js",
- "playwright-util.js",
- "visual.spec.js"
- ],
- "env": {
- "browser": false,
- "node": true,
- "webextensions": false
- },
- "rules": {
- "no-undefined": "off",
- "no-empty-pattern": "off"
- }
- },
- {
- "files": [
- "test/**/*.test.js"
- ],
- "plugins": [
- "vitest"
- ],
- "extends": [
- "plugin:vitest/recommended"
- ],
- "rules": {
- "vitest/prefer-to-be": "off"
- },
- "env": {}
- },
- {
- "files": [
- "dev/lib/**/*.js"
- ],
- "extends": [
- "plugin:@typescript-eslint/disable-type-checked"
- ]
}
]
}
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 5aa6512c..bb9b3c80 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,6 +1,6 @@
{
"markdown.extension.toc.levels": "1..3",
- "[javascript]": {
+ "[javascript][json][jsonc]": {
"editor.codeActionsOnSave": {
"source.addMissingImports": "explicit",
"source.organizeImports": "explicit",
@@ -22,7 +22,9 @@
"editor.insertSpaces": true,
"eslint.validate": [
"javascript",
- "typescript"
+ "typescript",
+ "json",
+ "jsonc"
],
"files.eol": "\n",
"files.trimTrailingWhitespace": true,
diff --git a/ext/js/app/frontend.js b/ext/js/app/frontend.js
index 5f412340..27e7700e 100644
--- a/ext/js/app/frontend.js
+++ b/ext/js/app/frontend.js
@@ -19,7 +19,7 @@
import {createApiMap, invokeApiMapHandler} from '../core/api-map.js';
import {EventListenerCollection} from '../core/event-listener-collection.js';
import {log} from '../core/logger.js';
-import {promiseAnimationFrame} from '../core/utilities.js';
+import {promiseAnimationFrame} from '../core/promise-animation-frame.js';
import {DocumentUtil} from '../dom/document-util.js';
import {TextSourceElement} from '../dom/text-source-element.js';
import {TextSourceGenerator} from '../dom/text-source-generator.js';
@@ -115,7 +115,7 @@ export class Frontend {
/** @type {?import('settings').OptionsContext} */
this._optionsContextOverride = null;
- /* eslint-disable no-multi-spaces */
+ /* eslint-disable @stylistic/no-multi-spaces */
/** @type {import('application').ApiMap} */
this._runtimeApiMap = createApiMap([
['frontendRequestReadyBroadcast', this._onMessageRequestFrontendReadyBroadcast.bind(this)],
@@ -127,7 +127,7 @@ export class Frontend {
['scanSelectedText', this._onActionScanSelectedText.bind(this)],
['scanTextAtCaret', this._onActionScanTextAtCaret.bind(this)]
]);
- /* eslint-enable no-multi-spaces */
+ /* eslint-enable @stylistic/no-multi-spaces */
}
/**
@@ -187,7 +187,7 @@ export class Frontend {
this._textScanner.on('searchEmpty', this._onSearchEmpty.bind(this));
this._textScanner.on('searchError', this._onSearchError.bind(this));
- /* eslint-disable no-multi-spaces */
+ /* eslint-disable @stylistic/no-multi-spaces */
this._application.crossFrame.registerHandlers([
['frontendClosePopup', this._onApiClosePopup.bind(this)],
['frontendCopySelection', this._onApiCopySelection.bind(this)],
@@ -195,7 +195,7 @@ export class Frontend {
['frontendGetPopupInfo', this._onApiGetPopupInfo.bind(this)],
['frontendGetPageInfo', this._onApiGetPageInfo.bind(this)]
]);
- /* eslint-enable no-multi-spaces */
+ /* eslint-enable @stylistic/no-multi-spaces */
this._prepareSiteSpecific();
this._updateContentScale();
diff --git a/ext/js/app/popup-factory.js b/ext/js/app/popup-factory.js
index 1b7d21db..c5187291 100644
--- a/ext/js/app/popup-factory.js
+++ b/ext/js/app/popup-factory.js
@@ -49,7 +49,7 @@ export class PopupFactory {
*/
prepare() {
this._frameOffsetForwarder.prepare();
- /* eslint-disable no-multi-spaces */
+ /* eslint-disable @stylistic/no-multi-spaces */
this._application.crossFrame.registerHandlers([
['popupFactoryGetOrCreatePopup', this._onApiGetOrCreatePopup.bind(this)],
['popupFactorySetOptionsContext', this._onApiSetOptionsContext.bind(this)],
@@ -67,7 +67,7 @@ export class PopupFactory {
['popupFactoryGetFrameSize', this._onApiGetFrameSize.bind(this)],
['popupFactorySetFrameSize', this._onApiSetFrameSize.bind(this)]
]);
- /* eslint-enable no-multi-spaces */
+ /* eslint-enable @stylistic/no-multi-spaces */
}
/**
diff --git a/ext/js/application.js b/ext/js/application.js
index 13938aa8..227e9d5e 100644
--- a/ext/js/application.js
+++ b/ext/js/application.js
@@ -93,7 +93,7 @@ export class Application extends EventDispatcher {
/** @type {boolean} */
this._isReady = false;
- /* eslint-disable no-multi-spaces */
+ /* eslint-disable @stylistic/no-multi-spaces */
/** @type {import('application').ApiMap} */
this._apiMap = createApiMap([
['applicationIsReady', this._onMessageIsReady.bind(this)],
@@ -102,7 +102,7 @@ export class Application extends EventDispatcher {
['applicationDatabaseUpdated', this._onMessageDatabaseUpdated.bind(this)],
['applicationZoomChanged', this._onMessageZoomChanged.bind(this)]
]);
- /* eslint-enable no-multi-spaces */
+ /* eslint-enable @stylistic/no-multi-spaces */
}
/** @type {WebExtension} */
diff --git a/ext/js/background/backend.js b/ext/js/background/backend.js
index 85acac89..909faf29 100644
--- a/ext/js/background/backend.js
+++ b/ext/js/background/backend.js
@@ -139,7 +139,7 @@ export class Backend {
/** @type {Map<string, (() => void)[]>} */
this._applicationReadyHandlers = new Map();
- /* eslint-disable no-multi-spaces */
+ /* eslint-disable @stylistic/no-multi-spaces */
/** @type {import('api').ApiMap} */
this._apiMap = createApiMap([
['applicationReady', this._onApiApplicationReady.bind(this)],
@@ -185,7 +185,7 @@ export class Backend {
['findAnkiNotes', this._onApiFindAnkiNotes.bind(this)],
['openCrossFramePort', this._onApiOpenCrossFramePort.bind(this)]
]);
- /* eslint-enable no-multi-spaces */
+ /* eslint-enable @stylistic/no-multi-spaces */
/** @type {Map<string, (params?: import('core').SerializableObject) => void>} */
this._commandHandlers = new Map(/** @type {[name: string, handler: (params?: import('core').SerializableObject) => void][]} */ ([
diff --git a/ext/js/background/offscreen.js b/ext/js/background/offscreen.js
index b203e326..754db517 100644
--- a/ext/js/background/offscreen.js
+++ b/ext/js/background/offscreen.js
@@ -39,14 +39,13 @@ export class Offscreen {
});
/** @type {ClipboardReader} */
this._clipboardReader = new ClipboardReader({
- // eslint-disable-next-line no-undef
document: (typeof document === 'object' && document !== null ? document : null),
pasteTargetSelector: '#clipboard-paste-target',
richContentPasteTargetSelector: '#clipboard-rich-content-paste-target'
});
- /* eslint-disable no-multi-spaces */
+ /* eslint-disable @stylistic/no-multi-spaces */
/** @type {import('offscreen').ApiMap} */
this._apiMap = createApiMap([
['clipboardGetTextOffscreen', this._getTextHandler.bind(this)],
@@ -62,7 +61,7 @@ export class Offscreen {
['getTermFrequenciesOffscreen', this._getTermFrequenciesHandler.bind(this)],
['clearDatabaseCachesOffscreen', this._clearDatabaseCachesHandler.bind(this)]
]);
- /* eslint-enable no-multi-spaces */
+ /* eslint-enable @stylistic/no-multi-spaces */
/** @type {?Promise<void>} */
this._prepareDatabasePromise = null;
diff --git a/ext/js/core/promise-animation-frame.js b/ext/js/core/promise-animation-frame.js
new file mode 100644
index 00000000..0bcd6970
--- /dev/null
+++ b/ext/js/core/promise-animation-frame.js
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2023-2024 Yomitan Authors
+ * Copyright (C) 2019-2022 Yomichan Authors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+/**
+ * Creates a promise that will resolve after the next animation frame, using `requestAnimationFrame`.
+ * @param {number} [timeout] A maximum duration (in milliseconds) to wait until the promise resolves. If null or omitted, no timeout is used.
+ * @returns {Promise<{time: number, timeout: boolean}>} A promise that is resolved with `{time, timeout}`, where `time` is the timestamp from `requestAnimationFrame`,
+ * and `timeout` is a boolean indicating whether the cause was a timeout or not.
+ * @throws The promise throws an error if animation is not supported in this context, such as in a service worker.
+ */
+export function promiseAnimationFrame(timeout) {
+ return new Promise((resolve, reject) => {
+ if (typeof cancelAnimationFrame !== 'function' || typeof requestAnimationFrame !== 'function') {
+ reject(new Error('Animation not supported in this context'));
+ return;
+ }
+
+ /** @type {?import('core').Timeout} */
+ let timer = null;
+ /** @type {?number} */
+ let frameRequest = null;
+ /**
+ * @param {number} time
+ */
+ const onFrame = (time) => {
+ frameRequest = null;
+ if (timer !== null) {
+ clearTimeout(timer);
+ timer = null;
+ }
+ resolve({time, timeout: false});
+ };
+ const onTimeout = () => {
+ timer = null;
+ if (frameRequest !== null) {
+ cancelAnimationFrame(frameRequest);
+ frameRequest = null;
+ }
+ resolve({time: performance.now(), timeout: true});
+ };
+
+ frameRequest = requestAnimationFrame(onFrame);
+ if (typeof timeout === 'number') {
+ timer = setTimeout(onTimeout, timeout);
+ }
+ });
+}
diff --git a/ext/js/core/utilities.js b/ext/js/core/utilities.js
index 784acdaf..1b785e79 100644
--- a/ext/js/core/utilities.js
+++ b/ext/js/core/utilities.js
@@ -270,48 +270,3 @@ export function deferPromise() {
export function promiseTimeout(delay) {
return delay <= 0 ? Promise.resolve() : new Promise((resolve) => { setTimeout(resolve, delay); });
}
-
-/**
- * Creates a promise that will resolve after the next animation frame, using `requestAnimationFrame`.
- * @param {number} [timeout] A maximum duration (in milliseconds) to wait until the promise resolves. If null or omitted, no timeout is used.
- * @returns {Promise<{time: number, timeout: boolean}>} A promise that is resolved with `{time, timeout}`, where `time` is the timestamp from `requestAnimationFrame`,
- * and `timeout` is a boolean indicating whether the cause was a timeout or not.
- * @throws The promise throws an error if animation is not supported in this context, such as in a service worker.
- */
-export function promiseAnimationFrame(timeout) {
- return new Promise((resolve, reject) => {
- if (typeof cancelAnimationFrame !== 'function' || typeof requestAnimationFrame !== 'function') {
- reject(new Error('Animation not supported in this context'));
- return;
- }
-
- /** @type {?import('core').Timeout} */
- let timer = null;
- /** @type {?number} */
- let frameRequest = null;
- /**
- * @param {number} time
- */
- const onFrame = (time) => {
- frameRequest = null;
- if (timer !== null) {
- clearTimeout(timer);
- timer = null;
- }
- resolve({time, timeout: false});
- };
- const onTimeout = () => {
- timer = null;
- if (frameRequest !== null) {
- cancelAnimationFrame(frameRequest);
- frameRequest = null;
- }
- resolve({time: performance.now(), timeout: true});
- };
-
- frameRequest = requestAnimationFrame(onFrame);
- if (typeof timeout === 'number') {
- timer = setTimeout(onTimeout, timeout);
- }
- });
-}
diff --git a/ext/js/data/options-util.js b/ext/js/data/options-util.js
index 3f3a5ab8..d93927a7 100644
--- a/ext/js/data/options-util.js
+++ b/ext/js/data/options-util.js
@@ -687,7 +687,7 @@ export class OptionsUtil {
const rawPattern1 = '{{~#if definitionTags~}}<i>({{#each definitionTags}}{{name}}{{#unless @last}}, {{/unless}}{{/each}})</i> {{/if~}}';
const pattern1 = new RegExp(`((\r?\n)?[ \t]*)${escapeRegExp(rawPattern1)}`, 'g');
const replacement1 = (
- // eslint-disable-next-line indent
+ // eslint-disable-next-line @stylistic/indent
`{{~#scope~}}
{{~#set "any" false}}{{/set~}}
{{~#if definitionTags~}}{{#each definitionTags~}}
@@ -771,7 +771,7 @@ export class OptionsUtil {
};
delete profile.options.anki.sentenceExt;
profile.options.general.popupActionBarLocation = 'top';
- /* eslint-disable no-multi-spaces */
+ /* eslint-disable @stylistic/no-multi-spaces */
profile.options.inputs = {
hotkeys: [
{action: 'close', key: 'Escape', modifiers: [], scopes: ['popup'], enabled: true},
@@ -792,7 +792,7 @@ export class OptionsUtil {
{action: 'copyHostSelection', key: 'KeyC', modifiers: ['ctrl'], scopes: ['popup'], enabled: true}
]
};
- /* eslint-enable no-multi-spaces */
+ /* eslint-enable @stylistic/no-multi-spaces */
profile.options.anki.suspendNewCards = false;
profile.options.popupWindow = {
width: profile.options.general.popupWidth,
diff --git a/ext/js/display/display-anki.js b/ext/js/display/display-anki.js
index c19cfa22..665521dd 100644
--- a/ext/js/display/display-anki.js
+++ b/ext/js/display/display-anki.js
@@ -109,14 +109,14 @@ export class DisplayAnki {
/** */
prepare() {
this._noteContext = this._getNoteContext();
- /* eslint-disable no-multi-spaces */
+ /* eslint-disable @stylistic/no-multi-spaces */
this._display.hotkeyHandler.registerActions([
['addNoteKanji', () => { this._tryAddAnkiNoteForSelectedEntry('kanji'); }],
['addNoteTermKanji', () => { this._tryAddAnkiNoteForSelectedEntry('term-kanji'); }],
['addNoteTermKana', () => { this._tryAddAnkiNoteForSelectedEntry('term-kana'); }],
['viewNote', this._viewNoteForSelectedEntry.bind(this)]
]);
- /* eslint-enable no-multi-spaces */
+ /* eslint-enable @stylistic/no-multi-spaces */
this._display.on('optionsUpdated', this._onOptionsUpdated.bind(this));
this._display.on('contentClear', this._onContentClear.bind(this));
this._display.on('contentUpdateStart', this._onContentUpdateStart.bind(this));
diff --git a/ext/js/display/display-audio.js b/ext/js/display/display-audio.js
index 4acd6494..deaa0976 100644
--- a/ext/js/display/display-audio.js
+++ b/ext/js/display/display-audio.js
@@ -82,7 +82,7 @@ export class DisplayAudio {
/** */
prepare() {
this._audioSystem.prepare();
- /* eslint-disable no-multi-spaces */
+ /* eslint-disable @stylistic/no-multi-spaces */
this._display.hotkeyHandler.registerActions([
['playAudio', this._onHotkeyActionPlayAudio.bind(this)],
['playAudioFromSource', this._onHotkeyActionPlayAudioFromSource.bind(this)]
@@ -90,7 +90,7 @@ export class DisplayAudio {
this._display.registerDirectMessageHandlers([
['displayAudioClearAutoPlayTimer', this._onMessageClearAutoPlayTimer.bind(this)]
]);
- /* eslint-enable no-multi-spaces */
+ /* eslint-enable @stylistic/no-multi-spaces */
this._display.on('optionsUpdated', this._onOptionsUpdated.bind(this));
this._display.on('contentClear', this._onContentClear.bind(this));
this._display.on('contentUpdateEntry', this._onContentUpdateEntry.bind(this));
diff --git a/ext/js/display/display.js b/ext/js/display/display.js
index 676f1a4f..f05feac8 100644
--- a/ext/js/display/display.js
+++ b/ext/js/display/display.js
@@ -200,7 +200,7 @@ export class Display extends EventDispatcher {
/** @type {ThemeController} */
this._themeController = new ThemeController(document.documentElement);
- /* eslint-disable no-multi-spaces */
+ /* eslint-disable @stylistic/no-multi-spaces */
this._hotkeyHandler.registerActions([
['close', () => { this._onHotkeyClose(); }],
['nextEntry', this._onHotkeyActionMoveRelative.bind(this, 1)],
@@ -224,7 +224,7 @@ export class Display extends EventDispatcher {
this.registerWindowMessageHandlers([
['displayExtensionUnloaded', this._onMessageExtensionUnloaded.bind(this)]
]);
- /* eslint-enable no-multi-spaces */
+ /* eslint-enable @stylistic/no-multi-spaces */
}
/** @type {import('../application.js').Application} */
diff --git a/ext/js/pages/settings/keyboard-shortcuts-controller.js b/ext/js/pages/settings/keyboard-shortcuts-controller.js
index 9392f768..24d34d5b 100644
--- a/ext/js/pages/settings/keyboard-shortcuts-controller.js
+++ b/ext/js/pages/settings/keyboard-shortcuts-controller.js
@@ -45,7 +45,7 @@ export class KeyboardShortcutController {
this._stringComparer = new Intl.Collator('en-US'); // Invariant locale
/** @type {HTMLElement} */
this._scrollContainer = querySelectorNotNull(document, '#keyboard-shortcuts-modal .modal-body');
- /* eslint-disable no-multi-spaces */
+ /* eslint-disable @stylistic/no-multi-spaces */
/** @type {Map<string, import('keyboard-shortcut-controller').ActionDetails>} */
this._actionDetails = new Map([
['', {scopes: new Set()}],
@@ -70,7 +70,7 @@ export class KeyboardShortcutController {
['scanTextAtCaret', {scopes: new Set(['web'])}],
['toggleOption', {scopes: new Set(['popup', 'search']), argument: {template: 'hotkey-argument-setting-path', default: ''}}]
]);
- /* eslint-enable no-multi-spaces */
+ /* eslint-enable @stylistic/no-multi-spaces */
}
/** @type {import('./settings-controller.js').SettingsController} */
diff --git a/ext/js/pages/settings/popup-preview-frame.js b/ext/js/pages/settings/popup-preview-frame.js
index e9cfa541..1ad4859b 100644
--- a/ext/js/pages/settings/popup-preview-frame.js
+++ b/ext/js/pages/settings/popup-preview-frame.js
@@ -59,7 +59,7 @@ export class PopupPreviewFrame {
/** @type {string} */
this._targetOrigin = chrome.runtime.getURL('/').replace(/\/$/, '');
- /* eslint-disable no-multi-spaces */
+ /* eslint-disable @stylistic/no-multi-spaces */
/** @type {Map<string, (params: import('core').SerializableObjectAny) => void>} */
this._windowMessageHandlers = new Map(/** @type {[key: string, handler: (params: import('core').SerializableObjectAny) => void][]} */ ([
['PopupPreviewFrame.setText', this._onSetText.bind(this)],
@@ -67,7 +67,7 @@ export class PopupPreviewFrame {
['PopupPreviewFrame.setCustomOuterCss', this._setCustomOuterCss.bind(this)],
['PopupPreviewFrame.updateOptionsContext', this._updateOptionsContext.bind(this)]
]));
- /* eslint-enable no-multi-spaces */
+ /* eslint-enable @stylistic/no-multi-spaces */
}
/** */
diff --git a/ext/js/pages/settings/profile-conditions-ui.js b/ext/js/pages/settings/profile-conditions-ui.js
index d07751fb..5801af17 100644
--- a/ext/js/pages/settings/profile-conditions-ui.js
+++ b/ext/js/pages/settings/profile-conditions-ui.js
@@ -51,7 +51,7 @@ export class ProfileConditionsUI extends EventDispatcher {
const normalizeInteger = this._normalizeInteger.bind(this);
const validateFlags = this._validateFlags.bind(this);
const normalizeFlags = this._normalizeFlags.bind(this);
- /* eslint-disable no-multi-spaces */
+ /* eslint-disable @stylistic/no-multi-spaces */
/** @type {Map<import('profile-conditions-ui').DescriptorType, import('profile-conditions-ui').Descriptor>} */
this._descriptors = new Map([
[
@@ -107,7 +107,7 @@ export class ProfileConditionsUI extends EventDispatcher {
}
]
]);
- /* eslint-enable no-multi-spaces */
+ /* eslint-enable @stylistic/no-multi-spaces */
/** @type {Set<string>} */
this._validFlags = new Set([
'clipboard'
diff --git a/ext/js/templates/sandbox/anki-template-renderer.js b/ext/js/templates/sandbox/anki-template-renderer.js
index 8ece8e24..135200da 100644
--- a/ext/js/templates/sandbox/anki-template-renderer.js
+++ b/ext/js/templates/sandbox/anki-template-renderer.js
@@ -68,7 +68,7 @@ export class AnkiTemplateRenderer {
* Prepares the data that is necessary before the template renderer can be safely used.
*/
async prepare() {
- /* eslint-disable no-multi-spaces */
+ /* eslint-disable @stylistic/no-multi-spaces */
this._templateRenderer.registerHelpers([
['dumpObject', this._dumpObject.bind(this)],
['furigana', this._furigana.bind(this)],
@@ -98,7 +98,7 @@ export class AnkiTemplateRenderer {
['hiragana', this._hiragana.bind(this)],
['katakana', this._katakana.bind(this)]
]);
- /* eslint-enable no-multi-spaces */
+ /* eslint-enable @stylistic/no-multi-spaces */
this._templateRenderer.registerDataType('ankiNote', {
modifier: ({marker, commonData}) => createAnkiNoteData(marker, commonData),
composeData: ({marker}, commonData) => ({marker, commonData})
diff --git a/package-lock.json b/package-lock.json
index 74901853..8b27c630 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -19,7 +19,7 @@
"devDependencies": {
"@codspeed/vitest-plugin": "^3.1.0",
"@playwright/test": "^1.39.0",
- "@stylistic/eslint-plugin-ts": "^1.5.1",
+ "@stylistic/eslint-plugin": "^1.5.4",
"@stylistic/stylelint-plugin": "^2.0.0",
"@types/assert": "^1.5.10",
"@types/browserify": "^12.0.40",
@@ -1386,13 +1386,31 @@
"url": "https://github.com/sindresorhus/is?sponsor=1"
}
},
+ "node_modules/@stylistic/eslint-plugin": {
+ "version": "1.5.4",
+ "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-1.5.4.tgz",
+ "integrity": "sha512-zWPXr+O67GC9KDAFkbL1U9UVqE6Iv69YMKhkIECCmE0GvClUJwdfsimm4XebEDondV7kfjMrTDZaYfrI5aS0Jg==",
+ "dev": true,
+ "dependencies": {
+ "@stylistic/eslint-plugin-js": "1.5.4",
+ "@stylistic/eslint-plugin-jsx": "1.5.4",
+ "@stylistic/eslint-plugin-plus": "1.5.4",
+ "@stylistic/eslint-plugin-ts": "1.5.4"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "eslint": ">=8.40.0"
+ }
+ },
"node_modules/@stylistic/eslint-plugin-js": {
- "version": "1.5.1",
- "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-js/-/eslint-plugin-js-1.5.1.tgz",
- "integrity": "sha512-iZF0rF+uOhAmOJYOJx1Yvmm3CZ1uz9n0SRd9dpBYHA3QAvfABUORh9LADWwZCigjHJkp2QbCZelGFJGwGz7Siw==",
+ "version": "1.5.4",
+ "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-js/-/eslint-plugin-js-1.5.4.tgz",
+ "integrity": "sha512-3ctWb3NvJNV1MsrZN91cYp2EGInLPSoZKphXIbIRx/zjZxKwLDr9z4LMOWtqjq14li/OgqUUcMq5pj8fgbLoTw==",
"dev": true,
"dependencies": {
- "acorn": "^8.11.2",
+ "acorn": "^8.11.3",
"escape-string-regexp": "^4.0.0",
"eslint-visitor-keys": "^3.4.3",
"espree": "^9.6.1"
@@ -1404,14 +1422,166 @@
"eslint": ">=8.40.0"
}
},
+ "node_modules/@stylistic/eslint-plugin-jsx": {
+ "version": "1.5.4",
+ "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-jsx/-/eslint-plugin-jsx-1.5.4.tgz",
+ "integrity": "sha512-JUfrpCkeBCqt1IZ4QsP4WgxGza4PhK4LPbc0VnCjHKygl+rgqoDAovqOuzFJ49wJ4Ix3r6OIHFuwiBGswZEVvg==",
+ "dev": true,
+ "dependencies": {
+ "@stylistic/eslint-plugin-js": "^1.5.4",
+ "estraverse": "^5.3.0"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "eslint": ">=8.40.0"
+ }
+ },
+ "node_modules/@stylistic/eslint-plugin-plus": {
+ "version": "1.5.4",
+ "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-plus/-/eslint-plugin-plus-1.5.4.tgz",
+ "integrity": "sha512-dI0Cs5vYX/0uMhQDY+NK0cKQ0Pe9B6jWYxd0Ndud+mNloDaVLrsmJocK4zn+YfhGEDs1E4Nk5uAPZEumIpDuSg==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/utils": "^6.19.0"
+ },
+ "peerDependencies": {
+ "eslint": "*"
+ }
+ },
+ "node_modules/@stylistic/eslint-plugin-plus/node_modules/@typescript-eslint/scope-manager": {
+ "version": "6.20.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.20.0.tgz",
+ "integrity": "sha512-p4rvHQRDTI1tGGMDFQm+GtxP1ZHyAh64WANVoyEcNMpaTFn3ox/3CcgtIlELnRfKzSs/DwYlDccJEtr3O6qBvA==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "6.20.0",
+ "@typescript-eslint/visitor-keys": "6.20.0"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@stylistic/eslint-plugin-plus/node_modules/@typescript-eslint/types": {
+ "version": "6.20.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.20.0.tgz",
+ "integrity": "sha512-MM9mfZMAhiN4cOEcUOEx+0HmuaW3WBfukBZPCfwSqFnQy0grXYtngKCqpQN339X3RrwtzspWJrpbrupKYUSBXQ==",
+ "dev": true,
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@stylistic/eslint-plugin-plus/node_modules/@typescript-eslint/typescript-estree": {
+ "version": "6.20.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.20.0.tgz",
+ "integrity": "sha512-RnRya9q5m6YYSpBN7IzKu9FmLcYtErkDkc8/dKv81I9QiLLtVBHrjz+Ev/crAqgMNW2FCsoZF4g2QUylMnJz+g==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "6.20.0",
+ "@typescript-eslint/visitor-keys": "6.20.0",
+ "debug": "^4.3.4",
+ "globby": "^11.1.0",
+ "is-glob": "^4.0.3",
+ "minimatch": "9.0.3",
+ "semver": "^7.5.4",
+ "ts-api-utils": "^1.0.1"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@stylistic/eslint-plugin-plus/node_modules/@typescript-eslint/utils": {
+ "version": "6.20.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.20.0.tgz",
+ "integrity": "sha512-/EKuw+kRu2vAqCoDwDCBtDRU6CTKbUmwwI7SH7AashZ+W+7o8eiyy6V2cdOqN49KsTcASWsC5QeghYuRDTyOOg==",
+ "dev": true,
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.4.0",
+ "@types/json-schema": "^7.0.12",
+ "@types/semver": "^7.5.0",
+ "@typescript-eslint/scope-manager": "6.20.0",
+ "@typescript-eslint/types": "6.20.0",
+ "@typescript-eslint/typescript-estree": "6.20.0",
+ "semver": "^7.5.4"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/@stylistic/eslint-plugin-plus/node_modules/@typescript-eslint/visitor-keys": {
+ "version": "6.20.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.20.0.tgz",
+ "integrity": "sha512-E8Cp98kRe4gKHjJD4NExXKz/zOJ1A2hhZc+IMVD6i7w4yjIvh6VyuRI0gRtxAsXtoC35uGMaQ9rjI2zJaXDEAw==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "6.20.0",
+ "eslint-visitor-keys": "^3.4.1"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@stylistic/eslint-plugin-plus/node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/@stylistic/eslint-plugin-plus/node_modules/minimatch": {
+ "version": "9.0.3",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
+ "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
"node_modules/@stylistic/eslint-plugin-ts": {
- "version": "1.5.1",
- "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-ts/-/eslint-plugin-ts-1.5.1.tgz",
- "integrity": "sha512-oXM1V7Jp8G9+udxQTy+Igo79LR2e5HXiWqlA/3v+/PAqWxniR9nJqJSBjtQKJTPsGplDqn/ASpHUOETP4EI/4A==",
+ "version": "1.5.4",
+ "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-ts/-/eslint-plugin-ts-1.5.4.tgz",
+ "integrity": "sha512-NZDFVIlVNjuPvhT+0Cidm5IS3emtx338xbJTqs2xfOVRDGTpYwRHhNVEGa1rFOpYHmv0sAj6+OXbMDn7ul0K/g==",
"dev": true,
"dependencies": {
- "@stylistic/eslint-plugin-js": "1.5.1",
- "@typescript-eslint/utils": "^6.13.2"
+ "@stylistic/eslint-plugin-js": "1.5.4",
+ "@typescript-eslint/utils": "^6.19.0"
},
"engines": {
"node": "^16.0.0 || >=18.0.0"
@@ -1420,6 +1590,130 @@
"eslint": ">=8.40.0"
}
},
+ "node_modules/@stylistic/eslint-plugin-ts/node_modules/@typescript-eslint/scope-manager": {
+ "version": "6.20.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.20.0.tgz",
+ "integrity": "sha512-p4rvHQRDTI1tGGMDFQm+GtxP1ZHyAh64WANVoyEcNMpaTFn3ox/3CcgtIlELnRfKzSs/DwYlDccJEtr3O6qBvA==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "6.20.0",
+ "@typescript-eslint/visitor-keys": "6.20.0"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@stylistic/eslint-plugin-ts/node_modules/@typescript-eslint/types": {
+ "version": "6.20.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.20.0.tgz",
+ "integrity": "sha512-MM9mfZMAhiN4cOEcUOEx+0HmuaW3WBfukBZPCfwSqFnQy0grXYtngKCqpQN339X3RrwtzspWJrpbrupKYUSBXQ==",
+ "dev": true,
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@stylistic/eslint-plugin-ts/node_modules/@typescript-eslint/typescript-estree": {
+ "version": "6.20.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.20.0.tgz",
+ "integrity": "sha512-RnRya9q5m6YYSpBN7IzKu9FmLcYtErkDkc8/dKv81I9QiLLtVBHrjz+Ev/crAqgMNW2FCsoZF4g2QUylMnJz+g==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "6.20.0",
+ "@typescript-eslint/visitor-keys": "6.20.0",
+ "debug": "^4.3.4",
+ "globby": "^11.1.0",
+ "is-glob": "^4.0.3",
+ "minimatch": "9.0.3",
+ "semver": "^7.5.4",
+ "ts-api-utils": "^1.0.1"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@stylistic/eslint-plugin-ts/node_modules/@typescript-eslint/utils": {
+ "version": "6.20.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.20.0.tgz",
+ "integrity": "sha512-/EKuw+kRu2vAqCoDwDCBtDRU6CTKbUmwwI7SH7AashZ+W+7o8eiyy6V2cdOqN49KsTcASWsC5QeghYuRDTyOOg==",
+ "dev": true,
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.4.0",
+ "@types/json-schema": "^7.0.12",
+ "@types/semver": "^7.5.0",
+ "@typescript-eslint/scope-manager": "6.20.0",
+ "@typescript-eslint/types": "6.20.0",
+ "@typescript-eslint/typescript-estree": "6.20.0",
+ "semver": "^7.5.4"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/@stylistic/eslint-plugin-ts/node_modules/@typescript-eslint/visitor-keys": {
+ "version": "6.20.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.20.0.tgz",
+ "integrity": "sha512-E8Cp98kRe4gKHjJD4NExXKz/zOJ1A2hhZc+IMVD6i7w4yjIvh6VyuRI0gRtxAsXtoC35uGMaQ9rjI2zJaXDEAw==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "6.20.0",
+ "eslint-visitor-keys": "^3.4.1"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@stylistic/eslint-plugin-ts/node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/@stylistic/eslint-plugin-ts/node_modules/minimatch": {
+ "version": "9.0.3",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
+ "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
"node_modules/@stylistic/stylelint-plugin": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@stylistic/stylelint-plugin/-/stylelint-plugin-2.0.0.tgz",
@@ -1950,9 +2244,9 @@
}
},
"node_modules/acorn": {
- "version": "8.11.2",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz",
- "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==",
+ "version": "8.11.3",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz",
+ "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==",
"dev": true,
"bin": {
"acorn": "bin/acorn"
@@ -7865,26 +8159,211 @@
"integrity": "sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==",
"dev": true
},
+ "@stylistic/eslint-plugin": {
+ "version": "1.5.4",
+ "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-1.5.4.tgz",
+ "integrity": "sha512-zWPXr+O67GC9KDAFkbL1U9UVqE6Iv69YMKhkIECCmE0GvClUJwdfsimm4XebEDondV7kfjMrTDZaYfrI5aS0Jg==",
+ "dev": true,
+ "requires": {
+ "@stylistic/eslint-plugin-js": "1.5.4",
+ "@stylistic/eslint-plugin-jsx": "1.5.4",
+ "@stylistic/eslint-plugin-plus": "1.5.4",
+ "@stylistic/eslint-plugin-ts": "1.5.4"
+ }
+ },
"@stylistic/eslint-plugin-js": {
- "version": "1.5.1",
- "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-js/-/eslint-plugin-js-1.5.1.tgz",
- "integrity": "sha512-iZF0rF+uOhAmOJYOJx1Yvmm3CZ1uz9n0SRd9dpBYHA3QAvfABUORh9LADWwZCigjHJkp2QbCZelGFJGwGz7Siw==",
+ "version": "1.5.4",
+ "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-js/-/eslint-plugin-js-1.5.4.tgz",
+ "integrity": "sha512-3ctWb3NvJNV1MsrZN91cYp2EGInLPSoZKphXIbIRx/zjZxKwLDr9z4LMOWtqjq14li/OgqUUcMq5pj8fgbLoTw==",
"dev": true,
"requires": {
- "acorn": "^8.11.2",
+ "acorn": "^8.11.3",
"escape-string-regexp": "^4.0.0",
"eslint-visitor-keys": "^3.4.3",
"espree": "^9.6.1"
}
},
+ "@stylistic/eslint-plugin-jsx": {
+ "version": "1.5.4",
+ "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-jsx/-/eslint-plugin-jsx-1.5.4.tgz",
+ "integrity": "sha512-JUfrpCkeBCqt1IZ4QsP4WgxGza4PhK4LPbc0VnCjHKygl+rgqoDAovqOuzFJ49wJ4Ix3r6OIHFuwiBGswZEVvg==",
+ "dev": true,
+ "requires": {
+ "@stylistic/eslint-plugin-js": "^1.5.4",
+ "estraverse": "^5.3.0"
+ }
+ },
+ "@stylistic/eslint-plugin-plus": {
+ "version": "1.5.4",
+ "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-plus/-/eslint-plugin-plus-1.5.4.tgz",
+ "integrity": "sha512-dI0Cs5vYX/0uMhQDY+NK0cKQ0Pe9B6jWYxd0Ndud+mNloDaVLrsmJocK4zn+YfhGEDs1E4Nk5uAPZEumIpDuSg==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/utils": "^6.19.0"
+ },
+ "dependencies": {
+ "@typescript-eslint/scope-manager": {
+ "version": "6.20.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.20.0.tgz",
+ "integrity": "sha512-p4rvHQRDTI1tGGMDFQm+GtxP1ZHyAh64WANVoyEcNMpaTFn3ox/3CcgtIlELnRfKzSs/DwYlDccJEtr3O6qBvA==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/types": "6.20.0",
+ "@typescript-eslint/visitor-keys": "6.20.0"
+ }
+ },
+ "@typescript-eslint/types": {
+ "version": "6.20.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.20.0.tgz",
+ "integrity": "sha512-MM9mfZMAhiN4cOEcUOEx+0HmuaW3WBfukBZPCfwSqFnQy0grXYtngKCqpQN339X3RrwtzspWJrpbrupKYUSBXQ==",
+ "dev": true
+ },
+ "@typescript-eslint/typescript-estree": {
+ "version": "6.20.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.20.0.tgz",
+ "integrity": "sha512-RnRya9q5m6YYSpBN7IzKu9FmLcYtErkDkc8/dKv81I9QiLLtVBHrjz+Ev/crAqgMNW2FCsoZF4g2QUylMnJz+g==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/types": "6.20.0",
+ "@typescript-eslint/visitor-keys": "6.20.0",
+ "debug": "^4.3.4",
+ "globby": "^11.1.0",
+ "is-glob": "^4.0.3",
+ "minimatch": "9.0.3",
+ "semver": "^7.5.4",
+ "ts-api-utils": "^1.0.1"
+ }
+ },
+ "@typescript-eslint/utils": {
+ "version": "6.20.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.20.0.tgz",
+ "integrity": "sha512-/EKuw+kRu2vAqCoDwDCBtDRU6CTKbUmwwI7SH7AashZ+W+7o8eiyy6V2cdOqN49KsTcASWsC5QeghYuRDTyOOg==",
+ "dev": true,
+ "requires": {
+ "@eslint-community/eslint-utils": "^4.4.0",
+ "@types/json-schema": "^7.0.12",
+ "@types/semver": "^7.5.0",
+ "@typescript-eslint/scope-manager": "6.20.0",
+ "@typescript-eslint/types": "6.20.0",
+ "@typescript-eslint/typescript-estree": "6.20.0",
+ "semver": "^7.5.4"
+ }
+ },
+ "@typescript-eslint/visitor-keys": {
+ "version": "6.20.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.20.0.tgz",
+ "integrity": "sha512-E8Cp98kRe4gKHjJD4NExXKz/zOJ1A2hhZc+IMVD6i7w4yjIvh6VyuRI0gRtxAsXtoC35uGMaQ9rjI2zJaXDEAw==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/types": "6.20.0",
+ "eslint-visitor-keys": "^3.4.1"
+ }
+ },
+ "brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dev": true,
+ "requires": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "minimatch": {
+ "version": "9.0.3",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
+ "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^2.0.1"
+ }
+ }
+ }
+ },
"@stylistic/eslint-plugin-ts": {
- "version": "1.5.1",
- "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-ts/-/eslint-plugin-ts-1.5.1.tgz",
- "integrity": "sha512-oXM1V7Jp8G9+udxQTy+Igo79LR2e5HXiWqlA/3v+/PAqWxniR9nJqJSBjtQKJTPsGplDqn/ASpHUOETP4EI/4A==",
+ "version": "1.5.4",
+ "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-ts/-/eslint-plugin-ts-1.5.4.tgz",
+ "integrity": "sha512-NZDFVIlVNjuPvhT+0Cidm5IS3emtx338xbJTqs2xfOVRDGTpYwRHhNVEGa1rFOpYHmv0sAj6+OXbMDn7ul0K/g==",
"dev": true,
"requires": {
- "@stylistic/eslint-plugin-js": "1.5.1",
- "@typescript-eslint/utils": "^6.13.2"
+ "@stylistic/eslint-plugin-js": "1.5.4",
+ "@typescript-eslint/utils": "^6.19.0"
+ },
+ "dependencies": {
+ "@typescript-eslint/scope-manager": {
+ "version": "6.20.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.20.0.tgz",
+ "integrity": "sha512-p4rvHQRDTI1tGGMDFQm+GtxP1ZHyAh64WANVoyEcNMpaTFn3ox/3CcgtIlELnRfKzSs/DwYlDccJEtr3O6qBvA==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/types": "6.20.0",
+ "@typescript-eslint/visitor-keys": "6.20.0"
+ }
+ },
+ "@typescript-eslint/types": {
+ "version": "6.20.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.20.0.tgz",
+ "integrity": "sha512-MM9mfZMAhiN4cOEcUOEx+0HmuaW3WBfukBZPCfwSqFnQy0grXYtngKCqpQN339X3RrwtzspWJrpbrupKYUSBXQ==",
+ "dev": true
+ },
+ "@typescript-eslint/typescript-estree": {
+ "version": "6.20.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.20.0.tgz",
+ "integrity": "sha512-RnRya9q5m6YYSpBN7IzKu9FmLcYtErkDkc8/dKv81I9QiLLtVBHrjz+Ev/crAqgMNW2FCsoZF4g2QUylMnJz+g==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/types": "6.20.0",
+ "@typescript-eslint/visitor-keys": "6.20.0",
+ "debug": "^4.3.4",
+ "globby": "^11.1.0",
+ "is-glob": "^4.0.3",
+ "minimatch": "9.0.3",
+ "semver": "^7.5.4",
+ "ts-api-utils": "^1.0.1"
+ }
+ },
+ "@typescript-eslint/utils": {
+ "version": "6.20.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.20.0.tgz",
+ "integrity": "sha512-/EKuw+kRu2vAqCoDwDCBtDRU6CTKbUmwwI7SH7AashZ+W+7o8eiyy6V2cdOqN49KsTcASWsC5QeghYuRDTyOOg==",
+ "dev": true,
+ "requires": {
+ "@eslint-community/eslint-utils": "^4.4.0",
+ "@types/json-schema": "^7.0.12",
+ "@types/semver": "^7.5.0",
+ "@typescript-eslint/scope-manager": "6.20.0",
+ "@typescript-eslint/types": "6.20.0",
+ "@typescript-eslint/typescript-estree": "6.20.0",
+ "semver": "^7.5.4"
+ }
+ },
+ "@typescript-eslint/visitor-keys": {
+ "version": "6.20.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.20.0.tgz",
+ "integrity": "sha512-E8Cp98kRe4gKHjJD4NExXKz/zOJ1A2hhZc+IMVD6i7w4yjIvh6VyuRI0gRtxAsXtoC35uGMaQ9rjI2zJaXDEAw==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/types": "6.20.0",
+ "eslint-visitor-keys": "^3.4.1"
+ }
+ },
+ "brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dev": true,
+ "requires": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "minimatch": {
+ "version": "9.0.3",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
+ "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^2.0.1"
+ }
+ }
}
},
"@stylistic/stylelint-plugin": {
@@ -8279,9 +8758,9 @@
"integrity": "sha512-9Ox1meDIvIKE23LLA7Fxd/ewJpKjj2KryH92doHRqx2406LmIzorsiMawL0qIK7dvwN9K+mfk47lauoIE0o1zQ=="
},
"acorn": {
- "version": "8.11.2",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz",
- "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==",
+ "version": "8.11.3",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz",
+ "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==",
"dev": true
},
"acorn-jsx": {
diff --git a/package.json b/package.json
index 9ba91ba2..67344512 100644
--- a/package.json
+++ b/package.json
@@ -15,6 +15,7 @@
"build-libs": "node ./dev/bin/build-libs.js",
"test": "npm run test-lint-js && npm run test-ts && npm run test-lint-css && npm run test-lint-html && npm run test-code && npm run test-build",
"test-lint-js": "npx eslint .",
+ "test-lint-json": "npx eslint **/*.json",
"test-lint-css": "npx stylelint \"ext/**/*.css\" \"test/**/*.css\" \"dev/**/*.css\"",
"test-lint-html": "npx html-validate \"ext/**/*.html\" \"test/**/*.html\" \"dev/**/*.html\"",
"test-ts": "npm run test-ts-main && npm run test-ts-dev && npm run test-ts-test",
@@ -49,7 +50,7 @@
"devDependencies": {
"@codspeed/vitest-plugin": "^3.1.0",
"@playwright/test": "^1.39.0",
- "@stylistic/eslint-plugin-ts": "^1.5.1",
+ "@stylistic/eslint-plugin": "^1.5.4",
"@stylistic/stylelint-plugin": "^2.0.0",
"@types/assert": "^1.5.10",
"@types/browserify": "^12.0.40",
diff --git a/playwright.config.js b/playwright.config.js
index 4658ceb2..a13eb710 100644
--- a/playwright.config.js
+++ b/playwright.config.js
@@ -45,7 +45,7 @@ export default defineConfig({
/* Retry on CI only */
retries: process.env.CI ? 2 : 0,
/* Opt out of parallel tests on CI. */
- workers: process.env.CI ? 1 : undefined,
+ workers: process.env.CI ? 1 : void 0,
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: 'html',
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
diff --git a/test/cache-map.test.js b/test/cache-map.test.js
index 868c5d9a..9be5363a 100644
--- a/test/cache-map.test.js
+++ b/test/cache-map.test.js
@@ -37,7 +37,7 @@ function testConstructor() {
/** */
function testApi() {
describe('api', () => {
- /* eslint-disable no-multi-spaces */
+ /* eslint-disable @stylistic/no-multi-spaces */
const data = [
{
maxSize: 1,
@@ -89,7 +89,7 @@ function testApi() {
]
}
];
- /* eslint-enable no-multi-spaces */
+ /* eslint-enable @stylistic/no-multi-spaces */
test.each(data)('api-test-%#', ({maxSize, expectedSize, calls}) => {
const cache = new CacheMap(maxSize);
diff --git a/test/data/dictionaries/valid-dictionary1/term_bank_1.json b/test/data/dictionaries/valid-dictionary1/term_bank_1.json
index d2012d33..ae32d146 100644
--- a/test/data/dictionaries/valid-dictionary1/term_bank_1.json
+++ b/test/data/dictionaries/valid-dictionary1/term_bank_1.json
@@ -2,13 +2,13 @@
["打", "だ", "n", "n", 1, ["da definition 1", "da definition 2"], 1, "E1"],
["打", "ダース", "n abbr", "n", 1, ["daasu definition 1", "daasu definition 2"], 2, "E1"],
["打つ", "うつ", "vt", "v5", 10, ["utsu definition 1", "utsu definition 2"], 3, "P E1"],
- ["打つ", "うつ", "vt", "v5", 1, ["utsu definition 3", "utsu definition 4"], 3, "P E2"],
+ ["打つ", "うつ", "vt", "v5", 1, ["utsu definition 3", "utsu definition 4"], 3, "P E2"],
["打つ", "ぶつ", "vt", "v5", 10, ["butsu definition 1", "butsu definition 2"], 3, "P E1"],
- ["打つ", "ぶつ", "vt", "v5", 1, ["butsu definition 3", "butsu definition 4"], 3, "P E2"],
+ ["打つ", "ぶつ", "vt", "v5", 1, ["butsu definition 3", "butsu definition 4"], 3, "P E2"],
["打ち込む", "うちこむ", "vt", "v5", 10, ["uchikomu definition 1", "uchikomu definition 2"], 4, "P E1"],
- ["打ち込む", "うちこむ", "vt", "v5", 1, ["uchikomu definition 3", "uchikomu definition 4"], 4, "P E2"],
+ ["打ち込む", "うちこむ", "vt", "v5", 1, ["uchikomu definition 3", "uchikomu definition 4"], 4, "P E2"],
["打ち込む", "ぶちこむ", "vt", "v5", 10, ["buchikomu definition 1", "buchikomu definition 2"], 4, "P E1"],
- ["打ち込む", "ぶちこむ", "vt", "v5", 1, ["buchikomu definition 3", "buchikomu definition 4"], 4, "P E2"],
+ ["打ち込む", "ぶちこむ", "vt", "v5", 1, ["buchikomu definition 3", "buchikomu definition 4"], 4, "P E2"],
["画像", "がぞう", "n", "n", 1, ["gazou definition 1", {"type": "image", "path": "image.gif", "width": 350, "height": 350, "description": "gazou definition 2", "pixelated": true}], 5, "P E1"],
["読む", "よむ", "vt", "v5", 100, ["to read"], 6, "P E1"],
["強み", "つよみ", "n", "n", 90, ["strong point"], 7, "P E1"],
diff --git a/test/eslint-config.test.js b/test/eslint-config.test.js
new file mode 100644
index 00000000..bddde695
--- /dev/null
+++ b/test/eslint-config.test.js
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2024 Yomitan Authors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+import esbuild from 'esbuild';
+import {readFileSync} from 'fs';
+import {dirname, join} from 'path';
+import {fileURLToPath} from 'url';
+import {describe, test} from 'vitest';
+import {parseJson} from '../dev/json.js';
+
+const rootDir = join(dirname(fileURLToPath(import.meta.url)), '..');
+
+/**
+ * @param {string[]} scriptPaths
+ * @returns {Promise<string[]>}
+ */
+async function getDependencies(scriptPaths) {
+ const v = await esbuild.build({
+ entryPoints: scriptPaths,
+ bundle: true,
+ minify: false,
+ sourcemap: true,
+ target: 'es2022',
+ format: 'esm',
+ write: false,
+ metafile: true
+ });
+ const dependencies = Object.keys(v.metafile.inputs);
+ const stringComparer = new Intl.Collator('en-US'); // Invariant locale
+ dependencies.sort((a, b) => stringComparer.compare(a, b));
+ return dependencies;
+}
+
+/**
+ * @param {string[]} dependencies
+ * @returns {string[]}
+ */
+function removeLibraryDependencies(dependencies) {
+ const pattern = /^ext\/lib\//;
+ return dependencies.filter((v) => !pattern.test(v));
+}
+
+/**
+ * @param {{[key: string]: boolean}|undefined} env1
+ * @param {{[key: string]: boolean}} env2
+ * @returns {boolean}
+ */
+function envMatches(env1, env2) {
+ if (typeof env1 !== 'object' || env1 === null) { return false; }
+ const map1 = new Map(Object.entries(env1));
+ const map2 = new Map(Object.entries(env2));
+ if (map1.size !== map2.size) { return false; }
+ for (const [k1, v1] of map1) {
+ if (map2.get(k1) !== v1) { return false; }
+ }
+ return true;
+}
+
+/**
+ * @param {string[]} files1
+ * @param {string[]} files2
+ * @returns {boolean}
+ */
+function filesMatch(files1, files2) {
+ if (!Array.isArray(files1)) { return false; }
+ const set1 = new Set(files1);
+ const set2 = new Set(files2);
+ if (set1.size !== set2.size) { return false; }
+ for (const v of set1) {
+ if (!set2.has(v)) { return false; }
+ }
+ return true;
+}
+
+const targets = [
+ {
+ name: 'sandbox',
+ paths: [
+ 'ext/js/templates/sandbox/template-renderer-frame-main.js'
+ ],
+ /** @type {{[key: string]: boolean}} */
+ env: {
+ webextensions: false
+ }
+ },
+ {
+ name: 'worker',
+ paths: [
+ 'ext/js/dictionary/dictionary-worker-main.js'
+ ],
+ /** @type {{[key: string]: boolean}} */
+ env: {
+ browser: false,
+ worker: true
+ }
+ },
+ {
+ name: 'serviceworker',
+ paths: [
+ 'ext/js/background/background-main.js'
+ ],
+ /** @type {{[key: string]: boolean}} */
+ env: {
+ browser: false,
+ serviceworker: true
+ }
+ }
+];
+
+describe('Eslint configuration', () => {
+ const eslintConfigPath = '.eslintrc.json';
+ /** @type {import('core').SafeAny} */
+ const eslintConfig = parseJson(readFileSync(join(rootDir, eslintConfigPath), 'utf8'));
+ describe.each(targets)('Environment is $name', ({name, paths, env}) => {
+ test('Entry exists', async ({expect}) => {
+ const fullPaths = paths.map((v) => join(rootDir, v));
+ const dependencies = removeLibraryDependencies(await getDependencies(fullPaths));
+
+ let okay = false;
+ const candidates = [];
+ const {overrides} = eslintConfig;
+ for (let i = 0, ii = overrides.length; i < ii; ++i) {
+ const override = overrides[i];
+ if (!envMatches(override.env, env)) { continue; }
+ const {files} = override;
+ if (!Array.isArray(files)) { continue; }
+ candidates.push(i);
+ if (filesMatch(files, dependencies)) {
+ okay = true;
+ break;
+ }
+ }
+
+ if (okay) { return; }
+ switch (candidates.length) {
+ case 0:
+ {
+ const message = `No override found with "${name}" environment: ${JSON.stringify(env)}`;
+ expect(false, message).toStrictEqual(true);
+ }
+ break;
+ case 1:
+ {
+ const index = candidates[0];
+ const message = `Override at index ${index} does not have the expected files for the "${name}" environment.`;
+ expect(overrides[index].files, message).toStrictEqual(dependencies);
+ }
+ break;
+ default:
+ {
+ const message = `No override found with the correct file list for the "${name}" environment; candidate indices: [${candidates.join(', ')}].`;
+ expect([], message).toStrictEqual(dependencies);
+ }
+ break;
+ }
+ });
+ });
+});
diff --git a/test/hotkey-util.test.js b/test/hotkey-util.test.js
index 0a76d0f2..bf1124a5 100644
--- a/test/hotkey-util.test.js
+++ b/test/hotkey-util.test.js
@@ -22,7 +22,7 @@ import {HotkeyUtil} from '../ext/js/input/hotkey-util.js';
/** */
function testCommandConversions() {
describe('CommandConversions', () => {
- /* eslint-disable no-multi-spaces */
+ /* eslint-disable @stylistic/no-multi-spaces */
/** @type {{os: import('environment').OperatingSystem, command: string, expectedCommand: string, expectedInput: {key: string, modifiers: import('input').Modifier[]}}[]} */
const data = [
{os: 'win', command: 'Alt+F', expectedCommand: 'Alt+F', expectedInput: {key: 'KeyF', modifiers: ['alt']}},
@@ -40,7 +40,7 @@ function testCommandConversions() {
{os: 'linux', command: 'MacCtrl+Alt+Shift+F1', expectedCommand: 'Ctrl+Alt+Shift+F1', expectedInput: {key: 'F1', modifiers: ['ctrl', 'alt', 'shift']}},
{os: 'linux', command: 'Command+Alt+Shift+F1', expectedCommand: 'Command+Alt+Shift+F1', expectedInput: {key: 'F1', modifiers: ['meta', 'alt', 'shift']}}
];
- /* eslint-enable no-multi-spaces */
+ /* eslint-enable @stylistic/no-multi-spaces */
const hotkeyUtil = new HotkeyUtil();
for (const {command, os, expectedInput, expectedCommand} of data) {
@@ -58,7 +58,7 @@ function testCommandConversions() {
/** */
function testDisplayNames() {
describe('DisplayNames', () => {
- /* eslint-disable no-multi-spaces */
+ /* eslint-disable @stylistic/no-multi-spaces */
/** @type {{os: import('environment').OperatingSystem, key: ?string, modifiers: import('input').Modifier[], expected: string}[]} */
const data = [
{os: 'win', key: null, modifiers: [], expected: ''},
@@ -137,7 +137,7 @@ function testDisplayNames() {
{os: 'unknown', key: 'KeyF', modifiers: ['mouse1'], expected: 'Mouse 1 + F'},
{os: 'unknown', key: 'F1', modifiers: ['mouse1'], expected: 'Mouse 1 + F1'}
];
- /* eslint-enable no-multi-spaces */
+ /* eslint-enable @stylistic/no-multi-spaces */
const hotkeyUtil = new HotkeyUtil();
diff --git a/test/json-schema.test.js b/test/json-schema.test.js
index a3686758..ab2c0c65 100644
--- a/test/json-schema.test.js
+++ b/test/json-schema.test.js
@@ -123,7 +123,7 @@ function testValidate1() {
/** */
function testValidate2() {
describe('Validate2', () => {
- /* eslint-disable no-multi-spaces */
+ /* eslint-disable @stylistic/no-multi-spaces */
/** @type {{schema: import('ext/json-schema').Schema, inputs: {expected: boolean, value: unknown}[]}[]} */
const data = [
// String tests
@@ -517,7 +517,7 @@ function testValidate2() {
]
}
];
- /* eslint-enable no-multi-spaces */
+ /* eslint-enable @stylistic/no-multi-spaces */
describe.each(data)('Schema %#', ({schema, inputs}) => {
test.each(inputs)(`schemaValidate(${schema}, $value) -> $expected`, ({expected, value}) => {
@@ -890,7 +890,7 @@ function testGetValidValueOrDefault1() {
/** */
function testProxy1() {
describe('Proxy1', () => {
- /* eslint-disable no-multi-spaces */
+ /* eslint-disable @stylistic/no-multi-spaces */
/** @type {{schema: import('ext/json-schema').Schema, tests: {error: boolean, value?: import('ext/json-schema').Value, action: (value: import('core').SafeAny) => void}[]}[]} */
const data = [
// Object tests
@@ -1020,7 +1020,7 @@ function testProxy1() {
]
}
];
- /* eslint-enable no-multi-spaces */
+ /* eslint-enable @stylistic/no-multi-spaces */
describe.each(data)('Schema %#', ({schema, tests}) => {
test.each(tests)('proxy %#', ({error, value, action}) => {
diff --git a/test/language-transformer.test.js b/test/language-transformer.test.js
index 9e9a9ee3..857b5ed0 100644
--- a/test/language-transformer.test.js
+++ b/test/language-transformer.test.js
@@ -64,7 +64,7 @@ function hasTermReasons(languageTransformer, source, expectedTerm, expectedCondi
/** */
function testDeinflections() {
- /* eslint-disable no-multi-spaces */
+ /* eslint-disable @stylistic/no-multi-spaces */
const data = [
{
category: 'adjectives',
@@ -1146,7 +1146,7 @@ function testDeinflections() {
]
}
];
- /* eslint-enable no-multi-spaces */
+ /* eslint-enable @stylistic/no-multi-spaces */
/** @type {import('language-transformer').LanguageTransformDescriptor} */
const descriptor = parseJson(fs.readFileSync(path.join(dirname, '..', 'ext', 'data/language/japanese-transforms.json'), {encoding: 'utf8'}));
diff --git a/test/options-util.test.js b/test/options-util.test.js
index 25abe715..4a75fa14 100644
--- a/test/options-util.test.js
+++ b/test/options-util.test.js
@@ -475,7 +475,7 @@ function createProfileOptionsUpdatedTestData1() {
]
},
inputs: {
- /* eslint-disable no-multi-spaces */
+ /* eslint-disable @stylistic/no-multi-spaces */
hotkeys: [
{action: 'close', argument: '', key: 'Escape', modifiers: [], scopes: ['popup'], enabled: true},
{action: 'focusSearchBox', argument: '', key: 'Escape', modifiers: [], scopes: ['search'], enabled: true},
@@ -494,7 +494,7 @@ function createProfileOptionsUpdatedTestData1() {
{action: 'viewNote', argument: '', key: 'KeyV', modifiers: ['alt'], scopes: ['popup', 'search'], enabled: true},
{action: 'copyHostSelection', argument: '', key: 'KeyC', modifiers: ['ctrl'], scopes: ['popup'], enabled: true}
]
- /* eslint-enable no-multi-spaces */
+ /* eslint-enable @stylistic/no-multi-spaces */
},
popupWindow: {
width: 400,
diff --git a/test/playwright/playwright-util.js b/test/playwright/playwright-util.js
index 425d6140..bf171251 100644
--- a/test/playwright/playwright-util.js
+++ b/test/playwright/playwright-util.js
@@ -23,7 +23,8 @@ const dirname = path.dirname(fileURLToPath(import.meta.url));
export const root = path.join(dirname, '..', '..');
export const test = base.extend({
- context: async ({ }, use) => {
+ // eslint-disable-next-line no-empty-pattern
+ context: async ({}, use) => {
const pathToExtension = path.join(root, 'ext');
const context = await chromium.launchPersistentContext('', {
// headless: false,
diff --git a/test/playwright/visual.spec.js b/test/playwright/visual.spec.js
index 3ecf4c6e..cc2a50d0 100644
--- a/test/playwright/visual.spec.js
+++ b/test/playwright/visual.spec.js
@@ -60,11 +60,11 @@ test('visual', async ({page, extensionId}) => {
// Otherwise prepare for it to be attached
let frame_attached;
- if (popup_frame === undefined) {
+ if (typeof popup_frame === 'undefined') {
frame_attached = page.waitForEvent('frameattached');
}
await page.mouse.move(box.x + offset.x, box.y + offset.y, {steps: 10}); // hover over the test
- if (popup_frame === undefined) {
+ if (typeof popup_frame === 'undefined') {
popup_frame = await frame_attached; // wait for popup to be attached
}
try {
diff --git a/test/profile-conditions-util.test.js b/test/profile-conditions-util.test.js
index fcd53939..261225d9 100644
--- a/test/profile-conditions-util.test.js
+++ b/test/profile-conditions-util.test.js
@@ -59,7 +59,7 @@ function testNormalizeContext() {
/** */
function testSchemas() {
describe('Schemas', () => {
- /* eslint-disable no-multi-spaces */
+ /* eslint-disable @stylistic/no-multi-spaces */
/** @type {{conditionGroups: import('settings').ProfileConditionGroup[], expectedSchema?: import('ext/json-schema').Schema, inputs?: {expected: boolean, context: import('settings').OptionsContext}[]}[]} */
const data = [
// Empty
@@ -1097,7 +1097,7 @@ function testSchemas() {
]
}
];
- /* eslint-enable no-multi-spaces */
+ /* eslint-enable @stylistic/no-multi-spaces */
test.each(data)('schemas-test-%#', ({conditionGroups, expectedSchema, inputs}) => {
const schema = createSchema(conditionGroups);
diff --git a/types/ext/dictionary-database.d.ts b/types/ext/dictionary-database.d.ts
index 2c416c68..1ae4603f 100644
--- a/types/ext/dictionary-database.d.ts
+++ b/types/ext/dictionary-database.d.ts
@@ -198,7 +198,7 @@ export type ObjectStoreName = (
'media'
);
-/* eslint-disable @stylistic/ts/indent */
+/* eslint-disable @stylistic/indent */
export type ObjectStoreData<T extends ObjectStoreName> = (
T extends 'dictionaries' ? DictionaryImporter.Summary :
T extends 'terms' ? DatabaseTermEntry :
@@ -209,7 +209,7 @@ export type ObjectStoreData<T extends ObjectStoreName> = (
T extends 'media' ? MediaDataArrayBufferContent :
never
);
-/* eslint-enable @stylistic/ts/indent */
+/* eslint-enable @stylistic/indent */
export type DeleteDictionaryProgressData = {
count: number;