summaryrefslogtreecommitdiff
path: root/ext/js
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 /ext/js
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
Diffstat (limited to 'ext/js')
-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
15 files changed, 92 insertions, 76 deletions
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})