2018-10-25 20:03:19 -04:00
/ * *
2020-02-25 10:12:28 -05:00
* Copyright ( c ) Facebook , Inc . and its affiliates .
2018-10-25 20:03:19 -04:00
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree .
* /
2018-09-16 23:34:42 -04:00
const OFF = 0 ;
const WARNING = 1 ;
const ERROR = 2 ;
2022-06-24 11:22:44 -04:00
const ClientRestrictedImportPatterns = [
// Prevent importing lodash in client bundle for bundle size
'lodash' ,
'lodash.**' ,
'lodash/**' ,
// Prevent importing server code in client bundle
'**/../babel/**' ,
'**/../server/**' ,
'**/../commands/**' ,
'**/../webpack/**' ,
] ;
2018-09-16 23:34:42 -04:00
module . exports = {
2020-06-18 05:37:48 -04:00
root : true ,
2018-09-16 23:34:42 -04:00
env : {
browser : true ,
commonjs : true ,
jest : true ,
node : true ,
} ,
2020-06-18 05:37:48 -04:00
parser : '@typescript-eslint/parser' ,
2018-10-28 04:32:19 -04:00
parserOptions : {
2022-05-30 02:49:51 -04:00
// tsconfigRootDir: __dirname,
// project: ['./tsconfig.json', './website/tsconfig.json'],
2018-10-28 04:32:19 -04:00
} ,
2020-03-21 00:42:10 -04:00
globals : {
2022-01-30 21:31:24 -05:00
JSX : true ,
2020-03-21 00:42:10 -04:00
} ,
2020-06-18 05:37:48 -04:00
extends : [
'eslint:recommended' ,
2021-10-20 10:09:52 -04:00
'plugin:react-hooks/recommended' ,
2022-01-16 02:53:23 -05:00
'plugin:jest/recommended' ,
2020-06-18 05:37:48 -04:00
'airbnb' ,
2022-01-30 21:31:24 -05:00
'plugin:@typescript-eslint/recommended' ,
2022-05-30 02:49:51 -04:00
// 'plugin:@typescript-eslint/recommended-requiring-type-checking',
// 'plugin:@typescript-eslint/strict',
2022-03-13 06:32:17 -04:00
'plugin:regexp/recommended' ,
2020-06-18 05:37:48 -04:00
'prettier' ,
2022-04-29 12:04:25 -04:00
'plugin:@docusaurus/all' ,
2020-06-18 05:37:48 -04:00
] ,
settings : {
'import/resolver' : {
node : {
extensions : [ '.js' , '.jsx' , '.ts' , '.tsx' ] ,
} ,
} ,
} ,
2022-01-07 23:59:28 -05:00
reportUnusedDisableDirectives : true ,
2022-04-29 12:04:25 -04:00
plugins : [
'react-hooks' ,
'header' ,
'jest' ,
'@typescript-eslint' ,
'regexp' ,
'@docusaurus' ,
] ,
2018-09-16 23:34:42 -04:00
rules : {
2022-01-30 21:31:24 -05:00
'array-callback-return' : WARNING ,
camelcase : WARNING ,
2019-03-09 16:00:44 -05:00
'class-methods-use-this' : OFF , // It's a way of allowing private variables.
2022-01-30 21:31:24 -05:00
curly : [ WARNING , 'all' ] ,
'global-require' : WARNING ,
'lines-between-class-members' : OFF ,
2022-03-20 20:42:36 -04:00
'max-classes-per-file' : OFF ,
2022-01-30 21:31:24 -05:00
'max-len' : [
WARNING ,
2021-11-06 07:04:45 -04:00
{
2022-01-30 21:31:24 -05:00
code : Infinity , // Code width is already enforced by Prettier
tabWidth : 2 ,
comments : 80 ,
ignoreUrls : true ,
ignorePattern : '(eslint-disable|@)' ,
2021-11-06 07:04:45 -04:00
} ,
2019-05-09 09:01:48 -04:00
] ,
2022-01-30 21:31:24 -05:00
'no-await-in-loop' : OFF ,
'no-case-declarations' : WARNING ,
'no-console' : OFF ,
2022-04-22 23:55:01 -04:00
'no-constant-binary-expression' : ERROR ,
2022-03-17 05:59:41 -04:00
'no-continue' : OFF ,
2022-01-30 21:31:24 -05:00
'no-control-regex' : WARNING ,
'no-else-return' : [ WARNING , { allowElseIf : true } ] ,
'no-empty' : [ WARNING , { allowEmptyCatch : true } ] ,
'no-lonely-if' : WARNING ,
'no-nested-ternary' : WARNING ,
'no-param-reassign' : [ WARNING , { props : false } ] ,
'no-prototype-builtins' : WARNING ,
2021-11-18 08:15:37 -05:00
'no-restricted-exports' : OFF ,
2022-02-19 05:15:02 -05:00
'no-restricted-properties' : [
2022-01-30 21:31:24 -05:00
ERROR ,
2022-05-24 07:19:24 -04:00
... /** @type {[string, string][]} */ ( [
2022-02-19 05:15:02 -05:00
// TODO: TS doesn't make Boolean a narrowing function yet,
// so filter(Boolean) is problematic type-wise
// ['compact', 'Array#filter(Boolean)'],
[ 'concat' , 'Array#concat' ] ,
[ 'drop' , 'Array#slice(n)' ] ,
[ 'dropRight' , 'Array#slice(0, -n)' ] ,
[ 'fill' , 'Array#fill' ] ,
[ 'filter' , 'Array#filter' ] ,
[ 'find' , 'Array#find' ] ,
[ 'findIndex' , 'Array#findIndex' ] ,
[ 'first' , 'foo[0]' ] ,
[ 'flatten' , 'Array#flat' ] ,
[ 'flattenDeep' , 'Array#flat(Infinity)' ] ,
[ 'flatMap' , 'Array#flatMap' ] ,
[ 'fromPairs' , 'Object.fromEntries' ] ,
[ 'head' , 'foo[0]' ] ,
[ 'indexOf' , 'Array#indexOf' ] ,
[ 'initial' , 'Array#slice(0, -1)' ] ,
[ 'join' , 'Array#join' ] ,
// Unfortunately there's no great alternative to _.last yet
// Candidates: foo.slice(-1)[0]; foo[foo.length - 1]
// Array#at is ES2022; could replace _.nth as well
// ['last'],
[ 'map' , 'Array#map' ] ,
[ 'reduce' , 'Array#reduce' ] ,
[ 'reverse' , 'Array#reverse' ] ,
[ 'slice' , 'Array#slice' ] ,
[ 'take' , 'Array#slice(0, n)' ] ,
[ 'takeRight' , 'Array#slice(-n)' ] ,
[ 'tail' , 'Array#slice(1)' ] ,
2022-05-24 07:19:24 -04:00
] ) . map ( ( [ property , alternative ] ) => ( {
2022-02-19 05:15:02 -05:00
object : '_' ,
property ,
message : ` Use ${ alternative } instead. ` ,
} ) ) ,
2022-02-19 21:21:33 -05:00
... [
'readdirSync' ,
'readFileSync' ,
'statSync' ,
'lstatSync' ,
'existsSync' ,
'pathExistsSync' ,
'realpathSync' ,
'mkdirSync' ,
'mkdirpSync' ,
'mkdirsSync' ,
'writeFileSync' ,
'writeJsonSync' ,
'outputFileSync' ,
'outputJsonSync' ,
'moveSync' ,
'copySync' ,
'copyFileSync' ,
'ensureFileSync' ,
'ensureDirSync' ,
'ensureLinkSync' ,
'ensureSymlinkSync' ,
'unlinkSync' ,
'removeSync' ,
'emptyDirSync' ,
] . map ( ( property ) => ( {
object : 'fs' ,
property ,
message : 'Do not use sync fs methods.' ,
} ) ) ,
2022-01-30 21:31:24 -05:00
] ,
2022-02-04 08:57:10 -05:00
'no-restricted-syntax' : [
WARNING ,
// Copied from airbnb, removed for...of statement, added export all
{
selector : 'ForInStatement' ,
message :
'for..in loops iterate over the entire prototype chain, which is virtually never what you want. Use Object.{keys,values,entries}, and iterate over the resulting array.' ,
} ,
{
selector : 'LabeledStatement' ,
message :
'Labels are a form of GOTO; using them makes code confusing and hard to maintain and understand.' ,
} ,
{
selector : 'WithStatement' ,
message :
'`with` is disallowed in strict mode because it makes code impossible to predict and optimize.' ,
} ,
{
selector : 'ExportAllDeclaration' ,
message :
"Export all does't work well if imported in ESM due to how they are transpiled, and they can also lead to unexpected exposure of internal methods." ,
} ,
2022-02-24 04:25:17 -05:00
// TODO make an internal plugin to ensure this
// {
// selector:
// @ 'ExportDefaultDeclaration > Identifier, ExportNamedDeclaration[source=null] > ExportSpecifier',
// message: 'Export in one statement'
2022-03-11 06:04:27 -05:00
// },
... [ 'path' , 'fs-extra' , 'webpack' , 'lodash' ] . map ( ( m ) => ( {
selector : ` ImportDeclaration[importKind=value]:has(Literal[value= ${ m } ]) > ImportSpecifier[importKind=value] ` ,
message :
'Default-import this, both for readability and interoperability with ESM' ,
} ) ) ,
2022-02-04 08:57:10 -05:00
] ,
'no-template-curly-in-string' : WARNING ,
2022-01-30 21:31:24 -05:00
'no-unused-expressions' : [ WARNING , { allowTaggedTemplates : true } ] ,
2022-02-04 08:57:10 -05:00
'no-useless-escape' : WARNING ,
2022-06-07 09:42:17 -04:00
'no-void' : [ ERROR , { allowAsStatement : true } ] ,
2022-01-30 21:31:24 -05:00
'prefer-destructuring' : WARNING ,
2022-02-01 04:43:15 -05:00
'prefer-named-capture-group' : WARNING ,
2022-01-30 21:31:24 -05:00
'prefer-template' : WARNING ,
yoda : WARNING ,
2019-03-24 03:50:26 -04:00
'header/header' : [
ERROR ,
'block' ,
[
'*' ,
2020-03-21 03:22:25 -04:00
' * Copyright (c) Facebook, Inc. and its affiliates.' ,
2019-03-24 03:50:26 -04:00
' *' ,
2020-03-21 03:22:25 -04:00
' * This source code is licensed under the MIT license found in the' ,
' * LICENSE file in the root directory of this source tree.' ,
2019-03-24 03:50:26 -04:00
' ' ,
] ,
] ,
2022-01-30 21:31:24 -05:00
'import/extensions' : OFF ,
2022-06-15 13:15:11 -04:00
// This rule doesn't yet support resolving .js imports when the actual file
// is .ts. Plus it's not all that useful when our code is fully TS-covered.
2022-01-30 21:31:24 -05:00
'import/no-unresolved' : [
2022-06-15 13:15:11 -04:00
OFF ,
2022-01-30 21:31:24 -05:00
{
2022-06-15 13:15:11 -04:00
// Ignore certain webpack aliases because they can't be resolved
2022-03-23 11:35:26 -04:00
ignore : [
'^@theme' ,
'^@docusaurus' ,
'^@generated' ,
'^@site' ,
'^@testing-utils' ,
] ,
2022-01-30 21:31:24 -05:00
} ,
] ,
2022-05-14 11:39:50 -04:00
'import/order' : [
WARNING ,
{
groups : [
'builtin' ,
'external' ,
'internal' ,
[ 'parent' , 'sibling' , 'index' ] ,
'type' ,
] ,
pathGroups : [
{ pattern : '@jest/globals' , group : 'builtin' , position : 'before' } ,
{ pattern : 'react' , group : 'builtin' , position : 'before' } ,
{ pattern : 'fs-extra' , group : 'builtin' } ,
{ pattern : 'lodash' , group : 'external' , position : 'before' } ,
{ pattern : 'clsx' , group : 'external' , position : 'before' } ,
// 'Bit weird to not use the `import/internal-regex` option, but this
// way, we can make `import type { Props } from "@theme/*"` appear
// before `import styles from "styles.module.css"`, which is what we
// always did. This should be removable once we stop using ambient
// module declarations for theme aliases.
{ pattern : '@theme/**' , group : 'internal' } ,
{ pattern : '@site/**' , group : 'internal' } ,
{ pattern : '@theme-init/**' , group : 'internal' } ,
{ pattern : '@theme-original/**' , group : 'internal' } ,
] ,
pathGroupsExcludedImportTypes : [ ] ,
} ,
] ,
2022-01-30 21:31:24 -05:00
'import/prefer-default-export' : OFF ,
2022-03-11 19:43:09 -05:00
'jest/consistent-test-it' : WARNING ,
2022-01-30 21:31:24 -05:00
'jest/expect-expect' : OFF ,
2022-03-11 19:43:09 -05:00
'jest/no-large-snapshots' : [
WARNING ,
{ maxSize : Infinity , inlineMaxSize : 10 } ,
] ,
2022-03-12 00:17:21 -05:00
'jest/no-test-return-statement' : ERROR ,
2022-03-11 19:43:09 -05:00
'jest/prefer-expect-resolves' : WARNING ,
'jest/prefer-lowercase-title' : [ WARNING , { ignore : [ 'describe' ] } ] ,
2022-03-12 00:17:21 -05:00
'jest/prefer-spy-on' : WARNING ,
'jest/prefer-to-be' : WARNING ,
'jest/prefer-to-have-length' : WARNING ,
2022-03-11 19:43:09 -05:00
'jest/require-top-level-describe' : ERROR ,
'jest/valid-title' : [
ERROR ,
{
mustNotMatch : {
it : [
'^should|\\.$' ,
'Titles should not begin with "should" or end with a full-stop' ,
] ,
} ,
} ,
] ,
2022-01-30 21:31:24 -05:00
2019-05-09 09:01:48 -04:00
'jsx-a11y/click-events-have-key-events' : WARNING ,
'jsx-a11y/no-noninteractive-element-interactions' : WARNING ,
2021-08-31 09:40:37 -04:00
'jsx-a11y/html-has-lang' : OFF ,
2022-01-30 21:31:24 -05:00
'react-hooks/rules-of-hooks' : ERROR ,
'react-hooks/exhaustive-deps' : ERROR ,
// Sometimes we do need the props as a whole, e.g. when spreading
'react/destructuring-assignment' : OFF ,
2021-11-18 08:15:37 -05:00
'react/function-component-definition' : [
WARNING ,
{
namedComponents : 'function-declaration' ,
unnamedComponents : 'arrow-function' ,
} ,
] ,
2022-01-30 21:31:24 -05:00
'react/jsx-filename-extension' : OFF ,
2022-02-02 06:22:26 -05:00
'react/jsx-key' : [ ERROR , { checkFragmentShorthand : true } ] ,
2022-03-02 10:28:17 -05:00
'react/jsx-no-useless-fragment' : [ ERROR , { allowExpressions : true } ] ,
2022-01-30 21:31:24 -05:00
'react/jsx-props-no-spreading' : OFF ,
'react/no-array-index-key' : OFF , // We build a static site, and nearly all components don't change.
2021-11-18 08:15:37 -05:00
'react/no-unstable-nested-components' : [ WARNING , { allowAsProps : true } ] ,
2022-01-30 21:31:24 -05:00
'react/prefer-stateless-function' : WARNING ,
'react/prop-types' : OFF ,
'react/require-default-props' : [ ERROR , { ignoreFunctionalComponents : true } ] ,
2022-05-30 02:49:51 -04:00
'@typescript-eslint/consistent-type-definitions' : OFF ,
'@typescript-eslint/require-await' : OFF ,
2022-01-30 21:31:24 -05:00
'@typescript-eslint/ban-ts-comment' : [
ERROR ,
{ 'ts-expect-error' : 'allow-with-description' } ,
] ,
2022-03-25 06:06:30 -04:00
'@typescript-eslint/consistent-indexed-object-style' : [
WARNING ,
'index-signature' ,
] ,
2021-12-31 08:17:09 -05:00
'@typescript-eslint/consistent-type-imports' : [
WARNING ,
{ disallowTypeAnnotations : false } ,
] ,
2022-01-30 21:31:24 -05:00
'@typescript-eslint/explicit-module-boundary-types' : WARNING ,
'@typescript-eslint/method-signature-style' : ERROR ,
'@typescript-eslint/no-empty-function' : OFF ,
'@typescript-eslint/no-empty-interface' : [
ERROR ,
{
allowSingleExtends : true ,
} ,
] ,
'@typescript-eslint/no-inferrable-types' : OFF ,
2022-03-17 05:59:41 -04:00
'@typescript-eslint/no-namespace' : [ WARNING , { allowDeclarations : true } ] ,
2020-11-18 11:52:50 -05:00
'no-use-before-define' : OFF ,
'@typescript-eslint/no-use-before-define' : [
2020-06-18 05:37:48 -04:00
ERROR ,
{ functions : false , classes : false , variables : true } ,
] ,
2021-11-18 08:15:37 -05:00
'@typescript-eslint/no-non-null-assertion' : OFF ,
2020-11-18 11:52:50 -05:00
'no-redeclare' : OFF ,
'@typescript-eslint/no-redeclare' : ERROR ,
2022-01-30 21:31:24 -05:00
'no-shadow' : OFF ,
'@typescript-eslint/no-shadow' : ERROR ,
'no-unused-vars' : OFF ,
2022-03-17 05:59:41 -04:00
// We don't provide any escape hatches for this rule. Rest siblings and
// function placeholder params are always ignored, and any other unused
// locals must be justified with a disable comment.
'@typescript-eslint/no-unused-vars' : [ ERROR , { ignoreRestSiblings : true } ] ,
'@typescript-eslint/prefer-optional-chain' : ERROR ,
2022-04-29 12:04:25 -04:00
'@docusaurus/no-untranslated-text' : [
WARNING ,
{
2022-04-30 05:57:57 -04:00
ignoredStrings : [
2022-04-29 12:04:25 -04:00
'·' ,
'-' ,
'—' ,
'× ' ,
' ' , // zwj: ​
'@' ,
'WebContainers' ,
'Twitter' ,
'GitHub' ,
'Dev.to' ,
'1.x' ,
] ,
} ,
] ,
2018-09-16 23:34:42 -04:00
} ,
2019-12-15 04:16:27 -05:00
overrides : [
{
2022-06-24 11:22:44 -04:00
files : [ 'packages/docusaurus/src/client/**/*.{js,ts,tsx}' ] ,
rules : {
'no-restricted-imports' : [
'error' ,
{
patterns : ClientRestrictedImportPatterns ,
} ,
] ,
} ,
} ,
{
files : [ 'packages/docusaurus-*/src/theme/**/*.{js,ts,tsx}' ] ,
excludedFiles : '*.test.{js,ts,tsx}' ,
2022-01-07 08:44:55 -05:00
rules : {
2022-05-30 02:49:51 -04:00
'no-restricted-imports' : [
'error' ,
{
2022-06-24 11:22:44 -04:00
patterns : ClientRestrictedImportPatterns . concat (
// Prevents relative imports between React theme components
[
'../**' ,
'./**' ,
// Allows relative styles module import with consistent filename
'!./styles.module.css' ,
] ,
) ,
2022-05-30 02:49:51 -04:00
} ,
] ,
2022-01-07 08:44:55 -05:00
} ,
} ,
{
files : [
2022-05-30 02:49:51 -04:00
'packages/docusaurus-*/src/theme/**/*.{js,ts,tsx}' ,
'packages/docusaurus/src/client/theme-fallback/**/*.{js,ts,tsx}' ,
2020-04-09 00:58:01 -04:00
] ,
2019-12-15 04:16:27 -05:00
rules : {
2022-05-30 02:49:51 -04:00
'import/no-named-export' : ERROR ,
} ,
} ,
{
files : [ 'packages/create-docusaurus/templates/**/*.{js,ts,tsx}' ] ,
rules : {
2020-06-18 05:37:48 -04:00
'header/header' : OFF ,
2021-06-24 12:12:48 -04:00
'global-require' : OFF ,
2021-08-06 13:11:36 -04:00
'@typescript-eslint/no-var-requires' : OFF ,
2022-04-29 12:04:25 -04:00
'@docusaurus/no-untranslated-text' : OFF ,
2019-12-15 04:16:27 -05:00
} ,
} ,
2020-06-20 00:30:18 -04:00
{
2021-03-19 06:32:38 -04:00
files : [ '*.d.ts' ] ,
rules : {
'import/no-duplicates' : OFF ,
} ,
} ,
{
2022-05-30 02:49:51 -04:00
files : [ '*.{ts,tsx}' ] ,
2021-11-18 08:15:37 -05:00
rules : {
2022-01-30 21:31:24 -05:00
'no-undef' : OFF ,
2021-11-18 08:15:37 -05:00
'import/no-import-module-exports' : OFF ,
} ,
} ,
{
2022-05-30 02:49:51 -04:00
files : [ '*.{js,mjs,cjs}' ] ,
2020-06-20 00:30:18 -04:00
rules : {
// Make JS code directly runnable in Node.
'@typescript-eslint/no-var-requires' : OFF ,
'@typescript-eslint/explicit-module-boundary-types' : OFF ,
} ,
} ,
2022-03-11 06:04:27 -05:00
{
2022-04-29 12:04:25 -04:00
files : [
'**/__tests__/**' ,
'packages/docusaurus-plugin-debug/**' ,
'website/_dogfooding/**' ,
] ,
rules : {
'@docusaurus/no-untranslated-text' : OFF ,
} ,
} ,
{
2022-03-17 05:59:41 -04:00
// Internal files where extraneous deps don't matter much at long as
// they run
files : [
2022-05-30 02:49:51 -04:00
'*.test.{js,ts,tsx}' ,
2022-03-17 05:59:41 -04:00
'admin/**' ,
'jest/**' ,
'website/**' ,
2022-06-24 05:21:27 -04:00
'packages/docusaurus-theme-common/removeThemeInternalReexport.mjs' ,
2022-03-17 05:59:41 -04:00
'packages/docusaurus-theme-translations/update.mjs' ,
'packages/docusaurus-theme-translations/src/utils.ts' ,
] ,
2022-03-11 06:04:27 -05:00
rules : {
'import/no-extraneous-dependencies' : OFF ,
} ,
} ,
2022-05-30 02:49:51 -04:00
{
files : [ 'packages/eslint-plugin/**/*.{js,ts}' ] ,
extends : [ 'plugin:eslint-plugin/recommended' ] ,
} ,
2019-12-15 04:16:27 -05:00
] ,
2018-09-16 23:34:42 -04:00
} ;