{ "root": true, "parserOptions": { "ecmaVersion": 11, "sourceType": "script", "ecmaFeatures": { "globalReturn": true } }, "ignorePatterns": [ "logs/", "node_modules/", ".*-dist/", "tools/set-import/importer.js", "tools/set-import/sets", "tools/modlog/converter.js", "server/global-variables.d.ts" ], "env": { "es6": true, "node": true }, "extends": "eslint:recommended", "rules": { // TODO: add/revisit // "spaced-comment": ["error", "always", {"exceptions": ["*"]}], // "no-use-before-define": "off", // test only (should never be committed, but useful when testing) "no-debugger": "warn", "no-unused-vars": ["warn", {"args": "none"}], "no-warning-comments": "off", "prefer-const": ["warn", {"destructuring": "all"}], // PS code (code specific to PS) "consistent-return": "off", // sim event handlers mix them for ergonomics "func-style": "off", // used to type event handlers "no-console": "off", "no-control-regex": "off", // used to find invalid data in chat messages "no-invalid-this": "off", // `this` is used to pass context to sim event handlers, chat commands, etc "no-loop-func": "off", // synchronous "no-restricted-modules": ["error", "moment", "request", "sugar"], "no-sync": "off", "no-void": "off", // used for spawning Promises only "strict": ["error", "global"], // bad code, modern (new code patterns we don't like because they're less readable or performant) "no-restricted-globals": ["error", "Proxy", "Reflect", "Symbol", "WeakSet"], // bad code, deprecated (deprecated/bad patterns that should be written a different way) "eqeqeq": "error", "func-names": "off", // has minor advantages but way too verbose, hurting readability "guard-for-in": "off", // guarding is a deprecated pattern, we just use no-extend-native instead "init-declarations": "off", // TypeScript lets us delay initialization safely "no-caller": "error", "no-eval": "error", "no-extend-native": "error", "no-implied-eval": "error", "no-inner-declarations": ["error", "functions"], "no-iterator": "error", "no-labels": ["error", {"allowLoop": true, "allowSwitch": true}], "no-multi-str": "error", "no-new-func": "error", "no-new-wrappers": "error", "no-path-concat": "off", // Windows supports `/` as a path separator; concat is more readable "no-proto": "error", "no-restricted-syntax": ["error", "WithStatement"], "no-sparse-arrays": "error", "no-var": "error", "no-with": "error", // probably bugs (code with no reason to exist, probably typoes) "array-callback-return": "error", "block-scoped-var": "error", // not actually used; precluded by no-var "callback-return": [2, ["callback", "cb", "done"]], "consistent-this": "off", // we use arrow functions instead "constructor-super": "error", "default-case": "off", // hopefully TypeScript will let us skip `default` for things that are exhaustive "no-bitwise": "off", // used in Dashycode "no-case-declarations": "off", // meh, we have no-shadow "no-duplicate-case": "error", "no-empty": ["error", {"allowEmptyCatch": true}], "no-extra-bind": "error", "no-extra-label": "error", "no-fallthrough": "error", "no-label-var": "error", "no-new-require": "error", "no-new": "error", "no-redeclare": "error", "no-return-await": "error", "no-self-compare": "error", "no-sequences": "error", "no-shadow-restricted-names": "error", "no-shadow": "off", "no-template-curly-in-string": "error", "no-throw-literal": "error", "no-undef": "off", "no-unmodified-loop-condition": "error", "no-unused-expressions": "error", "no-unsafe-finally": "error", "no-unused-labels": "error", "use-isnan": "error", "valid-typeof": "error", // style choices "no-constant-condition": ["error", {"checkLoops": false}], "no-lonely-if": "off", "radix": ["error", "as-needed"], // naming style "camelcase": "off", // mostly only so we can import `child_process` "id-length": "off", "id-match": "off", "new-cap": ["error", {"newIsCap": true, "capIsNew": false}], "no-underscore-dangle": "off", // syntax style (local syntactical, usually autofixable formatting decisions) "arrow-parens": "off", "arrow-body-style": "error", "brace-style": ["error", "1tbs", {"allowSingleLine": true}], "comma-dangle": ["error", {"arrays": "always-multiline", "objects": "always-multiline", "imports": "always-multiline", "exports": "always-multiline", "functions": "ignore"}], "comma-style": ["error", "last"], "curly": ["error", "multi-line", "consistent"], "dot-notation": "off", "new-parens": "error", "no-array-constructor": "error", "no-div-regex": "error", "no-duplicate-imports": "error", "no-extra-parens": "off", "no-floating-decimal": "error", "no-mixed-requires": "error", "no-multi-spaces": "error", "no-new-object": "error", "no-octal-escape": "error", "no-return-assign": ["error", "except-parens"], "no-undef-init": "off", "no-unneeded-ternary": "error", "no-useless-call": "error", "no-useless-computed-key": "error", "no-useless-concat": "off", "no-useless-rename": "error", "object-shorthand": ["error", "methods"], "one-var": "off", "operator-assignment": "off", "prefer-arrow-callback": "off", "quote-props": "off", "quotes": "off", "semi": ["error", "always"], "sort-vars": "off", "vars-on-top": "off", "wrap-iife": ["error", "inside"], "wrap-regex": "off", "yoda": ["error", "never", { "exceptRange": true }], // whitespace "array-bracket-spacing": ["error", "never"], "arrow-spacing": ["error", {"before": true, "after": true}], "block-spacing": ["error", "always"], "comma-spacing": ["error", {"before": false, "after": true}], "computed-property-spacing": ["error", "never"], "dot-location": ["error", "property"], "eol-last": ["error", "always"], "func-call-spacing": "error", "function-paren-newline": ["error", "consistent"], "indent": ["error", "tab", {"flatTernaryExpressions": true}], "key-spacing": "error", "keyword-spacing": ["error", {"before": true, "after": true}], "lines-around-comment": "off", "no-mixed-spaces-and-tabs": ["error", "smart-tabs"], "no-multiple-empty-lines": ["error", {"max": 2, "maxEOF": 1}], "no-trailing-spaces": ["error", {"ignoreComments": false}], "object-curly-spacing": ["error", "never"], "operator-linebreak": ["error", "after"], "padded-blocks": ["error", "never"], "padding-line-between-statements": "off", "rest-spread-spacing": ["error", "never"], "semi-spacing": ["error", {"before": false, "after": true}], "space-before-blocks": ["error", "always"], "space-before-function-paren": ["error", {"anonymous": "always", "named": "never"}], "space-in-parens": ["error", "never"], "space-infix-ops": "error", "space-unary-ops": ["error", {"words": true, "nonwords": false}], "template-curly-spacing": ["error", "never"] }, "overrides": [ { "files": [ "./config/*.ts", "./data/**/*.ts", "./lib/*.ts", "./server/**/*.ts", "./server/**/*.tsx", "./sim/**/*.ts", "./tools/set-import/*.ts", "./tools/modlog/*.ts", "./translations/**/*.ts" ], "parser": "@typescript-eslint/parser", "parserOptions": { "ecmaVersion": 11, "sourceType": "module", "tsconfigRootDir": ".", "project": ["./tsconfig.json"] }, "extends": [ "plugin:@typescript-eslint/recommended" ], "rules": { // TODO revisit "@typescript-eslint/explicit-function-return-type": "off", "@typescript-eslint/explicit-module-boundary-types": "off", "@typescript-eslint/member-ordering": "off", // "@typescript-eslint/no-extraneous-class": "error", // "@typescript-eslint/no-type-alias": "error", "@typescript-eslint/prefer-optional-chain": "off", // "@typescript-eslint/consistent-type-imports": "error", // TODO after no-duplicate-imports fix // test only (should never be committed, but useful when testing) "no-unused-vars": "off", "@typescript-eslint/no-unused-vars": ["warn", {"args": "none"}], "max-len": ["warn", { "code": 120, "tabWidth": 0, // see bottom of file for source "ignorePattern": "^\\s*(?:\\/\\/ \\s*)?(?:(?:export )?(?:let |const |readonly )?[a-zA-Z0-9_$.]+(?: \\+?=>? )|[a-zA-Z0-9$]+: \\[?|(?:return |throw )?(?:new )?(?:[a-zA-Z0-9$.]+\\()?)?(?:Utils\\.html|(?:this\\.)?(?:room\\.)?tr|\\$\\()?['\"`/]" }], "prefer-const": ["warn", {"destructuring": "all"}], // typescript-eslint/recommended forces this so we need to re-override // PS code (code specific to PS) "@typescript-eslint/no-namespace": "off", "@typescript-eslint/unbound-method": "off", // used for sim event handlers, command handlers, etc "new-parens": "off", // used for the `new class {...}` pattern "no-prototype-builtins": "off", "no-shadow": "off", "@typescript-eslint/no-shadow": "error", "@typescript-eslint/no-var-requires": "off", // typescript-eslint defaults too strict "@typescript-eslint/ban-ts-comment": "off", "@typescript-eslint/no-empty-function": "off", "@typescript-eslint/no-explicit-any": "off", "@typescript-eslint/no-non-null-assertion": "off", "@typescript-eslint/no-use-before-define": "off", "@typescript-eslint/no-unsafe-argument": "off", // probably bugs "@typescript-eslint/ban-types": ["error", { "extendDefaults": true, "types": { "object": false } }], "@typescript-eslint/no-dupe-class-members": "error", "@typescript-eslint/no-empty-interface": "error", "@typescript-eslint/no-extra-non-null-assertion": "error", "@typescript-eslint/no-misused-new": "error", "@typescript-eslint/no-non-null-asserted-optional-chain": "error", "no-dupe-class-members": "off", "no-unused-expressions": "off", // ternary is used to convert callbacks to Promises "@typescript-eslint/no-unused-expressions": ["error", {"allowTernary": true}], // ternary is used to convert callbacks to Promises // naming style "@typescript-eslint/naming-convention": ["error", { "selector": ["class", "interface", "typeAlias"], "format": ["PascalCase"] }], // syntax style (local syntactical, usually autofixable formatting decisions) "@typescript-eslint/adjacent-overload-signatures": "error", "@typescript-eslint/array-type": "error", "@typescript-eslint/consistent-type-assertions": ["error", {"assertionStyle": "as"}], "@typescript-eslint/consistent-type-definitions": ["error", "interface"], "@typescript-eslint/explicit-member-accessibility": ["error", {"accessibility": "no-public"}], "@typescript-eslint/member-delimiter-style": ["error", {"overrides": {"typeLiteral": { "multiline": {"delimiter": "comma", "requireLast": true}, "singleline": {"delimiter": "comma", "requireLast": false} }}}], "@typescript-eslint/no-parameter-properties": "error", // `source` and `target` are frequently used as variables that may point to `this` // or to another `Pokemon` object, depending on how the given method is invoked "@typescript-eslint/no-this-alias": ["error", {"allowedNames": ["source", "target"]}], "@typescript-eslint/prefer-as-const": "error", "@typescript-eslint/prefer-for-of": "error", "@typescript-eslint/prefer-function-type": "error", "@typescript-eslint/prefer-includes": "error", "@typescript-eslint/prefer-namespace-keyword": "error", "prefer-object-spread": "error", "@typescript-eslint/triple-slash-reference": "error", "@typescript-eslint/unified-signatures": "error", // syntax style, overriding base "quotes": "off", "@typescript-eslint/quotes": "off", "semi": "off", "@typescript-eslint/semi": ["error", "always"], "func-call-spacing": "off", "@typescript-eslint/func-call-spacing": "error", // whitespace "@typescript-eslint/type-annotation-spacing": "error", "spaced-comment": ["error", "always", {"exceptions": ["*", "/"]}], // whitespace, overriding base "indent": "off", "@typescript-eslint/indent": ["error", "tab", {"flatTernaryExpressions": true}] } }, { "files": ["./translations/**/*.ts"], "rules": { "no-template-curly-in-string": "off" } }, { "env": { "mocha": true }, "files": ["test/**/*.js"] }, { "files": ["build"], "rules": { "no-var": "off" } }, { "files": ["server/chat-plugins/private/*"], "parserOptions": { "ecmaVersion": 2021 } } ] } /* REGEXFREE SOURCE FOR IGNOREPATTERN: https://zarel.github.io/regexfree/ # indentation ^\s* # possibly commented out (\/\/\ \s*)? ( # define a variable, append to a variable, or define a single-arg arrow function (export\ )? (let\ |const\ |readonly\ )? [a-zA-Z0-9_$.]+ (\ \+?=>?\ ) | # define a property (oversize arrays are only allowed in properties) [a-zA-Z0-9$]+:\ \[? | # optionally return or throw (return\ |throw\ )? # call a function or constructor (new\ )?([a-zA-Z0-9$.]+\()? )? ( Utils\.html | (this\.)?(room\.)?tr | \$\( )? # start of string or regex ['"`\/] */