or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

ast-helpers.mdconfiguration.mdformatters.mdindex.mdlinter.mdrule-development.mdrules.md
tile.json

tessl/npm-ember-template-lint

Linter for Ember or Handlebars templates.

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/ember-template-lint@7.9.x

To install, run

npx @tessl/cli install tessl/npm-ember-template-lint@7.9.0

index.mddocs/

Ember Template Lint

Ember Template Lint is a comprehensive linting tool specifically designed for Ember.js and Handlebars templates. It provides a robust rule engine with configurable linting rules that can detect common anti-patterns, accessibility issues, deprecated syntax, and style violations in Handlebars templates.

Package Information

  • Package Name: ember-template-lint
  • Package Type: npm
  • Language: JavaScript
  • Installation: npm install ember-template-lint

Core Imports

import Linter, { Rule, ASTHelpers, NodeMatcher, generateRuleTests, recast } from "ember-template-lint";

For CommonJS:

const Linter = require("ember-template-lint").default;
const { Rule, ASTHelpers, NodeMatcher, generateRuleTests, recast } = require("ember-template-lint");

Basic Usage

import Linter from "ember-template-lint";

// Initialize linter with configuration
const linter = new Linter({
  workingDir: process.cwd(),
  console: console
});

// Load configuration (async)
await linter.loadConfig();

// Lint a template
const results = await linter.verify({
  source: '<div class="my-class">{{message}}</div>',
  filePath: 'app/templates/example.hbs'
});

// Process results
if (results.length > 0) {
  console.log('Linting violations found:');
  results.forEach(result => {
    console.log(`${result.rule}: ${result.message} (${result.line}:${result.column})`);
  });
}

Architecture

Ember Template Lint is built around several key components:

  • Linter Class: Core engine for processing templates and executing rules
  • Rule System: Extensible rule architecture with 132+ built-in rules covering accessibility, style, and best practices
  • Configuration Engine: Flexible configuration system supporting presets, custom rules, and file-specific overrides
  • AST Processing: Uses ember-template-recast for parsing and transforming Handlebars templates
  • CLI Interface: Command-line tool for integrating with development workflows and CI/CD pipelines
  • Formatter System: Multiple output formats including pretty console output, JSON, SARIF, and editor integration

Capabilities

Core Linting Engine

Main linting functionality for processing Handlebars templates with configurable rules and output formats.

class Linter {
  constructor(options?: LinterOptions): Linter;
  loadConfig(): Promise<void>;
  verify(options: VerifyOptions): Promise<LintResult[]>;
  verifyAndFix(options: VerifyOptions): Promise<FixResult>;
}

interface LinterOptions {
  workingDir?: string;
  console?: Console;
  rule?: string;
  configPath?: string;
  allowInlineConfig?: boolean;
  reportUnusedDisableDirectives?: boolean;
  checkHbsTemplateLiterals?: boolean;
}

interface VerifyOptions {
  source: string;
  filePath: string;
  workingDir?: string;
  configResolver?: ConfigResolver;
}

interface LintResult {
  rule: string;
  message: string;
  line: number;
  column: number;
  severity: number;
  source?: string;
  fix?: FixInfo;
}

Linting Engine

Rule Development System

Framework for creating custom linting rules with AST visitor patterns and testing utilities.

class Rule {
  constructor(options: RuleOptions): Rule;
  visitor(): VisitorMethods;
  log(result: RuleResult): void;
}

interface RuleOptions {
  name: string;
  config: any;
  console: Console;
  defaultSeverity: number;
  workingDir: string;
  ruleNames: string[];
  allowInlineConfig: boolean;
  reportUnusedDisableDirectives: boolean;
}

function generateRuleTests(options: RuleTestOptions): void;

Rule Development

Built-in Rules Collection

Comprehensive set of 132+ linting rules covering accessibility, style, best practices, and Ember-specific patterns.

// Rule categories available
type RuleCategory = 
  | "accessibility"     // ARIA, semantic HTML, keyboard navigation
  | "components"        // Ember component best practices
  | "style"            // Formatting and code style
  | "deprecated"       // Deprecated Ember patterns
  | "security"         // Security-related checks
  | "performance"      // Performance optimizations
  | "maintainability"; // Code maintainability

Built-in Rules

Configuration System

Flexible configuration system supporting presets, custom rules, plugins, and file-specific overrides.

function getProjectConfig(workingDir: string, options?: ConfigOptions): Promise<ProjectConfig>;

interface ProjectConfig {
  rules: Record<string, RuleConfig>;
  extends?: string | string[];
  plugins?: string[];
  ignore?: string[];
  overrides?: Override[];
  format?: FormatConfig;
  reportUnusedDisableDirectives?: boolean;
  checkHbsTemplateLiterals?: boolean;
}

interface RuleConfig {
  severity: -1 | 0 | 1 | 2; // todo, ignore, warn, error
  config?: any;
}

Configuration

AST Helpers and Utilities

Utilities for analyzing and manipulating Handlebars AST nodes during rule execution.

class ASTHelpers {
  static isConfigurationHtmlComment(node: CommentStatement): boolean;
  static isIf(node: MustacheStatement | BlockStatement | SubExpression): boolean;
  static isUnless(node: MustacheStatement | BlockStatement | SubExpression): boolean;
  static isEach(node: MustacheStatement | BlockStatement | SubExpression): boolean;
  // ... additional AST analysis methods
}

class NodeMatcher {
  static match(testNode: Node, referenceNode: Node | Node[]): boolean;
}

AST Helpers

Command Line Interface

Comprehensive CLI for integrating with development workflows and CI/CD pipelines.

// Command line options interface
interface CLIOptions {
  configPath?: string;              // Custom config file path
  config?: string;                  // Inline JSON configuration
  quiet?: boolean;                  // Suppress warnings, show only errors
  rule?: string;                    // Single rule override "rule-name:severity"
  filename?: string;                // Filename for stdin input
  fix?: boolean;                    // Auto-fix issues where possible
  format?: string;                  // Output format: "pretty", "json", "sarif", "kakoune"
  printFullPath?: boolean;          // Print absolute file paths
  outputFile?: string;              // Write output to file
  verbose?: boolean;                // Include source descriptions
  workingDirectory?: string;        // Working directory
  noConfigPath?: boolean;           // Disable config file loading
  updateTodo?: boolean;             // Update TODO list
  includeTodo?: boolean;            // Include TODOs in output
  cleanTodo?: boolean;              // Clean expired TODOs
  compactTodo?: boolean;            // Compact TODO storage
  todoDaysToWarn?: number;          // Days until TODO becomes warning
  todoDaysToError?: number;         // Days until TODO becomes error
  ignorePattern?: string[];         // Ignore patterns
  noInlineConfig?: boolean;         // Disable inline config comments
  printConfig?: boolean;            // Print effective configuration
  maxWarnings?: number;             // Max warnings before exit 1
  noErrorOnUnmatchedPattern?: boolean; // Don't error on unmatched patterns
  reportUnusedDisableDirectives?: boolean; // Report unused disable directives
}

Output Formatters

Multiple output formats for linting results supporting console output, JSON, SARIF format, and editor integration.

// Formatter classes (no shared base class)
class PrettyFormatter {
  constructor(options?: FormatterOptions): PrettyFormatter;
  format(results: LintResult[], todoInfo?: TodoInfo): string;
}

class JsonFormatter {
  constructor(options?: FormatterOptions): JsonFormatter;
  format(results: LintResult[], todoInfo?: TodoInfo): string;
  defaultFileExtension: 'json';
}

class SarifFormatter {
  constructor(options?: FormatterOptions): SarifFormatter;
  format(results: LintResult[], todoInfo?: TodoInfo): string;
  defaultFileExtension: 'sarif';
}

class KakouneFormatter {
  constructor(options?: FormatterOptions): KakouneFormatter;
  format(results: LintResult[], todoInfo?: TodoInfo): string;
}

Formatters

Types

// Severity levels
const TODO_SEVERITY = -1;
const IGNORE_SEVERITY = 0;
const WARNING_SEVERITY = 1;
const ERROR_SEVERITY = 2;

// Formatter options
interface FormatterOptions {
  printFullPath?: boolean;        // Print absolute file paths
  includeTodo?: boolean;          // Include TODO items in output
  outputFile?: string;            // Output file path
  quiet?: boolean;                // Suppress warnings
  updateTodo?: boolean;           // Whether updating TODOs
  verbose?: boolean;              // Verbose output mode
  hasResultData?: boolean;        // Whether results contain data
  config?: any;                   // Configuration object
  workingDirectory?: string;      // Working directory path
  console?: Console;              // Console object for output
  isInteractive?: boolean;        // Interactive mode flag
}

// TODO information
interface TodoInfo {
  add: number;        // Number of TODOs added
  remove: number;     // Number of TODOs removed
  stable: number;     // Number of stable TODOs
  expired: number;    // Number of expired TODOs
}

// AST Node types (from ember-template-recast)
interface Template {
  type: "Template";
  body: Statement[];
  blockParams: string[];
  loc: SourceLocation;
}

interface ElementNode {
  type: "ElementNode";
  tag: string;
  attributes: AttrNode[];
  blockParams: string[];
  modifiers: ElementModifierStatement[];
  comments: MustacheCommentStatement[];
  children: Statement[];
  loc: SourceLocation;
}

interface MustacheStatement {
  type: "MustacheStatement";
  path: PathExpression;
  params: Expression[];
  hash: Hash;
  escaped: boolean;
  loc: SourceLocation;
}

interface BlockStatement {
  type: "BlockStatement";
  path: PathExpression;
  params: Expression[];
  hash: Hash;
  program: Program;
  inverse?: Program;
  loc: SourceLocation;
}

interface SourceLocation {
  start: Position;
  end: Position;
}

interface Position {
  line: number;
  column: number;
}