Files
brave-core/eslint.config.mjs
Claudio DeSouza 177820fff6 [cr148] ESLint checks for CrLitElement source name
Turn off `eslint-comments/no-unlimited-disable` for chromium_src overrides, so
that we can use `// eslint-disable-next-line` in our TypeScript overrides when
necessary. There was no simpler way to avoid the original lint check, as it
would require splitting our override into multiple source files and including
those in the build.

Chromium changes:
https://chromium.googlesource.com/chromium/src/+/d9c984b9e016d609c4cafbe55787123ded99ae14

commit d9c984b9e016d609c4cafbe55787123ded99ae14
Author: dpapad <dpapad@chromium.org>
Date:   Fri Mar 13 18:20:00 2026 -0700

    WebUI: Add ESLint check to disallow use of chrome.send in Desktop.

    This is added as part of build_webui() ESLint checks and is enforcing
    the updated guidance at [1]. Exceptions are added for all existing users
    of chrome.send().

    [1] https://chromium.googlesource.com/chromium/src/+/main/docs/webui/webui_explainer.md#Pre_Mojo-alternative_chrome_send_WebUIMessageHandler

    Bug: 40245923
    Change-Id: I175ce9be0f7c4ad3f280c93ee41ff54f399a18e9
    Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7662733
    Auto-Submit: Demetrios Papadopoulos <dpapad@chromium.org>
    Reviewed-by: Rebekah Potter <rbpotter@chromium.org>
    Commit-Queue: Demetrios Papadopoulos <dpapad@chromium.org>
    Cr-Commit-Position: refs/heads/main@{#1599429}
2026-04-27 12:00:47 +01:00

335 lines
13 KiB
JavaScript

// Copyright (c) 2026 The Brave Authors. All rights reserved.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at https://mozilla.org/MPL/2.0/.
import { defineConfig, globalIgnores } from 'eslint/config'
import jest from 'eslint-plugin-jest'
import importPlugin from 'eslint-plugin-import'
import licenses from 'eslint-plugin-licenses'
import noUnsanitized from 'eslint-plugin-no-unsanitized'
import reactHooks from 'eslint-plugin-react-hooks'
import love from 'eslint-config-love'
import prettier from 'eslint-config-prettier/flat'
import tslint from 'typescript-eslint'
import eslintJs from '@eslint/js'
import globals from 'globals'
// Config layout: each plugin or override is a separate array entry.
// Guidelines:
// - One section per plugin; do not combine rules from different plugins
// in one section.
// - Each section should have a comment stating its purpose and which files
// it targets.
// Verify changes with: npm run eslint (about 1 min).
export default defineConfig([
// Setup project-wide language options.
{
languageOptions: {
globals: {
...globals.browser,
...globals.jest,
...globals.node,
chrome: 'readonly',
},
},
},
// Turn off rules that conflict with Prettier formatting (all files).
prettier,
// ESLint core recommended rules for JavaScript (.js files + related).
eslintJs.configs.recommended,
// Prevents unsafe DOM injection, e.g. innerHTML (all files).
noUnsanitized.configs.recommended,
// React Hooks rules and related React best practices (.tsx and .jsx files).
reactHooks.configs.flat.recommended,
// Jest test lint rules. (.ts and .js test files).
jest.configs['flat/recommended'],
// TypeScript syntax and basic correctness; does not use type information (.ts, .tsx, .mts files).
tslint.configs.recommended,
// Stricter TypeScript rules using the type checker
{
...love,
files: ['**/*.{ts,tsx,mts}'],
languageOptions: {
...love.languageOptions,
parserOptions: {
project: './tsconfig-lint.json',
},
},
},
// Enforce license header in file (all files). Overlaps with PRESUBMIT.
{
plugins: {
licenses,
},
rules: {
'licenses/header': [
2,
{
tryUseCreatedYear: true,
comment: {
allow: 'both',
prefer: 'line',
},
header: [
'Copyright (c) {YEAR} The Brave Authors. All rights reserved.',
'This Source Code Form is subject to the terms of the Mozilla Public',
'License, v. 2.0. If a copy of the MPL was not distributed with this file,',
'You can obtain one at https://mozilla.org/MPL/2.0/.',
],
altHeaders: [
[
'Copyright (c) {YEAR} The Brave Authors. All rights reserved.',
'* This Source Code Form is subject to the terms of the Mozilla Public',
'* License, v. 2.0. If a copy of the MPL was not distributed with this file,',
'* You can obtain one at https://mozilla.org/MPL/2.0/.',
],
[
'This Source Code Form is subject to the terms of the Mozilla Public',
'* License, v. 2.0. If a copy of the MPL was not distributed with this file,',
'* You can obtain one at https://mozilla.org/MPL/2.0/.',
],
[
'Copyright (c) {YEAR} The Brave Authors. All rights reserved.',
'This Source Code Form is subject to the terms of the Mozilla Public',
'License, v. 2.0. If a copy of the MPL was not distributed with this file,',
'you can obtain one at https://mozilla.org/MPL/2.0/.',
],
],
},
],
},
},
globalIgnores([
'.storybook/*',
'browser/*',
'ui/webui/resources/*',
'**/*.d.ts',
'tools/chromium_src/lit_mangler/*.ts',
// External or vendored code; not maintained in this repo
'vendor/',
'third_party/',
'tools/crates/vendor/',
// Not purely JavaScript, contains `<template>` expressions.
'ios/brave-ios/Sources/Brave/Frontend/UserContent/UserScripts/',
'ios/brave-ios/Sources/Brave/Assets/**/*.js',
// Generated by scripts, skip linting
'ios/brave-ios/Sources/AIChat/Components/Markdown/CodeHighlight/Scripts/highlight.min.js',
'components/brave_wallet/resources/solana_web3_script.js',
'test/data/ephemeral-storage/static/js/libs/js.cookie.min.js',
]),
{
// Project-wide disabled rules (all files).
rules: {
'array-callback-return': 'off',
'arrow-body-style': 'off',
'complexity': 'off',
'curly': 'off',
'eqeqeq': 'off',
'guard-for-in': 'off',
'logical-assignment-operators': 'off',
'max-lines': 'off',
'max-nested-callbacks': 'off',
'new-cap': 'off',
'no-alert': 'off',
'no-async-promise-executor': 'off',
'no-await-in-loop': 'off',
'no-case-declarations': 'off',
'no-console': 'off',
'no-fallthrough': 'off',
'no-implicit-globals': 'off',
'no-lonely-if': 'off',
'no-multi-assign': 'off',
'no-named-default': 'off',
'no-negated-condition': 'off',
'no-new-func': 'off',
'no-new-wrappers': 'off',
'no-param-reassign': 'off',
'no-plusplus': 'off',
'no-promise-executor-return': 'off',
'no-prototype-builtins': 'off',
'no-return-assign': 'off',
'no-template-curly-in-string': 'off',
'no-useless-assignment': 'off',
'no-useless-concat': 'off',
'no-useless-escape': 'off',
'operator-assignment': 'off',
'prefer-arrow-callback': 'off',
'prefer-const': 'off',
'prefer-exponentiation-operator': 'off',
'prefer-named-capture-group': 'off',
'prefer-object-spread': 'off',
'prefer-regex-literals': 'off',
'prefer-spread': 'off',
'prefer-template': 'off',
'preserve-caught-error': 'off',
'promise/avoid-new': 'off',
'radix': 'off',
'require-atomic-updates': 'off',
'require-unicode-regexp': 'off',
'strict': 'off',
'@typescript-eslint/array-type': 'off',
'@typescript-eslint/await-thenable': 'off',
'@typescript-eslint/ban-ts-comment': 'off',
'@typescript-eslint/class-literal-property-style': 'off',
'@typescript-eslint/class-methods-use-this': 'off',
'@typescript-eslint/consistent-generic-constructors': 'off',
'@typescript-eslint/consistent-indexed-object-style': 'off',
'@typescript-eslint/consistent-type-assertions': 'off',
'@typescript-eslint/consistent-type-definitions': 'off',
'@typescript-eslint/consistent-type-exports': 'off',
'@typescript-eslint/consistent-type-imports': 'off',
'@typescript-eslint/dot-notation': 'off',
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/init-declarations': 'off',
'@typescript-eslint/max-params': 'off',
'@typescript-eslint/method-signature-style': 'off',
'@typescript-eslint/no-base-to-string': 'off',
'@typescript-eslint/no-confusing-void-expression': 'off',
'@typescript-eslint/no-deprecated': 'off',
'@typescript-eslint/no-duplicate-type-constituents': 'off',
'@typescript-eslint/no-dynamic-delete': 'off',
'@typescript-eslint/no-empty-function': 'off',
'@typescript-eslint/no-empty-object-type': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-floating-promises': 'off',
'@typescript-eslint/no-implied-eval': 'off',
'@typescript-eslint/no-import-type-side-effects': 'off',
'@typescript-eslint/no-inferrable-types': 'off',
'@typescript-eslint/no-invalid-void-type': 'off',
'@typescript-eslint/no-magic-numbers': 'off',
'@typescript-eslint/no-misused-promises': 'off',
'@typescript-eslint/no-misused-spread': 'off',
'@typescript-eslint/no-namespace': 'off',
'@typescript-eslint/no-non-null-assertion': 'off',
'@typescript-eslint/no-redundant-type-constituents': 'off',
'@typescript-eslint/no-unnecessary-boolean-literal-compare': 'off',
'@typescript-eslint/no-unnecessary-condition': 'off',
'@typescript-eslint/no-unnecessary-template-expression': 'off',
'@typescript-eslint/no-unnecessary-type-arguments': 'off',
'@typescript-eslint/no-unnecessary-type-assertion': 'off',
'@typescript-eslint/no-unnecessary-type-conversion': 'off',
'@typescript-eslint/no-unnecessary-type-parameters': 'off',
'@typescript-eslint/no-unsafe-argument': 'off',
'@typescript-eslint/no-unsafe-assignment': 'off',
'@typescript-eslint/no-unsafe-call': 'off',
'@typescript-eslint/no-unsafe-declaration-merging': 'off',
'@typescript-eslint/no-unsafe-enum-comparison': 'off',
'@typescript-eslint/no-unsafe-function-type': 'off',
'@typescript-eslint/no-unsafe-member-access': 'off',
'@typescript-eslint/no-unsafe-return': 'off',
'@typescript-eslint/no-unsafe-type-assertion': 'off',
'@typescript-eslint/no-unused-expressions': 'off',
'@typescript-eslint/no-unused-vars': 'off',
'@typescript-eslint/no-useless-constructor': 'off',
'@typescript-eslint/no-useless-default-assignment': 'off',
'@typescript-eslint/no-wrapper-object-types': 'off',
'@typescript-eslint/non-nullable-type-assertion-style': 'off',
'@typescript-eslint/prefer-destructuring': 'off',
'@typescript-eslint/prefer-find': 'off',
'@typescript-eslint/prefer-for-of': 'off',
'@typescript-eslint/prefer-literal-enum-member': 'off',
'@typescript-eslint/prefer-nullish-coalescing': 'off',
'@typescript-eslint/prefer-optional-chain': 'off',
'@typescript-eslint/prefer-promise-reject-errors': 'off',
'@typescript-eslint/prefer-readonly': 'off',
'@typescript-eslint/prefer-regexp-exec': 'off',
'@typescript-eslint/prefer-string-starts-ends-with': 'off',
'@typescript-eslint/promise-function-async': 'off',
'@typescript-eslint/require-array-sort-compare': 'off',
'@typescript-eslint/require-await': 'off',
'@typescript-eslint/restrict-plus-operands': 'off',
'@typescript-eslint/restrict-template-expressions': 'off',
'@typescript-eslint/return-await': 'off',
'@typescript-eslint/strict-boolean-expressions': 'off',
'@typescript-eslint/strict-void-return': 'off',
'@typescript-eslint/switch-exhaustiveness-check': 'off',
'@typescript-eslint/unbound-method': 'off',
'@typescript-eslint/use-unknown-in-catch-callback-variable': 'off',
'@eslint-community/eslint-comments/disable-enable-pair': 'off',
'@eslint-community/eslint-comments/no-duplicate-disable': 'off',
'@eslint-community/eslint-comments/require-description': 'off',
'import/enforce-node-protocol-usage': 'off',
'import/no-absolute-path': 'off',
'react-hooks/immutability': 'off',
'react-hooks/preserve-manual-memoization': 'off',
'react-hooks/purity': 'off',
'react-hooks/refs': 'off',
'react-hooks/rules-of-hooks': 'off',
'react-hooks/set-state-in-effect': 'off',
'react-hooks/static-components': 'off',
'react-hooks/use-memo': 'off',
},
},
{
// Brave JavaScript files uses require() to load modules.
files: ['**/*.{js,jsx,mjs,cjs}'],
rules: {
'@typescript-eslint/no-require-imports': 'off',
},
},
{
files: ['build/commands/**/*.{js,cjs,mjs,ts,cts,mts}'],
plugins: {
import: importPlugin,
},
rules: {
...importPlugin.flatConfigs.recommended.rules,
'import/enforce-node-protocol-usage': ['error', 'always'],
// Enforce import resolution for build/commands scripts. When running
// TypeScript natively via Node.js (no transpilation), imports must use
// the real file extension. For example, if a file is named config.ts,
// importing it as './config.js' is an error.
'import/no-unresolved': 'error',
},
},
{
// Test data files; skips some non-important rules.
files: ['test/data/**/*.js'],
rules: {
'licenses/header': 'off',
'no-undef': 'off',
},
},
{
// Specific rules for NodeJS targets (except build/commands)
files: ['**/*.test.{js,ts}', '**/*.{cts,cjs}'],
ignores: ['build/commands/**/*'],
plugins: {
import: importPlugin,
},
rules: {
...importPlugin.flatConfigs.recommended.rules,
'import/no-unresolved': 'off',
'import/enforce-node-protocol-usage': ['error', 'always'],
},
},
{
files: ['chromium_src/**/*.ts'],
rules: {
'@eslint-community/eslint-comments/no-unlimited-disable': 'off',
},
},
])