CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-eslint-plugin-unicorn

More than 100 powerful ESLint rules for enforcing code quality, consistency, and modern JavaScript best practices

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

code-style-rules.mddocs/

Code Style Rules

Rules for consistent code formatting, naming conventions, and stylistic preferences that improve code readability.

Capabilities

Naming and Case Conventions

Rules enforcing consistent naming patterns across the codebase.

/**
 * Enforces filename case conventions
 */
'unicorn/filename-case': 'error' | 'warn' | 'off' | [
  'error' | 'warn',
  {
    case?: 'camelCase' | 'kebabCase' | 'pascalCase' | 'snakeCase'; // Default: 'kebabCase'
    ignore?: (string | RegExp)[]; // Default: []
    multipleFileExtensions?: boolean; // Default: true
  }
];

/**
 * Prevents abbreviations in variable and function names
 */
'unicorn/prevent-abbreviations': 'error' | 'warn' | 'off' | [
  'error' | 'warn',
  {
    checkDefaultAndNamespaceImports?: boolean; // Default: false
    checkShorthandImports?: boolean; // Default: false
    checkShorthandProperties?: boolean; // Default: false
    checkVariables?: boolean; // Default: true
    checkProperties?: boolean; // Default: false
    checkFilenames?: boolean; // Default: false
    extendDefaultReplacements?: boolean; // Default: true
    replacements?: Record<string, Record<string, boolean>>;
    extendDefaultAllowList?: boolean; // Default: true
    allowList?: Record<string, boolean>;
    ignore?: (string | RegExp)[];
  }
];

/**
 * Prevents keyword prefixes in identifiers
 */
'unicorn/no-keyword-prefix': 'error' | 'warn' | 'off' | [
  'error' | 'warn',
  {
    onlyCamelCase?: boolean; // Default: false
    checkProperties?: boolean; // Default: false
    disallowedPrefixes?: string[]; // Default: ['new', 'for', 'class']
  }
];

Usage Examples:

// ❌ Bad - inconsistent filename cases
// myComponent.js (should be my-component.js with kebab-case)
// MyService.js (should be my-service.js with kebab-case)

// ✅ Good - consistent kebab-case filenames
// my-component.js
// user-service.js
// data-processor.js

// ❌ Bad - abbreviations
const btn = document.querySelector('button');
const userInfo = getUserInfo();
const temp = calculateTemperature();

// ✅ Good - full words
const button = document.querySelector('button');
const userInformation = getUserInformation();
const temperature = calculateTemperature();

// ❌ Bad - keyword prefixes
const newUser = 'John';
const className = 'active';

// ✅ Good - avoiding keyword prefixes
const user = 'John';
const cssClass = 'active';

Spacing and Formatting Rules

Rules for consistent spacing and formatting patterns.

/**
 * Enforces consistent empty brace spacing
 */
'unicorn/empty-brace-spaces': 'error' | 'warn' | 'off';

/**
 * Enforces consistent console spacing
 */
'unicorn/no-console-spaces': 'error' | 'warn' | 'off';

/**
 * Enforces proper template literal indentation
 */
'unicorn/template-indent': 'error' | 'warn' | 'off' | [
  'error' | 'warn',
  {
    indent?: string | number; // Default: detect from context
    tags?: string[]; // Default: []
    functions?: string[]; // Default: []
    selectors?: string[]; // Default: []
    comments?: string[]; // Default: []
  }
];

Usage Examples:

// ❌ Bad - inconsistent brace spacing
const obj = { };
if (condition) { }

// ✅ Good - consistent brace spacing
const obj = {};
if (condition) {}

// ❌ Bad - console spacing
console.log( 'message' );

// ✅ Good - no extra console spacing
console.log('message');

// ❌ Bad - template literal indentation
const html = `
<div>
<p>Content</p>
</div>
`;

// ✅ Good - proper template literal indentation
const html = `
  <div>
    <p>Content</p>
  </div>
`;

Case and Format Rules

Rules enforcing consistent case formatting for various constructs.

/**
 * Enforces consistent escape sequence case
 */
'unicorn/escape-case': 'error' | 'warn' | 'off';

/**
 * Enforces consistent number literal case
 */
'unicorn/number-literal-case': 'error' | 'warn' | 'off';

/**
 * Enforces consistent text encoding identifier case
 */
'unicorn/text-encoding-identifier-case': 'error' | 'warn' | 'off';

/**
 * Enforces consistent numeric separators style
 */
'unicorn/numeric-separators-style': 'error' | 'warn' | 'off' | [
  'error' | 'warn',
  {
    hexadecimal?: {
      minimumDigits?: number; // Default: 0
      groupLength?: number; // Default: 2
    };
    binary?: {
      minimumDigits?: number; // Default: 0
      groupLength?: number; // Default: 4
    };
    octal?: {
      minimumDigits?: number; // Default: 0
      groupLength?: number; // Default: 4
    };
    number?: {
      minimumDigits?: number; // Default: 5
      groupLength?: number; // Default: 3
    };
  }
];

Usage Examples:

// ❌ Bad - inconsistent escape case
const path = 'c:\\users\\documents';

// ✅ Good - consistent escape case
const path = 'C:\\Users\\Documents';

// ❌ Bad - inconsistent number literal case
const hex = 0xabc;
const scientific = 1e10;

// ✅ Good - consistent number literal case
const hex = 0xABC;
const scientific = 1E10;

// ❌ Bad - missing numeric separators
const largeNumber = 1000000;
const hexNumber = 0x1234567890abcdef;

// ✅ Good - using numeric separators
const largeNumber = 1_000_000;
const hexNumber = 0x12_34_56_78_90_ab_cd_ef;

Switch and Brace Style Rules

Rules for consistent switch statement and brace formatting.

/**
 * Enforces consistent switch case brace style
 */
'unicorn/switch-case-braces': 'error' | 'warn' | 'off' | [
  'error' | 'warn',
  'always' | 'avoid',
  {
    allowSingleLineStatement?: boolean; // Default: true
  }
];

/**
 * Prevents useless switch cases
 */
'unicorn/no-useless-switch-case': 'error' | 'warn' | 'off';

Usage Examples:

// ❌ Bad - inconsistent switch case braces
switch (value) {
  case 'a':
    doSomething();
    break;
  case 'b': {
    doSomethingElse();
    break;
  }
}

// ✅ Good - consistent switch case braces
switch (value) {
  case 'a': {
    doSomething();
    break;
  }
  case 'b': {
    doSomethingElse();
    break;
  }
}

// ❌ Bad - useless switch case
switch (value) {
  case 'a':
    return 'a';
  default:
    return value;
}

// ✅ Good - simplified logic
return value === 'a' ? 'a' : value;

String Content Rules

Rules for consistent string content and formatting.

/**
 * Enforces consistent string content rules
 */
'unicorn/string-content': 'error' | 'warn' | 'off' | [
  'error' | 'warn',
  {
    patterns?: Record<string, string | {
      suggest: string;
      message?: string;
      fix?: boolean;
    }>;
  }
];

/**
 * Prevents hex escape sequences in favor of Unicode
 */
'unicorn/no-hex-escape': 'error' | 'warn' | 'off';

Usage Examples:

// ❌ Bad - hex escape sequences
const copyright = '\xA9';

// ✅ Good - Unicode escape sequences
const copyright = '\u00A9';

// With custom string content patterns:
// ❌ Bad - inconsistent quotation marks (if configured)
const message = "Hello 'world'";

// ✅ Good - consistent quotation marks
const message = 'Hello "world"';

Comment Rules

Rules for consistent comment formatting and management.

/**
 * Adds expiration conditions to TODO comments
 * Enforces accountability for temporary code and technical debt
 */
'unicorn/expiring-todo-comments': 'error' | 'warn' | 'off' | [
  'error' | 'warn',
  {
    terms?: string[]; // Default: ['todo', 'fixme', 'xxx']
    ignore?: (string | RegExp)[]; // Default: []
    ignoreDatesOnPullRequests?: boolean; // Default: true
    allowWarningComments?: boolean; // Default: true
    date?: string; // ISO date format, defaults to current date
  }
];

Usage Examples:

// ❌ Bad - TODO without expiration
// TODO: Refactor this function

// ✅ Good -  TODO with expiration date
// TODO [2024-01-01]: Refactor this function

// ✅ Good - TODO with version expiration
// TODO [engine@>2.0.0]: Remove this compatibility code

// ✅ Good - TODO with dependency condition
// TODO [@babel/core@>7.0.0]: Use new babel API

// ❌ Bad - Expired TODO (if current date > 2023-01-01)
// TODO [2023-01-01]: This should have been fixed

// With custom terms configuration:
// ✅ Good - FIXME with expiration
// FIXME [2024-06-01]: Memory leak in this module

// ✅ Good - XXX with version condition  
// XXX [react@>18.0.0]: Update to new hooks API

File Structure Rules

Rules for file content and structure consistency.

/**
 * Prevents empty files
 */
'unicorn/no-empty-file': 'error' | 'warn' | 'off';

/**
 * Prevents anonymous default exports
 */
'unicorn/no-anonymous-default-export': 'error' | 'warn' | 'off';

/**
 * Prevents named default imports
 */
'unicorn/no-named-default': 'error' | 'warn' | 'off';

Usage Examples:

// ❌ Bad - empty file (file.js contains nothing)

// ✅ Good - file with content
export const utils = {};

// ❌ Bad - anonymous default export
export default function() {
  return 'helper';
}

// ✅ Good - named default export
export default function helper() {
  return 'helper';
}

// ❌ Bad - named default import
import { default as React } from 'react';

// ✅ Good - regular default import
import React from 'react';

Relative URL Style

Rules for consistent relative URL formatting.

/**
 * Enforces consistent relative URL style
 */
'unicorn/relative-url-style': 'error' | 'warn' | 'off' | [
  'error' | 'warn',
  'never' | 'always'
];

Usage Examples:

// With 'never' option:
// ❌ Bad - using relative URL style
const url = new URL('./path', base);

// ✅ Good - absolute URL construction
const url = new URL(base + '/path');

// With 'always' option:
// ❌ Bad - not using relative URL style
const url = new URL(base + '/path');

// ✅ Good - using relative URL style
const url = new URL('./path', base);

Configuration Examples

Comprehensive Style Rules Setup

export default [
  {
    plugins: {
      unicorn: eslintPluginUnicorn,
    },
    rules: {
      // Naming conventions
      'unicorn/filename-case': ['error', { case: 'kebabCase' }],
      'unicorn/prevent-abbreviations': ['error', {
        replacements: {
          btn: { button: true },
          elem: { element: true },
          prop: { property: true },
        }
      }],
      
      // Formatting
      'unicorn/empty-brace-spaces': 'error',
      'unicorn/no-console-spaces': 'error',
      'unicorn/template-indent': 'error',
      
      // Case formatting
      'unicorn/escape-case': 'error',
      'unicorn/number-literal-case': 'error',
      'unicorn/numeric-separators-style': 'error',
      
      // Switch and braces
      'unicorn/switch-case-braces': ['error', 'always'],
      'unicorn/no-useless-switch-case': 'error',
      
      // Comment management
      'unicorn/expiring-todo-comments': 'error',
      
      // File structure
      'unicorn/no-empty-file': 'error',
      'unicorn/no-anonymous-default-export': 'error',
    },
  },
];

Custom Style Configuration

export default [
  {
    plugins: {
      unicorn: eslintPluginUnicorn,
    },
    rules: {
      // Custom filename case for React projects
      'unicorn/filename-case': [
        'error',
        {
          case: 'pascalCase',
          ignore: [/^[a-z]+\.config\.js$/, /^[A-Z]+\.md$/]
        }
      ],
      
      // Custom abbreviation rules
      'unicorn/prevent-abbreviations': [
        'error',
        {
          checkFilenames: true,
          replacements: {
            btn: { button: true },
            ctx: { context: true },
            evt: { event: true },
            prop: false, // Allow 'prop' abbreviation
          },
          allowList: {
            idx: true, // Allow 'idx' as index
          }
        }
      ],
      
      // Custom numeric separators
      'unicorn/numeric-separators-style': [
        'error',
        {
          number: { minimumDigits: 4, groupLength: 3 },
          hexadecimal: { minimumDigits: 5, groupLength: 2 }
        }
      ],
    },
  },
];

docs

anti-pattern-prevention-rules.md

array-object-rules.md

code-quality-rules.md

code-style-rules.md

dom-browser-rules.md

import-export-rules.md

index.md

modern-javascript-rules.md

plugin-configuration.md

tile.json