UNPKG

eslint-plugin-css-modules

Version:

Checks that you are using the existent css/scss/less classes, no more no less

135 lines (126 loc) 16.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports["default"] = void 0; var _fp = _interopRequireDefault(require("lodash/fp")); var _lodash = _interopRequireDefault(require("lodash")); var _path = _interopRequireDefault(require("path")); var _core = require("../core"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } var _default = exports["default"] = { meta: { docs: { description: 'Checks that you are using all css/scss/less classes', recommended: true }, schema: [{ type: 'object', properties: { camelCase: { "enum": [true, 'dashes', 'only', 'dashes-only'] }, markAsUsed: { type: 'array' } } }] }, create: function create(context) { var markAsUsed = _lodash["default"].get(context, 'options[0].markAsUsed'); var camelCase = _lodash["default"].get(context, 'options[0].camelCase'); /* maps variable name to property Object map = { [variableName]: { classes: { foo: false, 'foo-bar': false }, classesMap: { foo: 'foo', fooBar: 'foo-bar', 'foo-bar': 'foo-bar' }, node: {...} } } example: import s from './foo.scss'; s is variable name property Object has two keys 1. classes: an object with className as key and a boolean as value. The boolean is marked if it is used in file 2. classesMap: an object with propertyName as key and its className as value 3. node: node that correspond to s (see example above) */ var map = {}; return { ImportDeclaration: function ImportDeclaration(node) { var styleImportNodeData = (0, _core.getStyleImportNodeData)(node); if (!styleImportNodeData) { return; } var importName = styleImportNodeData.importName, styleFilePath = styleImportNodeData.styleFilePath, importNode = styleImportNodeData.importNode; var styleFileAbsolutePath = (0, _core.getFilePath)(context, styleFilePath); var classes = {}; var classesMap = {}; if ((0, _core.fileExists)(styleFileAbsolutePath)) { // this will be used to mark s.foo as used in MemberExpression var ast = (0, _core.getAST)(styleFileAbsolutePath); classes = ast && (0, _core.getStyleClasses)(ast); classesMap = classes && (0, _core.getClassesMap)(classes, camelCase); } _lodash["default"].set(map, "".concat(importName, ".classes"), classes); _lodash["default"].set(map, "".concat(importName, ".classesMap"), classesMap); // save node for reporting unused styles _lodash["default"].set(map, "".concat(importName, ".node"), importNode); // save file path for reporting unused styles _lodash["default"].set(map, "".concat(importName, ".filePath"), styleFilePath); }, MemberExpression: function MemberExpression(node) { /* Check if property exists in css/scss file as class */ var objectName = node.object.name; var propertyName = (0, _core.getPropertyName)(node, camelCase); if (!propertyName) { return; } var className = _lodash["default"].get(map, "".concat(objectName, ".classesMap.").concat(propertyName)); if (className == null) { return; } // mark this property has used _lodash["default"].set(map, "".concat(objectName, ".classes.").concat(className), true); }, 'Program:exit': function ProgramExit() { /* Check if all classes defined in css/scss file are used */ /* we are looping over each import style node in program example: ``` import s from './foo.css'; import x from './bar.scss'; ``` then the loop will be run 2 times */ _lodash["default"].forIn(map, function (o) { var classes = o.classes, node = o.node, filePath = o.filePath; /* if option is passed to mark a class as used, example: eslint css-modules/no-unused-class: [2, { markAsUsed: ['container'] }] */ _lodash["default"].forEach(markAsUsed, function (usedClass) { classes[usedClass] = true; }); // classNames not marked as true are unused var unusedClasses = _fp["default"].compose(_fp["default"].keys, _fp["default"].omitBy(_fp["default"].identity) // omit truthy values )(classes); if (!_lodash["default"].isEmpty(unusedClasses)) { context.report(node, "Unused classes found in ".concat(_path["default"].basename(filePath), ": ").concat(unusedClasses.join(', '))); } }); } }; } }; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfZnAiLCJfaW50ZXJvcFJlcXVpcmVEZWZhdWx0IiwicmVxdWlyZSIsIl9sb2Rhc2giLCJfcGF0aCIsIl9jb3JlIiwib2JqIiwiX19lc01vZHVsZSIsIl9kZWZhdWx0IiwiZXhwb3J0cyIsIm1ldGEiLCJkb2NzIiwiZGVzY3JpcHRpb24iLCJyZWNvbW1lbmRlZCIsInNjaGVtYSIsInR5cGUiLCJwcm9wZXJ0aWVzIiwiY2FtZWxDYXNlIiwibWFya0FzVXNlZCIsImNyZWF0ZSIsImNvbnRleHQiLCJfIiwiZ2V0IiwibWFwIiwiSW1wb3J0RGVjbGFyYXRpb24iLCJub2RlIiwic3R5bGVJbXBvcnROb2RlRGF0YSIsImdldFN0eWxlSW1wb3J0Tm9kZURhdGEiLCJpbXBvcnROYW1lIiwic3R5bGVGaWxlUGF0aCIsImltcG9ydE5vZGUiLCJzdHlsZUZpbGVBYnNvbHV0ZVBhdGgiLCJnZXRGaWxlUGF0aCIsImNsYXNzZXMiLCJjbGFzc2VzTWFwIiwiZmlsZUV4aXN0cyIsImFzdCIsImdldEFTVCIsImdldFN0eWxlQ2xhc3NlcyIsImdldENsYXNzZXNNYXAiLCJzZXQiLCJjb25jYXQiLCJNZW1iZXJFeHByZXNzaW9uIiwib2JqZWN0TmFtZSIsIm9iamVjdCIsIm5hbWUiLCJwcm9wZXJ0eU5hbWUiLCJnZXRQcm9wZXJ0eU5hbWUiLCJjbGFzc05hbWUiLCJQcm9ncmFtRXhpdCIsImZvckluIiwibyIsImZpbGVQYXRoIiwiZm9yRWFjaCIsInVzZWRDbGFzcyIsInVudXNlZENsYXNzZXMiLCJmcCIsImNvbXBvc2UiLCJrZXlzIiwib21pdEJ5IiwiaWRlbnRpdHkiLCJpc0VtcHR5IiwicmVwb3J0IiwicGF0aCIsImJhc2VuYW1lIiwiam9pbiJdLCJzb3VyY2VzIjpbIi4uLy4uL2xpYi9ydWxlcy9uby11bnVzZWQtY2xhc3MuanMiXSwic291cmNlc0NvbnRlbnQiOlsiLyogQGZsb3cgKi9cbmltcG9ydCBmcCBmcm9tICdsb2Rhc2gvZnAnO1xuaW1wb3J0IF8gZnJvbSAnbG9kYXNoJztcbmltcG9ydCBwYXRoIGZyb20gJ3BhdGgnO1xuXG5pbXBvcnQge1xuICBnZXRTdHlsZUltcG9ydE5vZGVEYXRhLFxuICBnZXRTdHlsZUNsYXNzZXMsXG4gIGdldFByb3BlcnR5TmFtZSxcbiAgZ2V0Q2xhc3Nlc01hcCxcbiAgZ2V0RmlsZVBhdGgsXG4gIGdldEFTVCxcbiAgZmlsZUV4aXN0cyxcbn0gZnJvbSAnLi4vY29yZSc7XG5cbmltcG9ydCB0eXBlIHsgSnNOb2RlIH0gZnJvbSAnLi4vdHlwZXMnO1xuXG5leHBvcnQgZGVmYXVsdCB7XG4gIG1ldGE6IHtcbiAgICBkb2NzOiB7XG4gICAgICBkZXNjcmlwdGlvbjogJ0NoZWNrcyB0aGF0IHlvdSBhcmUgdXNpbmcgYWxsIGNzcy9zY3NzL2xlc3MgY2xhc3NlcycsXG4gICAgICByZWNvbW1lbmRlZDogdHJ1ZSxcbiAgICB9LFxuICAgIHNjaGVtYTogW1xuICAgICAge1xuICAgICAgICB0eXBlOiAnb2JqZWN0JyxcbiAgICAgICAgcHJvcGVydGllczoge1xuICAgICAgICAgIGNhbWVsQ2FzZTogeyBlbnVtOiBbdHJ1ZSwgJ2Rhc2hlcycsICdvbmx5JywgJ2Rhc2hlcy1vbmx5J10gfSxcbiAgICAgICAgICBtYXJrQXNVc2VkOiB7IHR5cGU6ICdhcnJheScgfSxcbiAgICAgICAgfSxcbiAgICAgIH1cbiAgICBdLFxuICB9LFxuICBjcmVhdGUgKGNvbnRleHQ6IE9iamVjdCkge1xuICAgIGNvbnN0IG1hcmtBc1VzZWQgPSBfLmdldChjb250ZXh0LCAnb3B0aW9uc1swXS5tYXJrQXNVc2VkJyk7XG4gICAgY29uc3QgY2FtZWxDYXNlID0gXy5nZXQoY29udGV4dCwgJ29wdGlvbnNbMF0uY2FtZWxDYXNlJyk7XG5cbiAgICAvKlxuICAgICAgIG1hcHMgdmFyaWFibGUgbmFtZSB0byBwcm9wZXJ0eSBPYmplY3RcbiAgICAgICBtYXAgPSB7XG4gICAgICAgICBbdmFyaWFibGVOYW1lXToge1xuICAgICAgICAgICBjbGFzc2VzOiB7IGZvbzogZmFsc2UsICdmb28tYmFyJzogZmFsc2UgfSxcbiAgICAgICAgICAgY2xhc3Nlc01hcDogeyBmb286ICdmb28nLCBmb29CYXI6ICdmb28tYmFyJywgJ2Zvby1iYXInOiAnZm9vLWJhcicgfSxcbiAgICAgICAgICAgbm9kZTogey4uLn1cbiAgICAgICAgIH1cbiAgICAgICB9XG5cbiAgICAgICBleGFtcGxlOlxuICAgICAgIGltcG9ydCBzIGZyb20gJy4vZm9vLnNjc3MnO1xuICAgICAgIHMgaXMgdmFyaWFibGUgbmFtZVxuXG4gICAgICAgcHJvcGVydHkgT2JqZWN0IGhhcyB0d28ga2V5c1xuICAgICAgIDEuIGNsYXNzZXM6IGFuIG9iamVjdCB3aXRoIGNsYXNzTmFtZSBhcyBrZXkgYW5kIGEgYm9vbGVhbiBhcyB2YWx1ZS4gVGhlIGJvb2xlYW4gaXMgbWFya2VkIGlmIGl0IGlzIHVzZWQgaW4gZmlsZVxuICAgICAgIDIuIGNsYXNzZXNNYXA6IGFuIG9iamVjdCB3aXRoIHByb3BlcnR5TmFtZSBhcyBrZXkgYW5kIGl0cyBjbGFzc05hbWUgYXMgdmFsdWVcbiAgICAgICAzLiBub2RlOiBub2RlIHRoYXQgY29ycmVzcG9uZCB0byBzIChzZWUgZXhhbXBsZSBhYm92ZSlcbiAgICAgKi9cbiAgICBjb25zdCBtYXAgPSB7fTtcblxuICAgIHJldHVybiB7XG4gICAgICBJbXBvcnREZWNsYXJhdGlvbiAobm9kZTogSnNOb2RlKSB7XG4gICAgICAgIGNvbnN0IHN0eWxlSW1wb3J0Tm9kZURhdGEgPSBnZXRTdHlsZUltcG9ydE5vZGVEYXRhKG5vZGUpO1xuXG4gICAgICAgIGlmICghc3R5bGVJbXBvcnROb2RlRGF0YSkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHtcbiAgICAgICAgICBpbXBvcnROYW1lLFxuICAgICAgICAgIHN0eWxlRmlsZVBhdGgsXG4gICAgICAgICAgaW1wb3J0Tm9kZSxcbiAgICAgICAgfSA9IHN0eWxlSW1wb3J0Tm9kZURhdGE7XG5cbiAgICAgICAgY29uc3Qgc3R5bGVGaWxlQWJzb2x1dGVQYXRoID0gZ2V0RmlsZVBhdGgoY29udGV4dCwgc3R5bGVGaWxlUGF0aCk7XG5cbiAgICAgICAgbGV0IGNsYXNzZXMgPSB7fTtcbiAgICAgICAgbGV0IGNsYXNzZXNNYXAgPSB7fTtcblxuICAgICAgICBpZiAoZmlsZUV4aXN0cyhzdHlsZUZpbGVBYnNvbHV0ZVBhdGgpKSB7XG4gICAgICAgICAgLy8gdGhpcyB3aWxsIGJlIHVzZWQgdG8gbWFyayBzLmZvbyBhcyB1c2VkIGluIE1lbWJlckV4cHJlc3Npb25cbiAgICAgICAgICBjb25zdCBhc3QgPSBnZXRBU1Qoc3R5bGVGaWxlQWJzb2x1dGVQYXRoKTtcbiAgICAgICAgICBjbGFzc2VzID0gYXN0ICYmIGdldFN0eWxlQ2xhc3Nlcyhhc3QpO1xuICAgICAgICAgIGNsYXNzZXNNYXAgPSBjbGFzc2VzICYmIGdldENsYXNzZXNNYXAoY2xhc3NlcywgY2FtZWxDYXNlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIF8uc2V0KG1hcCwgYCR7aW1wb3J0TmFtZX0uY2xhc3Nlc2AsIGNsYXNzZXMpO1xuICAgICAgICBfLnNldChtYXAsIGAke2ltcG9ydE5hbWV9LmNsYXNzZXNNYXBgLCBjbGFzc2VzTWFwKTtcblxuICAgICAgICAvLyBzYXZlIG5vZGUgZm9yIHJlcG9ydGluZyB1bnVzZWQgc3R5bGVzXG4gICAgICAgIF8uc2V0KG1hcCwgYCR7aW1wb3J0TmFtZX0ubm9kZWAsIGltcG9ydE5vZGUpO1xuXG4gICAgICAgIC8vIHNhdmUgZmlsZSBwYXRoIGZvciByZXBvcnRpbmcgdW51c2VkIHN0eWxlc1xuICAgICAgICBfLnNldChtYXAsIGAke2ltcG9ydE5hbWV9LmZpbGVQYXRoYCwgc3R5bGVGaWxlUGF0aCk7XG4gICAgICB9LFxuICAgICAgTWVtYmVyRXhwcmVzc2lvbjogKG5vZGU6IEpzTm9kZSkgPT4ge1xuICAgICAgICAvKlxuICAgICAgICAgICBDaGVjayBpZiBwcm9wZXJ0eSBleGlzdHMgaW4gY3NzL3Njc3MgZmlsZSBhcyBjbGFzc1xuICAgICAgICAgKi9cblxuICAgICAgICBjb25zdCBvYmplY3ROYW1lID0gbm9kZS5vYmplY3QubmFtZTtcbiAgICAgICAgY29uc3QgcHJvcGVydHlOYW1lID0gZ2V0UHJvcGVydHlOYW1lKG5vZGUsIGNhbWVsQ2FzZSk7XG5cbiAgICAgICAgaWYgKCFwcm9wZXJ0eU5hbWUpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBjbGFzc05hbWUgPSBfLmdldChtYXAsIGAke29iamVjdE5hbWV9LmNsYXNzZXNNYXAuJHtwcm9wZXJ0eU5hbWV9YCk7XG5cbiAgICAgICAgaWYgKGNsYXNzTmFtZSA9PSBudWxsKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gbWFyayB0aGlzIHByb3BlcnR5IGhhcyB1c2VkXG4gICAgICAgIF8uc2V0KG1hcCwgYCR7b2JqZWN0TmFtZX0uY2xhc3Nlcy4ke2NsYXNzTmFtZX1gLCB0cnVlKTtcbiAgICAgIH0sXG4gICAgICAnUHJvZ3JhbTpleGl0JyAoKSB7XG4gICAgICAgIC8qXG4gICAgICAgICAgIENoZWNrIGlmIGFsbCBjbGFzc2VzIGRlZmluZWQgaW4gY3NzL3Njc3MgZmlsZSBhcmUgdXNlZFxuICAgICAgICAgKi9cblxuICAgICAgICAvKlxuICAgICAgICAgICB3ZSBhcmUgbG9vcGluZyBvdmVyIGVhY2ggaW1wb3J0IHN0eWxlIG5vZGUgaW4gcHJvZ3JhbVxuICAgICAgICAgICBleGFtcGxlOlxuICAgICAgICAgICBgYGBcbiAgICAgICAgICAgICBpbXBvcnQgcyBmcm9tICcuL2Zvby5jc3MnO1xuICAgICAgICAgICAgIGltcG9ydCB4IGZyb20gJy4vYmFyLnNjc3MnO1xuICAgICAgICAgICBgYGBcbiAgICAgICAgICAgdGhlbiB0aGUgbG9vcCB3aWxsIGJlIHJ1biAyIHRpbWVzXG4gICAgICAgICAqL1xuICAgICAgICBfLmZvckluKG1hcCwgKG8pID0+IHtcbiAgICAgICAgICBjb25zdCB7IGNsYXNzZXMsIG5vZGUsIGZpbGVQYXRoIH0gPSBvO1xuXG4gICAgICAgICAgLypcbiAgICAgICAgICAgICBpZiBvcHRpb24gaXMgcGFzc2VkIHRvIG1hcmsgYSBjbGFzcyBhcyB1c2VkLCBleGFtcGxlOlxuICAgICAgICAgICAgIGVzbGludCBjc3MtbW9kdWxlcy9uby11bnVzZWQtY2xhc3M6IFsyLCB7IG1hcmtBc1VzZWQ6IFsnY29udGFpbmVyJ10gfV1cbiAgICAgICAgICAgKi9cbiAgICAgICAgICBfLmZvckVhY2gobWFya0FzVXNlZCwgKHVzZWRDbGFzcykgPT4ge1xuICAgICAgICAgICAgY2xhc3Nlc1t1c2VkQ2xhc3NdID0gdHJ1ZTtcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIC8vIGNsYXNzTmFtZXMgbm90IG1hcmtlZCBhcyB0cnVlIGFyZSB1bnVzZWRcbiAgICAgICAgICBjb25zdCB1bnVzZWRDbGFzc2VzID0gZnAuY29tcG9zZShcbiAgICAgICAgICAgIGZwLmtleXMsXG4gICAgICAgICAgICBmcC5vbWl0QnkoZnAuaWRlbnRpdHkpLCAvLyBvbWl0IHRydXRoeSB2YWx1ZXNcbiAgICAgICAgICApKGNsYXNzZXMpO1xuXG4gICAgICAgICAgaWYgKCFfLmlzRW1wdHkodW51c2VkQ2xhc3NlcykpIHtcbiAgICAgICAgICAgIGNvbnRleHQucmVwb3J0KG5vZGUsIGBVbnVzZWQgY2xhc3NlcyBmb3VuZCBpbiAke3BhdGguYmFzZW5hbWUoZmlsZVBhdGgpfTogJHt1bnVzZWRDbGFzc2VzLmpvaW4oJywgJyl9YCk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9O1xuICB9XG59O1xuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7QUFDQSxJQUFBQSxHQUFBLEdBQUFDLHNCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBQyxPQUFBLEdBQUFGLHNCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBRSxLQUFBLEdBQUFILHNCQUFBLENBQUFDLE9BQUE7QUFFQSxJQUFBRyxLQUFB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