Add custom Rules using Plugins
Each plugin is an npm module with a name.
It's recommended to use the format linthtml-plugin-<plugin-name>
. You can also use scoped packages in the format of @<scope>/linthtml-plugin-<plugin-name>
or even @<scope>/linthtml-plugin
.
Expose Rules in Plugins
Plugins can expose additional rules for use in LintHTML. To do so, the plugin must export an array of rules objects under the property rules
.
Each rules should contains a property name
matching the following pattern <plugin-name>/<rule-id>
.
For example:
- Plugin CJS format
- Plugin ESM format
// The package `@linthtml/dom-utils` has some util functions
const { is_tag_node, node_tag_name } = require('@linthtml/dom-utils/tags');
module.exports = {
rules: [{
name: "custom/no-center-tag",
lint(node, rule_config, { report }) {
if (!is_tag_node(node)) {
// Node is pure text, comment, CDATA, Doctype, directive or root tag
return;
}
// Node is a tag `span, div, button...`
if (node_tag_name(node, 'name')) {
report({
message: "Do not use deprecated center element, use CSS instead to center content",
position: node.loc
})
}
}
}]
};
// The package `@linthtml/dom-utils` has some util functions
import { is_tag_node, node_tag_name } from '@linthtml/dom-utils/tags';
exports default {
rules: [{
name: "custom/no-center-tag",
lint(node, rule_config, { report }) {
if (!is_tag_node(node)) {
// Node is pure text, comment, CDATA, Doctype, directive or root tag
return;
}
// Node is a tag `span, div, button...`
if (node_tag_name(node, 'name')) {
report({
message: "Do not use deprecated center element, use CSS instead to center content",
position: node.loc
})
}
}
}]
};
To use the rule in LintHTML, you would use same pattern (<plugin-name>/<rule-id>
).
So to activate/configure the rule "custom/no-center-tag"
, you would have to write the following in your LintHTML config file.
{
"rules": {
"custom/no-center-tag": "error"
}
}
Rules implementation
The source file for a rule exports an object with the following properties.
-
name
(string): The rule name, this property will be used to print the rule name along side an reported issue. -
validateConfig
(function): This function is optional and will be used to validate the config provided to the rule in the config file. This is usefull when you have a rule that only acceptnumbers
orstrings
as config or if you want to limit the config possibility.For example the rule
indent-style
only accepttabs
,spaces
andnonmixed
as config.const type_error = (option) =>
`Configuration for rule "indent-style" is invalid: Expected string${allow_reg ? " or RegExp" : ""} got ${typeof option}.`;
function list_value_error_message(value_list) {
const list_copy = [...value_list];
if (value_list.length > 1) {
const last_value = list_copy.pop();
return `Accepted values are ${list_copy.map((_) => `"${_}"`).join(", ")} and "${last_value}"`;
}
return `Accepted value is ${list_copy[0]}`;
}
return {
name: "indent-style",
validateConfig(config) {
const accepted_values = ["tabs", "spaces", "nonmixed"]
if (typeof option !== "string") {
throw new Error(type_error(option));
}
if (accepted_values.indexOf(option) === -1) {
throw new Error(
`Configuration for rule "indent-style" is invalid: "${option}" is not accepted. ${list_value_error_message(
accepted_values
)}.`
);
}
},
lint() {
//...
}
} -
lint
(function): This function will be called for every nodes in the abstract syntax tree (AST as defined here) for the documents that are linted. This function receive in input 3 parameters:node
(node spec the node traversed).rule_config
(any) the config for the rule. By default, it's the rule config defined in thelinthtmlrc.*
files but it can also be the config overrides defined in an inline instructionoptions
(object) this parameter contains the following property:report
(function) this is the function to use to report a lint issue. This function takes as argument the following objectposition
(Position see here) Location of the issuemessage
(string) Message describing the issue
global_config
(object) [deprecated] An object containing the config of all activated rules.