{"id":23772140,"url":"https://github.com/connorjs/eslint-config-connorjs","last_synced_at":"2026-01-20T06:33:32.088Z","repository":{"id":194186616,"uuid":"690272012","full_name":"connorjs/eslint-config-connorjs","owner":"connorjs","description":"@connorjs’s preferred ESLint configuration. With ESLint flat config.","archived":false,"fork":false,"pushed_at":"2024-08-11T22:44:20.000Z","size":243,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-12-25T01:52:07.209Z","etag":null,"topics":["eslint","eslint-config"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/connorjs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-09-11T21:57:47.000Z","updated_at":"2024-08-11T22:43:44.000Z","dependencies_parsed_at":null,"dependency_job_id":"591edafd-b7ce-42f8-b841-9f3406b1ae35","html_url":"https://github.com/connorjs/eslint-config-connorjs","commit_stats":null,"previous_names":["connorjs/eslint-config-connorjs"],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/connorjs/eslint-config-connorjs","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/connorjs%2Feslint-config-connorjs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/connorjs%2Feslint-config-connorjs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/connorjs%2Feslint-config-connorjs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/connorjs%2Feslint-config-connorjs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/connorjs","download_url":"https://codeload.github.com/connorjs/eslint-config-connorjs/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/connorjs%2Feslint-config-connorjs/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28597640,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-20T02:08:49.799Z","status":"ssl_error","status_checked_at":"2026-01-20T02:08:44.148Z","response_time":117,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["eslint","eslint-config"],"created_at":"2025-01-01T04:53:01.633Z","updated_at":"2026-01-20T06:33:32.069Z","avatar_url":"https://github.com/connorjs.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# eslint-config-connorjs\n\nMy ([@connorjs][connorjs]) preferred [ESLint][eslint] configuration.\nWith ESLint flat config.\n\nUse it directly ([§ Install](#install)) or take inspiration from it ([§ Rules and reasoning](#rules-and-reasoning)).\n\n\u003e 🛑 **IMPORTANT**\n\u003e\n\u003e [eslint-comments/require-description] is the single most important rule to configure! Please use it.\n\n\u003e 🟢 **Tip**: I highly recommend [eslint-plugin-unicorn], which my config uses.\n\n[connorjs]: https://github.com/connorjs\n[eslint]: https://eslint.org\n[eslint-comments/require-description]: https://mysticatea.github.io/eslint-plugin-eslint-comments/rules/require-description.html\n[eslint-plugin-unicorn]: https://www.npmjs.com/package/eslint-plugin-unicorn\n\n## Table of contents\n\n- [Install](#install)\n- [Project structure](#project-structure)\n- [Rules and reasoning](#rules-and-reasoning)\n  - [Base rules](#base-rules)\n  - [JSON (and JSONC)](#json)\n  - [JavaScript and TypeScript](#javascript-and-typescript)\n  - [React](#react)\n  - [HTML](#html)\n\n## Install\n\n1. Add the dependency\n\n   ```shell\n   npm i -D eslint-config-connorjs\n   ```\n\n2. Include the config in your ESLint flat config.\n\n   ```js\n   import connorjsConfig from \"eslint-config-connorjs\";\n\n   export default [\n   \t// earlier configuration\n   \t...connorjsConfig,\n   \t// later\n   ];\n   ```\n\nTo learn more about ESLint flat config, check out the [blog posts][eslint-flat-config-blog] or the [documentation][eslint-flat-config-docs].\n\n[eslint-flat-config-blog]: https://eslint.org/blog/2022/08/new-config-system-part-2/\n[eslint-flat-config-docs]: https://eslint.org/docs/latest/use/configure/configuration-files-new\n\n## Project structure\n\nThe [lib](./lib) directory contains the ESLint configuration files.\nIt groups them by “use case.”\nA use case could represent an entire language (`html` or `json` for example) or a tool (`react` or `vitest`).\n\nSplitting by use case helps to copy desired configuration or building a functional form of the ESLint config.\n(See [Sheriff] for an example of the functional form.)\n\n[Sheriff]: https://github.com/AndreaPontrandolfo/sheriff#readme\n\n## Rules and reasoning\n\nThe remainder of the README discusses the rules, configurations, and plugins used and why I used them.\n\nThe 🔧 emoji indicates that configured rules are automatically fixable with `--fix`.\n\n\u003e 🟢 **Tip**: The [source code](./lib) has inline comments that may provide more detail.\n\n### Base rules\n\nThe [base rules config](lib/base.js) apply to all file types.\n\n- Configures ESLint linter options.\n\n  - [reportUnusedDisableDirectives] to keep code clean and up to date.\n\n- Includes [eslint-plugin-eslint-comments] and enforces comment descriptions ([eslint-comments/require-description]) to document why the code should ignore a configured ESLint rule.\n\n- Includes [eslint-config-prettier] to turns off all rules that are unnecessary or might conflict with [Prettier].\n\n- 🔧 Enforces template literals (backtick strings) to allow easier change to interpolation with [eslint/quotes].\n\n- Configures the [global ignores][global-ignores].\n\n[eslint-config-prettier]: https://github.com/prettier/eslint-config-prettier/#readme\n[eslint-plugin-eslint-comments]: https://mysticatea.github.io/eslint-plugin-eslint-comments/\n[eslint/quotes]: https://eslint.org/docs/latest/rules/quotes\n[global-ignores]: https://eslint.org/docs/latest/use/configure/configuration-files-new#globally-ignoring-files-with-ignores\n[Prettier]: https://prettier.io\n[reportUnusedDisableDirectives]: https://eslint.org/docs/latest/use/configure/configuration-files-new#reporting-unused-disable-directives\n\n### JSON\n\nThe [JSON config](lib/json.js) applies to all JSON files. It handles JSONC (JSON with comments) and JSONC-like files.\n\n- Configures [jsonc-eslint-parser] as the parser for the `.json` and `.jsonc` files.\n\n  It does not lint `package-lock.json`.\n\n- Includes [eslint-plugin-jsonc] and registers its `recommended-with-json` and `prettier` rule sets.\n\n- 🔧 Configures sorting rules to standardize the order (no need to think or worry about the “best” order) and reduces merge conflicts.\n\tFeel free to `eslint-disable` at call sites.\n\n  - 🔧 [jsonc/sort-array-values]\n\n  - 🔧 [jsonc/sort-keys]\n\n- Allows comments in JSONC and JSONC-like files (for example, `tsconfig.json`).\n\n- 🔧 Configures an explicit sort order for `package.json` keys.\n\tSee the code for details.\n\n  \u003e 🔷 **Note**: This overrides the previous jsonc/sort-keys configuration. You\n  \u003e can configure specific sort orders for other files using similar logic.\n\n[eslint-plugin-jsonc]: https://ota-meshi.github.io/eslint-plugin-jsonc/\n[jsonc-eslint-parser]: https://www.npmjs.com/package/jsonc-eslint-parser\n[jsonc/sort-array-values]: https://ota-meshi.github.io/eslint-plugin-jsonc/rules/sort-array-values.html\n[jsonc/sort-keys]: https://ota-meshi.github.io/eslint-plugin-jsonc/rules/sort-keys.html\n\n### JavaScript and TypeScript\n\nThe [JS and TS config](lib/javascript-and-typescript.js) applies to all JS and\nTS files: `cjs,js,ts,tsx`. _The largest configuration set!_\n\n- Configures language options.\n\n  - `ecmaVersion: latest` because projects use bundlers or other build tools to transpile to target versions.\n  \n  - Includes isomorphic globals (shared by node and the browser) via [globals]\n  \n  - Also see the [@typescript-eslint/parser] documentation\n\n- 🔧 Configures sorting rules to standardize the order (no need to think or worry about the “best” order) and reduces merge conflicts.\n  Feel free to `eslint-disable` at call sites.\n  They are case-insensitive.\n\n  - 🔧 [sort-keys]\n  \n  - 🔧 [@typescript-eslint/member-ordering] with required properties first\n\n- Includes [@eslint/js] `recommended` rule set.\n\n- Includes [eslint-plugin-sonarjs] `recommended` rule set.\n\n- Includes [eslint-plugin-unicorn] `recommended` rule set and configures additional rules from unicorn.\n  Some specific call-outs follow.\n\n  - 🔧 Configures an allow list for [unicorn/prevent-abbreviations] to allow some abbreviations.\n    Example: Allow `props`, which React commonly uses.\n\n  - 🔧 Configures patterns for [unicorn/string-content] to enforce better string content.\n    Example: Use unicode arrow `→` instead of hyphen and greater than (`-\u003e`).\n\n    The auto-fix feature makes this rule very useful.\n    See the source code for a “smart quotes” pattern.\n\n- Uses [typescript-eslint] and includes its `recommended-type-checked` and `stylistic-type-checked` rule sets.\n\n  - 🔧 Configures [@typescript-eslint/consistent-type-definitions] to enforce using `type` instead of `interface` (as the default).\n\n    Interfaces use declaration merging, which I do not recommend as the default.\n    See the [_Differences Between Type Aliases and Interfaces_ documentation][type-vs-interface].\n\n  - 🔧 Configures [@typescript-eslint/no-non-null-assertion] to require a comment via `eslint-disable` when needed.\n    It allows non-null assertions in test files.\n\n- Uses [eslint-plugin-simple-import-sort] and [eslint-plugin-import] to configure import rules.\n  Some specific call-outs follow.\n\n  - 🔧 Includes `simple-import-sort/imports` and `simple-import-sort/exports` to sort the imports and re-exports.\n    See the [Sort order docs][eslint-plugin-simple-import-sort-sort-order].\n\n    I recommend the default configuration instead of creating your own order.\n\n  - Includes [eslint-plugin-import] `recommended` rule set.\n  \n  - Configures [import/no-default-export] to disallow default exports.\n\n    I have experienced various issues resulting from default exports over the years, so I strongly recommend configuring this rule.\n    You can always `eslint-disable` at the call site when you need it and explain why (example: dynamic imports for React code-splitting point).\n\n    1. Naming exports leads to a stronger contract and can help refactoring.\n    2. You can use `as` syntax to rename named exports very easily, so the supposed benefit of “name default exports whatever you want” has little benefit in practice.\n    3. _I want to add more of my reasons, so TODO!_\n\n    The ESLint configuration opts-out known configuration files that require default exports (example: storybook files).\n\n  - Configures [import/no-anonymous-default-export] to disallow anonymous default exports in the case that you `eslint-disable` the `import/no-default-export` rule.\n\n  - 🔧 Uses [@typescript-eslint/consistent-type-imports] and [import/consistent-type-specifier-style] to enforce consistent usage of type imports.\n\n    We need both rules for best fix-it developer experience: one to add `type` and the other to fix the placement.\n\n[@eslint/js]: https://www.npmjs.com/package/@eslint/js\n[eslint-plugin-import]: https://github.com/import-js/eslint-plugin-import#readme\n[eslint-plugin-simple-import-sort]: https://github.com/lydell/eslint-plugin-simple-import-sort#readme\n[eslint-plugin-simple-import-sort-sort-order]: https://github.com/lydell/eslint-plugin-simple-import-sort#sort-order\n[eslint-plugin-sonarjs]: https://www.npmjs.com/package/eslint-plugin-sonarjs\n[globals]: https://www.npmjs.com/package/globals\n[import/consistent-type-specifier-style]: https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/consistent-type-specifier-style.md\n[import/no-anonymous-default-export]: https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/no-anonymous-default-export.md\n[import/no-default-export]: https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/no-default-export.md\n[sort-keys]: https://eslint.org/docs/latest/rules/sort-keys\n[type-vs-interface]: https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#differences-between-type-aliases-and-interfaces\n[typescript-eslint]: https://typescript-eslint.io\n[@typescript-eslint/consistent-type-definitions]: https://typescript-eslint.io/rules/consistent-type-definitions/\n[@typescript-eslint/consistent-type-imports]: https://typescript-eslint.io/rules/consistent-type-imports/\n[@typescript-eslint/member-ordering]: https://typescript-eslint.io/rules/member-ordering/\n[@typescript-eslint/no-non-null-assertion]: https://typescript-eslint.io/rules/no-non-null-assertion/\n[@typescript-eslint/parser]: https://typescript-eslint.io/packages/parser\n[unicorn/prevent-abbreviations]: https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prevent-abbreviations.md\n[unicorn/string-content]: https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/string-content.md\n\n### React\n\nThe [react config](lib/react.js) applies to all typescript files (`ts` and `tsx`) and only makes sense to use in a React project.\n\n- Uses [eslint-plugin-jsx-a11y] and its `recommended` rule set.\n\n- Uses [eslint-plugin-react] and its `recommended` and `jsx-runtime` rule sets.\n\n- Uses [eslint-plugin-react-hooks] and its `recommended` rule set.\n\n- Configures [react/destructuring-assignment] to disallow destructuring props.\n  (Controversial, I know.)\n\n  I find it harder to update components that use destructuring.\n  Plus I think it looks bad with inline types given TypeScript usage.\n\n- Configures [react/forbid-component-props] to disallow props.\n  (Example: `style` to disallow inline styles.)\n\n- 🔧 Configures [react/function-component-definition] to enforce component definition consistency.\n\n  Uses “function declarations” for named components because they are the only way to support generics in TSX, so using it for consistency.\n  Remember: This will auto-fix.\n\n  Uses “arrow functions” for unnamed components to emphasize unnamed and for nice lambda readability (example: pass to `map`).\n\n- 🔧 Enables [react/hook-use-state] to enforce symmetric naming of the `useState` hook value and setter variables.\n\n- 🔧 Configures [react/jsx-boolean-value] and [react/jsx-curly-brace-presence] to enforce consistent JSX styles. See the code for details.\n\n- Configures the following rules to force a comment explaining the use case.\n  While this may seem like extra work, it helps catch improper usage.\n  - react/jsx-no-leaked-render\n  - react/jsx-props-no-spreading\n  - react/no-array-index-key\n  - react/no-danger\n\n[eslint-plugin-jsx-a11y]: https://github.com/jsx-eslint/eslint-plugin-jsx-a11y#readme\n[eslint-plugin-react]: https://github.com/jsx-eslint/eslint-plugin-react\n[eslint-plugin-react-hooks]: https://www.npmjs.com/package/eslint-plugin-react-hooks\n[react/destructuring-assignment]: https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/destructuring-assignment.md\n[react/forbid-component-props]: https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/forbid-component-props.md\n[react/hook-use-state]: https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/hook-use-state.md\n[react/jsx-boolean-value]: https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/\n[react/jsx-curly-brace-presence]: https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/\n\n### HTML\n\nThe [HTML config](lib/html.js) applies to all HTML files.\n\n- Uses [html-eslint].\n\n- Includes the `recommended` ruleset and accessibility and best practice oriented rules.\n\tSee the code for details, but some specific call-outs follow.\n\n  - [@html-eslint/id-naming-convention] to enforce kebab case for `id` naming.\n\n  - [@html-eslint/no-inline-styles] to disallow inline styles, mostly for [Content Security Policy (CSP)][mdn-csp] reasons.\n\n    Even if you allow `unsafe-inline` for the CSP, this rule would also require explanations for using inline styles instead of CSS with `eslint-disable`.\n\n  - [@html-eslint/no-skip-heading-levels] to disallow skipping heading levels.\n\n  - [@html-eslint/no-target-blank] to disallow usage of unsafe `target='_blank'`.\n\n[html-eslint]: https://yeonjuan.github.io/html-eslint/\n[@html-eslint/id-naming-convention]: https://yeonjuan.github.io/html-eslint/docs/rules/id-naming-convention/\n[@html-eslint/no-inline-styles]: https://yeonjuan.github.io/html-eslint/docs/rules/no-inline-styles/\n[@html-eslint/no-skip-heading-levels]: https://yeonjuan.github.io/html-eslint/docs/rules/no-skip-heading-levels/\n[@html-eslint/no-target-blank]: https://yeonjuan.github.io/html-eslint/docs/rules/no-target-blank/\n[mdn-csp]: https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fconnorjs%2Feslint-config-connorjs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fconnorjs%2Feslint-config-connorjs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fconnorjs%2Feslint-config-connorjs/lists"}