or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

anti-pattern-prevention-rules.mdarray-object-rules.mdcode-quality-rules.mdcode-style-rules.mddom-browser-rules.mdimport-export-rules.mdindex.mdmodern-javascript-rules.mdplugin-configuration.md
tile.json

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 }
        }
      ],
    },
  },
];