UNPKG

plugin-light

Version:

Webpack 相关插件、Loader、基础配置及 CLI 命令

226 lines (209 loc) 6.82 kB
'use strict'; var stylelint = require('stylelint'); var selectorParser = require('postcss-selector-parser'); var path = require('path'); var vueTemplateCompiler = require('vue-template-compiler'); var tComm = require('t-comm'); function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } function _interopNamespace(e) { if (e && e.__esModule) return e; var n = Object.create(null); if (e) { Object.keys(e).forEach(function (k) { if (k !== 'default') { var d = Object.getOwnPropertyDescriptor(e, k); Object.defineProperty(n, k, d.get ? d : { enumerable: true, get: function () { return e[k]; } }); } }); } n["default"] = e; return Object.freeze(n); } var stylelint__default = /*#__PURE__*/_interopDefaultLegacy(stylelint); var selectorParser__default = /*#__PURE__*/_interopDefaultLegacy(selectorParser); var path__namespace = /*#__PURE__*/_interopNamespace(path); function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); } function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); } var htmlClassReg = /class="([^"]+)"/g; function getHtmlClasses(file) { var content = tComm.readFileSync(file); var result = []; var match = htmlClassReg.exec(content); while (match) { result.push(parseVariableClass(match[1])); match = htmlClassReg.exec(content); } var flattened = result.reduce(function (acc, item) { var list = item.split(' '); acc.push.apply(acc, _toConsumableArray(list)); return acc; }, []).map(function (item) { return filterSymbols(item); }).filter(function (item) { return item; }); return flattened; } function filterSymbols(name) { var reg = /[:'"{[\]},]/g; return name.replace(reg, '').replace('\n', ''); } function parseVariableClass(name) { if (!name.includes('{{')) { return name; } var pure = name.replace(/^\{\{\[(.*)\]\}\}$/, '$1'); var list = pure.split(','); var newList = list.reduce(function (acc, item) { acc.push.apply(acc, _toConsumableArray(parseQuestionClass(item))); return acc; }, []); return newList.join(' '); } function parseQuestionClass(name) { name = name.replace(/^'(.*?)'$/g, '$1'); if (!name.includes('?')) { return [name]; } var reg = /\?'([^']*)':'([^']*)'/; var match = name.match(reg); if (!match) { return []; } return [match[1], match[2]].filter(function (item) { return item; }); } var TIP_STYLE_NAME = '@TIP_STYLE_NAME'; function getCssFilePath(file, vuePath) { if (file === TIP_STYLE_NAME) { return file; } if (file.startsWith('.')) { return path__namespace.resolve(path__namespace.dirname(vuePath), file); } if (file.startsWith('src')) { return path__namespace.resolve(process.cwd(), file); } return file; } function parseVue(file) { var content = tComm.readFileSync(file); var res = vueTemplateCompiler.parseComponent(content); var result = res.styles.map(function (item) { return item.src; }).filter(function (item) { return item; }).map(function (item) { return getCssFilePath(item, file); }); return result; } function checkCss(cssFile) { var firstDir = path__namespace.dirname(cssFile); var secondDir = path__namespace.resolve(firstDir, '..'); var result = []; tComm.traverseFolder(checkVue.bind(null, cssFile, result), secondDir); var classResult = []; result.map(function (item) { classResult.push.apply(classResult, _toConsumableArray(getHtmlClasses(item))); }); return classResult; } function checkVue(cssFile, vueResult, filePath) { if (!filePath.endsWith('.vue')) { return; } var result = parseVue(filePath); if (result.includes(cssFile) || result.includes(TIP_STYLE_NAME)) { vueResult.push(filePath); } } var _stylelint$utils = stylelint__default["default"].utils, report = _stylelint$utils.report, ruleMessages = _stylelint$utils.ruleMessages, validateOptions = _stylelint$utils.validateOptions; var ruleName = 'no-useless-css'; var messages = ruleMessages(ruleName, { expected: function expected(selector) { return "Unexpected ".concat(selector); } }); var rule = function rule(primaryOption) { return function lint(postcssRoot, postcssResult) { var validOptions = validateOptions(postcssResult, ruleName, { actual: primaryOption, possible: function possible(option) { if (![null, 'warning', 'error'].includes(option)) { return false; } return true; } }); if (!validOptions) { return; } var classList = checkCss(postcssRoot.source.input.file); postcssRoot.walkRules(function (ruleNode) { var selector = ruleNode.selector; selectorParser__default["default"](function (nodes) { nodes.walk(function (node) { if (node.type !== 'class') { return; } var value = node.value; if (!classList.includes(value)) { report({ ruleName: ruleName, result: postcssResult, message: messages.expected(node.value), node: ruleNode, word: node.value, severity: primaryOption }); } }); }).processSync(selector); }); }; }; rule.ruleName = ruleName; rule.messages = messages; var uselessCssPlugin = { ruleName: ruleName, messages: messages, rule: rule }; var nameSpace = function nameSpace(ruleName) { return "stylelint-plugin/".concat(ruleName); }; var RULES = [uselessCssPlugin].map(function (item) { return stylelint__default["default"].createPlugin(nameSpace(item.ruleName), item.rule); }); module.exports = RULES;