{ "root": true, "extends": [ "eslint:recommended", "plugin:jsonc/recommended-with-json", "plugin:@typescript-eslint/recommended" ], "parser": "@typescript-eslint/parser", "parserOptions": { "ecmaVersion": 2022, "sourceType": "module", "ecmaFeatures": { "globalReturn": false, "impliedStrict": true }, "project": [ "./jsconfig.json", "./dev/jsconfig.json", "./test/jsconfig.json" ] }, "env": { "browser": true, "es2022": true, "webextensions": true }, "plugins": [ "no-unsanitized", "header", "jsdoc", "jsonc", "unused-imports", "@typescript-eslint", "@stylistic/ts" ], "ignorePatterns": [ "/ext/lib/", "/dev/lib/handlebars/" ], "rules": { "arrow-parens": [ "error", "always" ], "comma-dangle": [ "error", "never" ], "curly": [ "error", "all" ], "dot-notation": "error", "eqeqeq": "error", "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-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", { "message": "Avoid using JSON.parse(), prefer parseJson.", "selector": "MemberExpression[object.name=JSON][property.name=parse]" }, { "message": "Avoid using Response.json(), prefer readResponseJson.", "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-unsanitized/method": "error", "no-unsanitized/property": "error", "jsdoc/check-access": "error", "jsdoc/check-alignment": "error", "jsdoc/check-line-alignment": [ "error", "never", { "wrapIndent": " " } ], "jsdoc/check-param-names": "error", "jsdoc/check-property-names": "error", "jsdoc/check-tag-names": "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-jsdoc": [ "error", { "require": { "ClassDeclaration": false, "FunctionDeclaration": true, "MethodDefinition": false }, "contexts": [ "MethodDefinition[kind=constructor]>FunctionExpression>BlockStatement>ExpressionStatement>AssignmentExpression[left.object.type=ThisExpression]", "ClassDeclaration>Classbody>PropertyDefinition", "MethodDefinition[kind!=constructor][kind!=set]", "MethodDefinition[kind=constructor][value.params.length>0]" ], "checkGetters": "no-setter", "checkSetters": "no-getter" } ], "jsdoc/require-description": "off", "jsdoc/require-param": "error", "jsdoc/require-param-description": "off", "jsdoc/require-param-name": "error", "jsdoc/require-param-type": "error", "jsdoc/require-property": "error", "jsdoc/require-property-description": "off", "jsdoc/require-property-name": "error", "jsdoc/require-property-type": "error", "jsdoc/require-returns": "error", "jsdoc/require-returns-check": "error", "jsdoc/require-returns-description": "off", "jsdoc/require-returns-type": "error", "jsdoc/require-throws": "error", "jsdoc/require-yields": "error", "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/no-octal-escape": "error", "jsonc/object-curly-newline": [ "error", { "consistent": true } ], "jsonc/object-curly-spacing": [ "error", "never" ], "jsonc/object-property-newline": [ "error", { "allowAllPropertiesOnSameLine": true } ], "@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-this-alias": "error", "@typescript-eslint/no-unused-vars": "off", "@typescript-eslint/no-var-requires": "off" }, "overrides": [ { "files": [ "*.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": [ "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/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": [ "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 }, "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" } }, { "files": [ "*.json" ], "parser": "jsonc-eslint-parser", "rules": { "no-multi-spaces": "off" } }, { "files": [ "test/data/anki-note-builder-test-results.json", "test/data/database-test-cases.json", "test/data/translator-test-results-note-data1.json", "test/data/translator-test-results.json" ], "rules": { "jsonc/indent": [ "error", 2 ] } }, { "files": [ "test/data/dictionaries/valid-dictionary1/term_bank_1.json", "test/data/dictionaries/valid-dictionary1/term_bank_2.json" ], "rules": { "jsonc/array-element-newline": [ "off" ], "jsonc/object-property-newline": [ "off" ] } }, { "files": [ "*.js", "*.ts" ], "rules": { "header/header": [ "error", "block", { "pattern": " \\* Copyright \\(C\\) (\\d+-)?2023 Yomitan Authors(\n \\* Copyright \\(C\\) (\\d+-)?2022 Yomichan Authors)?\n \\*\n \\* This program is free software: you can redistribute it and/or modify\n \\* it under the terms of the GNU General Public License as published by\n \\* the Free Software Foundation, either version 3 of the License, or\n \\* \\(at your option\\) any later version\\.\n \\*\n \\* This program is distributed in the hope that it will be useful,\n \\* but WITHOUT ANY WARRANTY; without even the implied warranty of\n \\* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE\\. See the\n \\* GNU General Public License for more details\\.\n \\*\n \\* You should have received a copy of the GNU General Public License\n \\* along with this program\\. If not, see \\.\n " } ] } }, { "files": [ "ext/**/*.js" ], "rules": { "no-console": "error" } }, { "files": [ "ext/js/core.js", "ext/js/core/extension-error.js", "ext/js/**/sandbox/**/*.js" ], "env": { "webextensions": false } }, { "files": [ "test/**/*.js", "dev/**/*.js" ], "env": { "browser": false, "node": true, "webextensions": false } }, { "files": [ "test/data/html/**/*.js" ], "parserOptions": { "sourceType": "script" }, "env": { "browser": true, "node": false, "webextensions": false } }, { "files": [ "test/data/html/**/*.js" ], "excludedFiles": [ "test/data/html/js/html-test-utilities.js" ], "globals": { "HtmlTestUtilities": "readonly" } }, { "files": [ "ext/js/core.js", "ext/js/core/extension-error.js", "ext/js/yomitan.js", "ext/js/accessibility/accessibility-controller.js", "ext/js/background/backend.js", "ext/js/background/offscreen.js", "ext/js/background/offscreen-proxy.js", "ext/js/background/profile-conditions-util.js", "ext/js/background/request-builder.js", "ext/js/background/script-manager.js", "ext/js/comm/anki-connect.js", "ext/js/comm/clipboard-monitor.js", "ext/js/comm/clipboard-reader.js", "ext/js/comm/mecab.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/dom/simple-dom-parser.js", "ext/js/extension/environment.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/deinflector.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" ], "env": { "browser": false, "serviceworker": true, "webextensions": true }, "globals": { "FileReader": "readonly", "Intl": "readonly", "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" ] } ] }