2023-03-15 06:42:14 +03:00
|
|
|
/** @file ESLint configuration file. */
|
|
|
|
/** NOTE: The "Experimental: Use Flat Config" option must be enabled.
|
|
|
|
* Flat config is still not quite mature, so is disabled by default. */
|
|
|
|
import * as path from 'node:path'
|
|
|
|
import * as url from 'node:url'
|
|
|
|
|
2023-06-19 02:02:08 +03:00
|
|
|
// The preferred syntax is `import * as name`, however these modules do not support it.
|
2023-03-15 06:42:14 +03:00
|
|
|
// This is specialcased in other files, but these modules shouldn't be used in other files anyway.
|
|
|
|
/* eslint-disable no-restricted-syntax */
|
|
|
|
import eslintJs from '@eslint/js'
|
|
|
|
import globals from 'globals'
|
|
|
|
import jsdoc from 'eslint-plugin-jsdoc'
|
2023-07-06 14:52:32 +03:00
|
|
|
import react from 'eslint-plugin-react'
|
|
|
|
import reactHooks from 'eslint-plugin-react-hooks'
|
2023-03-15 06:42:14 +03:00
|
|
|
import tsEslint from '@typescript-eslint/eslint-plugin'
|
|
|
|
import tsEslintParser from '@typescript-eslint/parser'
|
|
|
|
/* eslint-enable no-restricted-syntax */
|
|
|
|
|
2023-05-19 22:55:29 +03:00
|
|
|
// =================
|
|
|
|
// === Constants ===
|
|
|
|
// =================
|
|
|
|
|
Fix various issues on the Dashboard (#10256)
- Fix React DevTools not working in Firefox
- Fix selection of asset names when editing them, not working at all in Firefox
- Convert tick/cross buttons when editing assets, and the "plus" and "reload" buttons on the "shared with" column, "labels" column, and keyboard shortcuts table, to match more with the rest of the design
- Update clip path when the container resizes, so that the icons for hidden columns never overlap the actual table header
- Fix #10184
- Fix renames being committed even when cancelling
- Fix duplicate name detection - previously, all asset types only checked folders with the same name, not assets with the same name
- I'm not 100% sure this is the correct behavior still
- Stop using `kbd` (`aria.Keyboard`) to display keyboard shortcuts, since they should not be displayed in a monospace font.
- Fix "plus" and "reload" buttons going past the right side of their parent table cell
- Limit length of `PermissionDisplay` - if the username of a user with permission is too long, it uses a tooltip instead
- Update the username dynamically for all permissions owned by self, when changing username in the settings.
- This avoids having to fully invalidate the directory tree every time the username changes, given that nothing changes about the assets' metadata themselves.
- Cache children in the Drive tree
- This avoids loading spinners when closing a folder and immediately reopening it.
- Note that children are still re-fetched on reopen to ensure freshness
# Important Notes
- This MAY be split into multiple smaller PRs. However, I think it's better to QA as a single PR, to avoid duplicating work checking behavior that may be changed by a sibling PR (assuming the PR was split into multiple).
2024-06-20 21:30:24 +03:00
|
|
|
const DEBUG_STATEMENTS_MESSAGE = 'Avoid leaving debugging statements when committing code'
|
2023-03-15 06:42:14 +03:00
|
|
|
const DIR_NAME = path.dirname(url.fileURLToPath(import.meta.url))
|
|
|
|
const NAME = 'enso'
|
|
|
|
/** An explicit whitelist of CommonJS modules, which do not support namespace imports.
|
|
|
|
* Many of these have incorrect types, so no type error may not mean they support ESM,
|
|
|
|
* and conversely type errors may not mean they don't support ESM -
|
|
|
|
* but we add those to the whitelist anyway otherwise we get type errors.
|
2023-03-15 14:54:16 +03:00
|
|
|
* In particular, `string-length` supports ESM but its type definitions don't.
|
2023-07-26 15:59:48 +03:00
|
|
|
* `yargs` is a modules we explicitly want the default imports of.
|
2023-03-16 16:09:31 +03:00
|
|
|
* `node:process` is here because `process.on` does not exist on the namespace import. */
|
2023-03-15 14:54:16 +03:00
|
|
|
const DEFAULT_IMPORT_ONLY_MODULES =
|
2024-07-17 12:10:42 +03:00
|
|
|
'@vitejs\\u002Fplugin-react|node:process|chalk|string-length|yargs|yargs\\u002Fyargs|sharp|to-ico|connect|morgan|serve-static|tiny-invariant|clsx|create-servers|electron-is-dev|fast-glob|esbuild-plugin-.+|opener|tailwindcss.*|@modyfi\\u002Fvite-plugin-yaml|build-info|is-network-error|validator.+|.*[.]json$'
|
2023-07-26 15:59:48 +03:00
|
|
|
const OUR_MODULES = 'enso-.*'
|
2023-03-15 06:42:14 +03:00
|
|
|
const RELATIVE_MODULES =
|
2024-07-17 12:10:42 +03:00
|
|
|
'bin\\u002Fproject-manager|bin\\u002Fserver|config\\u002Fparser|authentication|config|debug|detect|file-associations|index|ipc|log|naming|paths|preload|project-management|security|url-associations|content-config|desktop-environment|#\\u002F.*'
|
2024-02-29 13:36:47 +03:00
|
|
|
const ALLOWED_DEFAULT_IMPORT_MODULES = `${DEFAULT_IMPORT_ONLY_MODULES}|postcss|ajv\\u002Fdist\\u002F2020|${RELATIVE_MODULES}`
|
2023-03-20 12:35:16 +03:00
|
|
|
const STRING_LITERAL = ':matches(Literal[raw=/^["\']/], TemplateLiteral)'
|
2023-06-19 02:02:08 +03:00
|
|
|
const NOT_CAMEL_CASE = '/^(?!_?[a-z][a-z0-9*]*([A-Z0-9][a-z0-9]*)*$)(?!React$)/'
|
2023-07-18 14:23:41 +03:00
|
|
|
const WHITELISTED_CONSTANTS = 'logger|.+Context|interpolationFunction.+'
|
2023-03-15 06:42:14 +03:00
|
|
|
const NOT_CONSTANT_CASE = `/^(?!${WHITELISTED_CONSTANTS}$|_?[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$)/`
|
2023-05-19 22:55:29 +03:00
|
|
|
|
|
|
|
// =======================================
|
|
|
|
// === Restricted syntactic constructs ===
|
|
|
|
// =======================================
|
2023-03-15 06:42:14 +03:00
|
|
|
|
|
|
|
// Extracted to a variable because it needs to be used twice:
|
|
|
|
// - once as-is for `.d.ts`
|
|
|
|
// - once explicitly disallowing `declare`s in regular `.ts`.
|
|
|
|
/** @type {{ selector: string; message: string; }[]} */
|
|
|
|
const RESTRICTED_SYNTAXES = [
|
|
|
|
{
|
2023-03-15 14:54:16 +03:00
|
|
|
selector: `ImportDeclaration[source.value=/^(?!(${ALLOWED_DEFAULT_IMPORT_MODULES})$)[^.]/] > ImportDefaultSpecifier`,
|
2023-03-15 06:42:14 +03:00
|
|
|
message:
|
2023-03-15 14:54:16 +03:00
|
|
|
'No default imports from modules. Add to `DEFAULT_IMPORT_ONLY_MODULES` in `eslint.config.js` if the module only has a default export.',
|
2023-03-15 06:42:14 +03:00
|
|
|
},
|
|
|
|
{
|
2023-03-15 14:54:16 +03:00
|
|
|
selector: `ImportDeclaration[source.value=/^(?:${DEFAULT_IMPORT_ONLY_MODULES})$/] > ImportNamespaceSpecifier`,
|
|
|
|
message: 'No namespace imports from modules that only have a default import',
|
2023-03-15 06:42:14 +03:00
|
|
|
},
|
|
|
|
{
|
|
|
|
selector: `ImportDeclaration[source.value=/\\.(?:json|yaml|yml)$/] > ImportDefaultSpecifier[local.name=${NOT_CONSTANT_CASE}]`,
|
|
|
|
message: 'Use `CONSTANT_CASE` for imports from data files',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
selector: `ImportDeclaration[source.value=/\\.json$/]:not(:has(ImportAttribute[key.name=type][value.value=json]))`,
|
|
|
|
message: "JSON imports must be { type: 'json' }",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
selector: `ImportDeclaration[source.value=/\\.(?:yaml|yml)$/]:not(:has(ImportAttribute[key.name=type][value.value=yaml]))`,
|
|
|
|
message: "YAML imports must be { type: 'yaml' }",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
selector: `ImportDeclaration[source.value=/\\.(?:json|yaml|yml)$/] > ImportNamespaceSpecifier`,
|
|
|
|
message: 'Use default imports for imports from data files',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
selector: `ImportNamespaceSpecifier > Identifier[name=${NOT_CAMEL_CASE}]`,
|
|
|
|
message: 'Use `camelCase` for imports',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
selector: `:matches(ImportDefaultSpecifier[local.name=/^${NAME}/i], ImportNamespaceSpecifier > Identifier[name=/^${NAME}/i])`,
|
|
|
|
message: `Don't prefix modules with \`${NAME}\``,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
selector: 'ForOfStatement > .left[kind=let]',
|
|
|
|
message: 'Use `for (const x of xs)`, not `for (let x of xs)`',
|
|
|
|
},
|
|
|
|
{
|
2023-07-19 12:48:39 +03:00
|
|
|
selector:
|
|
|
|
'TSTypeAliasDeclaration > TSTypeReference:not(:has(.typeParameters)) > Identifier',
|
2023-03-15 06:42:14 +03:00
|
|
|
message: 'No renamed types',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
selector: 'TSTypeAliasDeclaration > :matches(TSLiteralType)',
|
|
|
|
message: 'No aliases to literal types',
|
|
|
|
},
|
2023-03-18 03:22:04 +03:00
|
|
|
{
|
|
|
|
selector:
|
2023-04-24 15:56:26 +03:00
|
|
|
':not(:matches(FunctionDeclaration, FunctionExpression, ArrowFunctionExpression, SwitchStatement, SwitchCase, IfStatement:has(.consequent > :matches(ReturnStatement, ThrowStatement)):has(.alternate :matches(ReturnStatement, ThrowStatement)), Program > TryStatement, Program > TryStatement > .handler, TryStatement:has(.block > :matches(ReturnStatement, ThrowStatement)):has(:matches([handler=null], .handler :matches(ReturnStatement, ThrowStatement))), TryStatement:has(.block > :matches(ReturnStatement, ThrowStatement)):has(:matches([handler=null], .handler :matches(ReturnStatement, ThrowStatement))) > .handler)) > * > :matches(ReturnStatement, ThrowStatement)',
|
2023-03-18 03:22:04 +03:00
|
|
|
message: 'No early returns',
|
|
|
|
},
|
2023-03-15 06:42:14 +03:00
|
|
|
{
|
|
|
|
selector:
|
|
|
|
'TSTypeAliasDeclaration > :matches(TSBooleanKeyword, TSBigintKeyword, TSNullKeyword, TSNumberKeyword, TSObjectKeyword, TSStringKeyword, TSSymbolKeyword, TSUndefinedKeyword, TSUnknownKeyword, TSVoidKeyword)',
|
|
|
|
message:
|
|
|
|
'No aliases to primitives - consider using brands instead: `string & { _brand: "BrandName"; }`',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
// Matches non-functions.
|
Keyboard navigation between components (#9499)
- Close https://github.com/enso-org/cloud-v2/issues/982
- Add keyboard navigation via arrows between different components
- This is achieved by a `Navigator2D` class which keeps track of the closest adjacent elements.
Other changes:
- Switch much of the codebase to use `react-aria-components`
- This *should* (but does not necessarily) give us improved accessibility for free.
- Refactor various common styles into styled components
- `FocusArea` to perform automatic registration with `Navigator2D`
- `Button` and `UnstyledButton` to let buttons participate in keyboard navigation
- `HorizontalMenuBar` - used for buttons below the titles in the Drive page, Keyboard Shortcuts settings page, and Members List settings page
- `SettingsPage` in the settings pages
- `SettingsSection` in the settings page to wrap around `FocusArea` and the heading for each section
- Add debugging utilities
- Add debugging when `body` has the `data-debug` attribute: `document.body.dataset.debug = ''`
- This adds rings around elements (all with different colors):
- That are `FocusArea`s. `FocusArea` is a wrapper component that makes an element participate in `Navigator2D`.
- That are `:focus`ed, and that are `:focus-visible`
- That are `.focus-child`. This is because keyboard navigation via arrows ***ignores*** all focusable elements that are not `.focus-child`.
- Debug `Navigator2D` neighbors when `body` has the `debug-navigator2d` attribute: `document.body.dataset.debugNavigator2d = ''`
- This highlights neighbors of the currently focused element. This is a separate debug option because computing neighbors is potentially quite expensive.
# Important Notes
- :warning: Modals and the authentication flow are not yet fully tested.
- Up+Down to navigate through suggestions has been disabled to improve UX when accidentally navigating upwards to the assets search bar.
- There are a number of *known* issues with keyboard navigation. For the most part it's because a proper solution will be quite difficult.
- Focus is lost when a column (from the extra columns selector) is toggled - because the button stops existing
- It's not possible to navigate to the icons on the assets table - so it's current not possible to *hide* columns via the keyboard
- Neighbors of the extra columns selector are not ideal (both when it is being navigated from, and when it is being navigated to)
- The suggestions in the `AssetSearchBar` aren't *quite* fully integrated with arrow keyboard navigation.
- This is *semi*-intentional. I think it makes a lot more sense to integrate them in, *however* it stays like this for now largely because I think pressing `ArrowUp` then `ArrowDown` from the assets table should return to the assets table
- Likewise for the assets table. The reason here, however, is because we want multi-select. While `react-aria-components` has lists which support multi-select, it doesn't allow programmatic focus control, making it not particularly ideal, as we want to focus the topmost element when navigating in from above.
- Clicking on the "New Folder" icon (and the like) do not focus on the newly created child. This one should be pretty easy to do, but I'm not sure whether it's the right thing to do.
2024-04-05 10:21:02 +03:00
|
|
|
selector: `:matches(Program, ExportNamedDeclaration, TSModuleBlock) > VariableDeclaration[kind=const] > VariableDeclarator[id.name=${NOT_CONSTANT_CASE}]:not(:matches([init.callee.object.name=React][init.callee.property.name=forwardRef], :has(ArrowFunctionExpression), :has(CallExpression[callee.object.name=newtype][callee.property.name=newtypeConstructor])))`,
|
2023-03-15 06:42:14 +03:00
|
|
|
message: 'Use `CONSTANT_CASE` for top-level constants that are not functions',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
selector: `:matches(Program, ExportNamedDeclaration, TSModuleBlock) > VariableDeclaration > VariableDeclarator > ArrowFunctionExpression`,
|
|
|
|
message: 'Use `function foo() {}` instead of `const foo = () => {}`',
|
|
|
|
},
|
2023-03-17 18:26:59 +03:00
|
|
|
{
|
|
|
|
selector: `ClassBody > PropertyDefinition > ArrowFunctionExpression`,
|
|
|
|
message: 'Use `foo() {}` instead of `foo = () => {}`',
|
|
|
|
},
|
2023-03-15 06:42:14 +03:00
|
|
|
{
|
2024-02-07 14:26:59 +03:00
|
|
|
// This lint intentionally excludes classes and readonly arrays.
|
|
|
|
selector: 'TSInterfaceBody:has(TSPropertySignature[readonly=false])',
|
|
|
|
message: 'Add `readonly` modifier to all interface properties',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
selector: `TSAsExpression:not(:has(TSTypeReference > Identifier[name=const]))`,
|
2023-03-20 12:35:16 +03:00
|
|
|
message: 'Avoid `as T`. Consider using a type annotation instead.',
|
|
|
|
},
|
2023-03-15 06:42:14 +03:00
|
|
|
{
|
|
|
|
selector: 'ExportNamedDeclaration > VariableDeclaration[kind=let]',
|
|
|
|
message: 'Use `export const` instead of `export let`',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
selector: `Program > VariableDeclaration[kind=let] > * > ObjectExpression:has(Property > ${STRING_LITERAL}.value):not(:has(Property > .value:not(${STRING_LITERAL})))`,
|
|
|
|
message:
|
|
|
|
'Use `const` instead of `let` for top-level object literals only containing string literals',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
selector:
|
|
|
|
'ImportDeclaration[source.value=/^(?:assert|async_hooks|buffer|child_process|cluster|console|constants|crypto|dgram|diagnostics_channel|dns|domain|events|fs|fs\\u002Fpromises|http|http2|https|inspector|module|net|os|path|perf_hooks|process|punycode|querystring|readline|repl|stream|string_decoder|timers|tls|trace_events|tty|url|util|v8|vm|wasi|worker_threads|zlib)$/]',
|
|
|
|
message: 'Use `node:` prefix to import builtin node modules',
|
|
|
|
},
|
2023-04-06 13:00:55 +03:00
|
|
|
{
|
|
|
|
selector: 'TSEnumDeclaration:not(:has(TSEnumMember))',
|
|
|
|
message: 'Enums must not be empty',
|
|
|
|
},
|
2023-03-15 06:42:14 +03:00
|
|
|
{
|
|
|
|
selector:
|
|
|
|
'ImportDeclaration[source.value=/^(?!node:)/] ~ ImportDeclaration[source.value=/^node:/]',
|
|
|
|
message:
|
|
|
|
'Import node modules before npm modules, our modules, and relative imports, separated by a blank line',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
selector: `ImportDeclaration[source.value=/^(?:${OUR_MODULES}|${RELATIVE_MODULES})$/] ~ ImportDeclaration[source.value=/^(?!(|${OUR_MODULES}|${RELATIVE_MODULES})$|\\.)/]`,
|
|
|
|
message:
|
|
|
|
'Import npm modules before our modules and relative imports, separated by a blank line',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
selector: `ImportDeclaration[source.value=/^(?:${RELATIVE_MODULES})$/] ~ ImportDeclaration[source.value=/^(?:${OUR_MODULES})$/]`,
|
|
|
|
message: 'Import our modules before relative imports, separated by a blank line',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
selector: `ImportDeclaration[source.value=/^\\./] ~ ImportDeclaration[source.value=/^[^.]/]`,
|
|
|
|
message: 'Import relative imports last',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
selector: `ImportDeclaration[source.value=/^\\..+\\.(?:json|yml|yaml)$/] ~ ImportDeclaration[source.value=/^\\..+\\.(?!json|yml|yaml)[^.]+$/]`,
|
|
|
|
message: 'Import data files after other relative imports',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
selector:
|
|
|
|
'TSAsExpression:has(TSUnknownKeyword, TSNeverKeyword, TSAnyKeyword) > TSAsExpression',
|
|
|
|
message: 'Use type assertions to specific types instead of `unknown`, `any` or `never`',
|
|
|
|
},
|
2023-05-19 22:55:29 +03:00
|
|
|
{
|
|
|
|
selector: ':matches(MethodDeclaration, FunctionDeclaration) FunctionDeclaration',
|
|
|
|
message: 'Use arrow functions for nested functions',
|
|
|
|
},
|
2023-05-02 20:48:07 +03:00
|
|
|
{
|
|
|
|
selector: 'IfStatement > ExpressionStatement',
|
|
|
|
message: 'Wrap `if` branches in `{}`',
|
|
|
|
},
|
2023-07-19 12:48:39 +03:00
|
|
|
{
|
|
|
|
selector: ':matches(ForStatement[test=null], ForStatement[test.value=true])',
|
|
|
|
message: 'Use `while (true)` instead of `for (;;)`',
|
|
|
|
},
|
2023-08-09 12:30:40 +03:00
|
|
|
{
|
2024-03-25 11:13:24 +03:00
|
|
|
selector: `:matches(\
|
|
|
|
JSXAttribute[name.name=/^(?:alt|error|label|placeholder|text|title|actionButtonLabel|actionText|aria-label)$/][value.raw=/^'|^"|^\`/], \
|
|
|
|
JSXText[value=/\\S/], \
|
|
|
|
JSXAttribute[name.name=/^(?:alt|error|label|placeholder|text|title|actionButtonLabel|actionText|aria-label)$/] ConditionalExpression:matches(\
|
|
|
|
[consequent.raw=/^'|^"|^\`/], \
|
|
|
|
[alternate.raw=/^'|^"|^\`/]\
|
|
|
|
)\
|
|
|
|
)`,
|
|
|
|
message: 'Use a `getText()` from `useText` instead of a literal string',
|
2023-08-09 12:30:40 +03:00
|
|
|
},
|
2024-06-12 13:20:07 +03:00
|
|
|
{
|
|
|
|
selector: `JSXAttribute[name.name=/^(?:className)$/] TemplateLiteral`,
|
|
|
|
message:
|
Fix various issues on the Dashboard (#10256)
- Fix React DevTools not working in Firefox
- Fix selection of asset names when editing them, not working at all in Firefox
- Convert tick/cross buttons when editing assets, and the "plus" and "reload" buttons on the "shared with" column, "labels" column, and keyboard shortcuts table, to match more with the rest of the design
- Update clip path when the container resizes, so that the icons for hidden columns never overlap the actual table header
- Fix #10184
- Fix renames being committed even when cancelling
- Fix duplicate name detection - previously, all asset types only checked folders with the same name, not assets with the same name
- I'm not 100% sure this is the correct behavior still
- Stop using `kbd` (`aria.Keyboard`) to display keyboard shortcuts, since they should not be displayed in a monospace font.
- Fix "plus" and "reload" buttons going past the right side of their parent table cell
- Limit length of `PermissionDisplay` - if the username of a user with permission is too long, it uses a tooltip instead
- Update the username dynamically for all permissions owned by self, when changing username in the settings.
- This avoids having to fully invalidate the directory tree every time the username changes, given that nothing changes about the assets' metadata themselves.
- Cache children in the Drive tree
- This avoids loading spinners when closing a folder and immediately reopening it.
- Note that children are still re-fetched on reopen to ensure freshness
# Important Notes
- This MAY be split into multiple smaller PRs. However, I think it's better to QA as a single PR, to avoid duplicating work checking behavior that may be changed by a sibling PR (assuming the PR was split into multiple).
2024-06-20 21:30:24 +03:00
|
|
|
'Use `tv` from `#/utilities/tailwindVariants` or `twMerge` from `tailwind-merge` instead of template strings for classes',
|
2024-06-12 13:20:07 +03:00
|
|
|
},
|
Keyboard navigation between components (#9499)
- Close https://github.com/enso-org/cloud-v2/issues/982
- Add keyboard navigation via arrows between different components
- This is achieved by a `Navigator2D` class which keeps track of the closest adjacent elements.
Other changes:
- Switch much of the codebase to use `react-aria-components`
- This *should* (but does not necessarily) give us improved accessibility for free.
- Refactor various common styles into styled components
- `FocusArea` to perform automatic registration with `Navigator2D`
- `Button` and `UnstyledButton` to let buttons participate in keyboard navigation
- `HorizontalMenuBar` - used for buttons below the titles in the Drive page, Keyboard Shortcuts settings page, and Members List settings page
- `SettingsPage` in the settings pages
- `SettingsSection` in the settings page to wrap around `FocusArea` and the heading for each section
- Add debugging utilities
- Add debugging when `body` has the `data-debug` attribute: `document.body.dataset.debug = ''`
- This adds rings around elements (all with different colors):
- That are `FocusArea`s. `FocusArea` is a wrapper component that makes an element participate in `Navigator2D`.
- That are `:focus`ed, and that are `:focus-visible`
- That are `.focus-child`. This is because keyboard navigation via arrows ***ignores*** all focusable elements that are not `.focus-child`.
- Debug `Navigator2D` neighbors when `body` has the `debug-navigator2d` attribute: `document.body.dataset.debugNavigator2d = ''`
- This highlights neighbors of the currently focused element. This is a separate debug option because computing neighbors is potentially quite expensive.
# Important Notes
- :warning: Modals and the authentication flow are not yet fully tested.
- Up+Down to navigate through suggestions has been disabled to improve UX when accidentally navigating upwards to the assets search bar.
- There are a number of *known* issues with keyboard navigation. For the most part it's because a proper solution will be quite difficult.
- Focus is lost when a column (from the extra columns selector) is toggled - because the button stops existing
- It's not possible to navigate to the icons on the assets table - so it's current not possible to *hide* columns via the keyboard
- Neighbors of the extra columns selector are not ideal (both when it is being navigated from, and when it is being navigated to)
- The suggestions in the `AssetSearchBar` aren't *quite* fully integrated with arrow keyboard navigation.
- This is *semi*-intentional. I think it makes a lot more sense to integrate them in, *however* it stays like this for now largely because I think pressing `ArrowUp` then `ArrowDown` from the assets table should return to the assets table
- Likewise for the assets table. The reason here, however, is because we want multi-select. While `react-aria-components` has lists which support multi-select, it doesn't allow programmatic focus control, making it not particularly ideal, as we want to focus the topmost element when navigating in from above.
- Clicking on the "New Folder" icon (and the like) do not focus on the newly created child. This one should be pretty easy to do, but I'm not sure whether it's the right thing to do.
2024-04-05 10:21:02 +03:00
|
|
|
{
|
|
|
|
selector: 'JSXOpeningElement[name.name=button] > JSXIdentifier',
|
|
|
|
message: 'Use `Button` or `UnstyledButton` instead of `button`',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
selector: 'JSXOpeningElement[name.name=/^h[123456]$/] > JSXIdentifier',
|
|
|
|
message: 'Use `aria.Heading` instead of `h1`-`h6`',
|
|
|
|
},
|
2023-03-15 06:42:14 +03:00
|
|
|
]
|
|
|
|
|
2023-05-19 22:55:29 +03:00
|
|
|
// ============================
|
|
|
|
// === ESLint configuration ===
|
|
|
|
// ============================
|
|
|
|
|
2023-03-15 06:42:14 +03:00
|
|
|
/* eslint-disable @typescript-eslint/naming-convention */
|
|
|
|
export default [
|
|
|
|
eslintJs.configs.recommended,
|
2023-10-11 13:24:33 +03:00
|
|
|
{
|
2024-05-14 17:00:00 +03:00
|
|
|
// Playwright build cache and Vite build directory.
|
|
|
|
ignores: ['**/.cache/**', '**/playwright-report', '**/dist'],
|
2023-10-11 13:24:33 +03:00
|
|
|
},
|
2023-03-15 06:42:14 +03:00
|
|
|
{
|
2023-06-19 02:02:08 +03:00
|
|
|
settings: {
|
|
|
|
react: {
|
|
|
|
version: '18.2',
|
|
|
|
},
|
|
|
|
},
|
2023-03-15 06:42:14 +03:00
|
|
|
plugins: {
|
|
|
|
jsdoc: jsdoc,
|
|
|
|
'@typescript-eslint': tsEslint,
|
2023-07-06 14:52:32 +03:00
|
|
|
react: react,
|
|
|
|
'react-hooks': reactHooks,
|
2023-03-15 06:42:14 +03:00
|
|
|
},
|
|
|
|
languageOptions: {
|
|
|
|
parser: tsEslintParser,
|
|
|
|
parserOptions: {
|
|
|
|
tsconfigRootDir: DIR_NAME,
|
|
|
|
project: true,
|
|
|
|
},
|
|
|
|
globals: {
|
|
|
|
...globals.browser,
|
|
|
|
...globals.node,
|
|
|
|
...globals.es2015,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
rules: {
|
|
|
|
...tsEslint.configs['eslint-recommended']?.rules,
|
|
|
|
...tsEslint.configs.recommended?.rules,
|
|
|
|
...tsEslint.configs['recommended-requiring-type-checking']?.rules,
|
|
|
|
...tsEslint.configs.strict?.rules,
|
2024-03-23 21:44:56 +03:00
|
|
|
...react.configs['jsx-runtime'].rules,
|
2023-03-20 12:35:16 +03:00
|
|
|
eqeqeq: ['error', 'always', { null: 'never' }],
|
Keyboard navigation between components (#9499)
- Close https://github.com/enso-org/cloud-v2/issues/982
- Add keyboard navigation via arrows between different components
- This is achieved by a `Navigator2D` class which keeps track of the closest adjacent elements.
Other changes:
- Switch much of the codebase to use `react-aria-components`
- This *should* (but does not necessarily) give us improved accessibility for free.
- Refactor various common styles into styled components
- `FocusArea` to perform automatic registration with `Navigator2D`
- `Button` and `UnstyledButton` to let buttons participate in keyboard navigation
- `HorizontalMenuBar` - used for buttons below the titles in the Drive page, Keyboard Shortcuts settings page, and Members List settings page
- `SettingsPage` in the settings pages
- `SettingsSection` in the settings page to wrap around `FocusArea` and the heading for each section
- Add debugging utilities
- Add debugging when `body` has the `data-debug` attribute: `document.body.dataset.debug = ''`
- This adds rings around elements (all with different colors):
- That are `FocusArea`s. `FocusArea` is a wrapper component that makes an element participate in `Navigator2D`.
- That are `:focus`ed, and that are `:focus-visible`
- That are `.focus-child`. This is because keyboard navigation via arrows ***ignores*** all focusable elements that are not `.focus-child`.
- Debug `Navigator2D` neighbors when `body` has the `debug-navigator2d` attribute: `document.body.dataset.debugNavigator2d = ''`
- This highlights neighbors of the currently focused element. This is a separate debug option because computing neighbors is potentially quite expensive.
# Important Notes
- :warning: Modals and the authentication flow are not yet fully tested.
- Up+Down to navigate through suggestions has been disabled to improve UX when accidentally navigating upwards to the assets search bar.
- There are a number of *known* issues with keyboard navigation. For the most part it's because a proper solution will be quite difficult.
- Focus is lost when a column (from the extra columns selector) is toggled - because the button stops existing
- It's not possible to navigate to the icons on the assets table - so it's current not possible to *hide* columns via the keyboard
- Neighbors of the extra columns selector are not ideal (both when it is being navigated from, and when it is being navigated to)
- The suggestions in the `AssetSearchBar` aren't *quite* fully integrated with arrow keyboard navigation.
- This is *semi*-intentional. I think it makes a lot more sense to integrate them in, *however* it stays like this for now largely because I think pressing `ArrowUp` then `ArrowDown` from the assets table should return to the assets table
- Likewise for the assets table. The reason here, however, is because we want multi-select. While `react-aria-components` has lists which support multi-select, it doesn't allow programmatic focus control, making it not particularly ideal, as we want to focus the topmost element when navigating in from above.
- Clicking on the "New Folder" icon (and the like) do not focus on the newly created child. This one should be pretty easy to do, but I'm not sure whether it's the right thing to do.
2024-04-05 10:21:02 +03:00
|
|
|
// Any extra semicolons that exist, are required by Prettier.
|
|
|
|
'no-extra-semi': 'off',
|
2023-05-19 22:55:29 +03:00
|
|
|
'jsdoc/require-jsdoc': [
|
|
|
|
'error',
|
|
|
|
{
|
|
|
|
require: {
|
|
|
|
FunctionDeclaration: true,
|
|
|
|
MethodDefinition: true,
|
|
|
|
ClassDeclaration: true,
|
|
|
|
ArrowFunctionExpression: false,
|
|
|
|
FunctionExpression: true,
|
|
|
|
},
|
|
|
|
// Top-level constants should require JSDoc as well,
|
|
|
|
// however it does not seem like there is a way to do this.
|
|
|
|
contexts: [
|
|
|
|
'TSInterfaceDeclaration',
|
|
|
|
'TSEnumDeclaration',
|
|
|
|
'TSTypeAliasDeclaration',
|
|
|
|
'TSMethodSignature',
|
|
|
|
],
|
|
|
|
},
|
|
|
|
],
|
2023-07-19 12:48:39 +03:00
|
|
|
'no-constant-condition': ['error', { checkLoops: false }],
|
2023-03-15 06:42:14 +03:00
|
|
|
'no-restricted-syntax': ['error', ...RESTRICTED_SYNTAXES],
|
2023-06-19 02:02:08 +03:00
|
|
|
'prefer-const': 'error',
|
Fix various issues on the Dashboard (#10256)
- Fix React DevTools not working in Firefox
- Fix selection of asset names when editing them, not working at all in Firefox
- Convert tick/cross buttons when editing assets, and the "plus" and "reload" buttons on the "shared with" column, "labels" column, and keyboard shortcuts table, to match more with the rest of the design
- Update clip path when the container resizes, so that the icons for hidden columns never overlap the actual table header
- Fix #10184
- Fix renames being committed even when cancelling
- Fix duplicate name detection - previously, all asset types only checked folders with the same name, not assets with the same name
- I'm not 100% sure this is the correct behavior still
- Stop using `kbd` (`aria.Keyboard`) to display keyboard shortcuts, since they should not be displayed in a monospace font.
- Fix "plus" and "reload" buttons going past the right side of their parent table cell
- Limit length of `PermissionDisplay` - if the username of a user with permission is too long, it uses a tooltip instead
- Update the username dynamically for all permissions owned by self, when changing username in the settings.
- This avoids having to fully invalidate the directory tree every time the username changes, given that nothing changes about the assets' metadata themselves.
- Cache children in the Drive tree
- This avoids loading spinners when closing a folder and immediately reopening it.
- Note that children are still re-fetched on reopen to ensure freshness
# Important Notes
- This MAY be split into multiple smaller PRs. However, I think it's better to QA as a single PR, to avoid duplicating work checking behavior that may be changed by a sibling PR (assuming the PR was split into multiple).
2024-06-20 21:30:24 +03:00
|
|
|
'react/forbid-elements': [
|
|
|
|
'error',
|
|
|
|
{ forbid: [{ element: 'Debug', message: DEBUG_STATEMENTS_MESSAGE }] },
|
|
|
|
],
|
2023-07-06 14:52:32 +03:00
|
|
|
// Not relevant because TypeScript checks types.
|
|
|
|
'react/prop-types': 'off',
|
2024-03-23 21:44:56 +03:00
|
|
|
'react/self-closing-comp': 'error',
|
2023-07-06 14:52:32 +03:00
|
|
|
'react-hooks/rules-of-hooks': 'error',
|
Fix various issues on the Dashboard (#10256)
- Fix React DevTools not working in Firefox
- Fix selection of asset names when editing them, not working at all in Firefox
- Convert tick/cross buttons when editing assets, and the "plus" and "reload" buttons on the "shared with" column, "labels" column, and keyboard shortcuts table, to match more with the rest of the design
- Update clip path when the container resizes, so that the icons for hidden columns never overlap the actual table header
- Fix #10184
- Fix renames being committed even when cancelling
- Fix duplicate name detection - previously, all asset types only checked folders with the same name, not assets with the same name
- I'm not 100% sure this is the correct behavior still
- Stop using `kbd` (`aria.Keyboard`) to display keyboard shortcuts, since they should not be displayed in a monospace font.
- Fix "plus" and "reload" buttons going past the right side of their parent table cell
- Limit length of `PermissionDisplay` - if the username of a user with permission is too long, it uses a tooltip instead
- Update the username dynamically for all permissions owned by self, when changing username in the settings.
- This avoids having to fully invalidate the directory tree every time the username changes, given that nothing changes about the assets' metadata themselves.
- Cache children in the Drive tree
- This avoids loading spinners when closing a folder and immediately reopening it.
- Note that children are still re-fetched on reopen to ensure freshness
# Important Notes
- This MAY be split into multiple smaller PRs. However, I think it's better to QA as a single PR, to avoid duplicating work checking behavior that may be changed by a sibling PR (assuming the PR was split into multiple).
2024-06-20 21:30:24 +03:00
|
|
|
'react-hooks/exhaustive-deps': [
|
|
|
|
'error',
|
|
|
|
{ additionalHooks: 'useOnScroll|useStickyTableHeaderOnScroll' },
|
|
|
|
],
|
2024-03-23 21:44:56 +03:00
|
|
|
'react/jsx-pascal-case': ['error', { allowNamespace: true }],
|
2023-03-15 06:42:14 +03:00
|
|
|
// Prefer `interface` over `type`.
|
|
|
|
'@typescript-eslint/consistent-type-definitions': 'error',
|
2023-10-11 13:24:33 +03:00
|
|
|
'@typescript-eslint/consistent-type-imports': 'error',
|
2023-03-15 06:42:14 +03:00
|
|
|
'@typescript-eslint/member-ordering': 'error',
|
|
|
|
// Method syntax is not type-safe.
|
|
|
|
// See: https://typescript-eslint.io/rules/method-signature-style
|
|
|
|
'@typescript-eslint/method-signature-style': 'error',
|
|
|
|
'@typescript-eslint/naming-convention': [
|
|
|
|
'error',
|
|
|
|
{
|
|
|
|
selector: ['function'],
|
|
|
|
// PascalCase for React components, camelCase for all other situations
|
|
|
|
format: ['camelCase', 'PascalCase'],
|
|
|
|
},
|
|
|
|
{
|
|
|
|
selector: ['variable'],
|
|
|
|
modifiers: ['const', 'global'],
|
|
|
|
format: ['UPPER_CASE', 'camelCase', 'PascalCase'],
|
|
|
|
},
|
|
|
|
{
|
|
|
|
selector: ['variable'],
|
|
|
|
modifiers: ['const', 'exported'],
|
|
|
|
format: ['UPPER_CASE', 'camelCase', 'PascalCase'],
|
|
|
|
},
|
|
|
|
{
|
|
|
|
selector: ['variable'],
|
|
|
|
format: ['camelCase', 'PascalCase'],
|
|
|
|
},
|
|
|
|
{
|
2024-05-14 17:00:00 +03:00
|
|
|
selector: ['parameter', 'method'],
|
2023-03-15 06:42:14 +03:00
|
|
|
format: ['camelCase'],
|
|
|
|
},
|
|
|
|
{
|
|
|
|
selector: ['parameter'],
|
|
|
|
modifiers: ['unused'],
|
|
|
|
format: ['camelCase'],
|
|
|
|
leadingUnderscore: 'require',
|
|
|
|
},
|
2024-05-14 17:00:00 +03:00
|
|
|
{
|
|
|
|
selector: ['property'],
|
|
|
|
format: ['camelCase'],
|
|
|
|
filter: {
|
|
|
|
regex: '^(?:data-testid)$',
|
|
|
|
match: false,
|
|
|
|
},
|
|
|
|
},
|
2023-03-15 06:42:14 +03:00
|
|
|
],
|
|
|
|
'@typescript-eslint/no-confusing-void-expression': 'error',
|
2023-04-26 12:52:13 +03:00
|
|
|
'@typescript-eslint/no-empty-interface': 'off',
|
2023-03-15 06:42:14 +03:00
|
|
|
'@typescript-eslint/no-extraneous-class': 'error',
|
2023-03-15 14:54:16 +03:00
|
|
|
'@typescript-eslint/no-invalid-void-type': ['error', { allowAsThisParameter: true }],
|
2023-03-15 06:42:14 +03:00
|
|
|
// React 17 and later supports async functions as event handlers, so we need to disable this
|
|
|
|
// rule to avoid false positives.
|
|
|
|
//
|
|
|
|
// See: https://github.com/typescript-eslint/typescript-eslint/pull/4623
|
|
|
|
'@typescript-eslint/no-misused-promises': [
|
|
|
|
'error',
|
|
|
|
{ checksVoidReturn: { attributes: false } },
|
|
|
|
],
|
|
|
|
'@typescript-eslint/no-redundant-type-constituents': 'error',
|
2023-07-19 12:48:39 +03:00
|
|
|
'@typescript-eslint/no-unnecessary-condition': [
|
|
|
|
'error',
|
|
|
|
{ allowConstantLoopConditions: true },
|
|
|
|
],
|
2023-03-15 06:42:14 +03:00
|
|
|
'@typescript-eslint/no-useless-empty-export': 'error',
|
|
|
|
'@typescript-eslint/parameter-properties': ['error', { prefer: 'parameter-property' }],
|
|
|
|
'@typescript-eslint/prefer-enum-initializers': 'error',
|
|
|
|
'@typescript-eslint/prefer-readonly': 'error',
|
|
|
|
'@typescript-eslint/require-array-sort-compare': [
|
|
|
|
'error',
|
|
|
|
{ ignoreStringArrays: true },
|
|
|
|
],
|
|
|
|
'@typescript-eslint/restrict-template-expressions': 'error',
|
|
|
|
'@typescript-eslint/sort-type-constituents': 'error',
|
2023-07-06 14:52:32 +03:00
|
|
|
'@typescript-eslint/strict-boolean-expressions': 'error',
|
2023-03-15 06:42:14 +03:00
|
|
|
'@typescript-eslint/switch-exhaustiveness-check': 'error',
|
|
|
|
'default-param-last': 'off',
|
|
|
|
'@typescript-eslint/default-param-last': 'error',
|
|
|
|
'no-invalid-this': 'off',
|
|
|
|
'@typescript-eslint/no-invalid-this': ['error', { capIsConstructor: false }],
|
|
|
|
'jsdoc/no-magic-numbers': 'off',
|
|
|
|
'@typescript-eslint/no-magic-numbers': [
|
|
|
|
'error',
|
|
|
|
{
|
2023-10-11 13:24:33 +03:00
|
|
|
ignore: [-1, 0, 1, 2, 3, 4, 5],
|
2023-03-15 06:42:14 +03:00
|
|
|
ignoreArrayIndexes: true,
|
|
|
|
ignoreEnums: true,
|
|
|
|
detectObjects: true,
|
|
|
|
enforceConst: true,
|
|
|
|
},
|
|
|
|
],
|
|
|
|
'no-redeclare': 'off',
|
|
|
|
// Important to warn on accidental duplicated `interface`s e.g. when writing API wrappers.
|
2023-04-06 13:00:55 +03:00
|
|
|
'@typescript-eslint/no-redeclare': ['error', { ignoreDeclarationMerge: false }],
|
2023-03-15 06:42:14 +03:00
|
|
|
'no-shadow': 'off',
|
2023-10-11 13:24:33 +03:00
|
|
|
'@typescript-eslint/no-shadow': 'error',
|
2023-03-15 06:42:14 +03:00
|
|
|
'no-unused-expressions': 'off',
|
|
|
|
'@typescript-eslint/no-unused-expressions': 'error',
|
|
|
|
'jsdoc/require-param-type': 'off',
|
2023-10-11 13:24:33 +03:00
|
|
|
'jsdoc/check-access': 'error',
|
|
|
|
'jsdoc/check-alignment': 'error',
|
|
|
|
'jsdoc/check-indentation': 'error',
|
|
|
|
'jsdoc/check-line-alignment': 'error',
|
|
|
|
'jsdoc/check-param-names': 'error',
|
|
|
|
'jsdoc/check-property-names': 'error',
|
|
|
|
'jsdoc/check-syntax': 'error',
|
|
|
|
'jsdoc/check-tag-names': 'error',
|
|
|
|
'jsdoc/check-types': 'error',
|
|
|
|
'jsdoc/check-values': 'error',
|
|
|
|
'jsdoc/empty-tags': 'error',
|
|
|
|
'jsdoc/implements-on-classes': 'error',
|
|
|
|
'jsdoc/no-bad-blocks': 'error',
|
|
|
|
'jsdoc/no-defaults': 'error',
|
|
|
|
'jsdoc/no-multi-asterisks': 'error',
|
|
|
|
'jsdoc/no-types': 'error',
|
|
|
|
'jsdoc/no-undefined-types': 'error',
|
|
|
|
'jsdoc/require-asterisk-prefix': 'error',
|
|
|
|
'jsdoc/require-description': 'error',
|
2023-03-17 18:26:59 +03:00
|
|
|
// This rule does not handle `# Heading`s and "etc.", "e.g.", "vs." etc.
|
2023-10-11 13:24:33 +03:00
|
|
|
// 'jsdoc/require-description-complete-sentence': 'error',
|
|
|
|
'jsdoc/require-file-overview': 'error',
|
|
|
|
'jsdoc/require-hyphen-before-param-description': 'error',
|
|
|
|
'jsdoc/require-param-description': 'error',
|
|
|
|
'jsdoc/require-param-name': 'error',
|
|
|
|
'jsdoc/require-property': 'error',
|
|
|
|
'jsdoc/require-property-description': 'error',
|
|
|
|
'jsdoc/require-property-name': 'error',
|
|
|
|
'jsdoc/require-property-type': 'error',
|
|
|
|
'jsdoc/require-returns-check': 'error',
|
|
|
|
'jsdoc/require-returns-description': 'error',
|
|
|
|
'jsdoc/require-throws': 'error',
|
|
|
|
'jsdoc/require-yields': 'error',
|
|
|
|
'jsdoc/require-yields-check': 'error',
|
|
|
|
'jsdoc/tag-lines': 'error',
|
|
|
|
'jsdoc/valid-types': 'error',
|
2023-03-15 06:42:14 +03:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
files: ['**/*.js', '**/*.jsx', '**/*.cjs', '**/*.mjs'],
|
|
|
|
rules: {
|
|
|
|
'@typescript-eslint/no-var-requires': 'off',
|
|
|
|
// Parameter types must be specified using JSDoc in JS files.
|
|
|
|
'jsdoc/no-types': 'off',
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
files: ['**/*.ts', '**/*.mts', '**/*.cts', '**/*.tsx', '**/*.mtsx', '**/*.ctsx'],
|
|
|
|
ignores: ['**/*.d.ts'],
|
|
|
|
rules: {
|
|
|
|
'no-restricted-syntax': [
|
|
|
|
'error',
|
|
|
|
...RESTRICTED_SYNTAXES,
|
|
|
|
{
|
2024-02-01 11:47:43 +03:00
|
|
|
selector: ':not(TSModuleDeclaration)[declare=true]',
|
2023-03-15 06:42:14 +03:00
|
|
|
message: 'No ambient declarations',
|
|
|
|
},
|
|
|
|
],
|
|
|
|
// This rule does not work with TypeScript, and TypeScript already does this.
|
|
|
|
'no-undef': 'off',
|
|
|
|
},
|
|
|
|
},
|
2023-06-06 15:00:07 +03:00
|
|
|
{
|
|
|
|
files: [
|
2024-07-17 12:10:42 +03:00
|
|
|
'dashboard/src/**/*.ts',
|
|
|
|
'dashboard/src/**/*.mts',
|
|
|
|
'dashboard/src/**/*.cts',
|
|
|
|
'dashboard/src/**/*.tsx',
|
|
|
|
'dashboard/src/**/*.mtsx',
|
|
|
|
'dashboard/src/**/*.ctsx',
|
|
|
|
'dashboard/mock/**/*.ts',
|
|
|
|
'dashboard/mock/**/*.mts',
|
|
|
|
'dashboard/mock/**/*.cts',
|
|
|
|
'dashboard/mock/**/*.tsx',
|
|
|
|
'dashboard/mock/**/*.mtsx',
|
|
|
|
'dashboard/mock/**/*.ctsx',
|
2023-06-06 15:00:07 +03:00
|
|
|
],
|
|
|
|
rules: {
|
|
|
|
'no-restricted-properties': [
|
|
|
|
'error',
|
Fix various issues on the Dashboard (#10256)
- Fix React DevTools not working in Firefox
- Fix selection of asset names when editing them, not working at all in Firefox
- Convert tick/cross buttons when editing assets, and the "plus" and "reload" buttons on the "shared with" column, "labels" column, and keyboard shortcuts table, to match more with the rest of the design
- Update clip path when the container resizes, so that the icons for hidden columns never overlap the actual table header
- Fix #10184
- Fix renames being committed even when cancelling
- Fix duplicate name detection - previously, all asset types only checked folders with the same name, not assets with the same name
- I'm not 100% sure this is the correct behavior still
- Stop using `kbd` (`aria.Keyboard`) to display keyboard shortcuts, since they should not be displayed in a monospace font.
- Fix "plus" and "reload" buttons going past the right side of their parent table cell
- Limit length of `PermissionDisplay` - if the username of a user with permission is too long, it uses a tooltip instead
- Update the username dynamically for all permissions owned by self, when changing username in the settings.
- This avoids having to fully invalidate the directory tree every time the username changes, given that nothing changes about the assets' metadata themselves.
- Cache children in the Drive tree
- This avoids loading spinners when closing a folder and immediately reopening it.
- Note that children are still re-fetched on reopen to ensure freshness
# Important Notes
- This MAY be split into multiple smaller PRs. However, I think it's better to QA as a single PR, to avoid duplicating work checking behavior that may be changed by a sibling PR (assuming the PR was split into multiple).
2024-06-20 21:30:24 +03:00
|
|
|
{ object: 'console', message: DEBUG_STATEMENTS_MESSAGE },
|
|
|
|
{ property: 'useDebugState', message: DEBUG_STATEMENTS_MESSAGE },
|
|
|
|
{ property: 'useDebugEffect', message: DEBUG_STATEMENTS_MESSAGE },
|
|
|
|
{ property: 'useDebugMemo', message: DEBUG_STATEMENTS_MESSAGE },
|
|
|
|
{ property: 'useDebugCallback', message: DEBUG_STATEMENTS_MESSAGE },
|
2023-06-06 15:00:07 +03:00
|
|
|
],
|
|
|
|
},
|
|
|
|
},
|
2023-10-11 13:24:33 +03:00
|
|
|
{
|
|
|
|
files: [
|
2024-07-17 12:10:42 +03:00
|
|
|
'dashboard/e2e/**/*.ts',
|
|
|
|
'dashboard/e2e/**/*.mts',
|
|
|
|
'dashboard/e2e/**/*.cts',
|
|
|
|
'dashboard/e2e/**/*.tsx',
|
|
|
|
'dashboard/e2e/**/*.mtsx',
|
|
|
|
'dashboard/e2e/**/*.ctsx',
|
2023-10-11 13:24:33 +03:00
|
|
|
],
|
|
|
|
rules: {
|
|
|
|
'no-restricted-properties': [
|
|
|
|
'error',
|
|
|
|
{
|
|
|
|
object: 'console',
|
|
|
|
message: 'Avoid leaving debugging statements when committing code',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
object: 'hooks',
|
|
|
|
property: 'useDebugState',
|
|
|
|
message: 'Avoid leaving debugging statements when committing code',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
object: 'hooks',
|
|
|
|
property: 'useDebugEffect',
|
|
|
|
message: 'Avoid leaving debugging statements when committing code',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
object: 'hooks',
|
|
|
|
property: 'useDebugMemo',
|
|
|
|
message: 'Avoid leaving debugging statements when committing code',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
object: 'hooks',
|
|
|
|
property: 'useDebugCallback',
|
|
|
|
message: 'Avoid leaving debugging statements when committing code',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
object: 'page',
|
|
|
|
property: 'type',
|
|
|
|
message: 'Prefer `locator.type` instead',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
object: 'page',
|
|
|
|
property: 'click',
|
|
|
|
message: 'Prefer `locator.click` instead',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
object: 'page',
|
|
|
|
property: 'fill',
|
|
|
|
message: 'Prefer `locator.fill` instead',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
object: 'page',
|
|
|
|
property: 'locator',
|
|
|
|
message: 'Prefer `page.getBy*` instead',
|
|
|
|
},
|
|
|
|
],
|
|
|
|
},
|
|
|
|
},
|
2023-03-15 06:42:14 +03:00
|
|
|
{
|
|
|
|
files: ['**/*.d.ts'],
|
2023-03-17 18:26:59 +03:00
|
|
|
rules: {
|
|
|
|
'no-undef': 'off',
|
|
|
|
},
|
2023-03-15 06:42:14 +03:00
|
|
|
},
|
2023-12-06 10:50:44 +03:00
|
|
|
{
|
|
|
|
files: ['**/tailwind.config.ts'],
|
|
|
|
rules: {
|
|
|
|
'no-restricted-syntax': 'off',
|
|
|
|
'@typescript-eslint/naming-convention': 'off',
|
|
|
|
},
|
|
|
|
},
|
2023-03-15 06:42:14 +03:00
|
|
|
]
|