npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@noneforge/eslint-config-angular

v0.2.6

Published

Angular ESLint configuration with TypeScript, component rules, and accessibility

Readme

@noneforge/eslint-config-angular

Comprehensive Angular ESLint configuration with TypeScript support, component/template rules, accessibility, and CSS linting. Built on @noneforge/eslint-config ESLint 9+ flat config with Angular 20+ best practices and modern reactive patterns.

Features

  • ESLint 9 Flat Config - Modern configuration format with better performance
  • 🎯 Angular 20+ Optimized - Specific rules for components, directives, pipes, and services
  • 🔒 Accessibility First - Built-in a11y rules for templates with ARIA support
  • Signals & Control Flow - Support for Angular's latest reactive features
  • 📦 Full TypeScript Support - Extends @noneforge/eslint-config base with Angular specifics
  • 🎨 CSS/SCSS Linting - Integrated CSS validation for component styles
  • 🚀 Standalone Components - Promotes modern Angular architecture patterns
  • 🔧 Smart Detection - Different rules for tests, stories, schematics, and modules

Related Packages

Requirements

  • Node.js >=20.19.0
  • ESLint >=9.22.0
  • TypeScript >=5.9.0
  • Angular >=20.0.0
  • RxJS >=7.4.0

Installation

npm install --save-dev @noneforge/eslint-config-angular eslint typescript

or with Yarn:

yarn add --dev @noneforge/eslint-config-angular eslint typescript

Usage

Create an eslint.config.js file in your project root:

import config from '@noneforge/eslint-config-angular';

export default [
  ...config,
  // Your custom rules here
];

With Custom Rules

import config from '@noneforge/eslint-config-angular';

export default [
  ...config,
  {
    rules: {
      // Override or add custom rules
      '@angular-eslint/component-selector': ['error', {
        type: 'element',
        prefix: 'my-app',
        style: 'kebab-case',
      }],
    }
  }
];

For Nx Monorepos

import config from '@noneforge/eslint-config-angular';

export default [
  ...config,
  {
    languageOptions: {
      parserOptions: {
        projectService: true,
        tsconfigRootDir: import.meta.dirname,
        project: ['./apps/*/tsconfig.json', './libs/*/tsconfig.json'],
      }
    }
  }
];

Rule Categories

🎯 Angular Component Rules

Modern Angular patterns and best practices:

  • Standalone Components: prefer-standalone - Enforces standalone architecture
  • Signals: prefer-signals, no-uncalled-signals - Reactive state management
  • Change Detection: prefer-on-push-component-change-detection - Performance optimization
  • Lifecycle: contextual-lifecycle, no-empty-lifecycle-method, no-async-lifecycle-method
  • Component Structure: component-max-inline-declarations - Limits inline templates/styles
  • Dependency Injection: prefer-inject - Modern DI patterns over constructor injection
  • Naming Conventions: component-class-suffix, directive-class-suffix
  • Selectors: Enforces app- prefix with kebab-case for components, camelCase for directives
// ❌ Legacy patterns
@Component({
  selector: 'myComponent',
  template: `...very long template...`,
  standalone: false,  // Explicitly false triggers the rule
  changeDetection: ChangeDetectionStrategy.Default
})
export class MyComp {
  constructor(private service: MyService) {}
  value = 0;
}

// ✅ Modern Angular patterns
@Component({
  selector: 'app-my-component',
  templateUrl: './my-component.html',
  changeDetection: ChangeDetectionStrategy.OnPush
  // standalone: true is default in Angular 20, can be omitted
})
export class MyComponent {
  private service = inject(MyService);
  value = signal(0);
}

📝 Template Rules

Comprehensive template validation and best practices:

  • Control Flow: prefer-control-flow - New @if/@for/@switch syntax
  • Two-Way Binding: banana-in-box - Correct [(ngModel)] syntax
  • Type Safety: no-any - Prevents any types in templates
  • Performance: use-track-by-function - Required for @for loops
  • Image Optimization: prefer-ngsrc - NgOptimizedImage for better performance
  • Self-Closing Tags: prefer-self-closing-tags - Cleaner template syntax
  • Complexity: conditional-complexity, cyclomatic-complexity - Maintainable templates
<!-- ❌ Old patterns -->
<div *ngIf="condition">Content</div>
<img src="{{imageUrl}}" />
<div *ngFor="let item of items">{{item}}</div>

<!-- ✅ Modern patterns -->
@if (condition) {
  <div>Content</div>
}
<img [ngSrc]="imageUrl" width="200" height="100" />
@for (item of items; track item.id) {
  <div>{{item}}</div>
}

♿ Accessibility Rules

Built-in a11y compliance for inclusive applications:

  • Images: alt-text - Alternative text required
  • Keyboard Navigation: click-events-have-key-events, mouse-events-have-key-events
  • Interactive Elements: interactive-supports-focus - Focusable interactive elements
  • Forms: label-has-associated-control - Proper form labeling
  • ARIA: role-has-required-aria, valid-aria - Correct ARIA usage
  • Focus Management: no-autofocus, no-positive-tabindex
  • Tables: table-scope - Proper scope attributes
  • Distracting Elements: no-distracting-elements - No marquee/blink
<!-- ❌ Accessibility issues -->
<img [src]="imageUrl">
<div (click)="action()">Click me</div>
<input type="text">

<!-- ✅ Accessible patterns -->
<img [src]="imageUrl" [alt]="imageAlt">
<button (click)="action()">Click me</button>
<label for="name">Name</label>
<input id="name" type="text">

🎨 CSS/SCSS Rules

Style validation for component styles:

  • Import Management: no-duplicate-imports - Prevents duplicate @import
  • Selectors: no-duplicate-keyframe-selectors - Unique keyframe names
  • At-Rules: no-invalid-at-rules, no-invalid-at-rule-placement
  • Grid: no-invalid-named-grid-areas - Valid CSS Grid areas
  • Properties: no-invalid-properties - Catches typos in CSS properties
  • Quality: no-empty-blocks, font-family-fallbacks - Best practices
// ❌ CSS issues
@import 'theme';
@import 'theme';  // Duplicate

.empty {}  // Empty block

.text {
  font-family: 'CustomFont';  // No fallback
  colr: red;  // Typo
}

// ✅ Clean styles
@import 'theme';

.text {
  font-family: 'CustomFont', sans-serif;
  color: red;
}

🧩 Input/Output Rules

Modern Angular communication patterns:

  • Input Signals: Preferred over decorators for reactive inputs
  • Output Events: no-output-native, no-output-on-prefix - Avoids conflicts
  • Naming: no-input-rename, no-output-rename - Consistent API
  • Metadata: no-inputs-metadata-property, no-outputs-metadata-property
  • Readonly Outputs: prefer-output-readonly - Immutable event emitters
// ❌ Old patterns
@Component({
  inputs: ['value'],
  outputs: ['onChange']
})
export class OldComponent {
  @Input('aliased') value: string;
  @Output() onClick = new EventEmitter();
}

// ✅ Modern patterns
@Component({...})
export class ModernComponent {
  value = input<string>();
  readonly changed = output<string>();
}

📁 Smart File Detection

Test Files (*.spec.ts, *.test.ts, *.e2e-spec.ts)

Relaxed rules for testing:

  • Lifecycle calls allowed in tests
  • OnPush change detection not required
  • Injectable providedIn requirements relaxed

Storybook Stories (*.stories.ts)

Flexible rules for component documentation:

  • Console output allowed
  • Indentation and line length unrestricted
  • Component selector requirements relaxed
  • Type safety warnings instead of errors

Angular Schematics (schematics/**/*.ts)

Practical rules for code generation:

  • Console output allowed for CLI feedback
  • Any types allowed for dynamic operations
  • Unsafe operations permitted for metaprogramming

Angular Modules (*.module.ts)

Migration support:

  • Standalone preference as warning, not error
  • Supports gradual migration to standalone

Router Components (**/+*.ts)

Special routing patterns:

  • Component/directive selector rules disabled
  • Supports Angular's file-based routing conventions

Base Configuration

This package extends @noneforge/eslint-config which provides:

  • Comprehensive TypeScript type checking
  • Built-in formatting (Prettier replacement)
  • Import organization and sorting
  • Modern JavaScript best practices
  • JSDoc documentation rules

See the base configuration README for details on inherited rules.

Common Patterns

Signals and Effects

// ❌ Traditional reactive patterns
export class OldComponent {
  value = 0;
  valueSubject = new BehaviorSubject(0);
  
  ngOnInit() {
    this.valueSubject.subscribe(v => this.value = v);
  }
}

// ✅ Modern signals
export class ModernComponent {
  value = signal(0);
  computed = computed(() => this.value() * 2);
  
  constructor() {
    effect(() => {
      console.log('Value changed:', this.value());
    });
  }
}

Dependency Injection

// ❌ Constructor injection
export class OldService {
  constructor(
    private http: HttpClient,
    private router: Router,
    @Inject(CONFIG) private config: Config
  ) {}
}

// ✅ inject() function
export class ModernService {
  private http = inject(HttpClient);
  private router = inject(Router);
  private config = inject(CONFIG);
}

Control Flow Syntax

// Template file
@if (user()) {
  <app-user-profile [user]="user()" />
} @else if (loading()) {
  <app-spinner />
} @else {
  <p>No user found</p>
}

@for (item of items(); track item.id) {
  <app-item [data]="item" />
} @empty {
  <p>No items available</p>
}

@switch (status()) {
  @case ('active') { <app-active /> }
  @case ('pending') { <app-pending /> }
  @default { <app-inactive /> }
}

VSCode Integration

Add to .vscode/settings.json:

{
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": "explicit"
  },
  "eslint.experimental.useFlatConfig": true,
  "eslint.validate": [
    "javascript",
    "typescript",
    "html",
    "css",
    "scss"
  ]
}

Package.json Scripts

{
  "scripts": {
    "lint": "eslint .",
    "lint:fix": "eslint . --fix",
    "lint:debug": "eslint . --debug",
    "type-check": "tsc --noEmit"
  }
}

Migration from ESLint 8

  1. Remove .eslintrc.* files
  2. Create eslint.config.js with flat config
  3. Update VSCode settings for flat config
  4. Install this package and its peer dependencies
  5. Update scripts to use ESLint 9 CLI

Performance Tips

  • Use projectService: true for better TypeScript performance
  • Enable ESLint cache: eslint . --cache
  • Exclude dist and .angular in your tsconfig.json
  • Consider --max-warnings 0 in CI/CD pipelines

Philosophy

This configuration prioritizes:

  1. Modern Angular - Signals, standalone components, and latest APIs
  2. Accessibility - Built-in a11y rules for inclusive applications
  3. Performance - OnPush change detection and optimization patterns
  4. Type Safety - Leverage TypeScript for runtime error prevention
  5. Developer Experience - Clear errors with practical escape hatches

License

MIT

Contributing

Issues and PRs welcome at GitHub