CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-eslint-plugin-qwik

ESLint plugin providing comprehensive linting rules specifically designed for the Qwik framework with performance-focused development patterns

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

jsx-rules.mddocs/

JSX and Component Rules

Rules specifically for JSX patterns, React compatibility, and component best practices in Qwik.

Capabilities

No React Props

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:

  • Type: problem rule with code fixes
  • Category: JSX
  • Recommended: error level
  • Strict: error level

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>

JSX Key

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:

  • Type: problem rule
  • Category: JSX
  • Recommended: warn level
  • Strict: error level

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>

JSX Image

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:

  • Type: problem rule
  • Category: JSX
  • Recommended: warn level
  • Strict: error level

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" />

JSX Anchor

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:

  • Type: problem rule
  • Category: JSX
  • Recommended: warn level
  • Strict: error level

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>

JSX No Script URL

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:

  • Type: problem rule
  • Category: JSX
  • Recommended: warn level
  • Strict: error level

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>

JSX Best Practices

Performance Optimization

Image Loading:

  • Always provide width and height attributes for images
  • Prevents Cumulative Layout Shift (CLS) issues
  • Improves Core Web Vitals scoring

List Rendering:

  • Use unique key props for array items
  • Enables efficient re-rendering and DOM reconciliation
  • Improves application performance with dynamic lists

SEO Optimization

Link Semantics:

  • Always provide href attributes for anchor tags
  • Ensures proper crawling by search engines
  • Maintains accessibility for screen readers and keyboard navigation

Security Considerations

Script URL Prevention:

  • Avoid javascript: URLs in href attributes
  • Prevents potential XSS vulnerabilities
  • Use proper event handlers instead of inline JavaScript

React Migration

Prop Name Conversion: The plugin helps migrate from React by detecting and fixing React-specific prop names:

React PropQwik PropUsage
classNameclassCSS class assignment
htmlForforLabel 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>

Rule Examples Integration

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;

Types

// 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[];
  };
}

docs

configuration.md

core-rules.md

index.md

jsx-rules.md

quality-rules.md

tile.json