Linter for Ember or Handlebars templates.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Core linting functionality for processing Handlebars templates with configurable rules and comprehensive error reporting.
Main linting engine that processes templates and executes configured rules.
/**
* Main linting engine for Ember and Handlebars templates
* @param options - Configuration options for the linter instance
*/
class Linter {
constructor(options?: LinterOptions): Linter;
/**
* Load configuration from project files (.template-lintrc.js, etc.)
* Must be called before running verification
*/
loadConfig(): Promise<void>;
/**
* Lint a template and return violations
* @param options - Template content and metadata
* @returns Array of linting violations
*/
verify(options: VerifyOptions): Promise<LintResult[]>;
/**
* Lint a template and apply automatic fixes where possible
* @param options - Template content and metadata
* @returns Results with original source, fixed source, and remaining violations
*/
verifyAndFix(options: VerifyOptions): Promise<FixResult>;
}Configuration options for initializing a Linter instance.
interface LinterOptions {
/** Working directory for resolving config files and plugins (default: process.cwd()) */
workingDir?: string;
/** Console object for logging (default: console) */
console?: Console;
/** Inline rule specification in format "rule-name:severity" or "rule-name:[severity, config]" */
rule?: string;
/** Path to custom configuration file */
configPath?: string;
/** Allow inline configuration comments in templates (default: true) */
allowInlineConfig?: boolean;
/** Report unused template-lint-disable directives (default: false) */
reportUnusedDisableDirectives?: boolean;
/** Check HBS template literals in JavaScript/TypeScript files (default: true) */
checkHbsTemplateLiterals?: boolean;
}Options for template verification operations.
interface VerifyOptions {
/** Template source code to lint */
source: string;
/** File path for the template (used for configuration overrides and error reporting) */
filePath: string;
/** Working directory (defaults to linter's workingDir) */
workingDir?: string;
/** Configuration resolver for dynamic configuration */
configResolver?: ConfigResolver;
}
interface ConfigResolver {
/** Resolve EditorConfig settings for the file */
editorConfig?(): Record<string, any>;
}Structure of linting violation results.
interface LintResult {
/** Name of the rule that generated this violation */
rule: string;
/** Human-readable description of the violation */
message: string;
/** Line number where violation occurs (1-based) */
line: number;
/** Column number where violation occurs (0-based) */
column: number;
/** Severity level: -1=todo, 0=ignore, 1=warning, 2=error */
severity: -1 | 0 | 1 | 2;
/** Source code context where violation occurs */
source?: string;
/** Automatic fix information if available */
fix?: FixInfo;
/** End position for multi-character violations */
endLine?: number;
endColumn?: number;
/** Whether this is a fatal parsing error */
fatal?: boolean;
}
interface FixInfo {
/** Range to replace in the source */
range: [number, number];
/** Text to replace the range with */
text: string;
}Results from verifyAndFix operations.
interface FixResult {
/** Original template source */
source: string;
/** Fixed template source (may be same as source if no fixes applied) */
output: string;
/** Remaining violations that could not be auto-fixed */
messages: LintResult[];
/** Whether any fixes were applied */
isFixed: boolean;
}Usage Examples:
import Linter from "ember-template-lint";
// Basic linting
const linter = new Linter();
await linter.loadConfig();
const results = await linter.verify({
source: '<div>{{message}}</div>',
filePath: 'app/templates/component.hbs'
});
// Auto-fixing
const fixResult = await linter.verifyAndFix({
source: '<div class="example" >{{message}}</div>',
filePath: 'app/templates/component.hbs'
});
console.log('Fixed source:', fixResult.output);
console.log('Remaining issues:', fixResult.messages);
// Custom configuration
const customLinter = new Linter({
workingDir: '/path/to/project',
rule: 'no-bare-strings:error',
allowInlineConfig: false,
reportUnusedDisableDirectives: true
});
await customLinter.loadConfig();
// Lint JavaScript template literals
const jsResults = await customLinter.verify({
source: 'const template = hbs`<div>{{message}}</div>`;',
filePath: 'app/components/example.js'
});// Fatal errors (parsing failures) are included in results
interface FatalError extends LintResult {
fatal: true;
message: string;
source: string; // Stack trace
line?: number;
column?: number;
}Example with error handling:
try {
const results = await linter.verify({
source: '<div {{invalid-syntax}}',
filePath: 'broken-template.hbs'
});
const fatalErrors = results.filter(r => r.fatal);
const lintViolations = results.filter(r => !r.fatal);
if (fatalErrors.length > 0) {
console.error('Template parsing failed:', fatalErrors[0].message);
}
} catch (error) {
console.error('Linter configuration error:', error.message);
}Install with Tessl CLI
npx tessl i tessl/npm-ember-template-lint