eslint-plugin-san
Version:
Official ESLint plugin for San
114 lines (104 loc) • 4.06 kB
JavaScript
/**
* @author BUPTlhuanyu
*/
;
/* eslint-disable */
// ------------------------------------------------------------------------------
// Requirements
// ------------------------------------------------------------------------------
const utils = require('../utils');
const casing = require('../utils/casing');
// ------------------------------------------------------------------------------
// Helpers
// ------------------------------------------------------------------------------
function isHost(node) {
if (
(!utils.isHtmlElementNode(node) && !utils.isSvgElementNode(node)) ||
utils.isHtmlWellKnownElementName(node.rawName) ||
utils.isSvgWellKnownElementName(node.rawName)
) {
return true;
}
return false;
}
// ------------------------------------------------------------------------------
// Rule Definition
// ------------------------------------------------------------------------------
module.exports = {
meta: {
type: 'suggestion',
docs: {
description: 'Enforce custom components name',
categories: ['essential'],
url: 'https://ecomfe.github.io/eslint-plugin-san/rules/valid-components-name.html'
},
fixable: 'code',
schema: []
},
/** @param {RuleContext} context */
create(context) {
const sourceCode = context.getSourceCode();
function check(node, name, fix) {
if (!casing.isKebabCase(name)) {
const issue = {
node,
loc: node.loc,
message: 'Component name {{name}} must be kebab-case.',
data: {
name
}
};
typeof fix === 'function' && (issue.fix = fix);
context.report(issue);
}
}
function replace(fixer, node, name) {
const tagStr = sourceCode.getText(node);
const relativeStartLoc = tagStr.indexOf(name);
if (relativeStartLoc === -1) {
return;
}
const startLoc = node.range[0] + relativeStartLoc;
const range = [startLoc, startLoc + name.length]
const text = casing.kebabCase(name);
return fixer.replaceTextRange(range, text);
}
return utils.defineTemplateBodyVisitor(
context,
{
/** @param {VElement} node */
VElement(node) {
if (node && !isHost(node)) {
check(node, node.rawName, fixer => {
const fixedRes = [];
const name = node.rawName;
node.startTag && fixedRes.push(replace(fixer, node.startTag, name)); // startTag
node.endTag && fixedRes.push(replace(fixer, node.endTag, name)); // endTag
return fixedRes;
});
}
}
},
utils.executeOnSan(context, obj => {
const registeredComponents = utils.getRegisteredComponents(obj);
registeredComponents.forEach(node => {
if (!node || !node.node) {
return;
}
const realNode = node.node;
let fixFn = null;
if (realNode.key.type === 'Literal') {
fixFn = fixer => {
const range = realNode.key.range;
const raw = realNode.key.raw;
const text = casing.kebabCase(node.name);
const newRaw = raw.replace(node.name, text);
return fixer.replaceTextRange(range, newRaw);
};
}
check(realNode, node.name, fixFn);
})
})
);
}
};