npm package: @lms5400/eslint-plugin-rsx
Description: ESLint rules for RSX components
Latest version: 1.1.0

# @lms5400/eslint-plugin-rsx

ESLint rules for **RSX components**.

RSX files use JSX syntax but **do not follow React’s runtime or hook model**.  
This plugin enforces RSX-specific semantics while remaining compatible with React projects.

See https://github.com/LMS007/babel-plugin-rsx

---

## What this plugin enforces

RSX components are **not React components**. This plugin helps enforce that distinction by:

- Disallowing React hooks (`useState`, `useEffect`, etc.)
- Disallowing `useRef`
- Requiring RSX context destructuring
- Allowing JSX syntax

---

## Requirements

- **ESLint ≥ 8.57** (flat config)
- Node.js ≥ 18
- [babel-plugin-rsx](https://www.npmjs.com/package/@lms5400/babel-plugin-rsx/)

---

## Installation
npm
```bash
npm install --save-dev eslint @lms5400/eslint-plugin-rsx
```
Or yarn
```bash
yarn add -D eslint @lms5400/eslint-plugin-rsx
```

---

## Basic setup (React + RSX)

This setup assumes:
- `.jsx / .tsx` files use normal React rules
- `.rsx` files use RSX rules
- ESLint flat config is enabled

### eslint.config.js (or eslint.config.cjs)

```js
import js from "@eslint/js";
import globals from "globals";
import react from "eslint-plugin-react";
import reactHooks from "eslint-plugin-react-hooks";
import rsx from "@lms5400/eslint-plugin-rsx";

export default [
  // ----------------------------------------
  // React JSX / TSX files
  // ----------------------------------------
  {
    files: ["**/*.{jsx,tsx}"],
    plugins: {
      react,
      "react-hooks": reactHooks,
    },
    rules: {
      // React + hooks rules
    },
  },

  // ----------------------------------------
  // RSX files
  // ----------------------------------------
  {
    files: ["**/*.rsx"],
    plugins: {
      rsx,
    },
    languageOptions: {
      ecmaVersion: "latest",
      sourceType: "module",
      globals: {
        ...globals.browser,
        ...globals.node,
      },
      parserOptions: {
        ecmaFeatures: { jsx: true },
      },
    },
    rules: {
      // Base JS rules
      ...js.configs.recommended,
      // RSX rules
      ...rsx.configs.recommended
    },
  },
];
```

---

## Why React rules are not applied to `.rsx`

RSX files:
- may contain JSX
- do **not** use React hooks
- do **not** rely on React reconciliation
- have explicit lifecycle management

Applying `eslint-plugin-react` rules to `.rsx` files often produces **incorrect or misleading errors**.

If you want minimal JSX hygiene, you may selectively enable rules like:
- `react/jsx-no-undef`
- `react/jsx-uses-vars`

Full React recommended rules are **not advised** for RSX.

---

## VS Code setup (required)

The ESLint VS Code extension does **not** automatically lint custom extensions like `.rsx`.

Add the following to your workspace settings.

### .vscode/settings.json

```json
{
  "eslint.useFlatConfig": true,
  "eslint.validate": [
    "javascript",
    "javascriptreact",
  ],
  "files.associations": {
    "*.rsx": "javascriptreact"
  },
  "eslint.nodePath": "./node_modules"
}
```

After changing settings:
1. Open Command Palette
2. Run **“ESLint: Restart ESLint Server”**
3. Reload the window if needed

---

## Verifying the setup

Create a test RSX file:

```js
export default function Test(ctx) {
  useState(0);
}
```

Expected:
- ❌ ESLint error
- Rule: `rsx/no-react-hooks`
- Visible inline and in the Problems panel

---

## Rules

| Rule | Description |
|------|-------------|
| `rsx/no-react-hooks` | Disallow React hooks in RSX |
| `rsx/no-use-ref` | Disallow `useRef` |
| `rsx/require-ctx-destructure` | Require RSX context destructuring |
| `rsx/jsx-uses-vars` | Mark JSX components as used (prevents false-positive `no-unused-vars` errors) |


---

## Design philosophy

- RSX is explicit and lifecycle-driven
- JSX is syntax, not a runtime commitment
- Linting should enforce RSX semantics, not React assumptions

---

## License

MIT