@codelaw/rules-js 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/NOTICE +0 -9
  2. package/README.md +14 -47
  3. package/codelaw-pack.toml +3 -3
  4. package/corpus.toml +76 -0
  5. package/package.json +2 -2
  6. package/presets/js/conventions.toml +0 -4
  7. package/presets/js/project.toml +4 -0
  8. package/presets/js/typescript.toml +7 -0
  9. package/data/node/deprecated-api.json +0 -83
  10. package/data/react/dom-property-aliases.json +0 -131
  11. package/presets/node/recommended.toml +0 -13
  12. package/presets/react/recommended.toml +0 -22
  13. package/presets/stencil/recommended.toml +0 -18
  14. package/presets/ts/recommended.toml +0 -27
  15. package/rules/node/hashbang.md +0 -71
  16. package/rules/node/no-deprecated-api.md +0 -91
  17. package/rules/node/no-exports-assign.md +0 -92
  18. package/rules/node/no-extraneous-import.md +0 -118
  19. package/rules/node/no-extraneous-require.md +0 -117
  20. package/rules/node/no-missing-import.md +0 -118
  21. package/rules/node/no-missing-require.md +0 -117
  22. package/rules/node/no-process-exit.md +0 -99
  23. package/rules/node/no-unpublished-import.md +0 -134
  24. package/rules/node/no-unpublished-require.md +0 -133
  25. package/rules/react/display-name.md +0 -91
  26. package/rules/react/exhaustive-deps.md +0 -116
  27. package/rules/react/hook-prefix.md +0 -108
  28. package/rules/react/jsx-key.md +0 -99
  29. package/rules/react/jsx-no-comment-textnodes.md +0 -87
  30. package/rules/react/jsx-no-duplicate-props.md +0 -66
  31. package/rules/react/jsx-no-target-blank.md +0 -78
  32. package/rules/react/jsx-no-undef.md +0 -78
  33. package/rules/react/no-children-prop.md +0 -80
  34. package/rules/react/no-danger-with-children.md +0 -83
  35. package/rules/react/no-deprecated.md +0 -84
  36. package/rules/react/no-direct-mutation-state.md +0 -102
  37. package/rules/react/no-find-dom-node.md +0 -72
  38. package/rules/react/no-is-mounted.md +0 -109
  39. package/rules/react/no-render-return-value.md +0 -75
  40. package/rules/react/no-string-refs.md +0 -72
  41. package/rules/react/no-unescaped-entities.md +0 -69
  42. package/rules/react/no-unknown-property.md +0 -69
  43. package/rules/react/props-type-name.md +0 -43
  44. package/rules/react/require-render-return.md +0 -91
  45. package/rules/react/rules-of-hooks.md +0 -128
  46. package/rules/stencil/ban-default-true.md +0 -70
  47. package/rules/stencil/ban-exported-const-enums.md +0 -60
  48. package/rules/stencil/ban-prefix.md +0 -76
  49. package/rules/stencil/decorators-context.md +0 -61
  50. package/rules/stencil/host-data-deprecated.md +0 -73
  51. package/rules/stencil/methods-must-be-public.md +0 -69
  52. package/rules/stencil/no-unused-watch.md +0 -68
  53. package/rules/stencil/own-methods-must-be-private.md +0 -68
  54. package/rules/stencil/own-props-must-be-private.md +0 -60
  55. package/rules/stencil/prefer-vdom-listener.md +0 -67
  56. package/rules/stencil/prop-readonly.md +0 -63
  57. package/rules/stencil/props-must-be-public.md +0 -68
  58. package/rules/stencil/required-jsdoc.md +0 -66
  59. package/rules/stencil/reserved-member-names.md +0 -70
  60. package/rules/stencil/strict-mutable.md +0 -75
  61. package/rules/stencil/tag-prefix.md +0 -75
  62. package/rules/ts/ban-ts-comment.md +0 -64
  63. package/rules/ts/no-array-constructor.md +0 -58
  64. package/rules/ts/no-duplicate-enum-values.md +0 -65
  65. package/rules/ts/no-empty-object-type.md +0 -65
  66. package/rules/ts/no-explicit-any.md +0 -61
  67. package/rules/ts/no-extra-non-null-assertion.md +0 -50
  68. package/rules/ts/no-misused-new.md +0 -70
  69. package/rules/ts/no-namespace.md +0 -65
  70. package/rules/ts/no-non-null-asserted-optional-chain.md +0 -55
  71. package/rules/ts/no-require-imports.md +0 -54
  72. package/rules/ts/no-this-alias.md +0 -68
  73. package/rules/ts/no-unnecessary-type-constraint.md +0 -64
  74. package/rules/ts/no-unsafe-declaration-merging.md +0 -73
  75. package/rules/ts/no-unsafe-function-type.md +0 -57
  76. package/rules/ts/no-unused-expressions.md +0 -61
  77. package/rules/ts/no-unused-vars.md +0 -68
  78. package/rules/ts/no-wrapper-object-types.md +0 -49
  79. package/rules/ts/prefer-as-const.md +0 -47
  80. package/rules/ts/prefer-namespace-keyword.md +0 -63
  81. package/rules/ts/triple-slash-reference.md +0 -60
  82. package/rules/ts/type-only-imports.md +0 -57
@@ -1,99 +0,0 @@
1
- ---
2
- id: react/jsx-key
3
- title: "Elements in an array or a map() callback have a key"
4
- languages: [javascript, jsx, tsx]
5
- fix: manual
6
- fix_reason: "the key must be a stable identity of the item, which only the author knows"
7
- stability: preview
8
- ported_from: [eslint-plugin-react/jsx-key]
9
- since: 0.1.0
10
- ---
11
-
12
- An element written in an array literal, or returned by a `.map()` callback, has a `key` prop.
13
-
14
- **Why:** Without keys, React can't match list items between renders, which loses state and re-
15
- renders more than it must.
16
-
17
- ```codelaw
18
- match:
19
- any:
20
- - kind: jsx_element
21
- - kind: jsx_self_closing_element
22
- not:
23
- any:
24
- - has: { stopBy: neighbor, kind: jsx_attribute, regex: '^key\b' }
25
- - has: { field: open_tag, has: { stopBy: neighbor, kind: jsx_attribute, regex: '^key\b' } }
26
- - has: { stopBy: neighbor, kind: jsx_expression, regex: '^\{\s*\.\.\.' }
27
- - has: { field: open_tag, has: { stopBy: neighbor, kind: jsx_expression, regex: '^\{\s*\.\.\.' } }
28
- inside:
29
- stopBy: neighbor
30
- any:
31
- - kind: array
32
- - kind: arrow_function
33
- inside:
34
- stopBy: neighbor
35
- kind: arguments
36
- inside: { stopBy: neighbor, kind: call_expression, has: { field: function, kind: member_expression, regex: '\.map$' } }
37
- - kind: parenthesized_expression
38
- inside:
39
- stopBy: neighbor
40
- kind: arrow_function
41
- inside:
42
- stopBy: neighbor
43
- kind: arguments
44
- inside: { stopBy: neighbor, kind: call_expression, has: { field: function, kind: member_expression, regex: '\.map$' } }
45
- message: "An element in a list needs a `key` so React can tell its items apart"
46
- ```
47
-
48
- ## How to fix
49
-
50
- 1. Give the element a `key` that identifies the item, such as its id.
51
- 2. Avoid the array index if items can be reordered or removed.
52
-
53
- ## Examples
54
-
55
- ### JavaScript
56
-
57
- #### Don't
58
-
59
- ```js
60
- const items = todos.map((todo) => <li>{todo.text}</li>);
61
- ```
62
-
63
- #### Do
64
-
65
- ```js
66
- const items = todos.map((todo) => <li key={todo.id}>{todo.text}</li>);
67
- ```
68
-
69
- ### JSX
70
-
71
- #### Don't
72
-
73
- ```jsx
74
- const items = todos.map((todo) => <li>{todo.text}</li>);
75
- ```
76
-
77
- #### Do
78
-
79
- ```jsx
80
- const items = todos.map((todo) => <li key={todo.id}>{todo.text}</li>);
81
- ```
82
-
83
- ### TSX
84
-
85
- #### Don't
86
-
87
- ```tsx
88
- const items = todos.map((todo) => <li>{todo.text}</li>);
89
- ```
90
-
91
- #### Do
92
-
93
- ```tsx
94
- const items = todos.map((todo) => <li key={todo.id}>{todo.text}</li>);
95
- ```
96
-
97
- ## Differences from the source
98
-
99
- Elements returned from a `.map()` callback's block body (`return <li/>`) are not checked yet.
@@ -1,87 +0,0 @@
1
- ---
2
- id: react/jsx-no-comment-textnodes
3
- title: "No comment syntax as text inside JSX"
4
- languages: [javascript, jsx, tsx]
5
- fix: manual
6
- fix_reason: "whether the text is a comment or content needs the author"
7
- stability: preview
8
- ported_from: [eslint-plugin-react/jsx-no-comment-textnodes]
9
- since: 0.1.0
10
- ---
11
-
12
- Comments inside JSX are written as `{/* … */}`; `// …` and `/* … */` in JSX text are not.
13
-
14
- **Why:** In JSX, `// note` is text that ends up on the page.
15
-
16
- ```codelaw
17
- match:
18
- kind: jsx_text
19
- regex: ^\s*(//|/\*)
20
- message: "This is rendered as text, not a comment; write `{/* … */}`"
21
- ```
22
-
23
- ## How to fix
24
-
25
- 1. Wrap the comment in braces: `{/* … */}`.
26
-
27
- ## Examples
28
-
29
- ### JavaScript
30
-
31
- #### Don't
32
-
33
- ```js
34
- const a = <div>
35
- // the title
36
- <h1>Hi</h1>
37
- </div>;
38
- ```
39
-
40
- #### Do
41
-
42
- ```js
43
- const a = <div>
44
- {/* the title */}
45
- <h1>Hi</h1>
46
- </div>;
47
- ```
48
-
49
- ### JSX
50
-
51
- #### Don't
52
-
53
- ```jsx
54
- const a = <div>
55
- // the title
56
- <h1>Hi</h1>
57
- </div>;
58
- ```
59
-
60
- #### Do
61
-
62
- ```jsx
63
- const a = <div>
64
- {/* the title */}
65
- <h1>Hi</h1>
66
- </div>;
67
- ```
68
-
69
- ### TSX
70
-
71
- #### Don't
72
-
73
- ```tsx
74
- const a = <div>
75
- // the title
76
- <h1>Hi</h1>
77
- </div>;
78
- ```
79
-
80
- #### Do
81
-
82
- ```tsx
83
- const a = <div>
84
- {/* the title */}
85
- <h1>Hi</h1>
86
- </div>;
87
- ```
@@ -1,66 +0,0 @@
1
- ---
2
- id: react/jsx-no-duplicate-props
3
- title: "No prop given twice on one element"
4
- languages: [javascript, jsx, tsx]
5
- fix: manual
6
- fix_reason: "which value should win needs the author"
7
- stability: preview
8
- ported_from: [eslint-plugin-react/jsx-no-duplicate-props]
9
- since: 0.1.0
10
- ---
11
-
12
- A JSX element gives each prop once.
13
-
14
- **Why:** The last value silently wins, so the first is dead code or a mistake.
15
-
16
- ```codelaw
17
- native: react/jsx-no-duplicate-props
18
- ```
19
-
20
- ## How to fix
21
-
22
- 1. Keep the value that is right and remove the other.
23
-
24
- ## Examples
25
-
26
- ### JavaScript
27
-
28
- #### Don't
29
-
30
- ```js
31
- const a = <input type="text" type="email" />;
32
- ```
33
-
34
- #### Do
35
-
36
- ```js
37
- const a = <input type="email" />;
38
- ```
39
-
40
- ### JSX
41
-
42
- #### Don't
43
-
44
- ```jsx
45
- const a = <input type="text" type="email" />;
46
- ```
47
-
48
- #### Do
49
-
50
- ```jsx
51
- const a = <input type="email" />;
52
- ```
53
-
54
- ### TSX
55
-
56
- #### Don't
57
-
58
- ```tsx
59
- const a = <input type="text" type="email" />;
60
- ```
61
-
62
- #### Do
63
-
64
- ```tsx
65
- const a = <input type="email" />;
66
- ```
@@ -1,78 +0,0 @@
1
- ---
2
- id: react/jsx-no-target-blank
3
- title: "Links that open a new tab set rel=\"noreferrer\""
4
- languages: [javascript, jsx, tsx]
5
- fix: auto
6
- stability: preview
7
- ported_from: [eslint-plugin-react/jsx-no-target-blank]
8
- since: 0.1.0
9
- ---
10
-
11
- An `<a target="_blank">` with an `href` also has `rel="noreferrer"`.
12
-
13
- **Why:** Without it, older browsers give the opened page a handle on this one (`window.opener`), and
14
- the referrer leaks.
15
-
16
- ```codelaw
17
- match:
18
- kind: jsx_attribute
19
- regex: ^target=["']_blank["']$
20
- inside:
21
- stopBy: neighbor
22
- any: [{ kind: jsx_opening_element }, { kind: jsx_self_closing_element }]
23
- all:
24
- - has: { field: name, regex: ^a$ }
25
- - has: { stopBy: neighbor, kind: jsx_attribute, regex: ^href= }
26
- - not: { has: { stopBy: neighbor, kind: jsx_attribute, regex: ^rel= } }
27
- message: "A link with `target=\"_blank\"` gives the new page access to this one; add `rel=\"noreferrer\"`"
28
- fix:
29
- - insert-after: ' rel="noreferrer"'
30
- ```
31
-
32
- ## Examples
33
-
34
- ### JavaScript
35
-
36
- #### Don't
37
-
38
- ```js
39
- const a = <a href={url} target="_blank">Docs</a>;
40
- ```
41
-
42
- #### Do
43
-
44
- ```js
45
- const a = <a href={url} target="_blank" rel="noreferrer">Docs</a>;
46
- ```
47
-
48
- ### JSX
49
-
50
- #### Don't
51
-
52
- ```jsx
53
- const a = <a href={url} target="_blank">Docs</a>;
54
- ```
55
-
56
- #### Do
57
-
58
- ```jsx
59
- const a = <a href={url} target="_blank" rel="noreferrer">Docs</a>;
60
- ```
61
-
62
- ### TSX
63
-
64
- #### Don't
65
-
66
- ```tsx
67
- const a = <a href={url} target="_blank">Docs</a>;
68
- ```
69
-
70
- #### Do
71
-
72
- ```tsx
73
- const a = <a href={url} target="_blank" rel="noreferrer">Docs</a>;
74
- ```
75
-
76
- ## Differences from the source
77
-
78
- A link that already has a `rel` is not checked.
@@ -1,78 +0,0 @@
1
- ---
2
- id: react/jsx-no-undef
3
- title: "Components used in JSX are declared"
4
- languages: [javascript, jsx, tsx]
5
- fix: manual
6
- fix_reason: "the right import is the author's to choose"
7
- stability: preview
8
- ported_from: [eslint-plugin-react/jsx-no-undef]
9
- since: 0.1.0
10
- ---
11
-
12
- Every component used as a JSX tag is imported or declared.
13
-
14
- **Why:** An undeclared component throws a ReferenceError when it renders.
15
-
16
- ```codelaw
17
- match:
18
- kind: identifier
19
- regex: ^[A-Z]
20
- inside:
21
- stopBy: neighbor
22
- any: [{ kind: jsx_opening_element }, { kind: jsx_self_closing_element }]
23
- field: name
24
- where:
25
- $$MATCH: undeclared
26
- message: "`$$MATCH` is not defined; import or declare the component"
27
- ```
28
-
29
- ## How to fix
30
-
31
- 1. Import the component, or declare it, or correct the name.
32
-
33
- ## Examples
34
-
35
- ### JavaScript
36
-
37
- #### Don't
38
-
39
- ```js
40
- export const App = () => <Header />;
41
- ```
42
-
43
- #### Do
44
-
45
- ```js
46
- import { Header } from "./header";
47
- export const App = () => <Header />;
48
- ```
49
-
50
- ### JSX
51
-
52
- #### Don't
53
-
54
- ```jsx
55
- export const App = () => <Header />;
56
- ```
57
-
58
- #### Do
59
-
60
- ```jsx
61
- import { Header } from "./header";
62
- export const App = () => <Header />;
63
- ```
64
-
65
- ### TSX
66
-
67
- #### Don't
68
-
69
- ```tsx
70
- export const App = () => <Header />;
71
- ```
72
-
73
- #### Do
74
-
75
- ```tsx
76
- import { Header } from "./header";
77
- export const App = () => <Header />;
78
- ```
@@ -1,80 +0,0 @@
1
- ---
2
- id: react/no-children-prop
3
- title: "Children are passed as children, not as a prop"
4
- languages: [javascript, jsx, tsx]
5
- fix: manual
6
- fix_reason: "moving the children changes the element's shape by hand"
7
- stability: preview
8
- ported_from: [eslint-plugin-react/no-children-prop]
9
- since: 0.1.0
10
- ---
11
-
12
- Children go between an element's tags (or as the third argument of `createElement`), not in a
13
- `children` prop.
14
-
15
- **Why:** Passing `children` as a prop works, but hides the element's content where readers don't
16
- look for it.
17
-
18
- ```codelaw
19
- match:
20
- any:
21
- - kind: jsx_attribute
22
- regex: ^children\b
23
- - pattern: 'createElement($T, { children: $C, $$$REST })'
24
- - pattern: 'React.createElement($T, { children: $C, $$$REST })'
25
- message: "Pass children between the tags, not as the `children` prop"
26
- ```
27
-
28
- ## How to fix
29
-
30
- 1. Move the value between the opening and closing tags.
31
-
32
- ## Examples
33
-
34
- ### JavaScript
35
-
36
- #### Don't
37
-
38
- ```js
39
- const a = <Panel children={<p>Hi</p>} />;
40
- ```
41
-
42
- #### Do
43
-
44
- ```js
45
- const a = <Panel>
46
- <p>Hi</p>
47
- </Panel>;
48
- ```
49
-
50
- ### JSX
51
-
52
- #### Don't
53
-
54
- ```jsx
55
- const a = <Panel children={<p>Hi</p>} />;
56
- ```
57
-
58
- #### Do
59
-
60
- ```jsx
61
- const a = <Panel>
62
- <p>Hi</p>
63
- </Panel>;
64
- ```
65
-
66
- ### TSX
67
-
68
- #### Don't
69
-
70
- ```tsx
71
- const a = <Panel children={<p>Hi</p>} />;
72
- ```
73
-
74
- #### Do
75
-
76
- ```tsx
77
- const a = <Panel>
78
- <p>Hi</p>
79
- </Panel>;
80
- ```
@@ -1,83 +0,0 @@
1
- ---
2
- id: react/no-danger-with-children
3
- title: "No dangerouslySetInnerHTML together with children"
4
- languages: [javascript, jsx, tsx]
5
- fix: manual
6
- fix_reason: "which content the element should have needs the author"
7
- stability: preview
8
- ported_from: [eslint-plugin-react/no-danger-with-children]
9
- since: 0.1.0
10
- ---
11
-
12
- An element with `dangerouslySetInnerHTML` has no children.
13
-
14
- **Why:** React throws when an element has both, since it can't know which content wins.
15
-
16
- ```codelaw
17
- match:
18
- any:
19
- - kind: jsx_element
20
- all:
21
- - has: { field: open_tag, has: { stopBy: neighbor, kind: jsx_attribute, regex: ^dangerouslySetInnerHTML } }
22
- - has:
23
- stopBy: neighbor
24
- any:
25
- - kind: jsx_element
26
- - kind: jsx_self_closing_element
27
- - kind: jsx_expression
28
- - kind: jsx_text
29
- regex: \S
30
- - kind: jsx_self_closing_element
31
- all:
32
- - has: { stopBy: neighbor, kind: jsx_attribute, regex: ^dangerouslySetInnerHTML }
33
- - has: { stopBy: neighbor, kind: jsx_attribute, regex: ^children\b }
34
- message: "An element can't have both `dangerouslySetInnerHTML` and children"
35
- ```
36
-
37
- ## How to fix
38
-
39
- 1. Keep either the HTML or the children, not both.
40
-
41
- ## Examples
42
-
43
- ### JavaScript
44
-
45
- #### Don't
46
-
47
- ```js
48
- const a = <div dangerouslySetInnerHTML={{ __html: html }}>Fallback</div>;
49
- ```
50
-
51
- #### Do
52
-
53
- ```js
54
- const a = <div dangerouslySetInnerHTML={{ __html: html }} />;
55
- ```
56
-
57
- ### JSX
58
-
59
- #### Don't
60
-
61
- ```jsx
62
- const a = <div dangerouslySetInnerHTML={{ __html: html }}>Fallback</div>;
63
- ```
64
-
65
- #### Do
66
-
67
- ```jsx
68
- const a = <div dangerouslySetInnerHTML={{ __html: html }} />;
69
- ```
70
-
71
- ### TSX
72
-
73
- #### Don't
74
-
75
- ```tsx
76
- const a = <div dangerouslySetInnerHTML={{ __html: html }}>Fallback</div>;
77
- ```
78
-
79
- #### Do
80
-
81
- ```tsx
82
- const a = <div dangerouslySetInnerHTML={{ __html: html }} />;
83
- ```
@@ -1,84 +0,0 @@
1
- ---
2
- id: react/no-deprecated
3
- title: "No deprecated React APIs"
4
- languages: [javascript, jsx, tsx]
5
- fix: manual
6
- fix_reason: "each deprecated API has its own replacement"
7
- stability: preview
8
- ported_from: [eslint-plugin-react/no-deprecated]
9
- since: 0.1.0
10
- ---
11
-
12
- Code doesn't use React APIs that are deprecated: the legacy `componentWill…` lifecycles,
13
- `React.createClass`, `React.PropTypes`, `ReactDOM.render`, `hydrate` and `unmountComponentAtNode`.
14
-
15
- **Why:** Deprecated APIs are removed in later versions, and the legacy lifecycles misbehave with
16
- concurrent rendering.
17
-
18
- ```codelaw
19
- match:
20
- any:
21
- - kind: method_definition
22
- has: { field: name, regex: ^(componentWillMount|componentWillReceiveProps|componentWillUpdate)$ }
23
- - pattern: React.createClass($$$A)
24
- - pattern: React.PropTypes
25
- - pattern: ReactDOM.render($$$A)
26
- - pattern: ReactDOM.hydrate($$$A)
27
- - pattern: ReactDOM.unmountComponentAtNode($$$A)
28
- - pattern: ReactDOMServer.renderToNodeStream($$$A)
29
- message: "This React API is deprecated and is removed in a later version"
30
- ```
31
-
32
- ## How to fix
33
-
34
- 1. Replace `ReactDOM.render` with `createRoot(el).render(…)` and `hydrate` with `hydrateRoot`.
35
- 2. Rename legacy lifecycles to their `UNSAFE_` names, or move their work to `componentDidMount`/`componentDidUpdate`.
36
- 3. Use the `prop-types` package instead of `React.PropTypes`.
37
-
38
- ## Examples
39
-
40
- ### JavaScript
41
-
42
- #### Don't
43
-
44
- ```js
45
- ReactDOM.render(<App />, root);
46
- ```
47
-
48
- #### Do
49
-
50
- ```js
51
- createRoot(root).render(<App />);
52
- ```
53
-
54
- ### JSX
55
-
56
- #### Don't
57
-
58
- ```jsx
59
- ReactDOM.render(<App />, root);
60
- ```
61
-
62
- #### Do
63
-
64
- ```jsx
65
- createRoot(root).render(<App />);
66
- ```
67
-
68
- ### TSX
69
-
70
- #### Don't
71
-
72
- ```tsx
73
- ReactDOM.render(<App />, root);
74
- ```
75
-
76
- #### Do
77
-
78
- ```tsx
79
- createRoot(root).render(<App />);
80
- ```
81
-
82
- ## Differences from the source
83
-
84
- The React version setting is not read: every listed API is reported.