diff options
| author | toasted-nutbread <toasted-nutbread@users.noreply.github.com> | 2024-02-14 22:26:29 -0500 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-02-15 03:26:29 +0000 | 
| commit | 6bf7b0055765c4f2011c9614753d6714dc09be65 (patch) | |
| tree | 0e782ae66556eaa61a34d9f32d77c831b2443ce5 /ext/js | |
| parent | 7a4096240ce4faf70a785d047945388baa0daab3 (diff) | |
Eslint rule updates (#673)
* Install unicorn
* Add rules
* Fix issues
* Install sonarjs
* Set up rules
* Fix issues
* Install eslint-plugin-import and fix import extensions
* Simplify permitted error names
Diffstat (limited to 'ext/js')
44 files changed, 127 insertions, 131 deletions
| diff --git a/ext/js/accessibility/google-docs-util.js b/ext/js/accessibility/google-docs-util.js index 969e650e..31ae5982 100644 --- a/ext/js/accessibility/google-docs-util.js +++ b/ext/js/accessibility/google-docs-util.js @@ -86,6 +86,8 @@ export class GoogleDocsUtil {          const content = document.createTextNode(text);          const svgText = document.createElementNS('http://www.w3.org/2000/svg', 'text');          const transform = element.getAttribute('transform') || ''; +        // Using getAttribute instead of dataset because element is an SVG element +        // eslint-disable-next-line unicorn/prefer-dom-node-dataset          const font = element.getAttribute('data-font-css') || '';          const elementX = element.getAttribute('x');          const elementY = element.getAttribute('y'); diff --git a/ext/js/app/frontend.js b/ext/js/app/frontend.js index 27e7700e..84a8f1e6 100644 --- a/ext/js/app/frontend.js +++ b/ext/js/app/frontend.js @@ -82,9 +82,9 @@ export class Frontend {          /** @type {?import('settings').ProfileOptions} */          this._options = null;          /** @type {number} */ -        this._pageZoomFactor = 1.0; +        this._pageZoomFactor = 1;          /** @type {number} */ -        this._contentScale = 1.0; +        this._contentScale = 1;          /** @type {Promise<void>} */          this._lastShowPromise = Promise.resolve();          /** @type {TextSourceGenerator} */ @@ -788,7 +788,7 @@ export class Frontend {          }          if (popupScaleRelativeToVisualViewport) {              const {visualViewport} = window; -            const visualViewportScale = (typeof visualViewport !== 'undefined' && visualViewport !== null ? visualViewport.scale : 1.0); +            const visualViewportScale = (typeof visualViewport !== 'undefined' && visualViewport !== null ? visualViewport.scale : 1);              contentScale /= visualViewportScale;          }          if (contentScale === this._contentScale) { return; } diff --git a/ext/js/app/popup.js b/ext/js/app/popup.js index 08ff0661..103a5468 100644 --- a/ext/js/app/popup.js +++ b/ext/js/app/popup.js @@ -68,7 +68,7 @@ export class Popup extends EventDispatcher {          /** @type {?import('settings').OptionsContext} */          this._optionsContext = null;          /** @type {number} */ -        this._contentScale = 1.0; +        this._contentScale = 1;          /** @type {string} */          this._targetOrigin = chrome.runtime.getURL('/').replace(/\/$/, ''); @@ -777,7 +777,7 @@ export class Popup extends EventDispatcher {      _getPosition(sourceRects, writingMode, viewport) {          sourceRects = this._convertSourceRectsCoordinateSpace(sourceRects);          const contentScale = this._contentScale; -        const scaleRatio = this._frameSizeContentScale === null ? 1.0 : contentScale / this._frameSizeContentScale; +        const scaleRatio = this._frameSizeContentScale === null ? 1 : contentScale / this._frameSizeContentScale;          this._frameSizeContentScale = contentScale;          const frameRect = this._frame.getBoundingClientRect();          const frameWidth = Math.max(frameRect.width * scaleRatio, this._initialWidth * contentScale); @@ -1133,6 +1133,8 @@ class PopupError extends ExtensionError {       */      constructor(message, source) {          super(message); +        /** @type {string} */ +        this.name = 'PopupError';          /** @type {Popup} */          this._source = source;      } diff --git a/ext/js/app/theme-controller.js b/ext/js/app/theme-controller.js index 559a6e57..384fbcc8 100644 --- a/ext/js/app/theme-controller.js +++ b/ext/js/app/theme-controller.js @@ -190,9 +190,9 @@ export class ThemeController {          if (color === null) { return; }          const a = color[3]; -        if (a <= 0.0) { return; } +        if (a <= 0) { return; } -        const aInv = 1.0 - a; +        const aInv = 1 - a;          for (let i = 0; i < 3; ++i) {              target[i] = target[i] * aInv + color[i] * a;          } @@ -212,7 +212,7 @@ export class ThemeController {              Number.parseInt(m[1], 10),              Number.parseInt(m[2], 10),              Number.parseInt(m[3], 10), -            m4 ? Math.max(0.0, Math.min(1.0, Number.parseFloat(m4))) : 1.0 +            m4 ? Math.max(0, Math.min(1, Number.parseFloat(m4))) : 1          ];      }  } diff --git a/ext/js/background/backend.js b/ext/js/background/backend.js index 090ba7b3..8ab56232 100644 --- a/ext/js/background/backend.js +++ b/ext/js/background/backend.js @@ -701,7 +701,7 @@ export class Backend {                  typeof chrome.tabs.getZoom === 'function'              )) {                  // Not supported -                resolve({zoomFactor: 1.0}); +                resolve({zoomFactor: 1});                  return;              }              chrome.tabs.getZoom(tabId, (zoomFactor) => { @@ -1701,10 +1701,8 @@ export class Backend {                  // NOP              } -            if (okay && !done) { -                if (add(item)) { -                    done = true; -                } +            if (okay && !done && add(item)) { +                done = true;              }          }; @@ -2294,7 +2292,7 @@ export class Backend {       */      _replaceInvalidFileNameCharacters(fileName) {          // eslint-disable-next-line no-control-regex -        return fileName.replace(/[<>:"/\\|?*\x00-\x1F]/g, '-'); +        return fileName.replace(/[<>:"/\\|?*\u0000-\u001F]/g, '-');      }      /** diff --git a/ext/js/background/offscreen-proxy.js b/ext/js/background/offscreen-proxy.js index 8c3f63c9..2351cb96 100644 --- a/ext/js/background/offscreen-proxy.js +++ b/ext/js/background/offscreen-proxy.js @@ -144,8 +144,7 @@ export class DictionaryDatabaseProxy {       */      async getMedia(targets) {          const serializedMedia = /** @type {import('dictionary-database').Media<string>[]} */ (await this._offscreen.sendMessagePromise({action: 'databaseGetMediaOffscreen', params: {targets}})); -        const media = serializedMedia.map((m) => ({...m, content: base64ToArrayBuffer(m.content)})); -        return media; +        return serializedMedia.map((m) => ({...m, content: base64ToArrayBuffer(m.content)}));      }  } diff --git a/ext/js/background/offscreen.js b/ext/js/background/offscreen.js index 754db517..dbdb9773 100644 --- a/ext/js/background/offscreen.js +++ b/ext/js/background/offscreen.js @@ -109,8 +109,7 @@ export class Offscreen {      /** @type {import('offscreen').ApiHandler<'databaseGetMediaOffscreen'>} */      async _getMediaHandler({targets}) {          const media = await this._dictionaryDatabase.getMedia(targets); -        const serializedMedia = media.map((m) => ({...m, content: arrayBufferToBase64(m.content)})); -        return serializedMedia; +        return media.map((m) => ({...m, content: arrayBufferToBase64(m.content)}));      }      /** @type {import('offscreen').ApiHandler<'translatorPrepareOffscreen'>} */ diff --git a/ext/js/core/extension-error.js b/ext/js/core/extension-error.js index ab1c9dd7..6458f477 100644 --- a/ext/js/core/extension-error.js +++ b/ext/js/core/extension-error.js @@ -26,6 +26,8 @@ export class ExtensionError extends Error {       */      constructor(message) {          super(message); +        /** @type {string} */ +        this.name = 'ExtensionError';          /** @type {unknown} */          this._data = void 0;      } diff --git a/ext/js/data/json-schema.js b/ext/js/data/json-schema.js index 3342e387..9e1497e9 100644 --- a/ext/js/data/json-schema.js +++ b/ext/js/data/json-schema.js @@ -27,6 +27,8 @@ export class JsonSchemaError extends Error {       */      constructor(message, valueStack, schemaStack) {          super(message); +        /** @type {string} */ +        this.name = 'JsonSchemaError';          /** @type {import('ext/json-schema').ValueStackItem[]} */          this._valueStack = valueStack;          /** @type {import('ext/json-schema').SchemaStackItem[]} */ @@ -371,18 +373,16 @@ export class JsonSchema {              return {schema, stack: [{schema, path: null}]};          }          const {prefixItems} = schema; -        if (typeof prefixItems !== 'undefined') { -            if (index >= 0 && index < prefixItems.length) { -                const itemSchema = prefixItems[index]; -                if (typeof itemSchema !== 'undefined') { -                    return { -                        schema: itemSchema, -                        stack: [ -                            {schema: prefixItems, path: 'prefixItems'}, -                            {schema: itemSchema, path: index} -                        ] -                    }; -                } +        if (typeof prefixItems !== 'undefined' && index >= 0 && index < prefixItems.length) { +            const itemSchema = prefixItems[index]; +            if (typeof itemSchema !== 'undefined') { +                return { +                    schema: itemSchema, +                    stack: [ +                        {schema: prefixItems, path: 'prefixItems'}, +                        {schema: itemSchema, path: index} +                    ] +                };              }          }          const {items} = schema; diff --git a/ext/js/data/permissions-util.js b/ext/js/data/permissions-util.js index 837b6d5f..097fe34d 100644 --- a/ext/js/data/permissions-util.js +++ b/ext/js/data/permissions-util.js @@ -113,10 +113,8 @@ export function getRequiredPermissionsForAnkiFieldValue(fieldValue) {  export function hasRequiredPermissionsForOptions(permissions, options) {      const permissionsSet = new Set(permissions.permissions); -    if (!permissionsSet.has('nativeMessaging')) { -        if (options.parsing.enableMecabParser) { -            return false; -        } +    if (!permissionsSet.has('nativeMessaging') && options.parsing.enableMecabParser) { +        return false;      }      if (!permissionsSet.has('clipboardRead')) { diff --git a/ext/js/display/display-anki.js b/ext/js/display/display-anki.js index 4766f1ae..d37efa85 100644 --- a/ext/js/display/display-anki.js +++ b/ext/js/display/display-anki.js @@ -953,6 +953,8 @@ class DisplayAnkiError extends Error {       */      constructor(message) {          super(message); +        /** @type {string} */ +        this.name = 'DisplayAnkiError';          /** @type {?import('anki-note-builder').Requirement[]} */          this._requirements = null;          /** @type {?import('anki-note-builder').Requirement[]} */ diff --git a/ext/js/display/display-audio.js b/ext/js/display/display-audio.js index 7d75d6b0..5f4131d0 100644 --- a/ext/js/display/display-audio.js +++ b/ext/js/display/display-audio.js @@ -33,7 +33,7 @@ export class DisplayAudio {          /** @type {AudioSystem} */          this._audioSystem = new AudioSystem();          /** @type {number} */ -        this._playbackVolume = 1.0; +        this._playbackVolume = 1;          /** @type {boolean} */          this._autoPlay = false;          /** @type {?import('core').Timeout} */ @@ -166,7 +166,7 @@ export class DisplayAudio {      _onOptionsUpdated({options}) {          const {enabled, autoPlay, volume, sources} = options.audio;          this._autoPlay = enabled && autoPlay; -        this._playbackVolume = Number.isFinite(volume) ? Math.max(0.0, Math.min(1.0, volume / 100.0)) : 1.0; +        this._playbackVolume = Number.isFinite(volume) ? Math.max(0, Math.min(1, volume / 100)) : 1;          /** @type {Set<import('settings').AudioSourceType>} */          const requiredAudioSources = new Set([ @@ -534,7 +534,7 @@ export class DisplayAudio {          if (headwordNode !== null) {              const {index} = headwordNode.dataset;              if (typeof index === 'string') { -                const headwordIndex = parseInt(index, 10); +                const headwordIndex = Number.parseInt(index, 10);                  if (Number.isFinite(headwordIndex)) { return headwordIndex; }              }          } diff --git a/ext/js/display/display.js b/ext/js/display/display.js index a5dad2d1..d30ed8a0 100644 --- a/ext/js/display/display.js +++ b/ext/js/display/display.js @@ -619,7 +619,7 @@ export class Display extends EventDispatcher {          if (node === null) { return -1; }          const {index} = node.dataset;          if (typeof index !== 'string') { return -1; } -        const indexNumber = parseInt(index, 10); +        const indexNumber = Number.parseInt(index, 10);          return Number.isFinite(indexNumber) ? indexNumber : -1;      } @@ -1020,7 +1020,7 @@ export class Display extends EventDispatcher {          const node = /** @type {HTMLElement} */ (e.currentTarget);          const {index} = node.dataset;          if (typeof index !== 'string') { return; } -        const indexNumber = parseInt(index, 10); +        const indexNumber = Number.parseInt(index, 10);          if (!Number.isFinite(indexNumber)) { return; }          this._entrySetCurrent(indexNumber);      } @@ -1146,8 +1146,7 @@ export class Display extends EventDispatcher {       */      async _findDictionaryEntries(isKanji, source, wildcardsEnabled, optionsContext) {          if (isKanji) { -            const dictionaryEntries = await this._application.api.kanjiFind(source, optionsContext); -            return dictionaryEntries; +            return await this._application.api.kanjiFind(source, optionsContext);          } else {              /** @type {import('api').FindTermsDetails} */              const findDetails = {}; @@ -1555,11 +1554,11 @@ export class Display extends EventDispatcher {       * @returns {boolean}       */      _relativeTermView(next) { -        if (next) { -            return this._history.hasNext() && this._history.forward(); -        } else { -            return this._history.hasPrevious() && this._history.back(); -        } +        return ( +            next ? +            this._history.hasNext() && this._history.forward() : +            this._history.hasPrevious() && this._history.back() +        );      }      /** diff --git a/ext/js/display/element-overflow-controller.js b/ext/js/display/element-overflow-controller.js index e0b9035e..eb83dda4 100644 --- a/ext/js/display/element-overflow-controller.js +++ b/ext/js/display/element-overflow-controller.js @@ -157,11 +157,11 @@ export class ElementOverflowController {       * @returns {number|import('core').Timeout}       */      _requestIdleCallback(callback, timeout) { -        if (typeof requestIdleCallback === 'function') { -            return requestIdleCallback(callback, {timeout}); -        } else { -            return setTimeout(callback, timeout); -        } +        return ( +            typeof requestIdleCallback === 'function' ? +            requestIdleCallback(callback, {timeout}) : +            setTimeout(callback, timeout) +        );      }      /** diff --git a/ext/js/display/sandbox/structured-content-generator.js b/ext/js/display/sandbox/structured-content-generator.js index a04feaf2..1dfde39b 100644 --- a/ext/js/display/sandbox/structured-content-generator.js +++ b/ext/js/display/sandbox/structured-content-generator.js @@ -137,7 +137,7 @@ export class StructuredContentGenerator {              imageContainer.title = title;          } -        aspectRatioSizer.style.paddingTop = `${invAspectRatio * 100.0}%`; +        aspectRatioSizer.style.paddingTop = `${invAspectRatio * 100}%`;          if (this._contentManager !== null) {              this._contentManager.loadMedia( diff --git a/ext/js/display/search-display-controller.js b/ext/js/display/search-display-controller.js index ed2061e2..6767dce7 100644 --- a/ext/js/display/search-display-controller.js +++ b/ext/js/display/search-display-controller.js @@ -322,7 +322,7 @@ export class SearchDisplayController {       */      async _onProfileSelectChange(event) {          const node = /** @type {HTMLInputElement} */ (event.currentTarget); -        const value = parseInt(node.value, 10); +        const value = Number.parseInt(node.value, 10);          const optionsFull = await this._display.application.api.optionsGetFull();          if (typeof value === 'number' && Number.isFinite(value) && value >= 0 && value <= optionsFull.profiles.length) {              this._setPrimaryProfileIndex(value); @@ -574,8 +574,7 @@ export class SearchDisplayController {              case 'select':                  return true;          } -        if (element instanceof HTMLElement && element.isContentEditable) { return true; } -        return false; +        return element instanceof HTMLElement && !!element.isContentEditable;      }      /** diff --git a/ext/js/dom/document-util.js b/ext/js/dom/document-util.js index 1ec699e6..a98bfe86 100644 --- a/ext/js/dom/document-util.js +++ b/ext/js/dom/document-util.js @@ -18,7 +18,9 @@  /**   * This class contains utility functions related to the HTML document. + * TODO : This class should be made non-static   */ +// eslint-disable-next-line unicorn/no-static-only-class  export class DocumentUtil {      /** @type {?boolean} */      static _cssZoomSupported = null; @@ -460,7 +462,7 @@ export class DocumentUtil {              if (typeof value !== 'string' || value.length === 0) {                  return null;              } -            value = parseFloat(value); +            value = Number.parseFloat(value);          }          return !Number.isNaN(value) ? value : null;      } diff --git a/ext/js/dom/dom-text-scanner.js b/ext/js/dom/dom-text-scanner.js index f1dc3661..5b3ea564 100644 --- a/ext/js/dom/dom-text-scanner.js +++ b/ext/js/dom/dom-text-scanner.js @@ -488,8 +488,8 @@ export class DOMTextScanner {      static isStyleVisible(style) {          return !(              style.visibility === 'hidden' || -            parseFloat(style.opacity) <= 0 || -            parseFloat(style.fontSize) <= 0 || +            Number.parseFloat(style.opacity) <= 0 || +            Number.parseFloat(style.fontSize) <= 0 ||              (                  !DOMTextScanner.isStyleSelectable(style) &&                  ( diff --git a/ext/js/dom/panel-element.js b/ext/js/dom/panel-element.js index 9c1289d7..0f2801e6 100644 --- a/ext/js/dom/panel-element.js +++ b/ext/js/dom/panel-element.js @@ -89,16 +89,14 @@ export class PanelElement extends EventDispatcher {       * @param {(details: import('core').EventArgument<import('panel-element').Events, TName>) => void} callback       */      on(eventName, callback) { -        if (eventName === 'visibilityChanged') { -            if (this._mutationObserver === null) { -                this._visible = this.isVisible(); -                this._mutationObserver = new MutationObserver(this._onMutation.bind(this)); -                this._mutationObserver.observe(this._node, { -                    attributes: true, -                    attributeFilter: ['hidden'], -                    attributeOldValue: true -                }); -            } +        if (eventName === 'visibilityChanged' && this._mutationObserver === null) { +            this._visible = this.isVisible(); +            this._mutationObserver = new MutationObserver(this._onMutation.bind(this)); +            this._mutationObserver.observe(this._node, { +                attributes: true, +                attributeFilter: ['hidden'], +                attributeOldValue: true +            });          }          super.on(eventName, callback);      } @@ -111,11 +109,9 @@ export class PanelElement extends EventDispatcher {       */      off(eventName, callback) {          const result = super.off(eventName, callback); -        if (eventName === 'visibilityChanged' && !this.hasListeners(eventName)) { -            if (this._mutationObserver !== null) { -                this._mutationObserver.disconnect(); -                this._mutationObserver = null; -            } +        if (eventName === 'visibilityChanged' && !this.hasListeners(eventName) && this._mutationObserver !== null) { +            this._mutationObserver.disconnect(); +            this._mutationObserver = null;          }          return result;      } diff --git a/ext/js/dom/popup-menu.js b/ext/js/dom/popup-menu.js index 8a8a19ba..28bcc309 100644 --- a/ext/js/dom/popup-menu.js +++ b/ext/js/dom/popup-menu.js @@ -219,8 +219,8 @@ export class PopupMenu extends EventDispatcher {              (bottom - top) * ((-vertical + 1) * -0.5)          ); -        x = Math.max(0.0, Math.min(containerNodeRect.width - menuRect.width, x)); -        y = Math.max(0.0, Math.min(containerNodeRect.height - menuRect.height, y)); +        x = Math.max(0, Math.min(containerNodeRect.width - menuRect.width, x)); +        y = Math.max(0, Math.min(containerNodeRect.height - menuRect.height, y));          menu.style.left = `${x}px`;          menu.style.top = `${y}px`; diff --git a/ext/js/dom/scroll-element.js b/ext/js/dom/scroll-element.js index 8005469b..7cd00f01 100644 --- a/ext/js/dom/scroll-element.js +++ b/ext/js/dom/scroll-element.js @@ -133,10 +133,10 @@ export class ScrollElement {       */      _easeInOutCubic(t) {          if (t < 0.5) { -            return (4.0 * t * t * t); +            return (4 * t * t * t);          } else { -            t = 1.0 - t; -            return 1.0 - (4.0 * t * t * t); +            t = 1 - t; +            return 1 - (4 * t * t * t);          }      } diff --git a/ext/js/dom/selector-observer.js b/ext/js/dom/selector-observer.js index 791ce627..86607130 100644 --- a/ext/js/dom/selector-observer.js +++ b/ext/js/dom/selector-observer.js @@ -170,7 +170,7 @@ export class SelectorObserver {          if (              this._onChildrenUpdated !== null && -            (addedNodes.length !== 0 || addedNodes.length !== 0) +            (removedNodes.length > 0 || addedNodes.length > 0)          ) {              for (let node = /** @type {?Node} */ (target); node !== null; node = node.parentNode) {                  const observer = this._elementMap.get(node); diff --git a/ext/js/dom/text-source-generator.js b/ext/js/dom/text-source-generator.js index a5529779..83c7271c 100644 --- a/ext/js/dom/text-source-generator.js +++ b/ext/js/dom/text-source-generator.js @@ -307,8 +307,8 @@ export class TextSourceGenerator {          // Adjust size          const imposterRect = imposter.getBoundingClientRect();          if (imposterRect.width !== elementRect.width || imposterRect.height !== elementRect.height) { -            const width = parseFloat(elementStyle.width) + (elementRect.width - imposterRect.width); -            const height = parseFloat(elementStyle.height) + (elementRect.height - imposterRect.height); +            const width = Number.parseFloat(elementStyle.width) + (elementRect.width - imposterRect.width); +            const height = Number.parseFloat(elementStyle.height) + (elementRect.height - imposterRect.height);              this._setImposterStyle(imposterStyle, 'width', `${width}px`);              this._setImposterStyle(imposterStyle, 'height', `${height}px`);          } @@ -614,7 +614,7 @@ export class TextSourceGenerator {          }          const style = window.getComputedStyle(element);          return ( -            parseFloat(style.opacity) <= 0 || +            Number.parseFloat(style.opacity) <= 0 ||              style.visibility === 'hidden' ||              (style.backgroundImage === 'none' && this._isColorTransparent(style.backgroundColor))          ); diff --git a/ext/js/general/object-property-accessor.js b/ext/js/general/object-property-accessor.js index d50948d9..ac9e2a54 100644 --- a/ext/js/general/object-property-accessor.js +++ b/ext/js/general/object-property-accessor.js @@ -117,14 +117,14 @@ export class ObjectPropertyAccessor {          /** @type {import('core').SerializableObject} */ (target1)[key1] = value2;          try {              /** @type {import('core').SerializableObject} */ (target2)[key2] = value1; -        } catch (e) { +        } catch (error) {              // Revert              try {                  /** @type {import('core').SerializableObject} */ (target1)[key1] = value1; -            } catch (e2) { +            } catch (error2) {                  // NOP              } -            throw e; +            throw error;          }      } diff --git a/ext/js/input/hotkey-handler.js b/ext/js/input/hotkey-handler.js index 9caedcc2..6d7d3d7a 100644 --- a/ext/js/input/hotkey-handler.js +++ b/ext/js/input/hotkey-handler.js @@ -254,7 +254,7 @@ export class HotkeyHandler extends EventDispatcher {       */      _updateEventHandlers() {          if (this._isPrepared && (this._hotkeys.size > 0 || this._hasEventListeners)) { -            if (this._eventListeners.size !== 0) { return; } +            if (this._eventListeners.size > 0) { return; }              this._eventListeners.addEventListener(document, 'keydown', this._onKeyDown.bind(this), false);          } else {              this._eventListeners.removeAllEventListeners(); diff --git a/ext/js/language/ja/japanese.js b/ext/js/language/ja/japanese.js index a4508040..818daa0b 100644 --- a/ext/js/language/ja/japanese.js +++ b/ext/js/language/ja/japanese.js @@ -92,7 +92,7 @@ const JAPANESE_RANGES = [      [0xffe0, 0xffee] // Currency markers  ]; -const SMALL_KANA_SET = new Set(Array.from('ぁぃぅぇぉゃゅょゎァィゥェォャュョヮ')); +const SMALL_KANA_SET = new Set('ぁぃぅぇぉゃゅょゎァィゥェォャュョヮ');  const HALFWIDTH_KATAKANA_MAPPING = new Map([      ['ヲ', 'ヲヺ-'], diff --git a/ext/js/language/text-scanner.js b/ext/js/language/text-scanner.js index 811c7987..1cf346a9 100644 --- a/ext/js/language/text-scanner.js +++ b/ext/js/language/text-scanner.js @@ -1294,11 +1294,9 @@ export class TextScanner extends EventDispatcher {      async _searchAtFromMouseMove(x, y, inputInfo) {          if (this._pendingLookup) { return; } -        if (inputInfo.passive) { -            if (!await this._scanTimerWait()) { -                // Aborted -                return; -            } +        if (inputInfo.passive && !await this._scanTimerWait()) { +            // Aborted +            return;          }          await this._searchAt(x, y, inputInfo); diff --git a/ext/js/language/translator.js b/ext/js/language/translator.js index 007a7d1e..2ba1ce0d 100644 --- a/ext/js/language/translator.js +++ b/ext/js/language/translator.js @@ -491,11 +491,11 @@ export class Translator {       * @returns {number}       */      _getNextSubstringLength(searchResolution, currentLength, source) { -        if (searchResolution === 'word') { -            return source.search(/[^\p{Letter}][\p{Letter}\p{Number}]*$/u); -        } else { -            return currentLength - 1; -        } +        return ( +            searchResolution === 'word' ? +            source.search(/[^\p{Letter}][\p{Letter}\p{Number}]*$/u) : +            currentLength - 1 +        );      }      /** @@ -620,7 +620,7 @@ export class Translator {              for (const group of groupedDictionaryEntries) {                  this._sortTermDictionaryEntriesById(group.dictionaryEntries);              } -            if (ungroupedDictionaryEntriesMap.size !== 0 || secondarySearchDictionaryMap.size !== 0) { +            if (ungroupedDictionaryEntriesMap.size > 0 || secondarySearchDictionaryMap.size > 0) {                  await this._addSecondaryRelatedDictionaryEntries(groupedDictionaryEntries, ungroupedDictionaryEntriesMap, enabledDictionaryMap, secondarySearchDictionaryMap, tagAggregator);              }          } diff --git a/ext/js/pages/action-popup-main.js b/ext/js/pages/action-popup-main.js index b5728215..f58083a7 100644 --- a/ext/js/pages/action-popup-main.js +++ b/ext/js/pages/action-popup-main.js @@ -238,7 +238,7 @@ class DisplayController {       */      _onProfileSelectChange(event) {          const node = /** @type {HTMLInputElement} */ (event.currentTarget); -        const value = parseInt(node.value, 10); +        const value = Number.parseInt(node.value, 10);          if (typeof value === 'number' && Number.isFinite(value) && value >= 0 && value <= /** @type {import('settings').Options} */ (this._optionsFull).profiles.length) {              this._setPrimaryProfileIndex(value);          } diff --git a/ext/js/pages/info-main.js b/ext/js/pages/info-main.js index 7d7d56a5..0bc84d97 100644 --- a/ext/js/pages/info-main.js +++ b/ext/js/pages/info-main.js @@ -108,7 +108,7 @@ async function showDictionaryInfo(api) {      /** @type {HTMLElement} */      const noneElement = querySelectorNotNull(document, '#installed-dictionaries-none'); -    noneElement.hidden = (dictionaryInfos.length !== 0); +    noneElement.hidden = (dictionaryInfos.length > 0);      /** @type {HTMLElement} */      const container = querySelectorNotNull(document, '#installed-dictionaries');      container.textContent = ''; diff --git a/ext/js/pages/permissions-main.js b/ext/js/pages/permissions-main.js index 3092782b..17169c12 100644 --- a/ext/js/pages/permissions-main.js +++ b/ext/js/pages/permissions-main.js @@ -102,6 +102,8 @@ await Application.main(async (application) => {      /** @type {HTMLInputElement} */      const permissionCheckbox2 = querySelectorNotNull(document, '#permission-checkbox-allow-file-url-access');      /** @type {HTMLInputElement[]} */ +    // This collection is actually used, not sure why this eslint-disable is needed. +    // eslint-disable-next-line sonarjs/no-unused-collection      const permissionsCheckboxes = [permissionCheckbox1, permissionCheckbox2];      const permissions = await Promise.all([ diff --git a/ext/js/pages/settings/anki-controller.js b/ext/js/pages/settings/anki-controller.js index 3a6345ed..e161d86b 100644 --- a/ext/js/pages/settings/anki-controller.js +++ b/ext/js/pages/settings/anki-controller.js @@ -401,11 +401,11 @@ export class AnkiController {          if (typeof data !== 'undefined') {              details += `${JSON.stringify(data, null, 4)}\n\n`;          } -        details += `${error.stack}`.trimRight(); +        details += `${error.stack}`.trimEnd();          /** @type {HTMLElement} */ (this._ankiErrorMessageDetailsNode).textContent = details;          /** @type {HTMLElement} */ (this._ankiErrorMessageDetailsContainer).hidden = true; -        /** @type {HTMLElement} */ (this._ankiErrorInvalidResponseInfo).hidden = (errorString.indexOf('Invalid response') < 0); +        /** @type {HTMLElement} */ (this._ankiErrorInvalidResponseInfo).hidden = !errorString.includes('Invalid response');          /** @type {HTMLElement} */ (this._ankiErrorMessageDetailsToggle).hidden = false;      } @@ -762,7 +762,8 @@ class AnkiCardController {          const ELEMENT_NODE = Node.ELEMENT_NODE;          const container = this._ankiCardFieldsContainer;          if (container !== null) { -            for (const node of [...container.childNodes]) { +            const childNodesFrozen = [...container.childNodes]; +            for (const node of childNodesFrozen) {                  if (node.nodeType === ELEMENT_NODE && node instanceof HTMLElement && node.dataset.persistent === 'true') { continue; }                  container.removeChild(node);              } diff --git a/ext/js/pages/settings/audio-controller.js b/ext/js/pages/settings/audio-controller.js index 9633c4b3..5b597d33 100644 --- a/ext/js/pages/settings/audio-controller.js +++ b/ext/js/pages/settings/audio-controller.js @@ -144,7 +144,7 @@ export class AudioController extends EventDispatcher {              const text = input.value || '';              const voiceUri = input.dataset.voice;              const audio = this._audioSystem.createTextToSpeechAudio(text, typeof voiceUri === 'string' ? voiceUri : ''); -            audio.volume = 1.0; +            audio.volume = 1;              audio.play();          } catch (e) {              // NOP diff --git a/ext/js/pages/settings/backup-controller.js b/ext/js/pages/settings/backup-controller.js index 59bcaed9..2bab00e3 100644 --- a/ext/js/pages/settings/backup-controller.js +++ b/ext/js/pages/settings/backup-controller.js @@ -144,7 +144,7 @@ export class BackupController {              }          } -        const data = { +        return {              version: this._currentVersion,              date: this._getSettingsExportDateString(date, '-', ' ', ':', 6),              url: chrome.runtime.getURL('/'), @@ -154,8 +154,6 @@ export class BackupController {              permissions,              options: optionsFull          }; - -        return data;      }      /** diff --git a/ext/js/pages/settings/collapsible-dictionary-controller.js b/ext/js/pages/settings/collapsible-dictionary-controller.js index 5ba61e0c..62f84b96 100644 --- a/ext/js/pages/settings/collapsible-dictionary-controller.js +++ b/ext/js/pages/settings/collapsible-dictionary-controller.js @@ -156,9 +156,7 @@ export class CollapsibleDictionaryController {          const versionNode = querySelectorNotNull(node, '.dictionary-version');          versionNode.textContent = version; -        /** @type {HTMLSelectElement} */ -        const select = querySelectorNotNull(node, '.definitions-collapsible'); -        return select; +        return querySelectorNotNull(node, '.definitions-collapsible');      }      /** */ diff --git a/ext/js/pages/settings/dictionary-controller.js b/ext/js/pages/settings/dictionary-controller.js index 1d3c1730..5020dc7c 100644 --- a/ext/js/pages/settings/dictionary-controller.js +++ b/ext/js/pages/settings/dictionary-controller.js @@ -558,7 +558,7 @@ export class DictionaryController {          const {profiles} = optionsFull;          for (let i = 0, ii = profiles.length; i < ii; ++i) {              let modified = false; -            const missingDictionaries = new Set([...installedDictionaries]); +            const missingDictionaries = new Set(installedDictionaries);              const dictionaryOptionsArray = profiles[i].options.dictionaries;              for (let j = dictionaryOptionsArray.length - 1; j >= 0; --j) {                  const {name} = dictionaryOptionsArray[j]; @@ -871,8 +871,8 @@ export class DictionaryController {              const onProgress = ({processed, count, storeCount, storesProcesed}) => {                  const percent = (                      (count > 0 && storesProcesed > 0) ? -                    (processed / count) * (storesProcesed / storeCount) * 100.0 : -                    0.0 +                    (processed / count) * (storesProcesed / storeCount) * 100 : +                    0                  );                  const cssString = `${percent}%`;                  const statusString = `${percent.toFixed(0)}%`; diff --git a/ext/js/pages/settings/dictionary-import-controller.js b/ext/js/pages/settings/dictionary-import-controller.js index 0484001d..34e21c5d 100644 --- a/ext/js/pages/settings/dictionary-import-controller.js +++ b/ext/js/pages/settings/dictionary-import-controller.js @@ -172,7 +172,7 @@ export class DictionaryImportController {                      for (const label of infoLabels) { label.textContent = labelText; }                  } -                const percent = count > 0 ? (index / count * 100.0) : 0.0; +                const percent = count > 0 ? (index / count * 100) : 0;                  const cssString = `${percent}%`;                  const statusString = `${Math.floor(percent).toFixed(0)}%`;                  for (const progressBar of progressBars) { progressBar.style.width = cssString; } @@ -199,8 +199,8 @@ export class DictionaryImportController {                  await this._importDictionary(files[i], importDetails, onProgress);              } -        } catch (err) { -            this._showErrors([toError(err)]); +        } catch (error) { +            this._showErrors([toError(error)]);          } finally {              prevention.end();              for (const progress of progressContainers) { progress.hidden = true; } diff --git a/ext/js/pages/settings/extension-keyboard-shortcuts-controller.js b/ext/js/pages/settings/extension-keyboard-shortcuts-controller.js index 61eefffa..b9d107ae 100644 --- a/ext/js/pages/settings/extension-keyboard-shortcuts-controller.js +++ b/ext/js/pages/settings/extension-keyboard-shortcuts-controller.js @@ -353,7 +353,7 @@ class ExtensionKeyboardShortcutHotkeyEntry {       * @param {boolean} updateInput       */      async _tryUpdateInput(key, modifiers, updateInput) { -        let okay = (key === null ? (modifiers.length === 0) : (modifiers.length !== 0)); +        let okay = (key === null ? (modifiers.length === 0) : (modifiers.length > 0));          if (okay) {              try {                  await this._parent.updateCommand(this._name, key, modifiers); diff --git a/ext/js/pages/settings/keyboard-shortcuts-controller.js b/ext/js/pages/settings/keyboard-shortcuts-controller.js index 7b28a322..907cf4a1 100644 --- a/ext/js/pages/settings/keyboard-shortcuts-controller.js +++ b/ext/js/pages/settings/keyboard-shortcuts-controller.js @@ -183,7 +183,7 @@ export class KeyboardShortcutController {          const listContainer = /** @type {HTMLElement} */ (this._listContainer);          listContainer.appendChild(fragment);          listContainer.hidden = (hotkeys.length === 0); -        /** @type {HTMLElement} */ (this._emptyIndicator).hidden = (hotkeys.length !== 0); +        /** @type {HTMLElement} */ (this._emptyIndicator).hidden = (hotkeys.length > 0);      }      /** diff --git a/ext/js/pages/settings/profile-controller.js b/ext/js/pages/settings/profile-controller.js index 5a7b5ed4..a82a4b4e 100644 --- a/ext/js/pages/settings/profile-controller.js +++ b/ext/js/pages/settings/profile-controller.js @@ -544,7 +544,7 @@ export class ProfileController {       */      _tryGetValidProfileIndex(stringValue) {          if (typeof stringValue !== 'string') { return null; } -        const intValue = parseInt(stringValue, 10); +        const intValue = Number.parseInt(stringValue, 10);          return (              Number.isFinite(intValue) &&              intValue >= 0 && @@ -573,7 +573,7 @@ export class ProfileController {              suffix = match[5];              if (typeof match[2] === 'string') {                  space = match[3]; -                index = parseInt(match[4], 10) + 1; +                index = Number.parseInt(match[4], 10) + 1;              } else {                  space = ' ';                  index = 2; diff --git a/ext/js/pages/settings/sentence-termination-characters-controller.js b/ext/js/pages/settings/sentence-termination-characters-controller.js index c393aaa1..4ceed22b 100644 --- a/ext/js/pages/settings/sentence-termination-characters-controller.js +++ b/ext/js/pages/settings/sentence-termination-characters-controller.js @@ -125,8 +125,9 @@ export class SentenceTerminationCharactersController {              entry.prepare();          } -        /** @type {HTMLElement} */ (this._listTable).hidden = (terminationCharacters.length === 0); -        /** @type {HTMLElement} */ (this._emptyIndicator).hidden = (terminationCharacters.length !== 0); +        const empty = terminationCharacters.length === 0; +        /** @type {HTMLElement} */ (this._listTable).hidden = empty; +        /** @type {HTMLElement} */ (this._emptyIndicator).hidden = !empty;      }      /** diff --git a/ext/js/pages/settings/settings-controller.js b/ext/js/pages/settings/settings-controller.js index 3f389271..c835f8e6 100644 --- a/ext/js/pages/settings/settings-controller.js +++ b/ext/js/pages/settings/settings-controller.js @@ -195,6 +195,7 @@ export class SettingsController extends EventDispatcher {       */      preventPageExit() {          /** @type {import('settings-controller').PageExitPrevention} */ +        // eslint-disable-next-line sonarjs/prefer-object-literal          const obj = {};          obj.end = this._endPreventPageExit.bind(this, obj);          if (this._pageExitPreventionEventListeners.size === 0) { @@ -226,8 +227,7 @@ export class SettingsController extends EventDispatcher {      async getDefaultOptions() {          const optionsUtil = new OptionsUtil();          await optionsUtil.prepare(); -        const optionsFull = optionsUtil.getDefault(); -        return optionsFull; +        return optionsUtil.getDefault();      }      // Private diff --git a/ext/js/pages/settings/settings-display-controller.js b/ext/js/pages/settings/settings-display-controller.js index 0a729d96..47aa9c9c 100644 --- a/ext/js/pages/settings/settings-display-controller.js +++ b/ext/js/pages/settings/settings-display-controller.js @@ -290,7 +290,7 @@ export class SettingsDisplayController {       */      _getMoreContainer(link) {          const v = link.dataset.parentDistance; -        const distance = v ? parseInt(v, 10) : 1; +        const distance = v ? Number.parseInt(v, 10) : 1;          if (Number.isNaN(distance)) { return null; }          /** @type {?Element} */ @@ -338,7 +338,7 @@ export class SettingsDisplayController {          let indent = '\t';          if (args.length > 1) { -            const count = parseInt(args[1], 10); +            const count = Number.parseInt(args[1], 10);              indent = (Number.isFinite(count) && count >= 0 ? ' '.repeat(count) : args[1]);          } diff --git a/ext/js/templates/sandbox/anki-template-renderer.js b/ext/js/templates/sandbox/anki-template-renderer.js index 2320a0b1..ad2b0042 100644 --- a/ext/js/templates/sandbox/anki-template-renderer.js +++ b/ext/js/templates/sandbox/anki-template-renderer.js @@ -171,11 +171,11 @@ export class AnkiTemplateRenderer {          for (const {text, reading: reading2} of segments) {              const safeText = this._escape(text);              const safeReading = this._escape(reading2); -            if (safeReading.length > 0) { -                result += `<ruby>${safeText}<rt>${safeReading}</rt></ruby>`; -            } else { -                result += safeText; -            } +            result += ( +                safeReading.length > 0 ? +                `<ruby>${safeText}<rt>${safeReading}</rt></ruby>` : +                safeText +            );          }          return this._safeString(result); |