Skip to content

Commit

Permalink
Eslint rule updates (#673)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
toasted-nutbread authored Feb 15, 2024
1 parent 7a40962 commit 6bf7b00
Show file tree
Hide file tree
Showing 66 changed files with 3,190 additions and 196 deletions.
107 changes: 105 additions & 2 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@
"jsonc",
"unused-imports",
"@typescript-eslint",
"@stylistic"
"@stylistic",
"unicorn",
"sonarjs",
"import"
],
"ignorePatterns": [
"/ext/lib/",
Expand Down Expand Up @@ -247,7 +250,107 @@

"eslint-comments/no-unused-disable": "error",

"unused-imports/no-unused-imports": "error"
"unused-imports/no-unused-imports": "error",

"import/extensions": ["error", "ignorePackages"],

"unicorn/catch-error-name": ["error", {"ignore": ["^(e|error2?)$"]}],
"unicorn/custom-error-definition": "error",
"unicorn/empty-brace-spaces": "error",
"unicorn/error-message": "error",
"unicorn/expiring-todo-comments": "error",
"unicorn/explicit-length-check": "error",
"unicorn/new-for-builtins": "error",
"unicorn/no-abusive-eslint-disable": "error",
"unicorn/no-array-for-each": "error",
"unicorn/no-array-method-this-argument": "error",
"unicorn/no-array-push-push": "error",
"unicorn/no-array-reduce": "error",
"unicorn/no-console-spaces": "error",
"unicorn/no-document-cookie": "error",
"unicorn/no-empty-file": "error",
"unicorn/no-hex-escape": "error",
"unicorn/no-instanceof-array": "error",
"unicorn/no-invalid-remove-event-listener": "error",
"unicorn/no-lonely-if": "error",
"unicorn/no-nested-ternary": "error",
"unicorn/no-new-buffer": "error",
"unicorn/no-object-as-default-parameter": "error",
"unicorn/no-static-only-class": "error",
"unicorn/no-thenable": "error",
"unicorn/no-unnecessary-await": "error",
"unicorn/no-unnecessary-polyfills": "error",
"unicorn/no-unreadable-array-destructuring": "error",
"unicorn/no-unreadable-iife": "error",
"unicorn/no-useless-fallback-in-spread": "error",
"unicorn/no-useless-length-check": "error",
"unicorn/no-useless-promise-resolve-reject": "error",
"unicorn/no-useless-spread": "error",
"unicorn/no-useless-switch-case": "error",
"unicorn/no-useless-undefined": "error",
"unicorn/no-zero-fractions": "error",
"unicorn/prefer-array-find": "error",
"unicorn/prefer-array-flat": "error",
"unicorn/prefer-array-flat-map": "error",
"unicorn/prefer-array-index-of": "error",
"unicorn/prefer-array-some": "error",
"unicorn/prefer-date-now": "error",
"unicorn/prefer-default-parameters": "error",
"unicorn/prefer-dom-node-dataset": "error",
"unicorn/prefer-dom-node-text-content": "error",
"unicorn/prefer-event-target": "error",
"unicorn/prefer-export-from": "error",
"unicorn/prefer-includes": "error",
"unicorn/prefer-keyboard-event-key": "error",
"unicorn/prefer-logical-operator-over-ternary": "error",
"unicorn/prefer-modern-math-apis": "error",
"unicorn/prefer-module": "error",
"unicorn/prefer-native-coercion-functions": "error",
"unicorn/prefer-negative-index": "error",
"unicorn/prefer-number-properties": "error",
"unicorn/prefer-object-from-entries": "error",
"unicorn/prefer-prototype-methods": "error",
"unicorn/prefer-reflect-apply": "error",
"unicorn/prefer-regexp-test": "error",
"unicorn/prefer-set-has": "error",
"unicorn/prefer-set-size": "error",
"unicorn/prefer-spread": "error",
"unicorn/prefer-string-starts-ends-with": "error",
"unicorn/prefer-string-trim-start-end": "error",
"unicorn/prefer-switch": "error",
"unicorn/prefer-ternary": "error",
"unicorn/relative-url-style": "error",
"unicorn/require-array-join-separator": "error",
"unicorn/require-number-to-fixed-digits-argument": "error",
"unicorn/template-indent": "error",
"unicorn/throw-new-error": "error",

"sonarjs/max-switch-cases": "error",
"sonarjs/no-all-duplicated-branches": "error",
"sonarjs/no-collapsible-if": "error",
"sonarjs/no-collection-size-mischeck": "error",
"sonarjs/no-duplicated-branches": "error",
"sonarjs/no-element-overwrite": "error",
"sonarjs/no-empty-collection": "error",
"sonarjs/no-extra-arguments": "error",
"sonarjs/no-gratuitous-expressions": "error",
"sonarjs/no-identical-conditions": "error",
"sonarjs/no-identical-expressions": "error",
"sonarjs/no-identical-functions": "error",
"sonarjs/no-ignored-return": "error",
"sonarjs/no-inverted-boolean-check": "error",
"sonarjs/no-one-iteration-loop": "error",
"sonarjs/no-redundant-boolean": "error",
"sonarjs/no-redundant-jump": "error",
"sonarjs/no-same-line-conditional": "error",
"sonarjs/no-unused-collection": "error",
"sonarjs/no-use-of-empty-return-value": "error",
"sonarjs/no-useless-catch": "error",
"sonarjs/non-existent-operator": "error",
"sonarjs/prefer-immediate-return": "error",
"sonarjs/prefer-object-literal": "error",
"sonarjs/prefer-single-boolean-return": "error",
"sonarjs/prefer-while": "error"
},
"overrides": [
{
Expand Down
10 changes: 4 additions & 6 deletions dev/bin/build.js
Original file line number Diff line number Diff line change
Expand Up @@ -195,12 +195,10 @@ async function build(buildDir, extDir, manifestUtil, variantNames, manifestPath,
await createZip(extDir, excludeFiles, fullFileName, sevenZipExes, onUpdate, dryRun);
}

if (!dryRun) {
if (Array.isArray(fileCopies)) {
for (const fileName2 of fileCopies) {
const fileName2Safe = path.basename(fileName2);
fs.copyFileSync(fullFileName, path.join(buildDir, fileName2Safe));
}
if (!dryRun && Array.isArray(fileCopies)) {
for (const fileName2 of fileCopies) {
const fileName2Safe = path.basename(fileName2);
fs.copyFileSync(fullFileName, path.join(buildDir, fileName2Safe));
}
}
}
Expand Down
1 change: 1 addition & 0 deletions dev/build-libs.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ export async function buildLibs() {
const schemaFileNames = fs.readdirSync(schemaDir);
const schemas = schemaFileNames.map((schemaFileName) => {
/** @type {import('ajv').AnySchema} */
// eslint-disable-next-line sonarjs/prefer-immediate-return
const result = parseJson(fs.readFileSync(path.join(schemaDir, schemaFileName), {encoding: 'utf8'}));
return result;
});
Expand Down
8 changes: 3 additions & 5 deletions dev/data-error.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@
/**
* Schema validation error type.
*/
class DataError extends Error {
export class DataError extends Error {
/**
* @param {string} message
*/
constructor(message) {
super(message);
/** @type {string} */
this.name = 'DataError';
/** @type {unknown} */
this._data = void 0;
}
Expand All @@ -32,7 +34,3 @@ class DataError extends Error {
get data() { return this._data; }
set data(value) { this._data = value; }
}

module.exports = {
DataError
};
10 changes: 5 additions & 5 deletions dev/generate-css-json.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,11 +101,11 @@ export function formatRulesJson(rules) {
for (const {selectors, styles} of rules) {
if (ruleIndex > 0) { result += ','; }
result += `\n${indent1}{\n${indent2}"selectors": `;
if (selectors.length === 1) {
result += `[${JSON.stringify(selectors[0], null, 4)}]`;
} else {
result += JSON.stringify(selectors, null, 4).replace(/\n/g, '\n' + indent2);
}
result += (
selectors.length === 1 ?
`[${JSON.stringify(selectors[0], null, 4)}]` :
JSON.stringify(selectors, null, 4).replace(/\n/g, '\n' + indent2)
);
result += `,\n${indent2}"styles": [`;
let styleIndex = 0;
for (const [key, value] of styles) {
Expand Down
5 changes: 2 additions & 3 deletions dev/lib/dexie.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

import Dexie from 'dexie';
import 'dexie-export-import';
export {default as Dexie} from 'dexie';

export {Dexie};
import 'dexie-export-import';
3 changes: 2 additions & 1 deletion dev/schema-validate.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import Ajv from 'ajv';
import {readFileSync} from 'fs';
import {fileURLToPath} from 'url';
import {JsonSchema} from '../ext/js/data/json-schema.js';
import {DataError} from './data-error.js';
import {parseJson} from './json.js';
Expand All @@ -32,7 +33,7 @@ class JsonSchemaAjv {
strictTuples: false,
allowUnionTypes: true
});
const metaSchemaPath = require.resolve('ajv/dist/refs/json-schema-draft-07.json');
const metaSchemaPath = fileURLToPath(import.meta.resolve('ajv/dist/refs/json-schema-draft-07.json'));
/** @type {import('ajv').AnySchemaObject} */
const metaSchema = parseJson(readFileSync(metaSchemaPath, {encoding: 'utf8'}));
ajv.addMetaSchema(metaSchema);
Expand Down
6 changes: 2 additions & 4 deletions dev/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,8 @@ export function getAllFiles(baseDirectory, predicate = null) {
if (typeof predicate !== 'function' || predicate(relativeFileName, false)) {
results.push(relativeFileName);
}
} else if (stats.isDirectory()) {
if (typeof predicate !== 'function' || predicate(relativeFileName, true)) {
directories.push(fullFileName);
}
} else if (stats.isDirectory() && (typeof predicate !== 'function' || predicate(relativeFileName, true))) {
directories.push(fullFileName);
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions ext/js/accessibility/google-docs-util.js
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand Down
6 changes: 3 additions & 3 deletions ext/js/app/frontend.js
Original file line number Diff line number Diff line change
Expand Up @@ -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} */
Expand Down Expand Up @@ -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; }
Expand Down
6 changes: 4 additions & 2 deletions ext/js/app/popup.js
Original file line number Diff line number Diff line change
Expand Up @@ -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(/\/$/, '');

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -1133,6 +1133,8 @@ class PopupError extends ExtensionError {
*/
constructor(message, source) {
super(message);
/** @type {string} */
this.name = 'PopupError';
/** @type {Popup} */
this._source = source;
}
Expand Down
6 changes: 3 additions & 3 deletions ext/js/app/theme-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -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
];
}
}
10 changes: 4 additions & 6 deletions ext/js/background/backend.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) => {
Expand Down Expand Up @@ -1701,10 +1701,8 @@ export class Backend {
// NOP
}

if (okay && !done) {
if (add(item)) {
done = true;
}
if (okay && !done && add(item)) {
done = true;
}
};

Expand Down Expand Up @@ -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, '-');
}

/**
Expand Down
3 changes: 1 addition & 2 deletions ext/js/background/offscreen-proxy.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)}));
}
}

Expand Down
3 changes: 1 addition & 2 deletions ext/js/background/offscreen.js
Original file line number Diff line number Diff line change
Expand Up @@ -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'>} */
Expand Down
2 changes: 2 additions & 0 deletions ext/js/core/extension-error.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ export class ExtensionError extends Error {
*/
constructor(message) {
super(message);
/** @type {string} */
this.name = 'ExtensionError';
/** @type {unknown} */
this._data = void 0;
}
Expand Down
Loading

0 comments on commit 6bf7b00

Please sign in to comment.