ESLint plugin providing comprehensive linting rules specifically designed for the Qwik framework with performance-focused development patterns
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Rules specifically for JSX patterns, React compatibility, and component best practices in Qwik.
Disallows React-specific className/htmlFor props and suggests Qwik alternatives.
/**
* Disallows React-specific className/htmlFor props with automatic code fixes
* Provides fix suggestions to convert to Qwik alternatives (class/for)
*/
noReactProps: Rule;
/**
* Utility function to check if a name is a DOM element using regex test
* @param name Element name to check
* @returns true if the name is a standard lowercase DOM element
*/
export function isDOMElementName(name: string): boolean;Rule Configuration:
Usage Example:
// ❌ Invalid: React-specific props
<div className="container" htmlFor="input-id"> // Error: use 'class' and 'for'
<label htmlFor="name">Name</label>
</div>
// ✅ Valid: Qwik props
<div class="container">
<label for="name">Name</label>
</div>Disallows missing key props in iterators and collection literals.
/**
* Disallows missing key props in iterators/collection literals
* Ensures proper key attribution for list rendering performance
*/
jsxKey: Rule;Rule Configuration:
Options Schema:
{
type: 'object',
properties: {
checkFragmentShorthand: {
type: 'boolean',
default: false
},
checkKeyMustBeforeSpread: {
type: 'boolean',
default: false
},
warnOnDuplicates: {
type: 'boolean',
default: false
}
},
additionalProperties: false
}Usage Example:
// ❌ Invalid: missing key props
const items = ['a', 'b', 'c'];
<div>
{items.map(item => <span>{item}</span>)} // Error: missing key
</div>
// ✅ Valid: proper key props
<div>
{items.map((item, index) => <span key={index}>{item}</span>)}
</div>Enforces width and height attributes for img elements to prevent layout shifts.
/**
* Enforces width and height attributes for img elements
* Prevents layout shifts by requiring dimensions for performance
*/
jsxImg: Rule;Rule Configuration:
Usage Example:
// ❌ Invalid: missing dimensions
<img src="/image.jpg" alt="Description" /> // Error: missing width/height
// ✅ Valid: proper dimensions
<img src="/image.jpg" alt="Description" width="300" height="200" />Enforces href attribute for anchor elements for SEO optimization.
/**
* Enforces href attribute for anchor elements for SEO
* Ensures proper link semantics for search engine optimization
*/
jsxAtag: Rule;Rule Configuration:
Usage Example:
// ❌ Invalid: missing href
<a onClick$={() => navigate('/page')}>Link</a> // Error: missing href
// ✅ Valid: proper href attribute
<a href="/page" onClick$={() => navigate('/page')}>Link</a>Disallows javascript: URLs in JSX attributes for security.
/**
* Disallows javascript: URLs in JSX attributes
* Prevents potential security vulnerabilities from inline JavaScript
*/
jsxNoScriptUrl: Rule;Rule Configuration:
Usage Example:
// ❌ Invalid: javascript: URL
<a href="javascript:alert('xss')">Click</a> // Error: javascript: URL not allowed
// ✅ Valid: proper URL or event handler
<a href="/page" onClick$={() => alert('safe')}>Click</a>Image Loading:
width and height attributes for imagesList Rendering:
key props for array itemsLink Semantics:
href attributes for anchor tagsScript URL Prevention:
javascript: URLs in href attributesProp Name Conversion: The plugin helps migrate from React by detecting and fixing React-specific prop names:
| React Prop | Qwik Prop | Usage |
|---|---|---|
className | class | CSS class assignment |
htmlFor | for | Label association |
Migration Example:
// React style (invalid in Qwik)
<label className="field-label" htmlFor="username">
Username
</label>
// Qwik style (valid)
<label class="field-label" for="username">
Username
</label>The JSX rules integrate with the plugin's example system for documentation generation:
// Example type definitions for rule documentation
interface QwikEslintExample {
code: string;
codeTitle?: string;
codeHighlight?: string;
description?: string;
}
interface QwikEslintExamples {
[scenario: string]: {
good?: QwikEslintExample[];
bad?: QwikEslintExample[];
};
}
// Available examples (exported from examples.ts)
const noReactPropsExamples: QwikEslintExamples;
const jsxNoScriptUrlExamples: QwikEslintExamples;
const jsxKeyExamples: QwikEslintExamples;
const jsxImgExamples: QwikEslintExamples;// JSX rule definitions (standardized to TSESLint)
type Rule = TSESLint.RuleModule<any, any>;
// DOM element validation
type DOMElementNames = 'div' | 'span' | 'img' | 'a' | 'label' | 'input' | 'button' | /* ... */;
// JSX attribute types
interface JSXAttribute {
type: 'JSXAttribute';
name: JSXIdentifier | JSXNamespacedName;
value: JSXExpressionContainer | Literal | null;
}
interface JSXIdentifier {
type: 'JSXIdentifier';
name: string;
}
// Example system types
interface QwikEslintExample {
code: string;
codeTitle?: string;
codeHighlight?: string;
description?: string;
}
interface QwikEslintExamples {
[scenario: string]: {
good?: QwikEslintExample[];
bad?: QwikEslintExample[];
};
}