@neralabs/rerail-pack-react 0.1.2 → 0.1.4

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.
package/README.md CHANGED
@@ -1,12 +1,21 @@
1
1
  # Rerail rule pack: React
2
2
 
3
- Ports of eslint-plugin-react 7.37.5 and eslint-plugin-react-hooks 7.1.1 rules. A port starts in `candidates/rules/`
4
- and moves to `rules/` and `pack.json` once it passes the V1 rule validation gates
5
- ([nera-rule-validation](https://github.com/neralabs/nera-rule-validation)). While `pack.json` lists no rules, the pack
6
- ships none and is never recommended. Every port is scored against the plugins' own findings on the plugins' test cases
7
- and the pinned corpus, through the engine's production workspace path. The conformance check (`--check`, run in CI)
8
- scores the test cases only: it gates the ports in `rules/` and reports the candidates without gating them. The corpus
9
- is scored on demand, with `--pack react --corpus excalidraw`.
3
+ Ports of eslint-plugin-react 7.37.5 and eslint-plugin-react-hooks 7.1.1 rules. A port starts in `candidates/rules/` and
4
+ moves to `rules/` and `pack.json` once it passes the [port readiness gates](../../docs/port-readiness.md), which CI runs on every
5
+ port. While `pack.json` lists no rules, the pack ships none and is never recommended. Every port is scored against the
6
+ plugins' own findings on the plugins' test cases and the pinned corpus, through the engine's production workspace path.
7
+ The conformance check (`--check`, run in CI) scores the test cases only: it gates the ports in `rules/` and reports the
8
+ candidates without gating them. The corpus is scored on demand, with `--pack react --corpus excalidraw`.
9
+
10
+ Every rule runs on JavaScript and TypeScript files whose JSX runtime is React or not known; a file whose JSX belongs to
11
+ another library is skipped. The runtime is the file's `@jsxImportSource` pragma when it names React, Emotion
12
+ (`@emotion/react`) or Theme UI (React) or Preact, Solid, Vue, Stencil, Hono, Qwik, Inferno, Mithril or Hyperapp (another
13
+ library), or its `@jsx` pragma when that names `React`; else an `h` or `createElement` imported from Stencil, Preact,
14
+ Vue, Solid, Hyperapp or Mithril (another library); else its nearest `package.json`: React when it depends on react,
15
+ react-dom, react-native or next and on none of vue, @stencil/core, preact, solid-js, @builder.io/qwik, inferno or
16
+ mithril, another library in the reverse case, unknown otherwise. `react-in-jsx-scope` also skips files whose `@jsx`
17
+ pragma names another factory (Emotion's `jsx`, for one): the plugin then asks for that factory in scope, which the
18
+ port does not check.
10
19
 
11
20
  The pack follows the [pack structure and validation contract](../../docs/pack-format.md): it is checked by
12
21
  `npx vitest run test/engine/catalog/packs.test.ts -t "pack react"`.
@@ -15,7 +24,8 @@ The pack follows the [pack structure and validation contract](../../docs/pack-fo
15
24
  |---|---|
16
25
  | `pack.json` | The pack (`rerail.rule-pack/v1`): its match definition, and no rules until a port passes |
17
26
  | `conformance.json` | Every port (shipped under `rules/`, or a candidate under `candidates/rules/`): its upstream tool and rule, how findings compare and the capabilities it exercises; the pinned tools and the pinned corpus (excalidraw). Written by `candidates/build.mjs` |
18
- | `upstream/<tool>/` | The plugin's copied tests (`tests/`), the cases extracted from them (`fixtures/`), its recordings (`fixtures.expected.json`, `corpus-excalidraw.expected.json`) and the recorder (`generate.mjs`, sharing `upstream/common.mjs` and `conformance/recorders/eslint-record.mjs`) |
27
+ | `upstream/<tool>/` | The plugin's copied tests (`tests/`), the cases extracted from them (`fixtures/`), its recordings (`fixtures.expected.json`, `corpus-excalidraw.expected.json`) and the recorder (`generate.mjs`, sharing `upstream/common.mjs` and `conformance/recorders/eslint-record.mjs`); `UPSTREAM.md` lists the fixtures Rerail wrote beside them (`common.mjs` `AUTHORED`): files of other JSX libraries, which the plugins report and the ports skip, and React files whose JSX goes through Emotion, which both report |
28
+ | `divergences.json` | Where the ports and the recordings disagree by design: the plugins' findings on the authored files of other JSX libraries |
19
29
  | `licenses/<project>/` | The upstream licence and `UPSTREAM.md`, listing every copied file and extracted case |
20
30
  | `candidates/` | Ports still being evaluated, scored but never shipped: the code-rule documents (`rules/`, written by `build.mjs` from `specs.mjs`, except the hand-written `react-no-array-index-key.json`); `probes/` holds the hand-labelled React fact probes |
21
31
 
@@ -35,3 +45,87 @@ every false positive and false negative printed:
35
45
  node candidates/build.mjs
36
46
  node --import tsx conformance/languages/cli.ts --pack react --rule react-jsx-key --fixtures
37
47
  ```
48
+
49
+ ## Rule details
50
+
51
+ What each rule matches beyond its one-line description: exact matching, edge cases, upstream settings and known divergences.
52
+
53
+ ### `react-button-has-type`
54
+
55
+ Port of eslint-plugin-react 7.37.5 react/button-has-type with button, submit and reset allowed. Reports a `<button>` with no `type` attribute (looked up case-insensitively, as jsx-ast-utils getProp does) or whose first `type` value is not a literal button/submit/reset. Each leaf of a conditional `type` is checked, and a non-literal leaf is reported at itself. The same applies to `React.createElement('button', props)` with the default pragma.
56
+
57
+ ### `react-hooks-exhaustive-deps`
58
+
59
+ Port of eslint-plugin-react-hooks 7.1.1 react-hooks/exhaustive-deps, missing-dependency report only (no unnecessary/duplicate-dependency reports). Checks the dependency array literal of useEffect, useLayoutEffect, useInsertionEffect, useCallback and useMemo (bare or as `React.*`) when the inline callback reads a name bound in the calling function (outside the callback) that no dependency's root names. useState/useReducer setters and dispatchers, useRef, useEffectEvent and useTransition results count as stable and need not be listed.
60
+
61
+ ### `react-hooks-rules-of-hooks`
62
+
63
+ Port of eslint-plugin-react-hooks 7.1.1 react-hooks/rules-of-hooks. A hook call (`use`, `useX`, `Namespace.useX`) is reported at its callee when it runs, in a component or hook (a function named `X…`/`useX`, or the callback of memo/forwardRef), conditionally (if/conditional/logical/switch/catch/default branch, or after an earlier return); in a class method or field; in another named function; at the top level; in an anonymous callback inside a component or hook; in a loop; in an async component or hook; and `use` inside try/catch. ESLint's code-path analysis is approximated syntactically.
64
+
65
+ ### `react-jsx-key`
66
+
67
+ Port of eslint-plugin-react 7.37.5 react/jsx-key, default options. Reports an element (not a fragment) without `key` that is an array literal's element, or that a `.map(fn)` / `.from(x, fn)` callback returns: the arrow's body, a branch of its conditional body, the right side of its logical body, or a return statement directly in the callback body or in nested if/else branches. Never reported inside `React.Children.toArray(...)` / `Children.toArray(...)`.
68
+
69
+ ### `react-jsx-no-comment-textnodes`
70
+
71
+ Port of eslint-plugin-react 7.37.5 react/jsx-no-comment-textnodes: JSX text with a line that starts (after whitespace) with `//` or `/*`.
72
+
73
+ ### `react-jsx-no-duplicate-props`
74
+
75
+ Port of eslint-plugin-react 7.37.5 react/jsx-no-duplicate-props, case-sensitive. Namespaced attribute names and spreads are skipped.
76
+
77
+ ### `react-jsx-no-target-blank`
78
+
79
+ Port of eslint-plugin-react 7.37.5 react/jsx-no-target-blank with default options (links only, enforceDynamicLinks always, allowReferrer false). Reports an `<a>` whose last `target` is possibly `_blank` (a string, or a conditional with a `_blank` branch), with an external last `href` string (`scheme:` or `//`) or any `href` expression, and whose last `rel` does not give `noreferrer` on every value it may take (a string, the first quasi of a template, both branches of a conditional, or, when target and rel test the same name, the branch on which target is `_blank`).
80
+
81
+ ### `react-jsx-no-undef`
82
+
83
+ Port of eslint-plugin-react 7.37.5 react/jsx-no-undef (allowGlobals: false, module code). Checks a non-DOM JSX tag name, or the root of a member tag name, against file-local bindings; globals, even configured ones, do not count in a module.
84
+
85
+ ### `react-no-children-prop`
86
+
87
+ Port of eslint-plugin-react 7.37.5 react/no-children-prop (allowFunctions: false): a `children` JSX attribute, and a createElement call (default pragma) whose second argument is an object literal with a `children` key.
88
+
89
+ ### `react-no-danger`
90
+
91
+ Port of eslint-plugin-react 7.37.5 react/no-danger, default options. Only DOM elements (tag name starting lower-case, per jsx-ast-utils elementType) are checked; custom components receiving the prop are not reported.
92
+
93
+ ### `react-no-danger-with-children`
94
+
95
+ Port of eslint-plugin-react 7.37.5 react/no-danger-with-children. Children means a first child that is not a line break, or a `children` prop. Props are also read through `{...name}` spreads of a variable initialised with an object literal. For `x.createElement(type, props, ...)`, props may be an object literal or a variable initialised with one, and children is a third argument or a `children` prop.
96
+
97
+ ### `react-no-direct-mutation-state`
98
+
99
+ Port of eslint-plugin-react 7.37.5 react/no-direct-mutation-state. Reports an assignment or update whose target is a member chain rooted at `this.state`, inside a class component (nearest class extends Component / PureComponent / React.Component / React.PureComponent) or a function that is a property of the object passed to createReactClass. In a constructor it is reported only when inside a call. Reported at `this`. Function components (the plugin's Components.detect stateless detection) are not modelled.
100
+
101
+ ### `react-no-find-dom-node`
102
+
103
+ Port of eslint-plugin-react 7.37.5 react/no-find-dom-node: any call whose callee is `findDOMNode` or a member `.findDOMNode`.
104
+
105
+ ### `react-no-is-mounted`
106
+
107
+ Port of eslint-plugin-react 7.37.5 react/no-is-mounted: `this.isMounted()` inside an object property or a method (ESTree Property / MethodDefinition ancestor).
108
+
109
+ ### `react-no-render-return-value`
110
+
111
+ Port of eslint-plugin-react 7.37.5 react/no-render-return-value (latest React). The value counts as used when the call's parent (parentheses aside) is a declarator, a property, a return, an arrow body or an assignment.
112
+
113
+ ### `react-no-string-refs`
114
+
115
+ Port of eslint-plugin-react 7.37.5 react/no-string-refs (latest React, noTemplateLiterals: false): a `ref` attribute whose value is a string literal, bare or in braces. Template literals are not reported. From React 18.3 on the plugin no longer reports `this.refs` reads, so neither does the port.
116
+
117
+ ### `react-no-unescaped-entities`
118
+
119
+ Port of eslint-plugin-react 7.37.5 react/no-unescaped-entities (forbids >, ", ', }). One finding per such character, but only on the first line of a JSX text node (the k-th check holds where that line has at least k of them; ESLint reports each character at its own column). Characters on a text node's later lines are not reported, because a finding is anchored at a node and a text node has no node per line.
120
+
121
+ ### `react-react-in-jsx-scope`
122
+
123
+ Port of eslint-plugin-react 7.37.5 react/react-in-jsx-scope (pragma React). A JSX opening element or fragment is reported when no `React` binding is visible: none declared at the top level (import, var/let/const, function), in an enclosing block's own declarations, or as an enclosing function's parameter.
124
+
125
+ ### `react-self-closing-comp`
126
+
127
+ Port of eslint-plugin-react 7.37.5 react/self-closing-comp (component: true, html: true). Reports an element with a closing tag and no children except whitespace that contains a line break (a same-line space is text and is not reported). Namespaced tags only when lower-case (DOM).
128
+
129
+ ### `react-void-dom-elements-no-children`
130
+
131
+ Port of eslint-plugin-react 7.37.5 react/void-dom-elements-no-children. Void elements: area, base, br, col, embed, hr, img, input, keygen, link, menuitem, meta, param, source, track, wbr. Reports children, a `children` attribute or a `dangerouslySetInnerHTML` attribute (one report each); the same through createElement with an object-literal props argument.