or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

binary-tools.mdconfigs.mdformatters.mdindex.mdplugin.mdrules.md
tile.json

rules.mddocs/

ESLint Rules

Collection of 17 custom ESLint rules covering accessibility, security, performance, and coding best practices specifically designed for GitHub's development standards.

Capabilities

Accessibility Rules

Rules that enforce web accessibility standards and ARIA best practices.

/**
 * Disallow interactive elements with visually hidden styling
 */
'a11y-no-visually-hidden-interactive-element': ESLintRule;

/**
 * Disallow generic link text like "click here" or "read more"
 */
'a11y-no-generic-link-text': ESLintRule;

/**
 * Disallow title attributes on elements
 */
'a11y-no-title-attribute': ESLintRule;

/**
 * Require ARIA labels to be well-formatted
 */
'a11y-aria-label-is-well-formatted': ESLintRule;

/**
 * Ensure ARIA roles support the specified ARIA properties
 */
'a11y-role-supports-aria-props': ESLintRule;

/**
 * Require SVG elements to have an accessible name
 */
'a11y-svg-has-accessible-name': ESLintRule;

Usage Examples:

// .eslintrc.js
module.exports = {
  plugins: ['github'],
  rules: {
    'github/a11y-svg-has-accessible-name': 'error',
    'github/a11y-no-generic-link-text': 'error',
    'github/a11y-role-supports-aria-props': 'error'
  }
};

// Examples that would trigger these rules:
// ❌ Bad: <svg></svg>
// ✅ Good: <svg aria-label="Chart showing sales data"></svg>

// ❌ Bad: <a href="/help">Click here</a>
// ✅ Good: <a href="/help">View help documentation</a>

Performance and Best Practice Rules

Rules that improve code performance and enforce coding best practices.

/**
 * Disallow Array.prototype.forEach in favor of for loops
 */
'array-foreach': ESLintRule;

/**
 * Disallow accessing currentTarget in async functions
 */
'async-currenttarget': ESLintRule;

/**
 * Disallow calling preventDefault in async functions
 */
'async-preventdefault': ESLintRule;

/**
 * Disallow Element.prototype.blur() usage
 */
'no-blur': ESLintRule;

/**
 * Disallow Promise.prototype.then() in favor of async/await
 */
'no-then': ESLintRule;

/**
 * Prefer observers over polling or manual checks
 */
'prefer-observers': ESLintRule;

/**
 * Disallow useless passive event listeners
 */
'no-useless-passive': ESLintRule;

/**
 * Require passive event listeners where appropriate
 */
'require-passive-events': ESLintRule;

Usage Examples:

// Examples that would trigger these rules:

// ❌ Bad: array-foreach
users.forEach(user => processUser(user));
// ✅ Good: 
for (const user of users) processUser(user);

// ❌ Bad: no-blur
element.blur();
// ✅ Good: restore focus to previous element

// ❌ Bad: no-then
fetch('/api/data').then(response => response.json());
// ✅ Good:
const response = await fetch('/api/data');
const data = await response.json();

Security Rules

Rules that prevent common security vulnerabilities and enforce secure coding practices.

/**
 * Disallow usage of CSRF tokens in JavaScript
 */
'authenticity-token': ESLintRule;

/**
 * Disallow dynamic script tag creation
 */
'no-dynamic-script-tag': ESLintRule;

/**
 * Disallow innerHTML usage
 */
'no-inner-html': ESLintRule;

/**
 * Disallow unescaped HTML literals
 */
'unescaped-html-literal': ESLintRule;

Usage Examples:

// Examples that would trigger security rules:

// ❌ Bad: authenticity-token
const token = document.querySelector('[name="authenticity_token"]').value;

// ❌ Bad: no-dynamic-script-tag
const script = document.createElement('script');
script.src = userInput;
document.head.appendChild(script);

// ❌ Bad: no-inner-html
element.innerHTML = userContent;
// ✅ Good:
element.textContent = userContent;

DOM and Utility Rules

Rules for DOM manipulation best practices and utility functions.

/**
 * Require filenames to match a specific regex pattern
 */
'filenames-match-regex': ESLintRule;

/**
 * Enforce specific patterns for getAttribute usage
 */
'get-attribute': ESLintRule;

/**
 * Enforce JavaScript class naming conventions
 */
'js-class-name': ESLintRule;

/**
 * Disallow Bootstrap's d-none class usage
 */
'no-d-none': ESLintRule;

/**
 * Disallow dataset API usage
 */
'no-dataset': ESLintRule;

/**
 * Disallow implicit buggy global variables
 */
'no-implicit-buggy-globals': ESLintRule;

/**
 * Disallow innerText usage in favor of textContent
 */
'no-innerText': ESLintRule;

Usage Examples:

// Examples for DOM rules:

// ❌ Bad: no-dataset
element.dataset.userId = '123';
// ✅ Good:
element.setAttribute('data-user-id', '123');

// ❌ Bad: no-innerText
element.innerText = 'Hello World';
// ✅ Good:
element.textContent = 'Hello World';

// ❌ Bad: get-attribute
const id = element.getAttribute('id');
// ✅ Good: (depending on rule configuration)
const id = element.id;

Rule Configuration

All rules can be configured with ESLint severity levels and options.

/**
 * ESLint rule severity levels
 */
type ESLintSeverity = 'off' | 'warn' | 'error' | 0 | 1 | 2;

/**
 * Rule configuration format
 */
type RuleConfig = ESLintSeverity | [ESLintSeverity, RuleOptions];

interface RuleOptions {
  [key: string]: any;
}

/**
 * ESLint rule structure
 */
interface ESLintRule {
  meta: {
    type: 'problem' | 'suggestion' | 'layout';
    docs: {
      description: string;
      url: string;
      recommended: boolean;
    };
    schema: any[];
    messages: Record<string, string>;
  };
  create(context: ESLintContext): Record<string, Function>;
}

Configuration Examples:

// Individual rule configuration
module.exports = {
  plugins: ['github'],
  rules: {
    'github/no-blur': 'error',
    'github/no-inner-html': 'warn',
    'github/a11y-svg-has-accessible-name': ['error', { /* options */ }]
  }
};

// Flat configuration
export default [
  {
    plugins: { github: eslintPluginGithub },
    rules: {
      'github/authenticity-token': 'error',
      'github/no-dynamic-script-tag': 'error',
      'github/prefer-observers': 'warn'
    }
  }
];

Types

interface ESLintContext {
  /** Report a linting violation */
  report(descriptor: {
    node: any;
    messageId: string;
    data?: Record<string, any>;
    fix?: (fixer: any) => any;
  }): void;
  
  /** Get the source code being linted */
  getSourceCode(): {
    getText(node?: any): string;
    getAllComments(): any[];
    getCommentsBefore(node: any): any[];
    getCommentsAfter(node: any): any[];
  };
  
  /** Get the filename being linted */
  getFilename(): string;
  
  /** Get rule options */
  options: any[];
}

interface ESLintMessage {
  line: number;
  column: number;
  endLine?: number;
  endColumn?: number;
  ruleId: string;
  message: string;
  severity: 1 | 2;
  fix?: ESLintFix;
}

interface ESLintFix {
  range: [number, number];
  text: string;
}