@wsxjs/eslint-plugin-wsx
v0.0.17
Published
ESLint plugin for WSX Framework
Downloads
1,297
Maintainers
Readme
@wsxjs/eslint-plugin-wsx
ESLint plugin for WSX Framework - enforces best practices and framework-specific rules for Web Components with JSX.
Installation
npm install --save-dev @wsxjs/eslint-plugin-wsx
# or
pnpm add -D @wsxjs/eslint-plugin-wsx
# or
yarn add -D @wsxjs/eslint-plugin-wsxSetup
ESLint 9+ (Flat Config)
Create or update eslint.config.js (or eslint.config.mjs):
import js from "@eslint/js";
import typescript from "@typescript-eslint/eslint-plugin";
import typescriptParser from "@typescript-eslint/parser";
import wsxPlugin from "@wsxjs/eslint-plugin-wsx";
import globals from "globals";
export default [
{
ignores: ["**/dist/", "**/node_modules/"],
},
js.configs.recommended,
{
files: ["**/*.{ts,tsx,js,jsx,wsx}"],
languageOptions: {
parser: typescriptParser,
parserOptions: {
ecmaVersion: "latest",
sourceType: "module",
ecmaFeatures: {
jsx: true,
},
jsxPragma: "h",
jsxFragmentName: "Fragment",
experimentalDecorators: true, // Required for @state decorator
extraFileExtensions: [".wsx"],
},
globals: {
...globals.browser,
...globals.es2021,
h: "readonly",
Fragment: "readonly",
},
},
plugins: {
"@typescript-eslint": typescript,
wsx: wsxPlugin,
},
rules: {
...typescript.configs.recommended.rules,
"@typescript-eslint/no-explicit-any": "warn",
"@typescript-eslint/no-unused-vars": [
"error",
{
argsIgnorePattern: "^_",
varsIgnorePattern: "^_",
},
],
// WSX plugin rules
"wsx/render-method-required": "error",
"wsx/no-react-imports": "error",
"wsx/web-component-naming": "warn",
"wsx/state-requires-initial-value": "error",
"no-undef": "off", // TypeScript handles this
},
},
];Required Dependencies
Make sure you have these peer dependencies installed:
npm install --save-dev eslint @typescript-eslint/eslint-plugin @typescript-eslint/parser globalsImportant: The experimentalDecorators: true option in parserOptions is required for the wsx/state-requires-initial-value rule to work correctly. Without it, ESLint cannot parse @state decorators and the rule will not detect violations.
Rules
wsx/render-method-required
Error level: error
Ensures WSX components implement the required render() method.
Invalid:
class MyComponent extends WebComponent {
// Missing render() method
}Valid:
class MyComponent extends WebComponent {
render() {
return <div>Hello</div>;
}
}wsx/no-react-imports
Error level: error
Prevents React imports in WSX files. WSX uses its own JSX runtime.
Invalid:
import React from "react"; // ❌
import { useState } from "react"; // ❌Valid:
import { WebComponent, state } from "@wsxjs/wsx-core"; // ✅wsx/web-component-naming
Error level: warn
Enforces proper Web Component tag naming conventions (kebab-case with at least one hyphen).
Invalid:
@autoRegister({ tagName: "mycomponent" }) // ❌ Missing hyphen
@autoRegister({ tagName: "MyComponent" }) // ❌ Not kebab-caseValid:
@autoRegister({ tagName: "my-component" }) // ✅
@autoRegister({ tagName: "wsx-button" }) // ✅wsx/state-requires-initial-value
Error level: error
Requires @state decorator properties to have initial values. This is mandatory because:
- The Babel plugin needs the initial value to determine if it's a primitive (uses
useState) or object/array (usesreactive) - Without an initial value, the decorator cannot be properly transformed at compile time
- The runtime fallback also requires an initial value to set up reactive state correctly
Invalid:
class MyComponent extends WebComponent {
@state private maskStrokeColor?: string; // ❌ Missing initial value
@state private count; // ❌ Missing initial value
@state private user; // ❌ Missing initial value
}Valid:
class MyComponent extends WebComponent {
@state private maskStrokeColor = ""; // ✅ String
@state private count = 0; // ✅ Number
@state private enabled = false; // ✅ Boolean
@state private user = { name: "John" }; // ✅ Object
@state private items = []; // ✅ Array
@state private optional: string | undefined = undefined; // ✅ Optional with explicit undefined
@state private size?: number = 32; // ✅ Optional with default value
}Error Message Example:
@state decorator on property 'size' requires an initial value.
Examples:
@state private size = ''; // for string
@state private size = 0; // for number
@state private size = {}; // for object
@state private size = []; // for array
@state private size = undefined; // for optionalConfiguration Options
Disable Specific Rules
If you need to disable a specific rule:
{
rules: {
"wsx/web-component-naming": "off", // Disable naming rule
"wsx/state-requires-initial-value": "warn", // Change to warning
},
}File-Specific Rules
Apply rules only to .wsx files:
{
files: ["**/*.wsx"],
rules: {
"wsx/render-method-required": "error",
"wsx/no-react-imports": "error",
},
}Testing Results
✅ 38 tests passed with 100% code coverage ✅ Professional test suite using Jest and ESLint RuleTester ✅ Integration tests verify real-world usage scenarios
Test Coverage Summary
- Statements: 100%
- Branches: 96.96%
- Functions: 100%
- Lines: 100%
Better Testing Approach
This plugin now uses industry-standard testing practices:
1. Unit Tests with RuleTester
- Each rule has dedicated test files
- Valid/invalid code examples with expected errors
- Proper AST node testing
2. Integration Tests
- Full plugin functionality testing
- Real ESLint configuration scenarios
- Complex component examples
3. Comprehensive Coverage
- All rules tested with edge cases
- Error messages and fix suggestions verified
- Plugin structure and exports validated
Features
- 🔍 render-method-required: Ensures WSX components implement the required
render()method - 🚫 no-react-imports: Prevents React imports in WSX files
- 🏷️ web-component-naming: Enforces proper Web Component tag naming conventions
- ✅ state-requires-initial-value: Requires
@statedecorator properties to have initial values
Framework Integration
The examples package serves as a real-world testing environment where:
- The ESLint plugin is properly configured and tested
- All WSX components demonstrate correct framework usage
- Plugin rules catch actual coding errors in development
- Framework developers can validate plugin effectiveness
This approach ensures the plugin works correctly in production environments, not just in isolated tests.
