aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.eslintrc.json143
-rw-r--r--dev/bin/build.js5
-rw-r--r--dev/generate-css-json.js5
-rw-r--r--dev/lib/dexie.js1
-rw-r--r--dev/lib/parse5.js1
-rw-r--r--dev/lib/ucs2length.js4
-rw-r--r--dev/lib/wanakana.js1
-rw-r--r--dev/lib/z-worker.js1
-rw-r--r--dev/lib/zip.js1
-rw-r--r--dev/manifest-util.js1
-rw-r--r--ext/data/language/japanese-transforms.json1
-rw-r--r--ext/js/background/backend.js2
-rw-r--r--ext/js/comm/cross-frame-api.js1
-rw-r--r--ext/js/core/logger.js1
-rw-r--r--ext/js/data/json-schema.js2
-rw-r--r--ext/js/data/options-util.js9
-rw-r--r--ext/js/dictionary/dictionary-database.js5
-rw-r--r--ext/js/display/display-audio.js6
-rw-r--r--ext/js/display/display.js6
-rw-r--r--ext/js/pages/action-popup-main.js3
-rw-r--r--ext/js/pages/settings/backup-controller.js12
-rw-r--r--ext/js/pages/settings/profile-controller.js3
-rw-r--r--ext/js/pages/welcome-main.js2
-rw-r--r--ext/js/templates/sandbox/anki-template-renderer.js6
-rw-r--r--ext/js/templates/template-renderer-proxy.js14
-rw-r--r--playwright.config.js3
-rw-r--r--test/core.test.js12
-rw-r--r--test/fixtures/dom-test.js11
-rw-r--r--test/hotkey-util.test.js2
-rw-r--r--test/json-schema.test.js18
-rw-r--r--test/playwright/playwright-util.js57
-rw-r--r--types/ext/backend.d.ts1
-rw-r--r--types/ext/dictionary-data.d.ts4
-rw-r--r--types/ext/dictionary-database.d.ts6
-rw-r--r--types/ext/input.d.ts3
-rw-r--r--types/ext/profile-conditions-util.d.ts2
-rw-r--r--types/ext/settings-modifications.d.ts10
-rw-r--r--types/ext/settings.d.ts18
-rw-r--r--types/other/rollup-parse-ast.d.ts1
39 files changed, 267 insertions, 117 deletions
diff --git a/.eslintrc.json b/.eslintrc.json
index 5b6ebd05..32bbdaec 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -3,8 +3,7 @@
"extends": [
"eslint:recommended",
"plugin:jsonc/recommended-with-json",
- "plugin:eslint-comments/recommended",
- "plugin:@typescript-eslint/recommended"
+ "plugin:eslint-comments/recommended"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
@@ -76,34 +75,84 @@
"prefer-const": ["error", {"destructuring": "all"}],
"require-atomic-updates": "off",
+ "@stylistic/array-bracket-newline": ["error", "consistent"],
"@stylistic/array-bracket-spacing": ["error", "never"],
+ "@stylistic/array-element-newline": ["error", "consistent"],
"@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/comma-style": ["error", "last"],
"@stylistic/computed-property-spacing": ["error", "never"],
+ "@stylistic/dot-location": ["error", "property"],
"@stylistic/eol-last": ["error", "always"],
"@stylistic/func-call-spacing": ["error", "never"],
+ "@stylistic/function-call-argument-newline": ["error", "consistent"],
+ "@stylistic/function-call-spacing": ["error", "never"],
"@stylistic/function-paren-newline": ["error", "multiline-arguments"],
"@stylistic/generator-star-spacing": ["error", "before"],
+ "@stylistic/implicit-arrow-linebreak": ["error", "beside"],
"@stylistic/indent": ["error", 4, {"SwitchCase": 1, "MemberExpression": 1, "flatTernaryExpressions": true, "ignoredNodes": ["ConditionalExpression"]}],
+ "@stylistic/indent-binary-ops": ["error", 0],
"@stylistic/key-spacing": ["error", {"beforeColon": false, "afterColon": true, "mode": "strict"}],
"@stylistic/keyword-spacing": ["error", {"before": true, "after": true}],
+ "@stylistic/linebreak-style": ["error", "unix"],
+ "@stylistic/lines-around-comment": "off",
+ "@stylistic/lines-between-class-members": ["error", "always", {"exceptAfterSingleLine": true}],
+ "@stylistic/max-len": "off",
+ "@stylistic/max-statements-per-line": ["error", {"max": 2}],
+ "@stylistic/member-delimiter-style": [
+ "error",
+ {
+ "multiline": {"delimiter": "semi", "requireLast": true},
+ "singleline": {"delimiter": "comma", "requireLast": false},
+ "multilineDetection": "brackets"
+ }
+ ],
+ "@stylistic/multiline-ternary": ["error", "always-multiline"],
"@stylistic/new-parens": "error",
+ "@stylistic/newline-per-chained-call": ["error", {"ignoreChainWithDepth": 3}],
+ "@stylistic/no-confusing-arrow": "error",
+ "@stylistic/no-extra-parens": "off",
+ "@stylistic/no-extra-semi": "error",
+ "@stylistic/no-floating-decimal": "error",
+ "@stylistic/no-mixed-operators": ["error", {"allowSamePrecedence": true, "groups": [["&&", "||"]]}],
+ "@stylistic/no-mixed-spaces-and-tabs": "error",
"@stylistic/no-multi-spaces": "error",
- "@stylistic/no-multiple-empty-lines": ["error", {"max": 2}],
+ "@stylistic/no-multiple-empty-lines": ["error", {"max": 2, "maxEOF": 0, "maxBOF": 0}],
+ "@stylistic/no-tabs": "error",
"@stylistic/no-trailing-spaces": "error",
"@stylistic/no-whitespace-before-property": "error",
+ "@stylistic/nonblock-statement-body-position": ["error", "beside"],
"@stylistic/object-curly-newline": "error",
"@stylistic/object-curly-spacing": ["error", "never"],
+ "@stylistic/object-property-newline": ["error", {"allowAllPropertiesOnSameLine": true}],
+ "@stylistic/one-var-declaration-per-line": ["error", "initializations"],
+ "@stylistic/operator-linebreak": ["error", "after"],
"@stylistic/padded-blocks": ["error", "never"],
- "@stylistic/quote-props": ["error", "consistent"],
+ "@stylistic/padding-line-between-statements": [
+ "error",
+ {"blankLine": "always", "prev": "*", "next": "import"},
+ {"blankLine": "always", "prev": "import", "next": "*"},
+ {"blankLine": "always", "prev": "*", "next": "export"},
+ {"blankLine": "always", "prev": "import", "next": "let"},
+ {"blankLine": "always", "prev": "import", "next": "const"},
+ {"blankLine": "always", "prev": "export", "next": "let"},
+ {"blankLine": "always", "prev": "export", "next": "const"},
+ {"blankLine": "always", "prev": "export", "next": "export"},
+ {"blankLine": "always", "prev": "export", "next": "type"},
+ {"blankLine": "always", "prev": "type", "next": "export"},
+ {"blankLine": "always", "prev": "type", "next": "type"},
+ {"blankLine": "never", "prev": "import", "next": "import"}
+ ],
+ "@stylistic/quote-props": ["error", "consistent-as-needed", {"numbers": true}],
"@stylistic/quotes": ["error", "single", "avoid-escape"],
"@stylistic/rest-spread-spacing": ["error", "never"],
"@stylistic/semi": "error",
"@stylistic/semi-spacing": ["error", {"before": false, "after": true}],
+ "@stylistic/semi-style": ["error", "last"],
"@stylistic/space-before-blocks": ["error", "always"],
"@stylistic/space-before-function-paren": ["error", {"anonymous": "never", "named": "never", "asyncArrow": "always"}],
"@stylistic/space-in-parens": ["error", "never"],
@@ -113,7 +162,21 @@
"@stylistic/switch-colon-spacing": ["error", {"after": true, "before": false}],
"@stylistic/template-curly-spacing": ["error", "never"],
"@stylistic/template-tag-spacing": ["error", "never"],
+ "@stylistic/type-annotation-spacing": [
+ "error",
+ {
+ "before": false,
+ "after": true,
+ "overrides": {
+ "arrow": {"before": true, "after": true}
+ }
+ }
+ ],
+ "@stylistic/type-generic-spacing": "error",
+ "@stylistic/type-named-tuple-spacing": "error",
"@stylistic/wrap-iife": ["error", "inside"],
+ "@stylistic/wrap-regex": "off",
+ "@stylistic/yield-star-spacing": ["error", {"before": true, "after": false}],
"no-unsanitized/method": "error",
"no-unsanitized/property": "error",
@@ -184,29 +247,44 @@
"eslint-comments/no-unused-disable": "error",
- "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-this-alias": "error",
- "@typescript-eslint/no-unused-vars": "off",
- "@typescript-eslint/no-var-requires": "off"
+ "unused-imports/no-unused-imports": "error"
},
"overrides": [
{
"files": [
+ "*.js",
"*.ts"
],
+ "extends": [
+ "plugin:@typescript-eslint/recommended-type-checked"
+ ],
"rules": {
- "no-undef": "off",
-
- "@typescript-eslint/no-unused-vars": ["error", {"vars": "local", "args": "after-used", "argsIgnorePattern": "^_", "caughtErrors": "none"}],
+ "@typescript-eslint/no-floating-promises": "off",
+ "@typescript-eslint/no-misused-promises": "off",
+ "@typescript-eslint/no-redundant-type-constituents": "off",
+ "@typescript-eslint/no-unsafe-argument": "off",
+ "@typescript-eslint/no-unsafe-assignment": "off",
+ "@typescript-eslint/no-unsafe-call": "off",
+ "@typescript-eslint/no-unsafe-enum-comparison": "off",
+ "@typescript-eslint/no-unsafe-member-access": "off",
+ "@typescript-eslint/no-unsafe-return": "off",
+ "@typescript-eslint/require-await": "off",
+ "@typescript-eslint/restrict-template-expressions": "off",
+ "@typescript-eslint/ban-ts-comment": ["error", {"ts-expect-error": {"descriptionFormat": "^ - .+$"}}],
+ "@typescript-eslint/ban-types": ["error", {"types": {"object": true}, "extendDefaults": true}],
+ "@typescript-eslint/no-explicit-any": "error",
+ "@typescript-eslint/no-shadow": ["error", {"builtinGlobals": false}],
+ "@typescript-eslint/no-this-alias": "error",
+ "@typescript-eslint/no-unused-vars": ["error", {"vars": "local", "args": "after-used", "argsIgnorePattern": "^_", "caughtErrors": "none"}]
+ }
+ },
+ {
+ "files": [
+ "*.ts"
+ ],
+ "rules": {
"@stylistic/block-spacing": "off",
- "@stylistic/brace-style": ["error", "1tbs", {"allowSingleLine": true}],
"@stylistic/comma-dangle": [
"error",
{
@@ -220,32 +298,9 @@
"tuples": "always-multiline"
}
],
- "@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",
- {
- "multiline": {"delimiter": "semi", "requireLast": true},
- "singleline": {"delimiter": "comma", "requireLast": false},
- "multilineDetection": "brackets"
- }
- ],
- "@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"
+ "@stylistic/indent-binary-ops": "off",
+ "@stylistic/no-multiple-empty-lines": ["error", {"max": 1, "maxEOF": 0, "maxBOF": 0}],
+ "@stylistic/no-extra-parens": ["error", "all"]
}
},
{
diff --git a/dev/bin/build.js b/dev/bin/build.js
index 190964d5..bc0a8cb8 100644
--- a/dev/bin/build.js
+++ b/dev/bin/build.js
@@ -23,10 +23,10 @@ import JSZip from 'jszip';
import {fileURLToPath} from 'node:url';
import path from 'path';
import readline from 'readline';
+import {parseArgs} from 'util';
import {buildLibs} from '../build-libs.js';
import {ManifestUtil} from '../manifest-util.js';
import {getAllFiles, testMain} from '../util.js';
-import {parseArgs} from 'util';
const dirname = path.dirname(fileURLToPath(import.meta.url));
@@ -267,7 +267,8 @@ export async function main(argv) {
await buildLibs();
const variantNames = /** @type {string[]} */ ((
argv.length === 0 || args.all ?
- manifestUtil.getVariants().filter(({buildable}) => buildable !== false).map(({name}) => name) : []
+ manifestUtil.getVariants().filter(({buildable}) => buildable !== false).map(({name}) => name) :
+ []
));
await build(buildDir, extDir, manifestUtil, variantNames, manifestPath, dryRun, dryRunBuildZip, yomitanVersion);
} finally {
diff --git a/dev/generate-css-json.js b/dev/generate-css-json.js
index b196e411..26bdfa64 100644
--- a/dev/generate-css-json.js
+++ b/dev/generate-css-json.js
@@ -151,7 +151,10 @@ export function generateRules(cssFilePath, overridesCssFilePath) {
const styles = [];
if (typeof declarations !== 'undefined') {
for (const declaration of declarations) {
- if (declaration.type !== 'declaration') { console.log(declaration); continue; }
+ if (declaration.type !== 'declaration') {
+ console.log(declaration);
+ continue;
+ }
const {property, value} = /** @type {css.Declaration} */ (declaration);
if (typeof property !== 'string' || typeof value !== 'string') { continue; }
styles.push([property, value]);
diff --git a/dev/lib/dexie.js b/dev/lib/dexie.js
index 834260e0..ffbd2923 100644
--- a/dev/lib/dexie.js
+++ b/dev/lib/dexie.js
@@ -14,6 +14,7 @@
* 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 Dexie from 'dexie';
import 'dexie-export-import';
diff --git a/dev/lib/parse5.js b/dev/lib/parse5.js
index 03249db4..ce92730d 100644
--- a/dev/lib/parse5.js
+++ b/dev/lib/parse5.js
@@ -14,4 +14,5 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+
export * from 'parse5';
diff --git a/dev/lib/ucs2length.js b/dev/lib/ucs2length.js
index ce9027de..7ca3c545 100644
--- a/dev/lib/ucs2length.js
+++ b/dev/lib/ucs2length.js
@@ -14,7 +14,9 @@
* 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 ucs2length from 'ajv/dist/runtime/ucs2length.js';
+
const ucs2length2 = ucs2length.default;
-export {ucs2length2 as ucs2length};
+export {ucs2length2 as ucs2length};
diff --git a/dev/lib/wanakana.js b/dev/lib/wanakana.js
index b2679cec..24cf63ab 100644
--- a/dev/lib/wanakana.js
+++ b/dev/lib/wanakana.js
@@ -14,4 +14,5 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+
export * from 'wanakana';
diff --git a/dev/lib/z-worker.js b/dev/lib/z-worker.js
index 142ed8fc..4e5fe318 100644
--- a/dev/lib/z-worker.js
+++ b/dev/lib/z-worker.js
@@ -14,4 +14,5 @@
* 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 '../../node_modules/@zip.js/zip.js/lib/z-worker.js';
diff --git a/dev/lib/zip.js b/dev/lib/zip.js
index 007b4285..62d0784c 100644
--- a/dev/lib/zip.js
+++ b/dev/lib/zip.js
@@ -14,4 +14,5 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+
export * from '@zip.js/zip.js/lib/zip.js';
diff --git a/dev/manifest-util.js b/dev/manifest-util.js
index 6ab81790..741f8b31 100644
--- a/dev/manifest-util.js
+++ b/dev/manifest-util.js
@@ -342,4 +342,3 @@ export class ManifestUtil {
return modifiedManifest;
}
}
-
diff --git a/ext/data/language/japanese-transforms.json b/ext/data/language/japanese-transforms.json
index b3a00a73..b1f39cbc 100644
--- a/ext/data/language/japanese-transforms.json
+++ b/ext/data/language/japanese-transforms.json
@@ -1010,4 +1010,3 @@
}
]
}
-
diff --git a/ext/js/background/backend.js b/ext/js/background/backend.js
index 909faf29..8b5e8383 100644
--- a/ext/js/background/backend.js
+++ b/ext/js/background/backend.js
@@ -2480,7 +2480,7 @@ export class Backend {
chrome.storage.session.get(['openedWelcomePage']).then((result) => {
if (!result.openedWelcomePage) {
this._openWelcomeGuidePage();
- chrome.storage.session.set({'openedWelcomePage': true});
+ chrome.storage.session.set({openedWelcomePage: true});
}
});
}
diff --git a/ext/js/comm/cross-frame-api.js b/ext/js/comm/cross-frame-api.js
index 8fbee20c..4b4e9419 100644
--- a/ext/js/comm/cross-frame-api.js
+++ b/ext/js/comm/cross-frame-api.js
@@ -410,6 +410,7 @@ export class CrossFrameAPI {
}
return await this._createCommPort(otherTabId, otherFrameId);
}
+
/**
* @param {number} otherTabId
* @param {number} otherFrameId
diff --git a/ext/js/core/logger.js b/ext/js/core/logger.js
index 165e1ae2..6cf1cc1f 100644
--- a/ext/js/core/logger.js
+++ b/ext/js/core/logger.js
@@ -59,6 +59,7 @@ export class Logger extends EventDispatcher {
} else {
errorString = (
typeof error === 'object' && error !== null ?
+ // eslint-disable-next-line @typescript-eslint/no-base-to-string
error.toString() :
`${error}`
);
diff --git a/ext/js/data/json-schema.js b/ext/js/data/json-schema.js
index 9b7ea011..3342e387 100644
--- a/ext/js/data/json-schema.js
+++ b/ext/js/data/json-schema.js
@@ -805,7 +805,7 @@ export class JsonSchema {
const {type: schemaType, const: schemaConst, enum: schemaEnum} = schema;
const type = this._getValueType(value);
if (!this._isValueTypeAny(value, type, schemaType)) {
- throw this._createError(`Value type ${type} does not match schema type ${schemaType}`);
+ throw this._createError(`Value type ${type} does not match schema type ${Array.isArray(schemaType) ? schemaType.join(',') : schemaType}`);
}
if (typeof schemaConst !== 'undefined' && !this._valuesAreEqual(value, schemaConst)) {
diff --git a/ext/js/data/options-util.js b/ext/js/data/options-util.js
index d93927a7..2ecd5527 100644
--- a/ext/js/data/options-util.js
+++ b/ext/js/data/options-util.js
@@ -46,7 +46,8 @@ export class OptionsUtil {
// Invalid options
let options = /** @type {{[key: string]: unknown}} */ (
typeof optionsInput === 'object' && optionsInput !== null && !Array.isArray(optionsInput) ?
- optionsInput : {}
+ optionsInput :
+ {}
);
// Check for legacy options
@@ -495,6 +496,7 @@ export class OptionsUtil {
* @returns {import('options-util').UpdateFunction[]}
*/
_getVersionUpdates(targetVersion) {
+ /* eslint-disable @typescript-eslint/unbound-method */
const result = [
this._updateVersion1,
this._updateVersion2,
@@ -521,6 +523,7 @@ export class OptionsUtil {
this._updateVersion23,
this._updateVersion24
];
+ /* eslint-enable @typescript-eslint/unbound-method */
if (typeof targetVersion === 'number' && targetVersion < result.length) {
result.splice(targetVersion);
}
@@ -1090,9 +1093,9 @@ export class OptionsUtil {
}
if (customTemplates && isObject(chrome.storage)) {
- chrome.storage.session.set({'needsCustomTemplatesWarning': true});
+ chrome.storage.session.set({needsCustomTemplatesWarning: true});
await this._createTab(chrome.runtime.getURL('/welcome.html'));
- chrome.storage.session.set({'openedWelcomePage': true});
+ chrome.storage.session.set({openedWelcomePage: true});
}
}
diff --git a/ext/js/dictionary/dictionary-database.js b/ext/js/dictionary/dictionary-database.js
index 1c52b7ab..6c7de339 100644
--- a/ext/js/dictionary/dictionary-database.js
+++ b/ext/js/dictionary/dictionary-database.js
@@ -37,7 +37,10 @@ export class DictionaryDatabase {
/** @type {import('dictionary-database').CreateQuery<string>} */
this._createBoundQuery1 = (item) => IDBKeyRange.bound(item, `${item}\uffff`, false, false);
/** @type {import('dictionary-database').CreateQuery<string>} */
- this._createBoundQuery2 = (item) => { item = stringReverse(item); return IDBKeyRange.bound(item, `${item}\uffff`, false, false); };
+ this._createBoundQuery2 = (item) => {
+ item = stringReverse(item);
+ return IDBKeyRange.bound(item, `${item}\uffff`, false, false);
+ };
/** @type {import('dictionary-database').CreateResult<import('dictionary-database').TermExactRequest, import('dictionary-database').DatabaseTermEntryWithId, import('dictionary-database').TermEntry>} */
this._createTermBind1 = this._createTermExact.bind(this);
/** @type {import('dictionary-database').CreateResult<import('dictionary-database').DictionaryAndQueryRequest, import('dictionary-database').DatabaseTermEntryWithId, import('dictionary-database').TermEntry>} */
diff --git a/ext/js/display/display-audio.js b/ext/js/display/display-audio.js
index deaa0976..7d75d6b0 100644
--- a/ext/js/display/display-audio.js
+++ b/ext/js/display/display-audio.js
@@ -514,8 +514,10 @@ export class DisplayAudio {
!canToggleOff ||
primaryCardAudio === null ||
primaryCardAudio.index !== index ||
- primaryCardAudio.subIndex !== subIndex
- ) ? {index: index, subIndex} : null;
+ primaryCardAudio.subIndex !== subIndex ?
+ {index: index, subIndex} :
+ null
+ );
cacheEntry.primaryCardAudio = primaryCardAudio;
if (menu !== null) {
diff --git a/ext/js/display/display.js b/ext/js/display/display.js
index f05feac8..a5dad2d1 100644
--- a/ext/js/display/display.js
+++ b/ext/js/display/display.js
@@ -806,8 +806,10 @@ export class Display extends EventDispatcher {
const historyMode = (
eventType === 'click' ||
!(typeof historyState === 'object' && historyState !== null) ||
- historyState.cause !== 'queryParser'
- ) ? 'new' : 'overwrite';
+ historyState.cause !== 'queryParser' ?
+ 'new' :
+ 'overwrite'
+ );
/** @type {import('display').ContentDetails} */
const details = {
focus: false,
diff --git a/ext/js/pages/action-popup-main.js b/ext/js/pages/action-popup-main.js
index e5738878..b5728215 100644
--- a/ext/js/pages/action-popup-main.js
+++ b/ext/js/pages/action-popup-main.js
@@ -50,7 +50,8 @@ class DisplayController {
typeof manifest.options_ui === 'object' &&
manifest.options_ui !== null &&
typeof manifest.options_ui.page === 'string' ?
- manifest.options_ui.page : ''
+ manifest.options_ui.page :
+ ''
);
this._setupButtonEvents('.action-open-settings', 'openSettingsPage', chrome.runtime.getURL(optionsPageUrl));
this._setupButtonEvents('.action-open-permissions', null, chrome.runtime.getURL('/permissions.html'));
diff --git a/ext/js/pages/settings/backup-controller.js b/ext/js/pages/settings/backup-controller.js
index 79733c4d..59bcaed9 100644
--- a/ext/js/pages/settings/backup-controller.js
+++ b/ext/js/pages/settings/backup-controller.js
@@ -579,7 +579,9 @@ export class BackupController {
*/
async _exportDatabase(databaseName) {
const db = await new Dexie(databaseName).open();
- const blob = await db.export({progressCallback: this._databaseExportProgressCallback});
+ const blob = await db.export({
+ progressCallback: this._databaseExportProgressCallback.bind(this)
+ });
await db.close();
return blob;
}
@@ -639,12 +641,14 @@ export class BackupController {
}
/**
- * @param {string} databaseName
+ * @param {string} _databaseName
* @param {File} file
*/
- async _importDatabase(databaseName, file) {
+ async _importDatabase(_databaseName, file) {
await this._settingsController.application.api.purgeDatabase();
- await Dexie.import(file, {progressCallback: this._databaseImportProgressCallback});
+ await Dexie.import(file, {
+ progressCallback: this._databaseImportProgressCallback.bind(this)
+ });
this._settingsController.application.api.triggerDatabaseUpdated('dictionary', 'import');
this._settingsController.application.triggerStorageChanged();
}
diff --git a/ext/js/pages/settings/profile-controller.js b/ext/js/pages/settings/profile-controller.js
index c5ccbe7d..5a7b5ed4 100644
--- a/ext/js/pages/settings/profile-controller.js
+++ b/ext/js/pages/settings/profile-controller.js
@@ -549,7 +549,8 @@ export class ProfileController {
Number.isFinite(intValue) &&
intValue >= 0 &&
intValue < this.profileCount ?
- intValue : null
+ intValue :
+ null
);
}
diff --git a/ext/js/pages/welcome-main.js b/ext/js/pages/welcome-main.js
index 82afaacb..9990b4e7 100644
--- a/ext/js/pages/welcome-main.js
+++ b/ext/js/pages/welcome-main.js
@@ -63,7 +63,7 @@ await Application.main(async (application) => {
setupEnvironmentInfo(application.api);
- chrome.storage.session.get({'needsCustomTemplatesWarning': false}).then((result) => {
+ chrome.storage.session.get({needsCustomTemplatesWarning: false}).then((result) => {
if (result.needsCustomTemplatesWarning) {
document.documentElement.dataset.warnCustomTemplates = 'true';
chrome.storage.session.remove(['needsCustomTemplatesWarning']);
diff --git a/ext/js/templates/sandbox/anki-template-renderer.js b/ext/js/templates/sandbox/anki-template-renderer.js
index 135200da..2320a0b1 100644
--- a/ext/js/templates/sandbox/anki-template-renderer.js
+++ b/ext/js/templates/sandbox/anki-template-renderer.js
@@ -279,7 +279,10 @@ export class AnkiTemplateRenderer {
const regex = new RegExp(pattern, typeof flags === 'string' ? flags : '');
/** @type {string[]} */
const parts = [];
- value.replace(regex, (g0) => { parts.push(g0); return g0; });
+ value.replace(regex, (g0) => {
+ parts.push(g0);
+ return g0;
+ });
value = parts.join('');
} catch (e) {
return `${e}`;
@@ -531,6 +534,7 @@ export class AnkiTemplateRenderer {
_concat(args) {
let result = '';
for (let i = 0, ii = args.length; i < ii; ++i) {
+ // eslint-disable-next-line @typescript-eslint/restrict-plus-operands
result += args[i];
}
return result;
diff --git a/ext/js/templates/template-renderer-proxy.js b/ext/js/templates/template-renderer-proxy.js
index e4814ec4..c1f5a5bf 100644
--- a/ext/js/templates/template-renderer-proxy.js
+++ b/ext/js/templates/template-renderer-proxy.js
@@ -16,8 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-import {generateId} from '../core/utilities.js';
import {ExtensionError} from '../core/extension-error.js';
+import {generateId} from '../core/utilities.js';
export class TemplateRendererProxy {
constructor() {
@@ -220,10 +220,14 @@ export class TemplateRendererProxy {
}
};
- let timer = (typeof timeout === 'number' ? setTimeout(() => {
- cleanup();
- reject(new Error('Timeout'));
- }, timeout) : null);
+ let timer = (
+ typeof timeout === 'number' ?
+ setTimeout(() => {
+ cleanup();
+ reject(new Error('Timeout'));
+ }, timeout) :
+ null
+ );
this._invocations.add(invocation);
diff --git a/playwright.config.js b/playwright.config.js
index a13eb710..4cd94b6b 100644
--- a/playwright.config.js
+++ b/playwright.config.js
@@ -14,9 +14,9 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+
// @ts-check
import {defineConfig, devices} from '@playwright/test';
-
/**
* Read environment variables from file.
* https://github.com/motdotla/dotenv
@@ -116,4 +116,3 @@ export default defineConfig({
// port: 3000,
// },
});
-
diff --git a/test/core.test.js b/test/core.test.js
index 0ddcc2d1..7e19d04d 100644
--- a/test/core.test.js
+++ b/test/core.test.js
@@ -269,8 +269,16 @@ function testDeepEqual() {
/** @type {import('test/core').DeepEqualTestData} */
const recursiveTestsData = [
{
- value1: (() => { const x = {}; x.x = x; return x; })(),
- value2: (() => { const x = {}; x.x = x; return x; })(),
+ value1: (() => {
+ const x = {};
+ x.x = x;
+ return x;
+ })(),
+ value2: (() => {
+ const x = {};
+ x.x = x;
+ return x;
+ })(),
expected: false
}
];
diff --git a/test/fixtures/dom-test.js b/test/fixtures/dom-test.js
index a0a17127..578b1324 100644
--- a/test/fixtures/dom-test.js
+++ b/test/fixtures/dom-test.js
@@ -43,10 +43,13 @@ function prepareWindow(window) {
export async function setupDomTest(htmlFilePath) {
const html = typeof htmlFilePath === 'string' ? fs.readFileSync(htmlFilePath, {encoding: 'utf8'}) : '<!DOCTYPE html>';
const env = builtinEnvironments.jsdom;
- const {teardown} = await env.setup(global, {jsdom: {html}});
+ const environment = await env.setup(global, {jsdom: {html}});
const window = /** @type {import('jsdom').DOMWindow} */ (/** @type {unknown} */ (global.window));
prepareWindow(window);
- return {window, teardown};
+ return {
+ window,
+ teardown: (global) => environment.teardown(global)
+ };
}
/**
@@ -59,13 +62,13 @@ export function createDomTest(htmlFilePath) {
// eslint-disable-next-line no-empty-pattern
window: async ({}, use) => {
const env = builtinEnvironments.jsdom;
- const {teardown} = await env.setup(global, {jsdom: {html}});
+ const environment = await env.setup(global, {jsdom: {html}});
const window = /** @type {import('jsdom').DOMWindow} */ (/** @type {unknown} */ (global.window));
prepareWindow(window);
try {
await use(window);
} finally {
- teardown(global);
+ environment.teardown(global);
}
}
});
diff --git a/test/hotkey-util.test.js b/test/hotkey-util.test.js
index bf1124a5..01a2b536 100644
--- a/test/hotkey-util.test.js
+++ b/test/hotkey-util.test.js
@@ -160,7 +160,7 @@ function testSortModifiers() {
const hotkeyUtil = new HotkeyUtil();
for (const {modifiers, expected} of data) {
- test(`[${modifiers}] -> [${expected}]`, () => {
+ test(`[${modifiers.join(',')}] -> [${expected.join(',')}]`, () => {
const modifiers2 = hotkeyUtil.sortModifiers(modifiers);
expect(modifiers2).toStrictEqual(modifiers);
expect(modifiers2).toStrictEqual(expected);
diff --git a/test/json-schema.test.js b/test/json-schema.test.js
index ab2c0c65..af4b7acd 100644
--- a/test/json-schema.test.js
+++ b/test/json-schema.test.js
@@ -520,7 +520,7 @@ function testValidate2() {
/* eslint-enable @stylistic/no-multi-spaces */
describe.each(data)('Schema %#', ({schema, inputs}) => {
- test.each(inputs)(`schemaValidate(${schema}, $value) -> $expected`, ({expected, value}) => {
+ test.each(inputs)(`schemaValidate(${JSON.stringify(schema)}, $value) -> $expected`, ({expected, value}) => {
const actual = schemaValidate(schema, value);
expect(actual).toStrictEqual(expected);
});
@@ -878,7 +878,7 @@ function testGetValidValueOrDefault1() {
];
describe.each(data)('Schema %#', ({schema, inputs}) => {
- test.each(inputs)(`getValidValueOrDefault(${schema}, %o) -> %o`, (value, expected) => {
+ test.each(inputs)(`getValidValueOrDefault(${JSON.stringify(schema)}, %o) -> %o`, (value, expected) => {
const actual = getValidValueOrDefault(schema, value);
expect(actual).toStrictEqual(expected);
});
@@ -985,11 +985,15 @@ function testProxy1() {
{error: true, value: ['default'], action: (value) => { value[0] = null; }},
{error: false, value: ['default'], action: (value) => { delete value[0]; }},
{error: false, value: ['default'], action: (value) => { value[1] = 'string'; }},
- {error: false, value: ['default'], action: (value) => {
- value[1] = 'string';
- if (value.length !== 2) { throw new Error(`Invalid length; expected=2; actual=${value.length}`); }
- if (typeof value.push !== 'function') { throw new Error(`Invalid push; expected=function; actual=${typeof value.push}`); }
- }}
+ {
+ error: false,
+ value: ['default'],
+ action: (value) => {
+ value[1] = 'string';
+ if (value.length !== 2) { throw new Error(`Invalid length; expected=2; actual=${value.length}`); }
+ if (typeof value.push !== 'function') { throw new Error(`Invalid push; expected=function; actual=${typeof value.push}`); }
+ }
+ }
]
},
diff --git a/test/playwright/playwright-util.js b/test/playwright/playwright-util.js
index bf171251..b364c80b 100644
--- a/test/playwright/playwright-util.js
+++ b/test/playwright/playwright-util.js
@@ -20,6 +20,7 @@ import path from 'path';
import {fileURLToPath} from 'url';
const dirname = path.dirname(fileURLToPath(import.meta.url));
+
export const root = path.join(dirname, '..', '..');
export const test = base.extend({
@@ -47,6 +48,7 @@ export const test = base.extend({
await use(extensionId);
}
});
+
export const expect = test.expect;
export const mockModelFieldNames = [
@@ -58,10 +60,10 @@ export const mockModelFieldNames = [
/** @type {{[key: string]: string|undefined}} */
export const mockModelFieldsToAnkiValues = {
- 'Word': '{expression}',
- 'Reading': '{furigana-plain}',
- 'Sentence': '{clipboard-text}',
- 'Audio': '{audio}'
+ Word: '{expression}',
+ Reading: '{furigana-plain}',
+ Sentence: '{clipboard-text}',
+ Audio: '{audio}'
};
/**
@@ -87,23 +89,30 @@ export const writeToClipboardFromPage = async (page, text) => {
};
export const expectedAddNoteBody = {
- 'action': 'addNote',
- 'params':
- {
- 'note': {
- 'fields': {
- 'Word': '読む', 'Reading': '読[よ]む', 'Audio': '[sound:mock_audio.mp3]', 'Sentence': '読むの例文'
+ version: 2,
+ action: 'addNote',
+ params: {
+ note: {
+ fields: {
+ Word: '読む',
+ Reading: '読[よ]む',
+ Audio: '[sound:mock_audio.mp3]',
+ Sentence: '読むの例文'
},
- 'tags': ['yomitan'],
- 'deckName': 'Mock Deck',
- 'modelName': 'Mock Model',
- 'options': {
- 'allowDuplicate': false, 'duplicateScope': 'collection', 'duplicateScopeOptions': {
- 'deckName': null, 'checkChildren': false, 'checkAllModels': false
+ tags: ['yomitan'],
+ deckName: 'Mock Deck',
+ modelName: 'Mock Model',
+ options: {
+ allowDuplicate: false,
+ duplicateScope: 'collection',
+ duplicateScopeOptions: {
+ deckName: null,
+ checkChildren: false,
+ checkAllModels: false
}
}
}
- }, 'version': 2
+ }
};
const baseAnkiResp = {
@@ -113,11 +122,11 @@ const baseAnkiResp = {
/** @type {{[key: string]: import('core').SerializableObject}} */
const ankiRouteResponses = {
- 'version': Object.assign({body: JSON.stringify(6)}, baseAnkiResp),
- 'deckNames': Object.assign({body: JSON.stringify(['Mock Deck'])}, baseAnkiResp),
- 'modelNames': Object.assign({body: JSON.stringify(['Mock Model'])}, baseAnkiResp),
- 'modelFieldNames': Object.assign({body: JSON.stringify(mockModelFieldNames)}, baseAnkiResp),
- 'canAddNotes': Object.assign({body: JSON.stringify([true, true])}, baseAnkiResp),
- 'storeMediaFile': Object.assign({body: JSON.stringify('mock_audio.mp3')}, baseAnkiResp),
- 'addNote': Object.assign({body: JSON.stringify(102312488912)}, baseAnkiResp)
+ version: Object.assign({body: JSON.stringify(6)}, baseAnkiResp),
+ deckNames: Object.assign({body: JSON.stringify(['Mock Deck'])}, baseAnkiResp),
+ modelNames: Object.assign({body: JSON.stringify(['Mock Model'])}, baseAnkiResp),
+ modelFieldNames: Object.assign({body: JSON.stringify(mockModelFieldNames)}, baseAnkiResp),
+ canAddNotes: Object.assign({body: JSON.stringify([true, true])}, baseAnkiResp),
+ storeMediaFile: Object.assign({body: JSON.stringify('mock_audio.mp3')}, baseAnkiResp),
+ addNote: Object.assign({body: JSON.stringify(102312488912)}, baseAnkiResp)
};
diff --git a/types/ext/backend.d.ts b/types/ext/backend.d.ts
index ce973630..a832e434 100644
--- a/types/ext/backend.d.ts
+++ b/types/ext/backend.d.ts
@@ -18,6 +18,7 @@
import type * as Api from './api';
export type DatabaseUpdateType = 'dictionary';
+
export type DatabaseUpdateCause = 'purge' | 'delete' | 'import';
export type MecabParseResults = [
diff --git a/types/ext/dictionary-data.d.ts b/types/ext/dictionary-data.d.ts
index 434f5a27..0128f83f 100644
--- a/types/ext/dictionary-data.d.ts
+++ b/types/ext/dictionary-data.d.ts
@@ -102,9 +102,13 @@ export type TermGlossaryContent = (
);
export type TermGlossaryString = string;
+
export type TermGlossaryText = {type: 'text', text: string};
+
export type TermGlossaryImage = {type: 'image'} & TermImage;
+
export type TermGlossaryStructuredContent = {type: 'structured-content', content: StructuredContent.Content};
+
export type TermGlossaryDeinflection = [
uninflected: string,
inflectionRuleChain: string[],
diff --git a/types/ext/dictionary-database.d.ts b/types/ext/dictionary-database.d.ts
index 1ae4603f..84c6da62 100644
--- a/types/ext/dictionary-database.d.ts
+++ b/types/ext/dictionary-database.d.ts
@@ -36,7 +36,9 @@ export type MediaDataArrayBufferContent = MediaDataBase<ArrayBuffer>;
export type MediaDataStringContent = MediaDataBase<string>;
-export type Media<T extends (ArrayBuffer | string) = ArrayBuffer> = {index: number} & MediaDataBase<T>;
+type MediaType = ArrayBuffer | string;
+
+export type Media<T extends MediaType = ArrayBuffer> = {index: number} & MediaDataBase<T>;
export type DatabaseTermEntry = {
expression: string;
@@ -198,7 +200,6 @@ export type ObjectStoreName = (
'media'
);
-/* eslint-disable @stylistic/indent */
export type ObjectStoreData<T extends ObjectStoreName> = (
T extends 'dictionaries' ? DictionaryImporter.Summary :
T extends 'terms' ? DatabaseTermEntry :
@@ -209,7 +210,6 @@ export type ObjectStoreData<T extends ObjectStoreName> = (
T extends 'media' ? MediaDataArrayBufferContent :
never
);
-/* eslint-enable @stylistic/indent */
export type DeleteDictionaryProgressData = {
count: number;
diff --git a/types/ext/input.d.ts b/types/ext/input.d.ts
index ab05f015..e71a0110 100644
--- a/types/ext/input.d.ts
+++ b/types/ext/input.d.ts
@@ -16,6 +16,9 @@
*/
export type ModifierKey = 'alt' | 'ctrl' | 'meta' | 'shift';
+
export type ModifierMouseButton = 'mouse0' | 'mouse1' | 'mouse2' | 'mouse3' | 'mouse4' | 'mouse5';
+
export type Modifier = ModifierKey | ModifierMouseButton;
+
export type ModifierType = 'key' | 'mouse';
diff --git a/types/ext/profile-conditions-util.d.ts b/types/ext/profile-conditions-util.d.ts
index 441c9b97..288a3f78 100644
--- a/types/ext/profile-conditions-util.d.ts
+++ b/types/ext/profile-conditions-util.d.ts
@@ -33,6 +33,6 @@ export type NormalizedOptionsContext1 = Settings.OptionsContext1 & {
export type NormalizedOptionsContext2 = Settings.OptionsContext2;
-export type NormalizedOptionsContext3 = Settings.OptionsContext2;
+export type NormalizedOptionsContext3 = Settings.OptionsContext3;
export type NormalizedOptionsContext = NormalizedOptionsContext1 | NormalizedOptionsContext2 | NormalizedOptionsContext3;
diff --git a/types/ext/settings-modifications.d.ts b/types/ext/settings-modifications.d.ts
index b052ba30..becfea5c 100644
--- a/types/ext/settings-modifications.d.ts
+++ b/types/ext/settings-modifications.d.ts
@@ -68,10 +68,15 @@ export type Modification = (
);
export type ScopedRead = Read & OptionsScope;
+
export type ScopedModificationSet = ModificationSet & OptionsScope;
+
export type ScopedModificationDelete = ModificationDelete & OptionsScope;
+
export type ScopedModificationSwap = ModificationSwap & OptionsScope;
+
export type ScopedModificationSplice = ModificationSplice & OptionsScope;
+
export type ScopedModificationPush = ModificationPush & OptionsScope;
export type ScopedModification = (
@@ -83,14 +88,19 @@ export type ScopedModification = (
);
export type ModificationSetResult = unknown;
+
export type ModificationDeleteResult = true;
+
export type ModificationSwapResult = true;
+
export type ModificationSpliceResult = unknown[];
+
export type ModificationPushResult = number;
export type ModificationResult = (
ModificationSetResult |
ModificationDeleteResult |
+ // eslint-disable-next-line @typescript-eslint/no-duplicate-type-constituents
ModificationSwapResult |
ModificationSpliceResult |
ModificationPushResult
diff --git a/types/ext/settings.d.ts b/types/ext/settings.d.ts
index 96440823..a900dbe6 100644
--- a/types/ext/settings.d.ts
+++ b/types/ext/settings.d.ts
@@ -349,25 +349,39 @@ export type PreventMiddleMouseOptions = {
};
export type ResultOutputMode = 'group' | 'merge' | 'split';
+
export type PopupDisplayMode = 'default' | 'full-width';
+
export type PopupHorizontalTextPosition = 'below' | 'above';
+
export type PopupVerticalTextPosition = 'default' | 'before' | 'after' | 'left' | 'right';
+
export type GlossaryLayoutMode = 'default' | 'compact';
+
export type PopupTheme = 'light' | 'dark' | 'browser';
+
export type PopupOuterTheme = 'light' | 'dark' | 'browser' | 'site';
+
export type PopupCurrentIndicatorMode = 'none' | 'asterisk' | 'triangle' | 'bar-left' | 'bar-right' | 'dot-left' | 'dot-right';
+
export type PopupActionBarVisibility = 'auto' | 'always';
+
export type PopupActionBarLocation = 'left' | 'right' | 'top' | 'bottom';
+
export type FrequencyDisplayMode = 'tags' | 'tags-grouped' | 'split-tags' | 'split-tags-grouped' | 'inline-list' | 'list';
+
export type TermDisplayMode = 'ruby' | 'ruby-and-reading' | 'term-and-reading';
+
export type SortFrequencyDictionaryOrder = 'ascending' | 'descending';
export type PopupWindowType = 'normal' | 'popup';
+
export type PopupWindowState = 'normal' | 'maximized' | 'fullscreen';
export type AudioSourceType = 'jpod101' | 'jpod101-alternate' | 'jisho' | 'text-to-speech' | 'text-to-speech-reading' | 'custom' | 'custom-json';
export type TranslationConvertType = 'false' | 'true' | 'variant';
+
export type TranslationCollapseEmphaticSequences = 'false' | 'true' | 'full';
export type DictionaryDefinitionsCollapsible = 'not-collapsible' | 'expanded' | 'collapsed' | 'force-collapsed' | 'force-expanded';
@@ -375,11 +389,15 @@ export type DictionaryDefinitionsCollapsible = 'not-collapsible' | 'expanded' |
export type ParsingReadingMode = 'hiragana' | 'katakana' | 'romaji' | 'dictionary-reading' | 'none';
export type AnkiScreenshotFormat = 'png' | 'jpeg';
+
export type AnkiDuplicateScope = 'collection' | 'deck' | 'deck-root';
+
export type AnkiDisplayTags = 'never' | 'always' | 'non-standard';
+
export type AnkiNoteGuiMode = 'browse' | 'edit';
export type SentenceTerminationCharacterMode = 'custom' | 'custom-no-newlines' | 'newlines' | 'none';
export type InputsHotkeyModifier = 'alt' | 'ctrl' | 'shift' | 'meta';
+
export type InputsHotkeyScope = 'popup' | 'search' | 'web';
diff --git a/types/other/rollup-parse-ast.d.ts b/types/other/rollup-parse-ast.d.ts
index d798f09e..efc42411 100644
--- a/types/other/rollup-parse-ast.d.ts
+++ b/types/other/rollup-parse-ast.d.ts
@@ -22,4 +22,5 @@
import type {ParseAst, ParseAstAsync} from 'rollup';
export const parseAst: ParseAst;
+
export const parseAstAsync: ParseAstAsync;