Skip to content

Commit 5257a79

Browse files
authored
chore(eslint): add eslint support (#89)
* chore(deps): add eslint dependencies * ci: add lint job * chore(eslint): update eslint config * refactor: update code to fix eslint errors * chore: change in to of * Update ci.yml * chore: run prettier, add markdownlint * ci: add lint:md task to lint job, add format job * chore: run format
1 parent fc0af87 commit 5257a79

25 files changed

+1284
-480
lines changed

.changeset/README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# Changesets
22

3-
Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
4-
with multi-package repos, or single-package repos to help you version and publish your code. You can
5-
find the full documentation for it [in our repository](https://github.com/changesets/changesets)
3+
Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works with
4+
multi-package repos, or single-package repos to help you version and publish your code. You can find the full
5+
documentation for it [in our repository](https://github.com/changesets/changesets)
66

77
We have a quick list of common questions to get you started engaging with this project in
88
[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)

.eslintrc.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
'use strict'
2+
3+
/**
4+
* @type {import('eslint').Linter.Config}
5+
*/
6+
module.exports = {
7+
extends: ['eslint:recommended', 'plugin:github/recommended'],
8+
parserOptions: {
9+
ecmaVersion: 'latest'
10+
},
11+
env: {
12+
commonjs: true,
13+
node: true
14+
},
15+
rules: {
16+
'import/no-commonjs': 'off',
17+
'no-shadow': 'off',
18+
'no-unused-vars': [
19+
'error',
20+
{
21+
varsIgnorePattern: '^_'
22+
}
23+
]
24+
},
25+
overrides: [
26+
{
27+
files: ['**/*.test.js'],
28+
env: {
29+
jest: true
30+
}
31+
},
32+
{
33+
files: ['.eslintrc.js'],
34+
rules: {
35+
'filenames/match-regex': 'off'
36+
}
37+
}
38+
]
39+
}

.github/workflows/ci.yml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,18 @@ on:
66
branches: [main]
77

88
jobs:
9+
format:
10+
runs-on: ubuntu-latest
11+
steps:
12+
- uses: actions/checkout@v4
13+
- name: Use Node.js
14+
uses: actions/setup-node@v3
15+
with:
16+
node-version: 18
17+
cache: 'npm'
18+
- run: npm ci
19+
- run: npm run format:check
20+
921
test:
1022
runs-on: ubuntu-latest
1123
steps:
@@ -17,3 +29,16 @@ jobs:
1729
cache: 'npm'
1830
- run: npm ci
1931
- run: npm test
32+
33+
lint:
34+
runs-on: ubuntu-latest
35+
steps:
36+
- uses: actions/checkout@v4
37+
- name: Use Node.js
38+
uses: actions/setup-node@v3
39+
with:
40+
node-version: 18
41+
cache: 'npm'
42+
- run: npm ci
43+
- run: npm run lint
44+
- run: npm run lint:md

.markdownlint-cli2.cjs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
'use strict'
2+
3+
const githubMarkdownOpinions = require('@github/markdownlint-github')
4+
5+
const options = githubMarkdownOpinions.init({
6+
// Rules we don't care to enforce (usually stylistic)
7+
'line-length': false,
8+
'blanks-around-headings': false,
9+
'blanks-around-lists': false,
10+
'no-trailing-spaces': false,
11+
'no-multiple-blanks': false,
12+
'no-trailing-punctuation': false,
13+
'single-trailing-newline': false,
14+
'ul-indent': false,
15+
'ul-style': false,
16+
'no-hard-tabs': false,
17+
'first-line-heading': false,
18+
'no-space-in-emphasis': false,
19+
'blanks-around-fences': false
20+
})
21+
22+
module.exports = {
23+
config: options,
24+
customRules: ['@github/markdownlint-github'],
25+
outputFormatters: [['markdownlint-cli2-formatter-pretty', {appendLink: true}]]
26+
}

.prettierignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.changeset
2+
node_modules
3+
CHANGELOG.md

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ ESLint rules for Primer React
66

77
## Installation
88

9-
1. Assuming you already have [ESLint](https://www.npmjs.com/package/eslint) and [Primer React](https://github.com/primer/react) installed, run:
9+
1. Assuming you already have [ESLint](https://www.npmjs.com/package/eslint) and
10+
[Primer React](https://github.com/primer/react) installed, run:
1011

1112
```shell
1213
npm install --save-dev eslint-plugin-primer-react
@@ -16,7 +17,8 @@ ESLint rules for Primer React
1617
yarn add --dev eslint-plugin-primer-react
1718
```
1819

19-
2. In your [ESLint configuration file](https://eslint.org/docs/user-guide/configuring/configuration-files), extend the recommended Primer React ESLint config:
20+
2. In your [ESLint configuration file](https://eslint.org/docs/user-guide/configuring/configuration-files), extend the
21+
recommended Primer React ESLint config:
2022

2123
```js
2224
{

docs/rules/a11y-explicit-heading.md

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,47 @@
11
## Require explicit heading level on `<Heading>` component
22

3-
The `Heading` component does not require you to use `as` to specify the heading level, as it will default to an `h2` if one isn't specified. This may lead to inaccessible usage if the default is out of order in the existing heading hierarchy.
3+
The `Heading` component does not require you to use `as` to specify the heading level, as it will default to an `h2` if
4+
one isn't specified. This may lead to inaccessible usage if the default is out of order in the existing heading
5+
hierarchy.
46

57
## Rule Details
68

7-
This rule enforces using `as` on the `<Heading>` component to specify a heading level (`h1`-`h6`). In addition, it enforces `as` usage to only be used for headings.
9+
This rule enforces using `as` on the `<Heading>` component to specify a heading level (`h1`-`h6`). In addition, it
10+
enforces `as` usage to only be used for headings.
811

912
👎 Examples of **incorrect** code for this rule
1013

1114
```jsx
1215
import {Heading} from '@primer/react'
1316

14-
<Heading>Heading without explicit heading level</Heading>
17+
function ExampleComponent() {
18+
return <Heading>Heading without explicit heading level</Heading>
19+
}
1520
```
1621

1722
`as` must only be for headings (`h1`-`h6`)
1823

1924
```jsx
2025
import {Heading} from '@primer/react'
2126

22-
<Heading as="span">Heading component used as "span"</Heading>
27+
function ExampleComponent() {
28+
return <Heading as="span">Heading component used as "span"</Heading>
29+
}
2330
```
2431

2532
👍 Examples of **correct** code for this rule:
2633

2734
```jsx
28-
import {Heading} from '@primer/react';
35+
import {Heading} from '@primer/react'
2936

30-
<Heading as="h2">Heading level 2</Heading>
37+
function ExampleComponent() {
38+
return <Heading as="h2">Heading level 2</Heading>
39+
}
3140
```
3241

3342
## Options
3443

3544
- `skipImportCheck` (default: `false`)
3645

37-
By default, the `a11y-explicit-heading` rule will only check for `<Heading>` components imported directly from `@primer/react`. You can disable this behavior by setting `skipImportCheck` to `true`.
46+
By default, the `a11y-explicit-heading` rule will only check for `<Heading>` components imported directly from
47+
`@primer/react`. You can disable this behavior by setting `skipImportCheck` to `true`.

docs/rules/a11y-tooltip-interactive-trigger.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
## Rule Details
22

3-
This rule enforces to use interactive elements as tooltip triggers. Interactive elements can be Primer `Button`, `IconButton` and `Link` components or native elements like `button`, `a` with an `href` attribute, `select`, `textarea`, `summary` and `input` (that is not a `hidden` type).
3+
This rule enforces to use interactive elements as tooltip triggers. Interactive elements can be Primer `Button`,
4+
`IconButton` and `Link` components or native elements like `button`, `a` with an `href` attribute, `select`, `textarea`,
5+
`summary` and `input` (that is not a `hidden` type).
46

57
👎 Examples of **incorrect** code for this rule:
68

@@ -38,4 +40,6 @@ const App = () => (
3840

3941
- `skipImportCheck` (default: `false`)
4042

41-
By default, the `a11y-tooltip-interactive-trigger` rule will only check for interactive elements in components that are imported from `@primer/react`. You can disable this behavior by setting `skipImportCheck` to `true`. This is used for internal linting in the [primer/react](https://github.com/prime/react) repository.
43+
By default, the `a11y-tooltip-interactive-trigger` rule will only check for interactive elements in components that
44+
are imported from `@primer/react`. You can disable this behavior by setting `skipImportCheck` to `true`. This is used
45+
for internal linting in the [primer/react](https://github.com/prime/react) repository.

docs/rules/direct-slot-children.md

Lines changed: 49 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,49 @@
1-
# Enforce direct parent-child relationship of slot components (direct-slot-children)
2-
3-
Some Primer React components use a slots pattern under the hood to render subcomponents in specific places. For example, the `PageLayout` component renders `PageLayout.Header` in the header area, and `PageLayout.Footer` in the footer area. These subcomponents must be direct children of the parent component, and cannot be nested inside other components.
4-
5-
## Rule details
6-
7-
This rule enforces that slot components are direct children of their parent component.
8-
9-
👎 Examples of **incorrect** code for this rule:
10-
11-
```jsx
12-
/* eslint primer-react/direct-slot-children: "error" */
13-
import {PageLayout} from '@primer/react'
14-
15-
const MyHeader = () => <PageLayout.Header>Header</PageLayout.Header>
16-
17-
const App = () => (
18-
<PageLayout>
19-
<MyHeader />
20-
</PageLayout>
21-
)
22-
```
23-
24-
👍 Examples of **correct** code for this rule:
25-
26-
```jsx
27-
/* eslint primer-react/direct-slot-children: "error" */
28-
import {PageLayout} from '@primer/react'
29-
30-
const MyHeader = () => <div>Header</div>
31-
32-
const App = () => (
33-
<PageLayout>
34-
<PageLayout.Header>
35-
<MyHeader />
36-
</PageLayout.Header>
37-
</PageLayout>
38-
)
39-
```
40-
41-
## Options
42-
43-
- `skipImportCheck` (default: `false`)
44-
45-
By default, the `direct-slot-children` rule will only check for direct slot children in components that are imported from `@primer/react`. You can disable this behavior by setting `skipImportCheck` to `true`. This is used for internal linting in the [primer/react](https://github.com/prime/react) repository.
46-
1+
# Enforce direct parent-child relationship of slot components (direct-slot-children)
2+
3+
Some Primer React components use a slots pattern under the hood to render subcomponents in specific places. For example,
4+
the `PageLayout` component renders `PageLayout.Header` in the header area, and `PageLayout.Footer` in the footer area.
5+
These subcomponents must be direct children of the parent component, and cannot be nested inside other components.
6+
7+
## Rule details
8+
9+
This rule enforces that slot components are direct children of their parent component.
10+
11+
👎 Examples of **incorrect** code for this rule:
12+
13+
```jsx
14+
/* eslint primer-react/direct-slot-children: "error" */
15+
import {PageLayout} from '@primer/react'
16+
17+
const MyHeader = () => <PageLayout.Header>Header</PageLayout.Header>
18+
19+
const App = () => (
20+
<PageLayout>
21+
<MyHeader />
22+
</PageLayout>
23+
)
24+
```
25+
26+
👍 Examples of **correct** code for this rule:
27+
28+
```jsx
29+
/* eslint primer-react/direct-slot-children: "error" */
30+
import {PageLayout} from '@primer/react'
31+
32+
const MyHeader = () => <div>Header</div>
33+
34+
const App = () => (
35+
<PageLayout>
36+
<PageLayout.Header>
37+
<MyHeader />
38+
</PageLayout.Header>
39+
</PageLayout>
40+
)
41+
```
42+
43+
## Options
44+
45+
- `skipImportCheck` (default: `false`)
46+
47+
By default, the `direct-slot-children` rule will only check for direct slot children in components that are imported
48+
from `@primer/react`. You can disable this behavior by setting `skipImportCheck` to `true`. This is used for internal
49+
linting in the [primer/react](https://github.com/prime/react) repository.

docs/rules/new-css-color-vars.md

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,31 @@
11
## Upgrade legacy color CSS variables to Primitives v8 in sx prop
22

3-
CSS variables are allowed within the `sx` prop in Primer React components. However, the legacy color CSS variables are deprecated in favor of the new CSS variables introduced in Primitives v8. This rule will warn you if you are using the deprecated color CSS variables in the `sx` prop, and autofix it including a fallback to the old value.
3+
CSS variables are allowed within the `sx` prop in Primer React components. However, the legacy color CSS variables are
4+
deprecated in favor of the new CSS variables introduced in Primitives v8. This rule will warn you if you are using the
5+
deprecated color CSS variables in the `sx` prop, and autofix it including a fallback to the old value.
46

57
## Rule Details
68

79
This rule looks inside the `sx` prop for the following properties:
810

9-
```
10-
'bg',
11-
'backgroundColor',
12-
'color',
13-
'borderColor',
14-
'borderTopColor',
15-
'borderRightColor',
16-
'borderBottomColor',
17-
'borderLeftColor',
18-
'border',
19-
'boxShadow',
20-
'caretColor'
11+
```json
12+
[
13+
"bg",
14+
"backgroundColor",
15+
"color",
16+
"borderColor",
17+
"borderTopColor",
18+
"borderRightColor",
19+
"borderBottomColor",
20+
"borderLeftColor",
21+
"border",
22+
"boxShadow",
23+
"caretColor"
24+
]
2125
```
2226

23-
The rule references a static JSON file called `css-variable-map.json` that matches the old color CSS variables to a new one based on the property. We only check `sx` because `stylelint` is used to lint other forms of CSS-in-JS.
27+
The rule references a static JSON file called `css-variable-map.json` that matches the old color CSS variables to a new
28+
one based on the property. We only check `sx` because `stylelint` is used to lint other forms of CSS-in-JS.
2429

2530
👎 Examples of **incorrect** code for this rule
2631

0 commit comments

Comments
 (0)