Giter Site home page Giter Site logo

eslint-config-pixiebrix's Introduction

eslint-config-pixiebrix

ESLint shareable config for PixieBrix

Install

$ npm install --save-dev eslint-config-pixiebrix

Usage

Add some ESLint config to your package.json:

{
	"name": "my-pixiebrix-project",
	"eslintConfig": {
		"extends": "pixiebrix"
	}
}

Or to .eslintrc:

{
	"extends": "pixiebrix"
}

npm publishing

Collaborators can publish a new version of what's on main via "workflow_dispatch" under Actions » Publish

eslint-config-pixiebrix's People

Contributors

dependabot[bot] avatar fregante avatar fungairino avatar github-actions[bot] avatar grahamlangford avatar johnnymetz avatar

Stargazers

 avatar

Watchers

 avatar  avatar  avatar  avatar

Forkers

fungairino

eslint-config-pixiebrix's Issues

Restore automated publishing

The branch protections recently enabled don't allow the automated publishing workflow to push some changes back to the repo:

- run: git push --follow-tags

This means that the version in the repo remains out of date (on the first successful publishing) and then future attempts will fail completely.

There might be a solution, but it needs setup/exploration:

https://github.com/orgs/community/discussions/13836#discussioncomment-5341603

Ensure `import()`ed dependencies are always dynamically imported

If you first import('react') and then import "react" in the same bundle, Webpack will not create a secondary chunk, it will just inline it.

In a large application, it's not easy to keep track of all the import decisions, so one optimization (deferred loading via import()) can be undone and left unnoticed forever.

We can now enforce that some dependencies are always dynamically imported:

  • ban the static imports of a set of dependencies (i.e. always import canvas-confetti via import())
  • remind developers to update this set of dependencies every time the linter encounters a new import("new-dependency")

Both of these are enforceable via no-restricted-syntax

Related

Replace `release-with-changelog` step in publish action

Background

The NPM publish action is emitted the following warning:

The set-output command is deprecated and will be disabled soon. Please upgrade to using Environment Files. For more information see: https://github.blog/changelog/2022-10-11-github-actions-deprecating-save-state-and-set-output-commands/

The warning is coming from the fregante/release-with-changelog@v3 step.

Per the project repo, the action is deprecated and recommends using the gh release create command instead.

Restrict imports of classnames to cx

Motivation

  • We want to enforce our convention of prefering import cx from 'classnames' over import classnames from 'classnames'

Acceptance Criteria

  • Find an existing linting rule that would allow us to enforce this
    OR
  • Create our own custom linting rule

Notes

Replace `import/no-restricted-paths` with hand-rolled version?

$ TIMING=1 nr lint
Rule                                            | Time (ms) | Relative
:-----------------------------------------------|----------:|--------:
import/no-restricted-paths                      | 71530.176 |    56.0%
@typescript-eslint/promise-function-async       | 10734.587 |     8.4%
@typescript-eslint/no-unsafe-argument           |  5984.000 |     4.7%
@typescript-eslint/no-floating-promises         |  3182.511 |     2.5%
import/no-self-import                           |  2680.865 |     2.1%
@typescript-eslint/no-confusing-void-expression |  1603.084 |     1.3%
@typescript-eslint/no-redeclare                 |  1254.564 |     1.0%
unicorn/no-thenable                             |   898.581 |     0.7%
react/no-direct-mutation-state                  |   799.667 |     0.6%
unicorn/prevent-abbreviations                   |   799.234 |     0.6%

I believe that's an excessive amount of time to what's essentially string matching. Given it doubles the lint time (locally and on CI), we could probably think about fixing it, also because it's an important rule for the extension.

Enable more React rules

Once all of the rules mentioned on this issue are merged or closed, let's use this issue to migrate those rules from the Extension's eslintrc.js to eslint-config-pixiebrix.

Notes

The config only uses the recommended list, but apparently there are lot more rules:

https://github.com/jsx-eslint/eslint-plugin-react/tree/master#list-of-supported-rules

A very useful one is react/jsx-no-useless-fragment, which I'll enable soon in a PR.

Q: Do you see any other rules that might be useful in that list?

Note: A lot of them are formatting related and that's already taken care by Prettier.

Disable background imports in content script files and vice versa

This could export a backgroundContext config to be set on /background/* files in order to exclude direct /options/* and /contentScript/* imports. Same goes for contentScriptContext, etc.

Only */messenger/api imports will be allowed across contexts.


Not sure how they can be combined since there can only be one no-restricted-imports rule.

Related:

Enforce removal of events on `addEventListener`

Every addEventListener must be followed by a removeEventListener or else they'll be left behind and cause hard-to-debug issues:

Enforcing removeEventListener might be difficult, but requiring a signal could be done via types. For example:

addEventListener(
	type: string,
	listener: EventListenerOrEventListenerObject,
-	options?: boolean | AddEventListenerOptions
+	options: AddEventListenerOptions & {signal: AbortSignal}
): void;

Or just via no-restricted-syntax.


The most recent issue I found was this listener, left behind between reloads:

https://github.com/pixiebrix/pixiebrix-extension/blob/4878e51b4466cf6d628b5085c6ac964510a924f4/src/contentScript/selectionTooltip/tooltipController.tsx#L281-L299

`@typescript-eslint/naming-convention` configuration

I dropped this rule because it's too complex and incomplete. If we want to enforce some naming conventions with the linter I suggest we use someone else's config and stick to it without exceptions or else we (I) will end up doing this:

Unfortunately the biggest drawback of Sindre Sorhus’ configuration for this rule excludes UPPER_SNAKE_CASE, which you might not like.

From https://github.com/pixiebrix/pixiebrix-app/pull/1246#discussion_r811072628

Related:

Update eqeqeq eslint rule

Implementation Sketch

  • Switch from smart to always
  • Add the optional { null: "never" } second afgument
  • Open/merge PR
  • Use the Publish workflow to publish a new patch version of the repo
  • Install the latest version in the Extension project
  • Run the linter and fix any issues it finds

Replace `import/no-restricted-paths` with `no-restricted-imports`

With a recent update, eslint became unreasonably slow, with lints running at 7 minutes locally. I think this started happening after a ts-eslint or import-plugin update. A good chunk of time seems to be taken by the import/no-restricted-paths rule currently, like 2 whole minutes.

I think the native no-restricted-imports could match the functionality, with the exception that it does not accept "per-directory" options. This can be achieved by using the native eslint overrides, but these overrides cancel out any other config for this rule, unless you manually re-apply it, like:

"no-restricted-imports": [
"error",
{
// Documentation: https://eslint.org/docs/rules/no-restricted-imports#options
patterns: [
// Extend the existing patterns
...config.rules["no-restricted-imports"][1].patterns,
{
group: ["./*"],
message:
'Use root-based imports (`import "@/something"`) instead of relative imports.',
},
],

Move to flat config

https://eslint.org/blog/2022/08/new-config-system-part-2/

This would let us reuse rules by just changing names (I presume) instead of manually merging them each time, like:

"no-restricted-imports": [
"error",
{
// Documentation: https://eslint.org/docs/rules/no-restricted-imports#options
patterns: [
// Extend the existing patterns
...config.rules["no-restricted-imports"][1].patterns,
{
group: ["./*"],
message:
'Use root-based imports (`import "@/something"`) instead of relative imports.',
},
],

This change would make the following change more reasonable:

eslint.org/docs/latest/use/configure/configuration-files-new

Suggested in #176 (comment)

I'm not sure if this is immediately possible due to our dependencies, but I can look into it if desired.

Move some custom rules from the extension to the shared config

I think someone suggested this before but I can't find it. Maybe it was just me?

I don’t think any of these rules is extension-specific, so it can be shared with other repos

https://github.com/pixiebrix/pixiebrix-extension/blob/main/eslint-local-rules/

    "local-rules/noNullRtkQueryArgs": "error",
    "local-rules/noInvalidDataTestId": "error",
    "local-rules/noExpressionLiterals": "error",
    "local-rules/notBothLabelAndLockableProps": "error",
    "local-rules/preferNullish": "warn",
    "local-rules/preferNullishable": "warn",

Only persistBackgroundData and noCrossBoundaryImports are really specific to the extension I think.

cc @grahamlangford @fungairino

Related

Automatically enable strict rules on files appearing in `tsconfig.strictNullChecks`

There are some rules that were disabled due to the loose config. We could enable them automatically on the files that appear in the new config.

This might not be practical, depending on how many errors they trigger, but it might be worth a check.

Rules:

https://github.com/pixiebrix/pixiebrix-extension/blob/ecc09cc5ebb3b55791762983be861d0ca786128a/.eslintrc.js#L79-L82

"@typescript-eslint/no-unsafe-assignment": "off",
"@typescript-eslint/no-unsafe-member-access": "off",
"@typescript-eslint/no-unsafe-return": "off",
"@typescript-eslint/no-unsafe-call": "off",
"@typescript-eslint/prefer-nullish-coalescing": "off", // Requires strictNullChecks

Example usage in the overrides array:

    {
      files: require("./src/tsconfig.strictNullChecks.json").files,
      rules: {
        "@typescript-eslint/no-explicit-any": "error",
      },
    },

Enable `no-non-null-assertion` (?)

Graham mentioned this rule in a review in pixiebrix/pixiebrix-extension#6534, I thought I'd open an issue here to discuss it and potentially add it to this config.

https://typescript-eslint.io/rules/no-non-null-assertion

I'm not entirely sure we should enable it. It's ideal in theory, but very often code guarantees that a value is not null in a way that TypeScript can't verify. Or maybe the types are just too broad (e.g. we know paragraphEl.textContent exists but its type is string | undefined)

In that case we have 3 options:

  • add a condition, e.g. if (!x), return or throw, writing code that will never be run
  • use ?., pushing the non-existent null down the line
  • use !, silence the rule, write explanation

All of these make the code more verbose for non-existent benefit. Maybe the last one works as documentation, but it's still noisy and a cause of additional time spent on an unimportant piece of code.

cc @grahamlangford @mnholtz

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.