mirror of
https://github.com/actualbudget/actual.git
synced 2026-03-09 06:03:01 -05:00
413 lines
12 KiB
JSON
413 lines
12 KiB
JSON
{
|
|
"$schema": "./node_modules/oxlint/configuration_schema.json",
|
|
"plugins": ["react", "typescript", "import", "jsx-a11y"],
|
|
"jsPlugins": [
|
|
"./packages/eslint-plugin-actual/lib/index.js",
|
|
"eslint-plugin-typescript-paths",
|
|
"eslint-plugin-perfectionist"
|
|
],
|
|
"env": {
|
|
"browser": true,
|
|
"node": true,
|
|
"vitest": true
|
|
},
|
|
"globals": {
|
|
"vi": "readonly",
|
|
"backend": "readonly",
|
|
"importScripts": "readonly",
|
|
"FS": "readonly"
|
|
},
|
|
"rules": {
|
|
// Import sorting
|
|
"perfectionist/sort-named-imports": [
|
|
"error",
|
|
{
|
|
"groups": ["value-import", "type-import"]
|
|
}
|
|
],
|
|
|
|
// Actual rules
|
|
"actual/typography": "error",
|
|
"actual/no-untranslated-strings": "error",
|
|
"actual/prefer-trans-over-t": "error",
|
|
"actual/prefer-if-statement": "error",
|
|
"actual/prefer-logger-over-console": "error",
|
|
"actual/object-shorthand-properties": "error",
|
|
"actual/prefer-const": "error",
|
|
"actual/no-anchor-tag": "error",
|
|
"actual/no-react-default-import": "error",
|
|
|
|
// JSX A11y rules
|
|
"jsx-a11y/no-autofocus": [
|
|
"error",
|
|
{
|
|
"ignoreNonDOM": true
|
|
}
|
|
],
|
|
"jsx-a11y/alt-text": "error",
|
|
"jsx-a11y/anchor-has-content": "error",
|
|
"jsx-a11y/anchor-is-valid": [
|
|
"error",
|
|
{
|
|
"aspects": ["noHref", "invalidHref"]
|
|
}
|
|
],
|
|
"jsx-a11y/aria-activedescendant-has-tabindex": "error",
|
|
"jsx-a11y/aria-props": "error",
|
|
"jsx-a11y/aria-proptypes": "error",
|
|
"jsx-a11y/aria-role": [
|
|
"error",
|
|
{
|
|
"ignoreNonDOM": true
|
|
}
|
|
],
|
|
"jsx-a11y/aria-unsupported-elements": "error",
|
|
"jsx-a11y/heading-has-content": "error",
|
|
"jsx-a11y/iframe-has-title": "error",
|
|
"jsx-a11y/img-redundant-alt": "error",
|
|
"jsx-a11y/no-access-key": "error",
|
|
"jsx-a11y/no-distracting-elements": "error",
|
|
"jsx-a11y/no-redundant-roles": "error",
|
|
"jsx-a11y/role-has-required-aria-props": "error",
|
|
"jsx-a11y/role-supports-aria-props": "error",
|
|
"jsx-a11y/scope": "error",
|
|
|
|
// Typescript rules
|
|
"typescript/ban-ts-comment": ["error"],
|
|
"typescript/consistent-type-definitions": ["error", "type"],
|
|
"typescript/consistent-type-imports": [
|
|
"error",
|
|
{
|
|
"prefer": "type-imports",
|
|
"fixStyle": "inline-type-imports"
|
|
}
|
|
],
|
|
"typescript/no-implied-eval": "error",
|
|
"typescript/no-explicit-any": "error",
|
|
"typescript/no-restricted-types": [
|
|
"error",
|
|
{
|
|
"types": {
|
|
// forbid FC as superfluous
|
|
"FunctionComponent": {
|
|
"message": "Type the props argument and let TS infer or use ComponentType for a component prop"
|
|
},
|
|
"FC": {
|
|
"message": "Type the props argument and let TS infer or use ComponentType for a component prop"
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"typescript/no-var-requires": "error",
|
|
|
|
// Import rules
|
|
"import/consistent-type-specifier-style": "error",
|
|
"import/first": "error",
|
|
"import/no-amd": "error",
|
|
"import/no-default-export": "error",
|
|
"import/no-webpack-loader-syntax": "error",
|
|
"import/no-useless-path-segments": "error",
|
|
"import/no-unresolved": "error",
|
|
"import/no-unused-modules": "error",
|
|
"import/no-duplicates": [
|
|
"error",
|
|
{
|
|
"prefer-inline": false
|
|
}
|
|
],
|
|
|
|
// React rules
|
|
"react/exhaustive-deps": [
|
|
"error",
|
|
{
|
|
"additionalHooks": "(^useQuery$|^useEffectAfterMount$)"
|
|
}
|
|
],
|
|
"react/jsx-curly-brace-presence": "error",
|
|
"react/jsx-filename-extension": [
|
|
"error",
|
|
{
|
|
"extensions": [".jsx", ".tsx"],
|
|
"allow": "as-needed"
|
|
}
|
|
],
|
|
"react/jsx-no-comment-textnodes": "error",
|
|
"react/jsx-no-duplicate-props": "error",
|
|
"react/jsx-no-target-blank": "error",
|
|
"react/jsx-no-undef": "error",
|
|
"react/jsx-no-useless-fragment": "error",
|
|
"react/jsx-pascal-case": [
|
|
"error",
|
|
{
|
|
"allowAllCaps": true,
|
|
"ignore": []
|
|
}
|
|
],
|
|
"react/no-danger-with-children": "error",
|
|
"react/no-direct-mutation-state": "error",
|
|
"react/no-is-mounted": "error",
|
|
"react/no-unstable-nested-components": "error",
|
|
"react/require-render-return": "error",
|
|
"react/rules-of-hooks": "error",
|
|
"react/self-closing-comp": "error",
|
|
"react/style-prop-object": "error",
|
|
"react/jsx-boolean-value": "error",
|
|
|
|
// ESLint rules
|
|
"eslint/array-callback-return": "error",
|
|
"eslint/curly": ["error", "multi-line", "consistent"],
|
|
"eslint/default-case": [
|
|
"error",
|
|
{
|
|
"commentPattern": "^no default$"
|
|
}
|
|
],
|
|
"eslint/eqeqeq": ["error", "smart"],
|
|
"eslint/no-array-constructor": "error",
|
|
"eslint/no-caller": "error",
|
|
"eslint/no-cond-assign": ["error", "except-parens"],
|
|
"eslint/no-const-assign": "error",
|
|
"eslint/no-control-regex": "error",
|
|
"eslint/no-delete-var": "error",
|
|
"eslint/no-dupe-class-members": "error",
|
|
"eslint/no-dupe-keys": "error",
|
|
"eslint/no-duplicate-case": "error",
|
|
"eslint/no-empty-character-class": "error",
|
|
"eslint/no-empty-function": "error",
|
|
"eslint/no-empty-pattern": "error",
|
|
"eslint/no-eval": "error",
|
|
"eslint/no-ex-assign": "error",
|
|
"eslint/no-extend-native": "error",
|
|
"eslint/no-extra-bind": "error",
|
|
"eslint/no-extra-label": "error",
|
|
"eslint/no-fallthrough": "error",
|
|
"eslint/no-func-assign": "error",
|
|
"eslint/no-invalid-regexp": "error",
|
|
"eslint/no-iterator": "error",
|
|
"eslint/no-label-var": "error",
|
|
"eslint/no-var": "error",
|
|
"eslint/no-labels": [
|
|
"error",
|
|
{
|
|
"allowLoop": true,
|
|
"allowSwitch": false
|
|
}
|
|
],
|
|
"eslint/no-new-func": "error",
|
|
"eslint/no-script-url": "error",
|
|
"eslint/no-self-assign": "error",
|
|
"eslint/no-self-compare": "error",
|
|
"eslint/no-sequences": "error",
|
|
"eslint/no-shadow-restricted-names": "error",
|
|
"eslint/no-sparse-arrays": "error",
|
|
"eslint/no-template-curly-in-string": "error",
|
|
"eslint/no-this-before-super": "error",
|
|
"eslint/no-throw-literal": "error",
|
|
"eslint/no-unreachable": "error",
|
|
"eslint/no-obj-calls": "error",
|
|
"eslint/no-new-wrappers": "error",
|
|
"eslint/no-unsafe-negation": "error",
|
|
"eslint/no-multi-str": "error",
|
|
"eslint/no-global-assign": "error",
|
|
"eslint/no-lone-blocks": "error",
|
|
"eslint/no-unused-labels": "error",
|
|
"eslint/no-object-constructor": "error",
|
|
"eslint/no-new-native-nonconstructor": "error",
|
|
"eslint/no-redeclare": "error",
|
|
"eslint/no-useless-computed-key": "error",
|
|
"eslint/no-useless-concat": "error",
|
|
"eslint/no-useless-escape": "error",
|
|
"eslint/require-yield": "error",
|
|
"eslint/getter-return": "error",
|
|
"eslint/unicode-bom": ["error", "never"],
|
|
"eslint/no-use-isnan": "error",
|
|
"eslint/valid-typeof": "error",
|
|
"eslint/no-useless-rename": [
|
|
"error",
|
|
{
|
|
"ignoreDestructuring": false,
|
|
"ignoreImport": false,
|
|
"ignoreExport": false
|
|
}
|
|
],
|
|
"eslint/no-with": "error",
|
|
"eslint/no-regex-spaces": "error",
|
|
"eslint/no-restricted-globals": [
|
|
"error",
|
|
|
|
// https://github.com/facebook/create-react-app/tree/main/packages/confusing-browser-globals
|
|
"addEventListener",
|
|
"blur",
|
|
"close",
|
|
"closed",
|
|
"confirm",
|
|
"defaultStatus",
|
|
"defaultstatus",
|
|
"event",
|
|
"external",
|
|
"find",
|
|
"focus",
|
|
"frameElement",
|
|
"frames",
|
|
"history",
|
|
"innerHeight",
|
|
"innerWidth",
|
|
"length",
|
|
"location",
|
|
"locationbar",
|
|
"menubar",
|
|
"moveBy",
|
|
"moveTo",
|
|
"name",
|
|
"onblur",
|
|
"onerror",
|
|
"onfocus",
|
|
"onload",
|
|
"onresize",
|
|
"onunload",
|
|
"open",
|
|
"opener",
|
|
"opera",
|
|
"outerHeight",
|
|
"outerWidth",
|
|
"pageXOffset",
|
|
"pageYOffset",
|
|
"parent",
|
|
"print",
|
|
"removeEventListener",
|
|
"resizeBy",
|
|
"resizeTo",
|
|
"screen",
|
|
"screenLeft",
|
|
"screenTop",
|
|
"screenX",
|
|
"screenY",
|
|
"scroll",
|
|
"scrollbars",
|
|
"scrollBy",
|
|
"scrollTo",
|
|
"scrollX",
|
|
"scrollY",
|
|
"status",
|
|
"statusbar",
|
|
"stop",
|
|
"toolbar",
|
|
"top"
|
|
],
|
|
"eslint/no-restricted-imports": [
|
|
"error",
|
|
{
|
|
"paths": [
|
|
{
|
|
"name": "react-router",
|
|
"importNames": ["useNavigate"],
|
|
"message": "Please import Actual's useNavigate() hook from `src/hooks` instead."
|
|
},
|
|
{
|
|
"name": "react-redux",
|
|
"importNames": ["useDispatch"],
|
|
"message": "Please import Actual's useDispatch() hook from `src/redux` instead."
|
|
},
|
|
{
|
|
"name": "react-redux",
|
|
"importNames": ["useSelector"],
|
|
"message": "Please import Actual's useSelector() hook from `src/redux` instead."
|
|
},
|
|
{
|
|
"name": "react-redux",
|
|
"importNames": ["useStore"],
|
|
"message": "Please import Actual's useStore() hook from `src/redux` instead."
|
|
}
|
|
],
|
|
"patterns": [
|
|
{
|
|
"group": ["**/*.api", "**/*.web", "**/*.electron"],
|
|
"message": "Don't directly reference imports from other platforms"
|
|
},
|
|
{
|
|
"group": ["uuid"],
|
|
"importNames": ["*"],
|
|
"message": "Use `import { v4 as uuidv4 } from 'uuid'` instead"
|
|
},
|
|
{
|
|
"group": ["**/style", "**/colors"],
|
|
"importNames": ["colors"],
|
|
"message": "Please use themes instead of colors"
|
|
},
|
|
{
|
|
"group": ["**/style/themes/*"],
|
|
"message": "Please do not import theme files directly"
|
|
},
|
|
{
|
|
"group": ["@actual-app/web/**/*"],
|
|
"message": "Please do not import `@actual-app/web` in `loot-core`"
|
|
}
|
|
]
|
|
}
|
|
],
|
|
"eslint/no-useless-constructor": "error",
|
|
"eslint/no-undef": "error",
|
|
"eslint/no-unused-expressions": "error"
|
|
},
|
|
"overrides": [
|
|
{
|
|
"files": ["packages/desktop-electron/**/*"],
|
|
"rules": {
|
|
"react/rules-of-hooks": "off"
|
|
}
|
|
},
|
|
{
|
|
"files": ["**/*.test.{js,ts,jsx,tsx}", "packages/docs/**/*"],
|
|
"rules": {
|
|
"actual/no-untranslated-strings": "off",
|
|
"actual/prefer-logger-over-console": "off"
|
|
}
|
|
},
|
|
{
|
|
"files": [
|
|
"packages/api/migrations/*",
|
|
"packages/loot-core/migrations/*",
|
|
"packages/sync-server/src/app-gocardless/banks/*.js",
|
|
"*.config.{ts,mts,mjs}"
|
|
],
|
|
"rules": {
|
|
"import/no-default-export": "off"
|
|
}
|
|
},
|
|
{
|
|
"files": ["packages/docs/**/*"],
|
|
"rules": {
|
|
"actual/no-anchor-tag": "off"
|
|
}
|
|
},
|
|
{
|
|
"files": ["packages/desktop-client/**/*.{js,ts,jsx,tsx}"],
|
|
"rules": {
|
|
"typescript-paths/absolute-parent-import": [
|
|
"error",
|
|
{ "preferPathOverBaseUrl": true }
|
|
],
|
|
"typescript-paths/absolute-import": ["error", { "enableAlias": false }]
|
|
}
|
|
},
|
|
{
|
|
"files": ["packages/desktop-client/src/style/themes/*"],
|
|
"rules": {
|
|
"eslint/no-restricted-imports": "off"
|
|
}
|
|
},
|
|
// TODO: enable these
|
|
{
|
|
"files": [
|
|
"packages/desktop-client/src/components/ManageRules.tsx",
|
|
"packages/desktop-client/src/components/mobile/budget/ExpenseGroupList.tsx",
|
|
"packages/desktop-client/src/components/reports/reports/Calendar.tsx",
|
|
"packages/desktop-client/src/components/table.tsx"
|
|
],
|
|
"rules": {
|
|
"eslint/no-empty-function": "off"
|
|
}
|
|
}
|
|
]
|
|
}
|