You can customize the linter with rules that are more specific to your use case with the ember-template-lint plugin system.
Plugins can define new rules and set up default configurations that can be extended.
Each plugin object can include these properties.
-
name--string(required)The name of the plugin. Will be used to namespace any configuration objects.
-
rules--ObjectObject that defines new rules. Each key represents the name of the rule that is defined. Each value should be a Rule object. See Rule APIs for more detail.
-
configurations--ObjectObject that defines new configurations that can be extended. Each key represents the name of the configuration object. Each value should be a configuration object, that can include the same properties as the base config object in any
.template-lintrc.js-- i.e.rules,extends,ignore, etc.
Sample plugin object:
{
// Name of plugin
name: 'my-plugin',
// Define rules for this plugin. Each path should map to a plugin rule
rules: {
'disallow-inline-components': require('./lib/template-lint-rules/disallow-inline-components'),
'another-custom-rule': require('.lib/template-lint-rules/another-custom-rule')
},
// Define configurations for this plugin that can be extended by the base configuration
configurations: {
'no-inline': {
rules: {
'disallow-inline-components': true
}
}
}
}In order to enable a plugin, you must add it to the plugins key in your configuration file.
plugins accepts an array of either plugin objects or strings to be passed to require which resolve to plugin objects.
// .template-lintrc.js
module.exports = {
plugins: [
// Define a plugin inline
{
name: 'inline-plugin',
...
},
// Define a plugin that is exported elsewhere (i.e. a third-party plugin)
'./plugins/some-local-plugin',
'some-npm-package/third-party-plugin',
],
extends: [
// Extend configuration defined in inline plugins
'configuration-defined-in-my-inline-plugin',
// Extend configuration defined in plugins in other files
'some-local-plugin:recommended',
'third-party-plugin:another-configuration'
],
rules: {
// Use rules defined in plugins
'rule-defined-in-my-inline-plugin': true
'rule-defined-in-some-local-plugin': true
}
}Every rule defined by a plugin can use these public APIs defined by ember-template-lint.
Each file that defines a rule should export a class that extends from the base rule object.
Sample rule:
'use strict';
const Rule = require('ember-template-lint').Rule;
module.exports = class NoEmptyComments extends Rule {
visitor() {
return {
CommentStatement(node) {
if (node.value.trim() === '') {
this.log({
message: 'comments cannot be empty',
line: node.loc && node.loc.start.line,
column: node.loc && node.loc.start.column,
source: this.sourceForNode(node)
});
}
}
};
}
};You can override the following methods on the base plugin class:
-
function visitor(): visitorObjectThe
visitorfunction should return an object that maps Handlebars node types to functions. Whenever the Handlebars parser encounters a particular type of node, any handler function that you define for that node will be called on it. You can reference the Handlebars Compiler API for more detail on the types of nodes and their interfaces.
The base rule also has a few helper functions that can be useful in defining rule behavior:
-
function log(options)Report a lint error. The
logfunction accepts an Object as its only argument, which can contain the following parameters:message--stringThe error message to display.line--numberThe line number of the error in the source string.column--numberThe column number of the error in the source string.source--stringThe source string that caused the error.fix--stringAn optional string to display with the recommended fix.
-
function sourceForNode(node): stringGiven a Handlebars AST node, return the string source of that node. Useful to generate
sourcewhen logging errors withlog.
There are a number of helper functions exported by ember-template-lint that can be used with AST nodes in your rule's visitor handlers.
You can access these helpers via:
const helpers = require('ember-template-lint').ASTHelpers;-
function isConfigurationHtmlComment(node): booleanReturns true if this node is an HTML comment that is meant to set linter configuration (i.e.
<!-- template-lint enabled=false -->). -
function isNonConfigurationHtmlComment(node): booleanReturns true if this node is not an HTML comment that is meant to set linter configuration.
-
function isTextNode(node): booleanReturns true if this node is a
TextNodenode. -
function isCommentStatement(node): booleanReturns true if this node is a
CommentStatementnode. -
function isMustacheCommentStatement(node): booleanReturns true if this node is a
MustacheCommentStatementnode. -
function isElementNode(node): booleanReturns true if this node is an
ElementNodenode. -
function isComponentNode(node): booleanReturns true if this node is a
ComponentNodenode. -
function isMustacheStatement(node): booleanReturns true if this node is a
MustacheStatementnode. -
function isBlockStatement(node): booleanReturns true if this node is a
BlockStatementnode. -
function hasAttribute(node, attributeName): booleanReturns true if this node has an attribute whose name matches
attributeName. -
function findAttribute(node, attributeName): ObjectReturns any attributes on the node with a name that matches
attributeName. -
function isImgElement(node): booleanReturns true if this node is an
imgelement. -
function isLinkElement(node): booleanReturns true if this node is a link (
a) element. -
function childrenFor(node): Object[]Returns any child nodes of this node.
-
function hasChildren(node): booleanReturns true if this node has any child nodes.