UNPKG

10.6 kBJavaScriptView Raw
1'use strict';
2
3var _path = require('path');
4
5var _path2 = _interopRequireDefault(_path);
6
7var _sumBy = require('lodash/sumBy');
8
9var _sumBy2 = _interopRequireDefault(_sumBy);
10
11var _resolve = require('eslint-module-utils/resolve');
12
13var _resolve2 = _interopRequireDefault(_resolve);
14
15var _moduleVisitor = require('eslint-module-utils/moduleVisitor');
16
17var _moduleVisitor2 = _interopRequireDefault(_moduleVisitor);
18
19var _docsUrl = require('../docsUrl');
20
21var _docsUrl2 = _interopRequireDefault(_docsUrl);
22
23function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
24
25/**
26 * convert a potentially relative path from node utils into a true
27 * relative path.
28 *
29 * ../ -> ..
30 * ./ -> .
31 * .foo/bar -> ./.foo/bar
32 * ..foo/bar -> ./..foo/bar
33 * foo/bar -> ./foo/bar
34 *
35 * @param rel {string} relative posix path potentially missing leading './'
36 * @returns {string} relative posix path that always starts with a ./
37 **/
38function toRel(rel) {
39 const stripped = rel.replace(/\/$/g, '');
40 return (/^((\.\.)|(\.))($|\/)/.test(stripped) ? stripped : `./${stripped}`
41 );
42} /**
43 * @fileOverview Ensures that there are no useless path segments
44 * @author Thomas Grainger
45 */
46
47function normalize(fn) {
48 return toRel(_path2.default.posix.normalize(fn));
49}
50
51const countRelParent = x => (0, _sumBy2.default)(x, v => v === '..');
52
53module.exports = {
54 meta: {
55 docs: {
56 url: (0, _docsUrl2.default)('no-useless-path-segments')
57 },
58
59 schema: [{
60 type: 'object',
61 properties: {
62 commonjs: { type: 'boolean' }
63 },
64 additionalProperties: false
65 }],
66
67 fixable: 'code'
68 },
69
70 create: function (context) {
71 const currentDir = _path2.default.dirname(context.getFilename());
72
73 function checkSourceValue(source) {
74 const value = source.value;
75
76
77 function report(proposed) {
78 context.report({
79 node: source,
80 message: `Useless path segments for "${value}", should be "${proposed}"`,
81 fix: fixer => fixer.replaceText(source, JSON.stringify(proposed))
82 });
83 }
84
85 if (!value.startsWith('.')) {
86 return;
87 }
88
89 const resolvedPath = (0, _resolve2.default)(value, context);
90 const normed = normalize(value);
91 if (normed !== value && resolvedPath === (0, _resolve2.default)(normed, context)) {
92 return report(normed);
93 }
94
95 if (value.startsWith('./')) {
96 return;
97 }
98
99 if (resolvedPath === undefined) {
100 return;
101 }
102
103 const expected = _path2.default.relative(currentDir, resolvedPath);
104 const expectedSplit = expected.split(_path2.default.sep);
105 const valueSplit = value.replace(/^\.\//, '').split('/');
106 const valueNRelParents = countRelParent(valueSplit);
107 const expectedNRelParents = countRelParent(expectedSplit);
108 const diff = valueNRelParents - expectedNRelParents;
109
110 if (diff <= 0) {
111 return;
112 }
113
114 return report(toRel(valueSplit.slice(0, expectedNRelParents).concat(valueSplit.slice(valueNRelParents + diff)).join('/')));
115 }
116
117 return (0, _moduleVisitor2.default)(checkSourceValue, context.options[0]);
118 }
119};
120//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInJ1bGVzL25vLXVzZWxlc3MtcGF0aC1zZWdtZW50cy5qcyJdLCJuYW1lcyI6WyJ0b1JlbCIsInJlbCIsInN0cmlwcGVkIiwicmVwbGFjZSIsInRlc3QiLCJub3JtYWxpemUiLCJmbiIsInBhdGgiLCJwb3NpeCIsImNvdW50UmVsUGFyZW50IiwieCIsInYiLCJtb2R1bGUiLCJleHBvcnRzIiwibWV0YSIsImRvY3MiLCJ1cmwiLCJzY2hlbWEiLCJ0eXBlIiwicHJvcGVydGllcyIsImNvbW1vbmpzIiwiYWRkaXRpb25hbFByb3BlcnRpZXMiLCJmaXhhYmxlIiwiY3JlYXRlIiwiY29udGV4dCIsImN1cnJlbnREaXIiLCJkaXJuYW1lIiwiZ2V0RmlsZW5hbWUiLCJjaGVja1NvdXJjZVZhbHVlIiwic291cmNlIiwidmFsdWUiLCJyZXBvcnQiLCJwcm9wb3NlZCIsIm5vZGUiLCJtZXNzYWdlIiwiZml4IiwiZml4ZXIiLCJyZXBsYWNlVGV4dCIsIkpTT04iLCJzdHJpbmdpZnkiLCJzdGFydHNXaXRoIiwicmVzb2x2ZWRQYXRoIiwibm9ybWVkIiwidW5kZWZpbmVkIiwiZXhwZWN0ZWQiLCJyZWxhdGl2ZSIsImV4cGVjdGVkU3BsaXQiLCJzcGxpdCIsInNlcCIsInZhbHVlU3BsaXQiLCJ2YWx1ZU5SZWxQYXJlbnRzIiwiZXhwZWN0ZWROUmVsUGFyZW50cyIsImRpZmYiLCJzbGljZSIsImNvbmNhdCIsImpvaW4iLCJvcHRpb25zIl0sIm1hcHBpbmdzIjoiOztBQUtBOzs7O0FBQ0E7Ozs7QUFDQTs7OztBQUNBOzs7O0FBQ0E7Ozs7OztBQUVBOzs7Ozs7Ozs7Ozs7O0FBYUEsU0FBU0EsS0FBVCxDQUFlQyxHQUFmLEVBQW9CO0FBQ2xCLFFBQU1DLFdBQVdELElBQUlFLE9BQUosQ0FBWSxNQUFaLEVBQW9CLEVBQXBCLENBQWpCO0FBQ0EsU0FBTyx3QkFBdUJDLElBQXZCLENBQTRCRixRQUE1QixJQUF3Q0EsUUFBeEMsR0FBb0QsS0FBSUEsUUFBUztBQUF4RTtBQUNELEMsQ0EzQkQ7Ozs7O0FBNkJBLFNBQVNHLFNBQVQsQ0FBbUJDLEVBQW5CLEVBQXVCO0FBQ3JCLFNBQU9OLE1BQU1PLGVBQUtDLEtBQUwsQ0FBV0gsU0FBWCxDQUFxQkMsRUFBckIsQ0FBTixDQUFQO0FBQ0Q7O0FBRUQsTUFBTUcsaUJBQWlCQyxLQUFLLHFCQUFNQSxDQUFOLEVBQVNDLEtBQUtBLE1BQU0sSUFBcEIsQ0FBNUI7O0FBRUFDLE9BQU9DLE9BQVAsR0FBaUI7QUFDZkMsUUFBTTtBQUNKQyxVQUFNO0FBQ0pDLFdBQUssdUJBQVEsMEJBQVI7QUFERCxLQURGOztBQUtKQyxZQUFRLENBQ047QUFDRUMsWUFBTSxRQURSO0FBRUVDLGtCQUFZO0FBQ1ZDLGtCQUFVLEVBQUVGLE1BQU0sU0FBUjtBQURBLE9BRmQ7QUFLRUcsNEJBQXNCO0FBTHhCLEtBRE0sQ0FMSjs7QUFlSkMsYUFBUztBQWZMLEdBRFM7O0FBbUJmQyxVQUFRLFVBQVVDLE9BQVYsRUFBbUI7QUFDekIsVUFBTUMsYUFBYWxCLGVBQUttQixPQUFMLENBQWFGLFFBQVFHLFdBQVIsRUFBYixDQUFuQjs7QUFFQSxhQUFTQyxnQkFBVCxDQUEwQkMsTUFBMUIsRUFBa0M7QUFBQSxZQUN4QkMsS0FEd0IsR0FDZEQsTUFEYyxDQUN4QkMsS0FEd0I7OztBQUdoQyxlQUFTQyxNQUFULENBQWdCQyxRQUFoQixFQUEwQjtBQUN4QlIsZ0JBQVFPLE1BQVIsQ0FBZTtBQUNiRSxnQkFBTUosTUFETztBQUViSyxtQkFBVSw4QkFBNkJKLEtBQU0saUJBQWdCRSxRQUFTLEdBRnpEO0FBR2JHLGVBQUtDLFNBQVNBLE1BQU1DLFdBQU4sQ0FBa0JSLE1BQWxCLEVBQTBCUyxLQUFLQyxTQUFMLENBQWVQLFFBQWYsQ0FBMUI7QUFIRCxTQUFmO0FBS0Q7O0FBRUQsVUFBSSxDQUFDRixNQUFNVSxVQUFOLENBQWlCLEdBQWpCLENBQUwsRUFBNEI7QUFDMUI7QUFDRDs7QUFFRCxZQUFNQyxlQUFlLHVCQUFRWCxLQUFSLEVBQWVOLE9BQWYsQ0FBckI7QUFDQSxZQUFNa0IsU0FBU3JDLFVBQVV5QixLQUFWLENBQWY7QUFDQSxVQUFJWSxXQUFXWixLQUFYLElBQW9CVyxpQkFBaUIsdUJBQVFDLE1BQVIsRUFBZ0JsQixPQUFoQixDQUF6QyxFQUFtRTtBQUNqRSxlQUFPTyxPQUFPVyxNQUFQLENBQVA7QUFDRDs7QUFFRCxVQUFJWixNQUFNVSxVQUFOLENBQWlCLElBQWpCLENBQUosRUFBNEI7QUFDMUI7QUFDRDs7QUFFRCxVQUFJQyxpQkFBaUJFLFNBQXJCLEVBQWdDO0FBQzlCO0FBQ0Q7O0FBRUQsWUFBTUMsV0FBV3JDLGVBQUtzQyxRQUFMLENBQWNwQixVQUFkLEVBQTBCZ0IsWUFBMUIsQ0FBakI7QUFDQSxZQUFNSyxnQkFBZ0JGLFNBQVNHLEtBQVQsQ0FBZXhDLGVBQUt5QyxHQUFwQixDQUF0QjtBQUNBLFlBQU1DLGFBQWFuQixNQUFNM0IsT0FBTixDQUFjLE9BQWQsRUFBdUIsRUFBdkIsRUFBMkI0QyxLQUEzQixDQUFpQyxHQUFqQyxDQUFuQjtBQUNBLFlBQU1HLG1CQUFtQnpDLGVBQWV3QyxVQUFmLENBQXpCO0FBQ0EsWUFBTUUsc0JBQXNCMUMsZUFBZXFDLGFBQWYsQ0FBNUI7QUFDQSxZQUFNTSxPQUFPRixtQkFBbUJDLG1CQUFoQzs7QUFFQSxVQUFJQyxRQUFRLENBQVosRUFBZTtBQUNiO0FBQ0Q7O0FBRUQsYUFBT3JCLE9BQ0wvQixNQUFNaUQsV0FDSEksS0FERyxDQUNHLENBREgsRUFDTUYsbUJBRE4sRUFFSEcsTUFGRyxDQUVJTCxXQUFXSSxLQUFYLENBQWlCSCxtQkFBbUJFLElBQXBDLENBRkosRUFHSEcsSUFIRyxDQUdFLEdBSEYsQ0FBTixDQURLLENBQVA7QUFNRDs7QUFFRCxXQUFPLDZCQUFjM0IsZ0JBQWQsRUFBZ0NKLFFBQVFnQyxPQUFSLENBQWdCLENBQWhCLENBQWhDLENBQVA7QUFDRDtBQXZFYyxDQUFqQiIsImZpbGUiOiJydWxlcy9uby11c2VsZXNzLXBhdGgtc2VnbWVudHMuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBmaWxlT3ZlcnZpZXcgRW5zdXJlcyB0aGF0IHRoZXJlIGFyZSBubyB1c2VsZXNzIHBhdGggc2VnbWVudHNcbiAqIEBhdXRob3IgVGhvbWFzIEdyYWluZ2VyXG4gKi9cblxuaW1wb3J0IHBhdGggZnJvbSAncGF0aCdcbmltcG9ydCBzdW1CeSBmcm9tICdsb2Rhc2gvc3VtQnknXG5pbXBvcnQgcmVzb2x2ZSBmcm9tICdlc2xpbnQtbW9kdWxlLXV0aWxzL3Jlc29sdmUnXG5pbXBvcnQgbW9kdWxlVmlzaXRvciBmcm9tICdlc2xpbnQtbW9kdWxlLXV0aWxzL21vZHVsZVZpc2l0b3InXG5pbXBvcnQgZG9jc1VybCBmcm9tICcuLi9kb2NzVXJsJ1xuXG4vKipcbiAqIGNvbnZlcnQgYSBwb3RlbnRpYWxseSByZWxhdGl2ZSBwYXRoIGZyb20gbm9kZSB1dGlscyBpbnRvIGEgdHJ1ZVxuICogcmVsYXRpdmUgcGF0aC5cbiAqXG4gKiAuLi8gLT4gLi5cbiAqIC4vIC0+IC5cbiAqIC5mb28vYmFyIC0+IC4vLmZvby9iYXJcbiAqIC4uZm9vL2JhciAtPiAuLy4uZm9vL2JhclxuICogZm9vL2JhciAtPiAuL2Zvby9iYXJcbiAqXG4gKiBAcGFyYW0gcmVsIHtzdHJpbmd9IHJlbGF0aXZlIHBvc2l4IHBhdGggcG90ZW50aWFsbHkgbWlzc2luZyBsZWFkaW5nICcuLydcbiAqIEByZXR1cm5zIHtzdHJpbmd9IHJlbGF0aXZlIHBvc2l4IHBhdGggdGhhdCBhbHdheXMgc3RhcnRzIHdpdGggYSAuL1xuICoqL1xuZnVuY3Rpb24gdG9SZWwocmVsKSB7XG4gIGNvbnN0IHN0cmlwcGVkID0gcmVsLnJlcGxhY2UoL1xcLyQvZywgJycpXG4gIHJldHVybiAvXigoXFwuXFwuKXwoXFwuKSkoJHxcXC8pLy50ZXN0KHN0cmlwcGVkKSA/IHN0cmlwcGVkIDogYC4vJHtzdHJpcHBlZH1gXG59XG5cbmZ1bmN0aW9uIG5vcm1hbGl6ZShmbikge1xuICByZXR1cm4gdG9SZWwocGF0aC5wb3NpeC5ub3JtYWxpemUoZm4pKVxufVxuXG5jb25zdCBjb3VudFJlbFBhcmVudCA9IHggPT4gc3VtQnkoeCwgdiA9PiB2ID09PSAnLi4nKVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgbWV0YToge1xuICAgIGRvY3M6IHtcbiAgICAgIHVybDogZG9jc1VybCgnbm8tdXNlbGVzcy1wYXRoLXNlZ21lbnRzJyksXG4gICAgfSxcblxuICAgIHNjaGVtYTogW1xuICAgICAge1xuICAgICAgICB0eXBlOiAnb2JqZWN0JyxcbiAgICAgICAgcHJvcGVydGllczoge1xuICAgICAgICAgIGNvbW1vbmpzOiB7IHR5cGU6ICdib29sZWFuJyB9LFxuICAgICAgICB9LFxuICAgICAgICBhZGRpdGlvbmFsUHJvcGVydGllczogZmFsc2UsXG4gICAgICB9LFxuICAgIF0sXG5cbiAgICBmaXhhYmxlOiAnY29kZScsXG4gIH0sXG5cbiAgY3JlYXRlOiBmdW5jdGlvbiAoY29udGV4dCkge1xuICAgIGNvbnN0IGN1cnJlbnREaXIgPSBwYXRoLmRpcm5hbWUoY29udGV4dC5nZXRGaWxlbmFtZSgpKVxuXG4gICAgZnVuY3Rpb24gY2hlY2tTb3VyY2VWYWx1ZShzb3VyY2UpIHtcbiAgICAgIGNvbnN0IHsgdmFsdWUgfSA9IHNvdXJjZVxuXG4gICAgICBmdW5jdGlvbiByZXBvcnQocHJvcG9zZWQpIHtcbiAgICAgICAgY29udGV4dC5yZXBvcnQoe1xuICAgICAgICAgIG5vZGU6IHNvdXJjZSxcbiAgICAgICAgICBtZXNzYWdlOiBgVXNlbGVzcyBwYXRoIHNlZ21lbnRzIGZvciBcIiR7dmFsdWV9XCIsIHNob3VsZCBiZSBcIiR7cHJvcG9zZWR9XCJgLFxuICAgICAgICAgIGZpeDogZml4ZXIgPT4gZml4ZXIucmVwbGFjZVRleHQoc291cmNlLCBKU09OLnN0cmluZ2lmeShwcm9wb3NlZCkpLFxuICAgICAgICB9KVxuICAgICAgfVxuXG4gICAgICBpZiAoIXZhbHVlLnN0YXJ0c1dpdGgoJy4nKSkge1xuICAgICAgICByZXR1cm5cbiAgICAgIH1cblxuICAgICAgY29uc3QgcmVzb2x2ZWRQYXRoID0gcmVzb2x2ZSh2YWx1ZSwgY29udGV4dClcbiAgICAgIGNvbnN0IG5vcm1lZCA9IG5vcm1hbGl6ZSh2YWx1ZSlcbiAgICAgIGlmIChub3JtZWQgIT09IHZhbHVlICYmIHJlc29sdmVkUGF0aCA9PT0gcmVzb2x2ZShub3JtZWQsIGNvbnRleHQpKSB7XG4gICAgICAgIHJldHVybiByZXBvcnQobm9ybWVkKVxuICAgICAgfVxuXG4gICAgICBpZiAodmFsdWUuc3RhcnRzV2l0aCgnLi8nKSkge1xuICAgICAgICByZXR1cm5cbiAgICAgIH1cblxuICAgICAgaWYgKHJlc29sdmVkUGF0aCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHJldHVyblxuICAgICAgfVxuXG4gICAgICBjb25zdCBleHBlY3RlZCA9IHBhdGgucmVsYXRpdmUoY3VycmVudERpciwgcmVzb2x2ZWRQYXRoKVxuICAgICAgY29uc3QgZXhwZWN0ZWRTcGxpdCA9IGV4cGVjdGVkLnNwbGl0KHBhdGguc2VwKVxuICAgICAgY29uc3QgdmFsdWVTcGxpdCA9IHZhbHVlLnJlcGxhY2UoL15cXC5cXC8vLCAnJykuc3BsaXQoJy8nKVxuICAgICAgY29uc3QgdmFsdWVOUmVsUGFyZW50cyA9IGNvdW50UmVsUGFyZW50KHZhbHVlU3BsaXQpXG4gICAgICBjb25zdCBleHBlY3RlZE5SZWxQYXJlbnRzID0gY291bnRSZWxQYXJlbnQoZXhwZWN0ZWRTcGxpdClcbiAgICAgIGNvbnN0IGRpZmYgPSB2YWx1ZU5SZWxQYXJlbnRzIC0gZXhwZWN0ZWROUmVsUGFyZW50c1xuXG4gICAgICBpZiAoZGlmZiA8PSAwKSB7XG4gICAgICAgIHJldHVyblxuICAgICAgfVxuXG4gICAgICByZXR1cm4gcmVwb3J0KFxuICAgICAgICB0b1JlbCh2YWx1ZVNwbGl0XG4gICAgICAgICAgLnNsaWNlKDAsIGV4cGVjdGVkTlJlbFBhcmVudHMpXG4gICAgICAgICAgLmNvbmNhdCh2YWx1ZVNwbGl0LnNsaWNlKHZhbHVlTlJlbFBhcmVudHMgKyBkaWZmKSlcbiAgICAgICAgICAuam9pbignLycpKVxuICAgICAgKVxuICAgIH1cblxuICAgIHJldHVybiBtb2R1bGVWaXNpdG9yKGNoZWNrU291cmNlVmFsdWUsIGNvbnRleHQub3B0aW9uc1swXSlcbiAgfSxcbn1cbiJdfQ==
\No newline at end of file