diff options
| -rw-r--r-- | .eslintrc.json | 36 | ||||
| -rw-r--r-- | dev/generate-css-json.js | 1 | ||||
| -rw-r--r-- | dev/util.js | 8 | ||||
| -rw-r--r-- | ext/js/background/backend.js | 6 | ||||
| -rw-r--r-- | ext/js/background/offscreen-proxy.js | 2 | ||||
| -rw-r--r-- | ext/js/background/profile-conditions-util.js | 2 | ||||
| -rw-r--r-- | ext/js/data/permissions-util.js | 72 | ||||
| -rw-r--r-- | ext/js/dictionary/dictionary-data-util.js | 2 | ||||
| -rw-r--r-- | ext/js/dom/dom-text-scanner.js | 6 | ||||
| -rw-r--r-- | ext/js/language/ja/japanese.js | 6 | ||||
| -rw-r--r-- | ext/js/language/translator.js | 2 | ||||
| -rw-r--r-- | ext/js/pages/permissions-main.js | 4 | ||||
| -rw-r--r-- | test/fixtures/dom-test.js | 1 | ||||
| -rw-r--r-- | test/language-transformer.test.js | 3 | ||||
| -rw-r--r-- | test/options-util.test.js | 14 | ||||
| -rw-r--r-- | test/playwright/integration.spec.js | 4 | ||||
| -rw-r--r-- | test/playwright/playwright-util.js | 2 | ||||
| -rw-r--r-- | test/playwright/visual.spec.js | 12 | ||||
| -rw-r--r-- | test/profile-conditions-util.test.js | 4 | ||||
| -rw-r--r-- | test/utilities/translator.js | 1 | ||||
| -rw-r--r-- | types/ext/application.d.ts | 3 | 
21 files changed, 116 insertions, 75 deletions
| diff --git a/.eslintrc.json b/.eslintrc.json index 30d495d2..361e5f24 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -42,18 +42,42 @@          "/dev/lib/handlebars/"      ],      "rules": { +        "accessor-pairs": "error", +        "capitalized-comments": [ +            "error", +            "always", +            { +                "ignorePattern": "case|[a-z]+[A-Z0-9]|[a-z]+\\.\\w", +                "ignoreInlineComments": true, +                "ignoreConsecutiveComments": true +            } +        ],          "curly": ["error", "all"], +        "default-case-last": "error",          "dot-notation": "error",          "eqeqeq": "error",          "func-names": ["error", "always"],          "guard-for-in": "error", +        "grouped-accessor-pairs": "error", +        "new-cap": "error", +        "no-alert": "error",          "no-case-declarations": "error", +        "no-caller": "error",          "no-const-assign": "error", -        "no-constant-condition": "off", +        "no-constant-condition": ["error", {"checkLoops": false}], +        "no-constructor-return": "error", +        "no-duplicate-imports": "error", +        "no-eval": "error", +        "no-extend-native": "error",          "no-global-assign": "error",          "no-implicit-globals": "error", +        "no-implied-eval": "error",          "no-new": "error", +        "no-new-native-nonconstructor": "error", +        "no-octal": "off", +        "no-octal-escape": "off",          "no-param-reassign": "off", +        "no-promise-executor-return": "error",          "no-prototype-builtins": "error",          "no-restricted-syntax": [              "error", @@ -66,7 +90,11 @@                  "selector": "MemberExpression[property.name=json]"              }          ], -        "no-shadow": ["off", {"builtinGlobals": false}], +        "no-self-compare": "error", +        "no-sequences": "error", +        "no-shadow": ["error", {"builtinGlobals": false}], +        "no-shadow-restricted-names": "error", +        "no-template-curly-in-string": "error",          "no-undef": "error",          "no-undefined": "error",          "no-underscore-dangle": ["error", {"allowAfterThis": true, "allowAfterSuper": false, "allowAfterThisConstructor": false}], @@ -75,8 +103,12 @@          "no-unused-vars": ["error", {"vars": "local", "args": "after-used", "argsIgnorePattern": "^_", "caughtErrors": "none"}],          "no-unused-expressions": "error",          "no-var": "error", +        "no-with": "error",          "prefer-const": ["error", {"destructuring": "all"}], +        "radix": "error",          "require-atomic-updates": "off", +        "sort-imports": "off", +        "yoda": ["error", "never"],          "@stylistic/array-bracket-newline": ["error", "consistent"],          "@stylistic/array-bracket-spacing": ["error", "never"], diff --git a/dev/generate-css-json.js b/dev/generate-css-json.js index a837c9e2..adb75495 100644 --- a/dev/generate-css-json.js +++ b/dev/generate-css-json.js @@ -91,6 +91,7 @@ function removeProperty(styles, property, removedProperties) {   * @returns {string}   */  export function formatRulesJson(rules) { +    // This is similar to the following code, but formatted a but more succinctly:      // return JSON.stringify(rules, null, 4);      const indent1 = '    ';      const indent2 = indent1.repeat(2); diff --git a/dev/util.js b/dev/util.js index eee16964..817b0d84 100644 --- a/dev/util.js +++ b/dev/util.js @@ -57,7 +57,7 @@ export function getAllFiles(baseDirectory, predicate = null) {  export function createDictionaryArchive(dictionaryDirectory, dictionaryName) {      const fileNames = fs.readdirSync(dictionaryDirectory); -    // const zipFileWriter = new BlobWriter(); +    // Const zipFileWriter = new BlobWriter();      // const zipWriter = new ZipWriter(zipFileWriter);      const archive = new JSZip(); @@ -70,7 +70,7 @@ export function createDictionaryArchive(dictionaryDirectory, dictionaryName) {              }              archive.file(fileName, JSON.stringify(json, null, 0)); -            // await zipWriter.add(fileName, new TextReader(JSON.stringify(json, null, 0))); +            // Await zipWriter.add(fileName, new TextReader(JSON.stringify(json, null, 0)));          } else {              const content = fs.readFileSync(path.join(dictionaryDirectory, fileName), {encoding: null});              archive.file(fileName, content); @@ -83,14 +83,14 @@ export function createDictionaryArchive(dictionaryDirectory, dictionaryName) {              // console.log('??');          }      } -    // await zipWriter.close(); +    // Await zipWriter.close();      // Retrieves the Blob object containing the zip content into `zipFileBlob`. It      // is also returned by zipWriter.close() for more convenience.      // const zipFileBlob = await zipFileWriter.getData();      return archive; -    // return zipFileBlob; +    // Return zipFileBlob;  }  /** diff --git a/ext/js/background/backend.js b/ext/js/background/backend.js index 8ab56232..e246f0bb 100644 --- a/ext/js/background/backend.js +++ b/ext/js/background/backend.js @@ -437,7 +437,7 @@ export class Backend {      /** @type {import('api').ApiHandler<'requestBackendReadySignal'>} */      _onApiRequestBackendReadySignal(_params, sender) { -        // tab ID isn't set in background (e.g. browser_action) +        // Tab ID isn't set in background (e.g. browser_action)          /** @type {import('application').ApiMessage<'applicationBackendReady'>} */          const data = {action: 'applicationBackendReady'};          if (typeof sender.tab === 'undefined') { @@ -1547,7 +1547,7 @@ export class Backend {          return (              isObject(chrome.action) &&              typeof chrome.action.getTitle === 'function' ? -                new Promise((resolve) => chrome.action.getTitle({}, resolve)) : +                new Promise((resolve) => { chrome.action.getTitle({}, resolve); }) :                  Promise.resolve('')          );      } @@ -2601,7 +2601,7 @@ export class Backend {              const match = /^\d+/.exec(version);              if (match === null) { return; } -            const versionNumber = Number.parseInt(match[0]); +            const versionNumber = Number.parseInt(match[0], 10);              if (!(Number.isFinite(versionNumber) && versionNumber >= 77)) { return; }              await navigator.storage.persist(); diff --git a/ext/js/background/offscreen-proxy.js b/ext/js/background/offscreen-proxy.js index 085048c1..5a79f41a 100644 --- a/ext/js/background/offscreen-proxy.js +++ b/ext/js/background/offscreen-proxy.js @@ -85,7 +85,7 @@ export class OffscreenProxy {       */      async _hasOffscreenDocument() {          const offscreenUrl = chrome.runtime.getURL('offscreen.html'); -        if (!chrome.runtime.getContexts) { // chrome version below 116 +        if (!chrome.runtime.getContexts) { // Chrome version below 116              // Clients: https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerGlobalScope/clients              // @ts-expect-error - Types not set up for service workers yet              const matchedClients = await clients.matchAll(); diff --git a/ext/js/background/profile-conditions-util.js b/ext/js/background/profile-conditions-util.js index e2d58725..4e4e38d7 100644 --- a/ext/js/background/profile-conditions-util.js +++ b/ext/js/background/profile-conditions-util.js @@ -229,7 +229,7 @@ function createSchemaPopupLevelGreaterThanOrEqual(value) {      };  } -// url schema creation functions +// URL schema creation functions  /**   * @param {string} value diff --git a/ext/js/data/permissions-util.js b/ext/js/data/permissions-util.js index 097fe34d..1ccc630f 100644 --- a/ext/js/data/permissions-util.js +++ b/ext/js/data/permissions-util.js @@ -40,14 +40,16 @@ function ankiFieldMarkerMayUseClipboard(marker) {   * @returns {Promise<boolean>}   */  export function hasPermissions(permissions) { -    return new Promise((resolve, reject) => chrome.permissions.contains(permissions, (result) => { -        const e = chrome.runtime.lastError; -        if (e) { -            reject(new Error(e.message)); -        } else { -            resolve(result); -        } -    })); +    return new Promise((resolve, reject) => { +        chrome.permissions.contains(permissions, (result) => { +            const e = chrome.runtime.lastError; +            if (e) { +                reject(new Error(e.message)); +            } else { +                resolve(result); +            } +        }); +    });  }  /** @@ -58,22 +60,26 @@ export function hasPermissions(permissions) {  export function setPermissionsGranted(permissions, shouldHave) {      return (          shouldHave ? -        new Promise((resolve, reject) => chrome.permissions.request(permissions, (result) => { -            const e = chrome.runtime.lastError; -            if (e) { -                reject(new Error(e.message)); -            } else { -                resolve(result); -            } -        })) : -        new Promise((resolve, reject) => chrome.permissions.remove(permissions, (result) => { -            const e = chrome.runtime.lastError; -            if (e) { -                reject(new Error(e.message)); -            } else { -                resolve(!result); -            } -        })) +        new Promise((resolve, reject) => { +            chrome.permissions.request(permissions, (result) => { +                const e = chrome.runtime.lastError; +                if (e) { +                    reject(new Error(e.message)); +                } else { +                    resolve(result); +                } +            }); +        }) : +        new Promise((resolve, reject) => { +            chrome.permissions.remove(permissions, (result) => { +                const e = chrome.runtime.lastError; +                if (e) { +                    reject(new Error(e.message)); +                } else { +                    resolve(!result); +                } +            }); +        })      );  } @@ -81,14 +87,16 @@ export function setPermissionsGranted(permissions, shouldHave) {   * @returns {Promise<chrome.permissions.Permissions>}   */  export function getAllPermissions() { -    return new Promise((resolve, reject) => chrome.permissions.getAll((result) => { -        const e = chrome.runtime.lastError; -        if (e) { -            reject(new Error(e.message)); -        } else { -            resolve(result); -        } -    })); +    return new Promise((resolve, reject) => { +        chrome.permissions.getAll((result) => { +            const e = chrome.runtime.lastError; +            if (e) { +                reject(new Error(e.message)); +            } else { +                resolve(result); +            } +        }); +    });  }  /** diff --git a/ext/js/dictionary/dictionary-data-util.js b/ext/js/dictionary/dictionary-data-util.js index a2a106cc..a90668f4 100644 --- a/ext/js/dictionary/dictionary-data-util.js +++ b/ext/js/dictionary/dictionary-data-util.js @@ -286,7 +286,7 @@ export function isNonNounVerbOrAdjective(wordClasses) {              case 'vs':                  isVerbOrAdjective = true;                  isSuruVerb = true; -                // falls through +                // Falls through              case 'n':                  isNoun = true;                  break; diff --git a/ext/js/dom/dom-text-scanner.js b/ext/js/dom/dom-text-scanner.js index 5b3ea564..e263d9f3 100644 --- a/ext/js/dom/dom-text-scanner.js +++ b/ext/js/dom/dom-text-scanner.js @@ -551,10 +551,10 @@ export class DOMTextScanner {              case 'block':              case 'flex':              case 'grid': -            case 'list': // list-item -            case 'table': // table, table-* +            case 'list': // Also includes: list-item +            case 'table': // Also includes: table, table-*                  return true; -            case 'ruby': // ruby-* +            case 'ruby': // Also includes: ruby-*                  return (pos >= 0);              default:                  return false; diff --git a/ext/js/language/ja/japanese.js b/ext/js/language/ja/japanese.js index 818daa0b..2c9a1f7f 100644 --- a/ext/js/language/ja/japanese.js +++ b/ext/js/language/ja/japanese.js @@ -557,17 +557,17 @@ export function convertHalfWidthKanaToFullWidth(text, sourceMap = null) {          let index = 0;          switch (text.charCodeAt(i + 1)) { -            case 0xff9e: // dakuten +            case 0xff9e: // Dakuten                  index = 1;                  break; -            case 0xff9f: // handakuten +            case 0xff9f: // Handakuten                  index = 2;                  break;          }          let c2 = mapping[index];          if (index > 0) { -            if (c2 === '-') { // invalid +            if (c2 === '-') { // Invalid                  index = 0;                  c2 = mapping[0];              } else { diff --git a/ext/js/language/translator.js b/ext/js/language/translator.js index 2ba1ce0d..b2342e8d 100644 --- a/ext/js/language/translator.js +++ b/ext/js/language/translator.js @@ -1609,7 +1609,7 @@ export class Translator {              sequence: rawSequence,              rules          } = databaseEntry; -        // cast is safe because getDeinflections filters out deinflection definitions +        // Cast is safe because getDeinflections filters out deinflection definitions          const contentDefinitions = /** @type {import('dictionary-data').TermGlossaryContent[]} */ (definitions);          const reading = (rawReading.length > 0 ? rawReading : term);          const {index: dictionaryIndex, priority: dictionaryPriority} = this._getDictionaryOrder(dictionary, enabledDictionaryMap); diff --git a/ext/js/pages/permissions-main.js b/ext/js/pages/permissions-main.js index 17169c12..3be97b78 100644 --- a/ext/js/pages/permissions-main.js +++ b/ext/js/pages/permissions-main.js @@ -43,14 +43,14 @@ async function setupEnvironmentInfo(api) {   * @returns {Promise<boolean>}   */  async function isAllowedIncognitoAccess() { -    return await new Promise((resolve) => chrome.extension.isAllowedIncognitoAccess(resolve)); +    return await new Promise((resolve) => { chrome.extension.isAllowedIncognitoAccess(resolve); });  }  /**   * @returns {Promise<boolean>}   */  async function isAllowedFileSchemeAccess() { -    return await new Promise((resolve) => chrome.extension.isAllowedFileSchemeAccess(resolve)); +    return await new Promise((resolve) => { chrome.extension.isAllowedFileSchemeAccess(resolve); });  }  /** diff --git a/test/fixtures/dom-test.js b/test/fixtures/dom-test.js index 578b1324..961e0a77 100644 --- a/test/fixtures/dom-test.js +++ b/test/fixtures/dom-test.js @@ -28,6 +28,7 @@ function prepareWindow(window) {      // Define innerText setter as an alias for textContent setter      Object.defineProperty(window.HTMLDivElement.prototype, 'innerText', { +        get() { return this.textContent; },          set(value) { this.textContent = value; }      }); diff --git a/test/language-transformer.test.js b/test/language-transformer.test.js index 0c8ef08d..7c0da48b 100644 --- a/test/language-transformer.test.js +++ b/test/language-transformer.test.js @@ -923,7 +923,7 @@ describe('LanguageTransformer', () => {                  {term: 'あかい',     source: 'あけえ',     rule: 'adj-i', reasons: ['-e']},                  {term: 'こわい',     source: 'こええ',     rule: 'adj-i', reasons: ['-e']},                  {term: 'つよい',     source: 'つええ',     rule: 'adj-i', reasons: ['-e']}, -                // small -e +                // Small -e                  {term: 'すごい',     source: 'すげぇ',     rule: 'adj-i', reasons: ['-e']},                  {term: 'やばい',     source: 'やべぇ',     rule: 'adj-i', reasons: ['-e']},                  {term: 'うるさい',   source: 'うるせぇ',   rule: 'adj-i', reasons: ['-e']}, @@ -1152,7 +1152,6 @@ describe('LanguageTransformer', () => {      languageTransformer.addDescriptor(descriptor);      describe('deinflections', () => { -        // for (const {valid, tests} of data) {          describe.each(data)('$category', ({valid, tests}) => {              for (const {source, term, rule, reasons} of tests) {                  const {has} = hasTermReasons(languageTransformer, source, term, rule, reasons); diff --git a/test/options-util.test.js b/test/options-util.test.js index a178aecb..3a1b1efb 100644 --- a/test/options-util.test.js +++ b/test/options-util.test.js @@ -702,7 +702,7 @@ describe('OptionsUtil', () => {              const match = fileNameRegex.exec(fileName);              if (match !== null) {                  updates.push({ -                    version: Number.parseInt(match[1]), +                    version: Number.parseInt(match[1], 10),                      changes: loadDataFile(path.join(templatesDirPath, match[0]))                  });              } @@ -846,7 +846,7 @@ describe('OptionsUtil', () => {  {{~> (lookup . "marker") ~}}  `.trimStart()              }, -            // glossary and glossary-brief update +            // Glossary and glossary-brief update              {                  oldVersion: 7,                  newVersion: 12, @@ -1238,7 +1238,7 @@ describe('OptionsUtil', () => {  <<<UPDATE-ADDITIONS>>>  {{~> (lookup . "marker") ~}}`.trimStart()              }, -            // block helper update: furigana and furiganaPlain +            // Block helper update: furigana and furiganaPlain              {                  oldVersion: 20,                  newVersion: 21, @@ -1326,7 +1326,7 @@ describe('OptionsUtil', () => {  {{~> (lookup . "marker") ~}}`.trimStart()              }, -            // block helper update: formatGlossary +            // Block helper update: formatGlossary              {                  oldVersion: 20,                  newVersion: 21, @@ -1400,7 +1400,7 @@ describe('OptionsUtil', () => {  {{~> (lookup . "marker") ~}}`.trimStart()              }, -            // block helper update: set and get +            // Block helper update: set and get              {                  oldVersion: 20,                  newVersion: 21, @@ -1502,7 +1502,7 @@ describe('OptionsUtil', () => {  {{~> (lookup . "marker") ~}}`.trimStart()              }, -            // block helper update: hasMedia and getMedia +            // Block helper update: hasMedia and getMedia              {                  oldVersion: 20,                  newVersion: 21, @@ -1584,7 +1584,7 @@ describe('OptionsUtil', () => {  {{~> (lookup . "marker") ~}}`.trimStart()              }, -            // block helper update: pronunciation +            // Block helper update: pronunciation              {                  oldVersion: 20,                  newVersion: 21, diff --git a/test/playwright/integration.spec.js b/test/playwright/integration.spec.js index 170714a1..06af3fd2 100644 --- a/test/playwright/integration.spec.js +++ b/test/playwright/integration.spec.js @@ -31,13 +31,13 @@ import {  test.beforeEach(async ({context}) => {      // Wait for the on-install welcome.html tab to load, which becomes the foreground tab      const welcome = await context.waitForEvent('page'); -    await welcome.close(); // close the welcome tab so our main tab becomes the foreground tab -- otherwise, the screenshot can hang +    await welcome.close(); // Close the welcome tab so our main tab becomes the foreground tab -- otherwise, the screenshot can hang  });  test('search clipboard', async ({page, extensionId}) => {      await page.goto(`chrome-extension://${extensionId}/search.html`);      await page.locator('#search-option-clipboard-monitor-container > label').click(); -    await page.waitForTimeout(200); // race +    await page.waitForTimeout(200); // Race      await writeToClipboardFromPage(page, 'あ');      await expect(page.locator('#search-textbox')).toHaveValue('あ'); diff --git a/test/playwright/playwright-util.js b/test/playwright/playwright-util.js index b364c80b..b9a4831a 100644 --- a/test/playwright/playwright-util.js +++ b/test/playwright/playwright-util.js @@ -28,7 +28,7 @@ export const test = base.extend({      context: async ({}, use) => {          const pathToExtension = path.join(root, 'ext');          const context = await chromium.launchPersistentContext('', { -            // headless: false, +            // Disabled: headless: false,              args: [                  '--headless=new',                  `--disable-extensions-except=${pathToExtension}`, diff --git a/test/playwright/visual.spec.js b/test/playwright/visual.spec.js index fc8bb8df..157cedc7 100644 --- a/test/playwright/visual.spec.js +++ b/test/playwright/visual.spec.js @@ -22,7 +22,7 @@ import {expect, root, test} from './playwright-util.js';  test.beforeEach(async ({context}) => {      // Wait for the on-install welcome.html tab to load, which becomes the foreground tab      const welcome = await context.waitForEvent('page'); -    welcome.close(); // close the welcome tab so our main tab becomes the foreground tab -- otherwise, the screenshot can hang +    welcome.close(); // Close the welcome tab so our main tab becomes the foreground tab -- otherwise, the screenshot can hang  });  test('visual', async ({page, extensionId}) => { @@ -63,9 +63,9 @@ test('visual', async ({page, extensionId}) => {          if (typeof popup_frame === 'undefined') {              frame_attached = page.waitForEvent('frameattached');          } -        await page.mouse.move(box.x + offset.x, box.y + offset.y, {steps: 10}); // hover over the test +        await page.mouse.move(box.x + offset.x, box.y + offset.y, {steps: 10}); // Hover over the test          if (typeof popup_frame === 'undefined') { -            popup_frame = await frame_attached; // wait for popup to be attached +            popup_frame = await frame_attached; // Wait for popup to be attached          }          try {              // Some tests don't have a popup, so don't fail if it's not there @@ -75,11 +75,11 @@ test('visual', async ({page, extensionId}) => {              console.log(test_name + ' has no popup');          } -        await page.bringToFront(); // bring the page to the foreground so the screenshot doesn't hang; for some reason the frames result in page being in the background +        await page.bringToFront(); // Bring the page to the foreground so the screenshot doesn't hang; for some reason the frames result in page being in the background          await expect.soft(page).toHaveScreenshot(test_name + '.png'); -        await page.mouse.click(0, 0); // click away so popup disappears -        await (await /** @type {import('@playwright/test').Frame} */ (popup_frame).frameElement()).waitForElementState('hidden'); // wait for popup to disappear +        await page.mouse.click(0, 0); // Click away so popup disappears +        await (await /** @type {import('@playwright/test').Frame} */ (popup_frame).frameElement()).waitForElementState('hidden'); // Wait for popup to disappear      };      // Test document 1 diff --git a/test/profile-conditions-util.test.js b/test/profile-conditions-util.test.js index 6de5ad1d..590e5873 100644 --- a/test/profile-conditions-util.test.js +++ b/test/profile-conditions-util.test.js @@ -250,7 +250,7 @@ describe('Profile conditions utilities', () => {                  ]              }, -            // url tests +            // Url tests              {                  conditionGroups: [                      { @@ -606,7 +606,7 @@ describe('Profile conditions utilities', () => {                  ]              }, -            // flags tests +            // Flags tests              {                  conditionGroups: [                      { diff --git a/test/utilities/translator.js b/test/utilities/translator.js index b77bfb39..f452e688 100644 --- a/test/utilities/translator.js +++ b/test/utilities/translator.js @@ -16,6 +16,7 @@   * along with this program.  If not, see <https://www.gnu.org/licenses/>.   */ +// eslint-disable-next-line no-template-curly-in-string  const placeholder = '${title}';  /** diff --git a/types/ext/application.d.ts b/types/ext/application.d.ts index 903c8e45..930220f0 100644 --- a/types/ext/application.d.ts +++ b/types/ext/application.d.ts @@ -15,11 +15,10 @@   * along with this program.  If not, see <https://www.gnu.org/licenses/>.   */ -import type {TokenString} from './core'; +import type {TokenString, EventNames, EventArgument as BaseEventArgument} from './core';  import type {SearchMode} from './display';  import type {FrameEndpointReadyDetails, FrameEndpointConnectedDetails} from './frame-client';  import type {DatabaseUpdateType, DatabaseUpdateCause} from './backend'; -import type {EventNames, EventArgument as BaseEventArgument} from './core';  import type {      ApiMap as BaseApiMap,      ApiHandler as BaseApiHandler, |