eslint-plugin-miniprogram
Version:
eslint plugin for mini programs
147 lines • 6.14 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
var utils_1 = __importDefault(require("eslint-plugin-vue/lib/utils"));
var path_1 = __importDefault(require("path"));
var kebabCase_1 = __importDefault(require("lodash/kebabCase"));
var mina_sfc_1 = __importDefault(require("@tinajs/mina-sfc"));
var json5_1 = __importDefault(require("json5"));
var constants_1 = require("../constants");
var DEFAULT_LOC = {
start: { line: 1, column: 0 },
end: { line: 1, column: 0 }
};
var isBuildInComponents = function (name) {
return constants_1.BUILD_IN_COMPONENTS.includes(name);
};
var trimTail = function (name) {
return path_1.default.basename(name.replace(/\.mina$/, "").replace(/\/index$/, ""));
};
var getScopedSpecificPrefixHandling = function (componentPath) {
var tokens = componentPath.split("/")[1].split("-");
var prefix = tokens[tokens.length - 1];
return prefix;
};
exports.getExpectedComponentName = function (componentPath, contextPath) {
var name = componentPath;
name = trimTail(name);
name = kebabCase_1.default(name);
// special handling for airbnb components
// TODO make this configurable
if (componentPath.startsWith("~@")) {
var prefix = getScopedSpecificPrefixHandling(componentPath);
name = prefix + "-" + name;
}
return name;
};
var RULE_DESCRIPTION = {
componentName: "Enforce specific casing for the component naming style",
unusedComponent: "Check unused components",
unregisteredComponent: "Check unregistered components"
};
exports.checkUsingComponents = function (intent) { return ({
meta: {
type: "suggestion",
docs: {
description: RULE_DESCRIPTION[intent],
category: "WeChat Mini Program Best Practices",
recommended: false,
url: "https://github.com/airbnb/eslint-plugin-miniprogram"
}
},
create: function (context) {
var source = context.getSource();
var configData;
try {
var blocks = mina_sfc_1.default.parse(source);
var configJson = blocks.config.content.trim();
if (!configJson) {
return {};
}
configData = json5_1.default.parse(configJson);
}
catch (error) {
context.report({
loc: {
start: { line: 1, column: 0 },
end: { line: 1, column: 0 }
},
message: "parse config error " + error.toString()
});
}
var usingComponents = configData.usingComponents || {};
if (intent === "componentName") {
var filename = context.getFilename();
for (var _i = 0, _a = Object.entries(usingComponents); _i < _a.length; _i++) {
var _b = _a[_i], componentName = _b[0], componentPath = _b[1];
var expectName = exports.getExpectedComponentName(componentPath, filename);
if (expectName !== componentName) {
context.report({
loc: DEFAULT_LOC,
message: "prefer `" + expectName + "` instead of `" + componentName + "` for `" + componentPath + "`"
});
}
}
return {};
}
var registedComponents = new Set();
for (var _c = 0, _d = Object.keys(usingComponents); _c < _d.length; _c++) {
var component = _d[_c];
registedComponents.add(component);
}
var usedComponents = new Set();
var usedComponentsNodeMap = new Map();
var addUsedComponents = function (componentName, node) {
if (isBuildInComponents(componentName)) {
return;
}
usedComponents.add(componentName);
usedComponentsNodeMap.set(componentName, (usedComponentsNodeMap.get(componentName) || []).concat([
node
]));
};
return utils_1.default.defineTemplateBodyVisitor(context, {
VElement: function (node) {
addUsedComponents(node.name, node);
},
VAttribute: function attribute(node) {
var attrName = node.key.name;
if (!attrName.startsWith("generic:")) {
return;
}
var componentName = node.value.value;
addUsedComponents(componentName, node);
},
"VElement[name='template']:exit": function exit() {
if (intent === "unregisteredComponent") {
for (var _i = 0, _a = Array.from(usedComponents); _i < _a.length; _i++) {
var component = _a[_i];
if (!registedComponents.has(component)) {
for (var _b = 0, _c = usedComponentsNodeMap.get(component) || []; _b < _c.length; _b++) {
var componentNode = _c[_b];
context.report({
node: componentNode,
message: "unregistered component `" + component + "` in `usingComponents`"
});
}
}
}
}
if (intent === "unusedComponent") {
for (var _d = 0, _e = Array.from(registedComponents); _d < _e.length; _d++) {
var component = _e[_d];
if (!usedComponents.has(component)) {
context.report({
loc: DEFAULT_LOC,
message: "unused component `" + component + "` in `usingComponents`"
});
}
}
}
}
});
}
}); };
//# sourceMappingURL=check-using-components.js.map