Skip to content

Commit

Permalink
Update eslint (#638)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
toasted-nutbread committed Feb 8, 2024
1 parent 725a90d commit d438183
Show file tree
Hide file tree
Showing 31 changed files with 1,000 additions and 641 deletions.
710 changes: 199 additions & 511 deletions .eslintrc.json

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"markdown.extension.toc.levels": "1..3",
"[javascript]": {
"[javascript][json][jsonc]": {
"editor.codeActionsOnSave": {
"source.addMissingImports": "explicit",
"source.organizeImports": "explicit",
Expand All @@ -22,7 +22,9 @@
"editor.insertSpaces": true,
"eslint.validate": [
"javascript",
"typescript"
"typescript",
"json",
"jsonc"
],
"files.eol": "\n",
"files.trimTrailingWhitespace": true,
Expand Down
10 changes: 5 additions & 5 deletions ext/js/app/frontend.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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)],
Expand All @@ -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 */
}

/**
Expand Down Expand Up @@ -187,15 +187,15 @@ 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)],
['frontendGetSelectionText', this._onApiGetSelectionText.bind(this)],
['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();
Expand Down
4 changes: 2 additions & 2 deletions ext/js/app/popup-factory.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)],
Expand All @@ -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 */
}

/**
Expand Down
4 changes: 2 additions & 2 deletions ext/js/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)],
Expand All @@ -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} */
Expand Down
4 changes: 2 additions & 2 deletions ext/js/background/backend.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)],
Expand Down Expand Up @@ -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][]} */ ([
Expand Down
5 changes: 2 additions & 3 deletions ext/js/background/offscreen.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)],
Expand All @@ -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;
Expand Down
62 changes: 62 additions & 0 deletions ext/js/core/promise-animation-frame.js
Original file line number Diff line number Diff line change
@@ -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);
}
});
}
45 changes: 0 additions & 45 deletions ext/js/core/utilities.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
});
}
6 changes: 3 additions & 3 deletions ext/js/data/options-util.js
Original file line number Diff line number Diff line change
Expand Up @@ -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~}}
Expand Down Expand Up @@ -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},
Expand All @@ -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,
Expand Down
4 changes: 2 additions & 2 deletions ext/js/display/display-anki.js
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down
4 changes: 2 additions & 2 deletions ext/js/display/display-audio.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,15 +82,15 @@ 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)]
]);
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));
Expand Down
4 changes: 2 additions & 2 deletions ext/js/display/display.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)],
Expand All @@ -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} */
Expand Down
4 changes: 2 additions & 2 deletions ext/js/pages/settings/keyboard-shortcuts-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -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()}],
Expand All @@ -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} */
Expand Down
4 changes: 2 additions & 2 deletions ext/js/pages/settings/popup-preview-frame.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,15 @@ 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)],
['PopupPreviewFrame.setCustomCss', this._setCustomCss.bind(this)],
['PopupPreviewFrame.setCustomOuterCss', this._setCustomOuterCss.bind(this)],
['PopupPreviewFrame.updateOptionsContext', this._updateOptionsContext.bind(this)]
]));
/* eslint-enable no-multi-spaces */
/* eslint-enable @stylistic/no-multi-spaces */
}

/** */
Expand Down
4 changes: 2 additions & 2 deletions ext/js/pages/settings/profile-conditions-ui.js
Original file line number Diff line number Diff line change
Expand Up @@ -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([
[
Expand Down Expand Up @@ -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'
Expand Down
Loading

0 comments on commit d438183

Please sign in to comment.