@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,102 +0,0 @@
1
- ---
2
- id: react/no-direct-mutation-state
3
- title: "No assigning to this.state outside the constructor"
4
- languages: [javascript, jsx, tsx]
5
- fix: manual
6
- fix_reason: "the update has to be rewritten as a `setState` call"
7
- stability: preview
8
- ported_from: [eslint-plugin-react/no-direct-mutation-state]
9
- since: 0.1.0
10
- ---
11
-
12
- A class component changes its state with `this.setState`, never by assigning to `this.state` outside
13
- the constructor.
14
-
15
- **Why:** A direct assignment doesn't trigger a re-render, and a later `setState` may overwrite it.
16
-
17
- ```codelaw
18
- match:
19
- kind: assignment_expression
20
- has:
21
- field: left
22
- regex: ^this\.state\b
23
- not:
24
- inside:
25
- kind: method_definition
26
- has: { field: name, regex: ^constructor$ }
27
- stopBy: end
28
- inside: { kind: class_body, stopBy: end }
29
- message: "Assigning to `this.state` doesn't re-render; call `this.setState`"
30
- ```
31
-
32
- ## How to fix
33
-
34
- 1. Replace the assignment with `this.setState(…)`; use the updater form when the new state depends on the old.
35
-
36
- ## Examples
37
-
38
- ### JavaScript
39
-
40
- #### Don't
41
-
42
- ```js
43
- class Counter extends React.Component {
44
- inc() {
45
- this.state.count = this.state.count + 1;
46
- }
47
- }
48
- ```
49
-
50
- #### Do
51
-
52
- ```js
53
- class Counter extends React.Component {
54
- inc() {
55
- this.setState((s) => ({ count: s.count + 1 }));
56
- }
57
- }
58
- ```
59
-
60
- ### JSX
61
-
62
- #### Don't
63
-
64
- ```jsx
65
- class Counter extends React.Component {
66
- inc() {
67
- this.state.count = this.state.count + 1;
68
- }
69
- }
70
- ```
71
-
72
- #### Do
73
-
74
- ```jsx
75
- class Counter extends React.Component {
76
- inc() {
77
- this.setState((s) => ({ count: s.count + 1 }));
78
- }
79
- }
80
- ```
81
-
82
- ### TSX
83
-
84
- #### Don't
85
-
86
- ```tsx
87
- class Counter extends React.Component {
88
- inc() {
89
- this.state.count = this.state.count + 1;
90
- }
91
- }
92
- ```
93
-
94
- #### Do
95
-
96
- ```tsx
97
- class Counter extends React.Component {
98
- inc() {
99
- this.setState((s) => ({ count: s.count + 1 }));
100
- }
101
- }
102
- ```
@@ -1,72 +0,0 @@
1
- ---
2
- id: react/no-find-dom-node
3
- title: "No findDOMNode"
4
- languages: [javascript, jsx, tsx]
5
- fix: manual
6
- fix_reason: "a ref has to be attached to the right element by hand"
7
- stability: preview
8
- ported_from: [eslint-plugin-react/no-find-dom-node]
9
- since: 0.1.0
10
- ---
11
-
12
- Code doesn't call `findDOMNode`.
13
-
14
- **Why:** `findDOMNode` breaks component abstraction, doesn't work with function components, and is
15
- removed in React 19.
16
-
17
- ```codelaw
18
- match:
19
- any:
20
- - pattern: findDOMNode($$$A)
21
- - pattern: $R.findDOMNode($$$A)
22
- message: "`findDOMNode` is deprecated; use a ref"
23
- ```
24
-
25
- ## How to fix
26
-
27
- 1. Attach a ref to the element you need (`ref={this.ref}`).
28
- 2. Read `ref.current` instead of calling `findDOMNode`.
29
-
30
- ## Examples
31
-
32
- ### JavaScript
33
-
34
- #### Don't
35
-
36
- ```js
37
- const el = ReactDOM.findDOMNode(this);
38
- ```
39
-
40
- #### Do
41
-
42
- ```js
43
- const el = this.ref.current;
44
- ```
45
-
46
- ### JSX
47
-
48
- #### Don't
49
-
50
- ```jsx
51
- const el = ReactDOM.findDOMNode(this);
52
- ```
53
-
54
- #### Do
55
-
56
- ```jsx
57
- const el = this.ref.current;
58
- ```
59
-
60
- ### TSX
61
-
62
- #### Don't
63
-
64
- ```tsx
65
- const el = ReactDOM.findDOMNode(this);
66
- ```
67
-
68
- #### Do
69
-
70
- ```tsx
71
- const el = this.ref.current;
72
- ```
@@ -1,109 +0,0 @@
1
- ---
2
- id: react/no-is-mounted
3
- title: "No this.isMounted()"
4
- languages: [javascript, jsx, tsx]
5
- fix: manual
6
- fix_reason: "the callback has to be cancelled where it starts"
7
- stability: preview
8
- ported_from: [eslint-plugin-react/no-is-mounted]
9
- since: 0.1.0
10
- ---
11
-
12
- Code doesn't call `this.isMounted()`.
13
-
14
- **Why:** `isMounted` hides leaks: a callback that outlives the component should be cancelled
15
- instead.
16
-
17
- ```codelaw
18
- match:
19
- pattern: this.isMounted()
20
- message: "`isMounted` is an anti-pattern and gone from ES6 classes"
21
- ```
22
-
23
- ## How to fix
24
-
25
- 1. Cancel pending work in `componentWillUnmount`.
26
- 2. Remove the `isMounted` check.
27
-
28
- ## Examples
29
-
30
- ### JavaScript
31
-
32
- #### Don't
33
-
34
- ```js
35
- class A extends React.Component {
36
- done() {
37
- if (this.isMounted()) {
38
- this.setState({ ok: true });
39
- }
40
- }
41
- }
42
- ```
43
-
44
- #### Do
45
-
46
- ```js
47
- class A extends React.Component {
48
- componentWillUnmount() {
49
- this.request.cancel();
50
- }
51
- done() {
52
- this.setState({ ok: true });
53
- }
54
- }
55
- ```
56
-
57
- ### JSX
58
-
59
- #### Don't
60
-
61
- ```jsx
62
- class A extends React.Component {
63
- done() {
64
- if (this.isMounted()) {
65
- this.setState({ ok: true });
66
- }
67
- }
68
- }
69
- ```
70
-
71
- #### Do
72
-
73
- ```jsx
74
- class A extends React.Component {
75
- componentWillUnmount() {
76
- this.request.cancel();
77
- }
78
- done() {
79
- this.setState({ ok: true });
80
- }
81
- }
82
- ```
83
-
84
- ### TSX
85
-
86
- #### Don't
87
-
88
- ```tsx
89
- class A extends React.Component {
90
- done() {
91
- if (this.isMounted()) {
92
- this.setState({ ok: true });
93
- }
94
- }
95
- }
96
- ```
97
-
98
- #### Do
99
-
100
- ```tsx
101
- class A extends React.Component {
102
- componentWillUnmount() {
103
- this.request.cancel();
104
- }
105
- done() {
106
- this.setState({ ok: true });
107
- }
108
- }
109
- ```
@@ -1,75 +0,0 @@
1
- ---
2
- id: react/no-render-return-value
3
- title: "The return value of ReactDOM.render is not used"
4
- languages: [javascript, jsx, tsx]
5
- fix: manual
6
- fix_reason: "code that used the instance needs a ref instead"
7
- stability: preview
8
- ported_from: [eslint-plugin-react/no-render-return-value]
9
- since: 0.1.0
10
- ---
11
-
12
- The value `ReactDOM.render` returns is not stored, returned or passed on.
13
-
14
- **Why:** It's a legacy handle that is `null` in some cases and gone in newer APIs.
15
-
16
- ```codelaw
17
- match:
18
- pattern: ReactDOM.render($$$A)
19
- inside:
20
- stopBy: neighbor
21
- any:
22
- - kind: variable_declarator
23
- - kind: return_statement
24
- - kind: assignment_expression
25
- - kind: arguments
26
- message: "Don't use what `ReactDOM.render` returns; use a ref"
27
- ```
28
-
29
- ## How to fix
30
-
31
- 1. Pass a ref to the root element and use it instead of the return value.
32
-
33
- ## Examples
34
-
35
- ### JavaScript
36
-
37
- #### Don't
38
-
39
- ```js
40
- const app = ReactDOM.render(<App />, root);
41
- ```
42
-
43
- #### Do
44
-
45
- ```js
46
- ReactDOM.render(<App ref={appRef} />, root);
47
- ```
48
-
49
- ### JSX
50
-
51
- #### Don't
52
-
53
- ```jsx
54
- const app = ReactDOM.render(<App />, root);
55
- ```
56
-
57
- #### Do
58
-
59
- ```jsx
60
- ReactDOM.render(<App ref={appRef} />, root);
61
- ```
62
-
63
- ### TSX
64
-
65
- #### Don't
66
-
67
- ```tsx
68
- const app = ReactDOM.render(<App />, root);
69
- ```
70
-
71
- #### Do
72
-
73
- ```tsx
74
- ReactDOM.render(<App ref={appRef} />, root);
75
- ```
@@ -1,72 +0,0 @@
1
- ---
2
- id: react/no-string-refs
3
- title: "No string refs"
4
- languages: [javascript, jsx, tsx]
5
- fix: manual
6
- fix_reason: "the ref object has to be created where the component can reach it"
7
- stability: preview
8
- ported_from: [eslint-plugin-react/no-string-refs]
9
- since: 0.1.0
10
- ---
11
-
12
- Refs are objects or callbacks, never strings (`ref="input"`, `this.refs.input`).
13
-
14
- **Why:** String refs are legacy, slow, and removed in React 19.
15
-
16
- ```codelaw
17
- match:
18
- any:
19
- - kind: jsx_attribute
20
- regex: ^ref=["']
21
- - pattern: this.refs.$X
22
- message: "String refs are legacy; use `useRef`, `createRef` or a callback ref"
23
- ```
24
-
25
- ## How to fix
26
-
27
- 1. Create a ref with `useRef` or `createRef`.
28
- 2. Pass it as `ref={…}` and read `.current`.
29
-
30
- ## Examples
31
-
32
- ### JavaScript
33
-
34
- #### Don't
35
-
36
- ```js
37
- const a = <input ref="name" />;
38
- ```
39
-
40
- #### Do
41
-
42
- ```js
43
- const a = <input ref={nameRef} />;
44
- ```
45
-
46
- ### JSX
47
-
48
- #### Don't
49
-
50
- ```jsx
51
- const a = <input ref="name" />;
52
- ```
53
-
54
- #### Do
55
-
56
- ```jsx
57
- const a = <input ref={nameRef} />;
58
- ```
59
-
60
- ### TSX
61
-
62
- #### Don't
63
-
64
- ```tsx
65
- const a = <input ref="name" />;
66
- ```
67
-
68
- #### Do
69
-
70
- ```tsx
71
- const a = <input ref={nameRef} />;
72
- ```
@@ -1,69 +0,0 @@
1
- ---
2
- id: react/no-unescaped-entities
3
- title: "No unescaped >, \", ' or } in JSX text"
4
- languages: [javascript, jsx, tsx]
5
- fix: manual
6
- fix_reason: "the right escape depends on the character and the author's style"
7
- stability: preview
8
- ported_from: [eslint-plugin-react/no-unescaped-entities]
9
- since: 0.1.0
10
- ---
11
-
12
- JSX text doesn't contain `>`, `"`, `'` or `}` unescaped.
13
-
14
- **Why:** These characters are easy to misread as markup or code, and a stray `}` is usually a typo.
15
-
16
- ```codelaw
17
- match:
18
- kind: jsx_text
19
- regex: '[>"''}]'
20
- message: "Escape this character in JSX text, e.g. `&apos;` or `{\"'\"}`"
21
- ```
22
-
23
- ## How to fix
24
-
25
- 1. Use an HTML entity (`&apos;`, `&quot;`, `&gt;`) or a string expression (`{"'"}`).
26
-
27
- ## Examples
28
-
29
- ### JavaScript
30
-
31
- #### Don't
32
-
33
- ```js
34
- const a = <p>Don't stop</p>;
35
- ```
36
-
37
- #### Do
38
-
39
- ```js
40
- const a = <p>Don&apos;t stop</p>;
41
- ```
42
-
43
- ### JSX
44
-
45
- #### Don't
46
-
47
- ```jsx
48
- const a = <p>Don't stop</p>;
49
- ```
50
-
51
- #### Do
52
-
53
- ```jsx
54
- const a = <p>Don&apos;t stop</p>;
55
- ```
56
-
57
- ### TSX
58
-
59
- #### Don't
60
-
61
- ```tsx
62
- const a = <p>Don't stop</p>;
63
- ```
64
-
65
- #### Do
66
-
67
- ```tsx
68
- const a = <p>Don&apos;t stop</p>;
69
- ```
@@ -1,69 +0,0 @@
1
- ---
2
- id: react/no-unknown-property
3
- title: "DOM elements use React's prop names, not HTML attribute names"
4
- languages: [javascript, jsx, tsx]
5
- fix: auto
6
- stability: preview
7
- ported_from: [eslint-plugin-react/no-unknown-property]
8
- since: 0.1.0
9
- ---
10
-
11
- A DOM element in JSX uses React's names for attributes: `className` not `class`, `htmlFor` not
12
- `for`, `onClick` not `onclick`, `tabIndex` not `tabindex`.
13
-
14
- **Why:** React ignores or warns about the HTML spellings, so the attribute silently does nothing.
15
-
16
- ```codelaw
17
- native: react/no-unknown-property
18
- ```
19
-
20
- ## Examples
21
-
22
- ### JavaScript
23
-
24
- #### Don't
25
-
26
- ```js
27
- const a = <input tabindex="1" onclick={go} />;
28
- ```
29
-
30
- #### Do
31
-
32
- ```js
33
- const a = <input tabIndex="1" onClick={go} />;
34
- ```
35
-
36
- ### JSX
37
-
38
- #### Don't
39
-
40
- ```jsx
41
- const a = <input tabindex="1" onclick={go} />;
42
- ```
43
-
44
- #### Do
45
-
46
- ```jsx
47
- const a = <input tabIndex="1" onClick={go} />;
48
- ```
49
-
50
- ### TSX
51
-
52
- #### Don't
53
-
54
- ```tsx
55
- const a = <label class="x" for="name" onclick={go}>Name</label>;
56
- ```
57
-
58
- #### Do
59
-
60
- ```tsx
61
- const a = <label className="x" htmlFor="name" onClick={go}>Name</label>;
62
- ```
63
-
64
- ## Differences from the source
65
-
66
- Only HTML spellings React renames are checked (the pack's `react/dom-property-aliases` data table);
67
- unknown attributes in general are not. In `.js` and `.jsx` files the JavaScript grammar can't parse
68
- `class=` and `for=` as JSX attributes (they are reserved words), so those two are found only in
69
- `.tsx`.
@@ -1,43 +0,0 @@
1
- ---
2
- id: react/props-type-name
3
- title: "A component's props type is named <Component>Props"
4
- languages: [tsx]
5
- fix: suggest
6
- fix_reason: "renaming a type other files import would break them, so it is offered, not applied"
7
- stability: preview
8
- since: 0.1.0
9
- ---
10
-
11
- The type of a component's props is named after the component: `CardProps` for `Card`.
12
-
13
- **Why:** One naming pattern makes props types easy to find and import.
14
-
15
- ```codelaw
16
- native: react/props-type-name
17
- ```
18
-
19
- ## Examples
20
-
21
- ### TSX
22
-
23
- #### Don't
24
-
25
- ```tsx
26
- type CardOptions = { title: string };
27
- export function Card(props: CardOptions) {
28
- return <h2>{props.title}</h2>;
29
- }
30
- ```
31
-
32
- #### Do
33
-
34
- ```tsx
35
- type CardProps = { title: string };
36
- export function Card(props: CardProps) {
37
- return <h2>{props.title}</h2>;
38
- }
39
- ```
40
-
41
- ## Differences from the source
42
-
43
- The type is renamed with its uses in the file; an exported type is reported without a fix.
@@ -1,91 +0,0 @@
1
- ---
2
- id: react/require-render-return
3
- title: "A class component's render() returns"
4
- languages: [javascript, jsx, tsx]
5
- fix: manual
6
- fix_reason: "what to render needs the author"
7
- stability: preview
8
- ported_from: [eslint-plugin-react/require-render-return]
9
- since: 0.1.0
10
- ---
11
-
12
- The `render()` method of a class component returns a value on every path.
13
-
14
- **Why:** A `render()` that falls off its end returns `undefined`, which is almost always a forgotten
15
- `return`.
16
-
17
- ```codelaw
18
- native: react/require-render-return
19
- ```
20
-
21
- ## How to fix
22
-
23
- 1. Return the element, or `null` to render nothing, on every path.
24
-
25
- ## Examples
26
-
27
- ### JavaScript
28
-
29
- #### Don't
30
-
31
- ```js
32
- class Title extends React.Component {
33
- render() {
34
- <h1>{this.props.text}</h1>;
35
- }
36
- }
37
- ```
38
-
39
- #### Do
40
-
41
- ```js
42
- class Title extends React.Component {
43
- render() {
44
- return <h1>{this.props.text}</h1>;
45
- }
46
- }
47
- ```
48
-
49
- ### JSX
50
-
51
- #### Don't
52
-
53
- ```jsx
54
- class Title extends React.Component {
55
- render() {
56
- <h1>{this.props.text}</h1>;
57
- }
58
- }
59
- ```
60
-
61
- #### Do
62
-
63
- ```jsx
64
- class Title extends React.Component {
65
- render() {
66
- return <h1>{this.props.text}</h1>;
67
- }
68
- }
69
- ```
70
-
71
- ### TSX
72
-
73
- #### Don't
74
-
75
- ```tsx
76
- class Title extends React.Component {
77
- render() {
78
- <h1>{this.props.text}</h1>;
79
- }
80
- }
81
- ```
82
-
83
- #### Do
84
-
85
- ```tsx
86
- class Title extends React.Component {
87
- render() {
88
- return <h1>{this.props.text}</h1>;
89
- }
90
- }
91
- ```