-
-
Notifications
You must be signed in to change notification settings - Fork 4
Update ESLint configuration #54
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
…tegrate new plugins for improved linting and code quality
…tion for improved code style enforcement
…pt ESLint support, and adjust test file inclusion in tsconfig.json
…default and 2-space indentation for JSX files
…rove context initialization in frontend
… for building and linking workspace packages
…treamline linting and testing steps
…to use specific visibility type
…scripts to include configs
…e rules for JSX files
…move unused bun.lock files from database, song, sounds, and thumbnail packages
8c29900
to
54ee6d5
Compare
Thank you for opening the pull request! I've given considerable thought to the proposed formatting changes, but I'm not particularly fond of applying them to the codebase. The crux of the issue is that formatting styles are highly personal. It's entirely fine, in a personal project or one maintained by a closed team, to tweak formatting options so the code looks better to those involved in maintaining it. 📝Formatting vs. lintingThe ESLint team has decided to stop maintaining all style-related rules in version 8, having deferred this responsibility to the community. They have a great reason to do that, as maintaining these formatting rules was taking a great chunk of their time. There's a strong case for not using ESLint to format code — linters and formatters are different tools, and tying up both operations makes formatting as slow as linting. Lately, I have noticed that Prettier is already integrated with the project and largely takes care of standardizing code style, thanks to its opinionated nature. Before migrating to ESLint 8, we were using whitespace rules to insert line breaks. The result is that this forced line breaks in a few awkward places where it wouldn't be necessary to add them. Nowadays, I would probably reconsider this addition — in many cases, the programmer knows best how to format their code, and these rules end up being too black and white. Proponents of However, I don't believe we have reached the point where this level of control would achieve a significant improvement in our workflow, to make it worth introducing such rules. The consequence of leaning heavily into stylistic rules is that it suddenly opens up a can of worms — there are 95 available rules in The time spent considering these rules and tweaking them so the code looks the best on every possible instance of these constructs adds up to a vast portion of our development time. And, although it's a 'set-and-forget' type of task, there is the possibility of some of these rules being discontinued in the future, or even ESLint changing enough that the behavior/implementation of these rules would change. Each of these rules can be considered a separate dependency, and, like every dependency, it must be maintained. In this case, it is much more beneficial to strive for simplicity than to have absolute customizability. Formatting rules are, for the most part, minor details. Sensible defaults go a long way, and, to a great extent, can be considered 'good enough'. I'd rather go with a widely used standard, but 'live with' limited customizability, than to spend a lot of time reasoning about these rules, and how they affect our codebase (decisions which often involve very subjective criteria; time that could be better spent developing actual features). An acceptable alternative would be to implement an opinionated set of rules, such as antfu/eslint-config. This defers the maintenance burden over these rules to someone else rather than us — unless, of course, we decide to customize it all ourselves. Lastly, we had agreed upon these defaults much earlier on the project, back when there wasn't nearly as much code around. Changing these now, amidst all the refactorings we are doing on the codebase, generates a lot of noise that's difficult to reason about, with little benefit to the project. I believe the most beneficial approach would be to stick with what we have already picked at the start — otherwise, what's preventing us from repeatedly changing the formatting style again down the line? On the specific formatting changes you suggested:
All in all, I believe the best course of action is just to pick the default values and go with them. 📍 ProposalI suggest we:
No rule conflicts, no maintenance burden, no disagreements, sensible defaults all the way. ✅ 🟢 Case in point: Open Collective's frontend codebaseAvailable at: https://github.com/opencollective/opencollective-frontend
This goes a long way! 🚀
There's still the issue that JSON and other configuration files have no associated configuration. As such, simply saving many of these files in my end reformats them to a different line break/indentation style (I'd have to figure out why). I agree with all the other linting changes! Though they did generate lots of warnings — it could be interesting to go through them at some point and fix them. |
@Bentroen Regarding the pre-commit hook, I have some reservations. They introduce significant friction to the development process. They slow down commits, which discourages making small, frequent "checkpoints," and can feel like a roadblock when you want to save your progress. They also add configuration bloat (like Husky), can be inconsistent across different machines, and are easily bypassed. Wouldn't it open to relying on format on save instead? It achieves the same goal by ensuring code is clean as we write. We could then use a CI check on the PR as a final backstop to catch anything that slips through, as it is. |
…e ESLint configuration for improved rule management
Thank you for making the changes! I'll do one final linting commit later as the final step before merging the PR. As for the pre-commit hook, I agree with the points you mentioned. We'd mostly be relying on format on save anyway; by following our recommended practice, other contributors would also rarely commit unformatted code. I suggested it more as a 'final resort' to catch potential slips early, rather than at the end of a PR — where many formatting changes could be necessary to get everything in order. I've thought about going with a middle-ground solution: in parallel with a CI action (which would only point out what's wrong instead of fixing it), we could set up a pre-commit hook only on specific branches, to make sure all code committed there adheres to the formatting and linting rules. It seems to be possible to configure |
Summary
This PR consolidates significant improvements to the project's linting infrastructure, code quality enforcement, and test reliability. The changes focus on standardizing code style, updating ESLint configuration to use modern TypeScript ESLint, and resolving workspace dependency issues that were causing test failures.
LLM's description of the rules:
General Configuration
node_modules
, build output folders (dist
,build
,.next
), and configuration files.js.configs.recommended
) and TypeScript-ESLint (tseslint.configs.recommended
) to provide a strong foundation of general best practices.globals.node
) and support ES2021 features.eslint-plugin-import
: For managing and ordering import statements.@stylistic/eslint-plugin
: For enforcing a consistent code style and format.eslint-plugin-react
: For enforcing React best practices and rules for JSX.Rule Summary with Examples
Here is a breakdown of what each specific rule enforces.
1. Code Quality & Best Practices
no-console
: Warns ifconsole.log()
or otherconsole
methods are used.console.log('Debugging data');
max-len
: Sets a maximum line length of 1024 characters but ignores comments, URLs, and strings to remain practical.@typescript-eslint/no-explicit-any
: Warns against using theany
type to encourage stronger type safety.let user: any = response.data;
let user: UserProfile = response.data;
@typescript-eslint/no-require-imports
: Disallowsrequire()
in favor of ES moduleimport
statements.const path = require('path');
import path from 'path';
@typescript-eslint/ban-ts-comment
: Warns against using suppression comments like// @ts-ignore
.@typescript-eslint/no-unused-vars
: Finds variables that are declared but never used. It is configured to ignore variables prefixed with an underscore (_
).const unusedValue = getData();
const _unusedValue = getData();
or removing it.2. Import Rules (
eslint-plugin-import
)import/order
: Enforces a strict order for imports, grouping them logically (built-in, external, internal, etc.). It is configured to treat paths starting with@/
as internal.import/newline-after-import
: Requires a blank line after the import block.import/no-duplicates
: Combines imports from the same module into a single line.import { A } from 'module'; import { B } from 'module';
import { A, B } from 'module';
3. Stylistic & Formatting Rules (
@stylistic/eslint-plugin
)@stylistic/indent
: Enforces 4-space indentation for most files. (This is overridden to 2 spaces for JSX/TSX files).@stylistic/space-infix-ops
: Requires spaces around operators.const sum=a+b;
const sum = a + b;
@stylistic/keyword-spacing
: Requires spaces around keywords likeif
,else
,for
.if(condition){...}
if (condition) {...}
@stylistic/arrow-spacing
: Requires spaces around the arrow in arrow functions.const add=(a, b)=>a + b;
const add = (a, b) => a + b;
@stylistic/space-before-blocks
: Requires a space before a block's opening brace.function myFunc(){...}
function myFunc() {...}
@stylistic/object-curly-spacing
: Requires spaces inside object braces.const user = {name: 'John'};
const user = { name: 'John' };
@stylistic/comma-spacing
: Requires a space after a comma, not before.const list = [1 , 2 , 3];
const list = [1, 2, 3];
@stylistic/comma-dangle
: Disallows trailing commas.const user = { name: 'John', };
const user = { name: 'John' };
@stylistic/key-spacing
: Enforces consistent spacing around the colon in object properties.const user = { name : 'John' };
const user = { name: 'John' };
4. React-Specific Rules (
eslint-plugin-react
)react.configs.recommended.rules
: This applies a large set of recommended best-practice rules for React, including:react/jsx-key
: Warns if you forget to add akey
prop to elements in a list.react/jsx-no-duplicate-props
: Prevents defining the same prop twice on a component.react/jsx-no-target-blank
: Ensuresrel="noreferrer"
is present on links withtarget="_blank"
for security.react/react-in-jsx-scope
: 'off': This rule is turned off because modern versions of React (17+) do not require you toimport React from 'react'
in every file that uses JSX.react/no-unknown-property
: Prevents you from using non-standard HTML attributes on DOM elements, which helps catch typos. This rule has been configured to specifically allow the following custom attributes:custom-prop
cmdk-input-wrapper
cmdk-group-heading
<div cmdk-input-wrapper="">...</div>
will now be considered valid.5. File-Specific Overrides
.jsx
and.tsx
files: The global indentation rule is overridden to enforce 2 spaces instead of 4, which is a common convention in the React community.