eslint-plugin-unicorn 4.0.2 → 6.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js CHANGED
@@ -13,8 +13,11 @@ module.exports = {
13
13
  ecmaVersion: 2018,
14
14
  sourceType: 'module'
15
15
  },
16
+ plugins: [
17
+ 'unicorn'
18
+ ],
16
19
  rules: {
17
- 'unicorn/catch-error-name': ['off', {name: 'err'}],
20
+ 'unicorn/catch-error-name': ['error', {name: 'error'}],
18
21
  'unicorn/explicit-length-check': 'error',
19
22
  'unicorn/filename-case': ['error', {case: 'kebabCase'}],
20
23
  'unicorn/no-abusive-eslint-disable': 'error',
@@ -35,7 +38,8 @@ module.exports = {
35
38
  'unicorn/prefer-spread': 'error',
36
39
  'unicorn/error-message': 'error',
37
40
  'unicorn/no-unsafe-regex': 'off',
38
- 'unicorn/prefer-add-event-listener': 'error'
41
+ 'unicorn/prefer-add-event-listener': 'error',
42
+ 'unicorn/prefer-exponentiation-operator': 'error'
39
43
  }
40
44
  }
41
45
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-unicorn",
3
- "version": "4.0.2",
3
+ "version": "6.0.1",
4
4
  "description": "Various awesome ESLint rules",
5
5
  "license": "MIT",
6
6
  "repository": "sindresorhus/eslint-plugin-unicorn",
@@ -10,12 +10,11 @@
10
10
  "url": "sindresorhus.com"
11
11
  },
12
12
  "engines": {
13
- "node": ">=4"
13
+ "node": ">=6"
14
14
  },
15
15
  "scripts": {
16
- "test": "xo && nyc ava",
17
- "integration": "./test/integration/test.js",
18
- "coveralls": "nyc report --reporter=text-lcov | coveralls"
16
+ "test": "nyc ava",
17
+ "integration": "./test/integration/test.js"
19
18
  },
20
19
  "files": [
21
20
  "index.js",
@@ -46,17 +45,17 @@
46
45
  "chalk": "^2.0.1",
47
46
  "coveralls": "^3.0.0",
48
47
  "del": "^3.0.0",
49
- "eslint": "^4.0.0",
48
+ "eslint": "^5.0.0",
50
49
  "eslint-ava-rule-tester": "^2.0.0",
51
- "execa": "^0.9.0",
52
- "listr": "^0.13.0",
53
- "nyc": "^11.0.3",
50
+ "execa": "^0.10.0",
51
+ "listr": "^0.14.1",
52
+ "nyc": "^12.0.2",
54
53
  "pify": "^3.0.0",
55
54
  "tempy": "^0.2.1",
56
55
  "xo": "*"
57
56
  },
58
57
  "peerDependencies": {
59
- "eslint": ">=4"
58
+ "eslint": ">=5.0.0"
60
59
  },
61
60
  "ava": {
62
61
  "files": [
package/readme.md CHANGED
@@ -26,14 +26,14 @@ Configure it in `package.json`.
26
26
  "es6": true
27
27
  },
28
28
  "parserOptions": {
29
- "ecmaVersion": 2017,
29
+ "ecmaVersion": 2018,
30
30
  "sourceType": "module"
31
31
  },
32
32
  "plugins": [
33
33
  "unicorn"
34
34
  ],
35
35
  "rules": {
36
- "unicorn/catch-error-name": ["error", {"name": "err"}],
36
+ "unicorn/catch-error-name": ["error", {"name": "error"}],
37
37
  "unicorn/explicit-length-check": "error",
38
38
  "unicorn/filename-case": ["error", {"case": "kebabCase"}],
39
39
  "unicorn/no-abusive-eslint-disable": "error",
@@ -85,6 +85,7 @@ Configure it in `package.json`.
85
85
  - [error-message](docs/rules/error-message.md) - Enforce passing a `message` value when throwing a built-in error.
86
86
  - [no-unsafe-regex](docs/rules/no-unsafe-regex.md) - Disallow unsafe regular expressions.
87
87
  - [prefer-add-event-listener](docs/rules/prefer-add-event-listener.md) - Prefer `addEventListener` over `on`-functions. *(fixable)*
88
+ - [prefer-exponentiation-operator](docs/rules/prefer-exponentiation-operator.md) - Prefer the exponentiation operator over `Math.pow()` *(fixable)*
88
89
 
89
90
 
90
91
  ## Recommended config
@@ -97,9 +98,6 @@ Enable it in your `package.json` with the `extends` option:
97
98
  {
98
99
  "name": "my-awesome-project",
99
100
  "eslintConfig": {
100
- "plugins": [
101
- "unicorn"
102
- ],
103
101
  "extends": "plugin:unicorn/recommended"
104
102
  }
105
103
  }
Binary file
@@ -4,13 +4,13 @@ const getDocsUrl = require('./utils/get-docs-url');
4
4
 
5
5
  // Matches `someObj.then([FunctionExpression | ArrowFunctionExpression])`
6
6
  function isLintablePromiseCatch(node) {
7
- const callee = node.callee;
7
+ const {callee} = node;
8
8
 
9
9
  if (callee.type !== 'MemberExpression') {
10
10
  return false;
11
11
  }
12
12
 
13
- const property = callee.property;
13
+ const {property} = callee;
14
14
 
15
15
  if (property.type !== 'Identifier' || property.name !== 'catch') {
16
16
  return false;
@@ -20,7 +20,7 @@ function isLintablePromiseCatch(node) {
20
20
  return false;
21
21
  }
22
22
 
23
- const arg0 = node.arguments[0];
23
+ const [arg0] = node.arguments;
24
24
 
25
25
  return arg0.type === 'FunctionExpression' || arg0.type === 'ArrowFunctionExpression';
26
26
  }
@@ -38,11 +38,11 @@ function indexifyName(name, scope) {
38
38
 
39
39
  const create = context => {
40
40
  const options = Object.assign({}, {
41
- name: 'err',
41
+ name: 'error',
42
42
  caughtErrorsIgnorePattern: '^_$'
43
43
  }, context.options[0]);
44
44
 
45
- const name = options.name;
45
+ const {name} = options;
46
46
  const caughtErrorsIgnorePattern = new RegExp(options.caughtErrorsIgnorePattern);
47
47
  const stack = [];
48
48
 
@@ -68,7 +68,7 @@ const create = context => {
68
68
  return {
69
69
  CallExpression: node => {
70
70
  if (isLintablePromiseCatch(node)) {
71
- const params = node.arguments[0].params;
71
+ const {params} = node.arguments[0];
72
72
 
73
73
  if (params.length > 0 && params[0].name === '_') {
74
74
  push(!astUtils.containsIdentifier('_', node.arguments[0].body));
@@ -85,6 +85,12 @@ const create = context => {
85
85
  }
86
86
  },
87
87
  CatchClause: node => {
88
+ // Optional catch binding
89
+ if (!node || !node.param) {
90
+ push(true);
91
+ return;
92
+ }
93
+
88
94
  if (node.param.name === '_') {
89
95
  push(!astUtils.someContainIdentifier('_', node.body.body));
90
96
  return;
@@ -115,7 +121,7 @@ module.exports = {
115
121
  create,
116
122
  meta: {
117
123
  docs: {
118
- url: getDocsUrl()
124
+ url: getDocsUrl(__filename)
119
125
  },
120
126
  schema
121
127
  }
@@ -18,10 +18,10 @@ const hasValidSuperClass = node => {
18
18
  return false;
19
19
  }
20
20
 
21
- let name = node.superClass.name;
21
+ let {name} = node.superClass;
22
22
 
23
23
  if (node.superClass.type === 'MemberExpression') {
24
- name = node.superClass.property.name;
24
+ ({name} = node.superClass.property);
25
25
  }
26
26
 
27
27
  return nameRegexp.test(name);
@@ -48,7 +48,7 @@ const customErrorDefinition = (context, node) => {
48
48
  return;
49
49
  }
50
50
 
51
- const name = node.id.name;
51
+ const {name} = node.id;
52
52
  const className = getClassName(name);
53
53
 
54
54
  if (name !== className) {
@@ -58,8 +58,7 @@ const customErrorDefinition = (context, node) => {
58
58
  });
59
59
  }
60
60
 
61
- const body = node.body.body;
62
-
61
+ const {body} = node.body;
63
62
  const constructor = body.find(x => x.kind === 'constructor');
64
63
 
65
64
  if (!constructor) {
@@ -132,7 +131,7 @@ module.exports = {
132
131
  create,
133
132
  meta: {
134
133
  docs: {
135
- url: getDocsUrl()
134
+ url: getDocsUrl(__filename)
136
135
  },
137
136
  fixable: 'code'
138
137
  }
@@ -91,7 +91,7 @@ module.exports = {
91
91
  create,
92
92
  meta: {
93
93
  docs: {
94
- url: getDocsUrl()
94
+ url: getDocsUrl(__filename)
95
95
  }
96
96
  }
97
97
  };
@@ -56,7 +56,7 @@ module.exports = {
56
56
  create,
57
57
  meta: {
58
58
  docs: {
59
- url: getDocsUrl()
59
+ url: getDocsUrl(__filename)
60
60
  },
61
61
  fixable: 'code'
62
62
  }
@@ -36,13 +36,14 @@ function checkZeroType(context, node) {
36
36
  }
37
37
 
38
38
  function checkNonZeroType(context, node, type) {
39
- const value = node.right.value;
40
- const operator = node.operator;
39
+ const {value} = node.right;
40
+ const {operator} = node;
41
41
 
42
42
  switch (type) {
43
43
  case 'greater-than':
44
- if ((operatorTypes.gte.indexOf(operator) !== -1 && value === 1) ||
45
- (operatorTypes.ne.indexOf(operator) !== -1 && value === 0)
44
+ if (
45
+ (operatorTypes.gte.includes(operator) && value === 1) ||
46
+ (operatorTypes.ne.includes(operator) && value === 0)
46
47
  ) {
47
48
  reportError(
48
49
  context,
@@ -57,8 +58,9 @@ function checkNonZeroType(context, node, type) {
57
58
  }
58
59
  break;
59
60
  case 'greater-than-or-equal':
60
- if ((operatorTypes.gt.indexOf(operator) !== -1 && value === 0) ||
61
- (operatorTypes.ne.indexOf(operator) !== -1 && value === 0)
61
+ if (
62
+ (operatorTypes.gt.includes(operator) && value === 0) ||
63
+ (operatorTypes.ne.includes(operator) && value === 0)
62
64
  ) {
63
65
  reportError(
64
66
  context,
@@ -73,8 +75,9 @@ function checkNonZeroType(context, node, type) {
73
75
  }
74
76
  break;
75
77
  case 'not-equal':
76
- if ((operatorTypes.gt.indexOf(operator) !== -1 && value === 0) ||
77
- (operatorTypes.gte.indexOf(operator) !== -1 && value === 1)
78
+ if (
79
+ (operatorTypes.gt.includes(operator) && value === 0) ||
80
+ (operatorTypes.gte.includes(operator) && value === 1)
78
81
  ) {
79
82
  reportError(
80
83
  context,
@@ -133,6 +136,9 @@ const create = context => {
133
136
  return {
134
137
  IfStatement: node => {
135
138
  checkExpression(context, node.test);
139
+ },
140
+ ConditionalExpression: node => {
141
+ checkExpression(context, node.test);
136
142
  }
137
143
  };
138
144
  };
@@ -154,7 +160,7 @@ module.exports = {
154
160
  create,
155
161
  meta: {
156
162
  docs: {
157
- url: getDocsUrl()
163
+ url: getDocsUrl(__filename)
158
164
  },
159
165
  fixable: 'code',
160
166
  schema
@@ -68,7 +68,9 @@ function splitFilename(filename) {
68
68
  }
69
69
 
70
70
  const create = context => {
71
- const chosenCase = cases[context.options[0].case || 'camelCase'];
71
+ const options = context.options[0] || {};
72
+
73
+ const chosenCase = cases[options.case || 'camelCase'];
72
74
  const filenameWithExt = context.getFilename();
73
75
 
74
76
  if (filenameWithExt === '<text>') {
@@ -116,7 +118,7 @@ module.exports = {
116
118
  create,
117
119
  meta: {
118
120
  docs: {
119
- url: getDocsUrl()
121
+ url: getDocsUrl(__filename)
120
122
  },
121
123
  schema
122
124
  }
@@ -26,7 +26,7 @@ module.exports = {
26
26
  create,
27
27
  meta: {
28
28
  docs: {
29
- url: getDocsUrl()
29
+ url: getDocsUrl(__filename)
30
30
  },
31
31
  fixable: 'code'
32
32
  }
@@ -36,7 +36,7 @@ const disallowNew = new Set([
36
36
  const create = context => {
37
37
  return {
38
38
  CallExpression: node => {
39
- const name = node.callee.name;
39
+ const {name} = node.callee;
40
40
 
41
41
  if (enforceNew.has(name)) {
42
42
  context.report({
@@ -47,7 +47,7 @@ const create = context => {
47
47
  }
48
48
  },
49
49
  NewExpression: node => {
50
- const name = node.callee.name;
50
+ const {name} = node.callee;
51
51
 
52
52
  if (disallowNew.has(name)) {
53
53
  context.report({
@@ -67,7 +67,7 @@ module.exports = {
67
67
  create,
68
68
  meta: {
69
69
  docs: {
70
- url: getDocsUrl()
70
+ url: getDocsUrl(__filename)
71
71
  },
72
72
  fixable: 'code'
73
73
  }
@@ -5,11 +5,12 @@ const disableRegex = /^eslint-disable(-next-line|-line)?($|(\s+(@[\w-]+\/[\w-]+\
5
5
 
6
6
  const create = context => ({
7
7
  Program: node => {
8
- node.comments.forEach(comment => {
8
+ for (const comment of node.comments) {
9
9
  const value = comment.value.trim();
10
10
  const res = disableRegex.exec(value);
11
11
 
12
- if (res && // It's a eslint-disable comment
12
+ if (
13
+ res && // It's a eslint-disable comment
13
14
  !res[2] // But it did not specify any rules
14
15
  ) {
15
16
  context.report({
@@ -24,7 +25,7 @@ const create = context => ({
24
25
  data: comment.loc.start
25
26
  });
26
27
  }
27
- });
28
+ }
28
29
  }
29
30
  });
30
31
 
@@ -32,7 +33,7 @@ module.exports = {
32
33
  create,
33
34
  meta: {
34
35
  docs: {
35
- url: getDocsUrl()
36
+ url: getDocsUrl(__filename)
36
37
  }
37
38
  }
38
39
  };
@@ -20,7 +20,7 @@ module.exports = {
20
20
  create,
21
21
  meta: {
22
22
  docs: {
23
- url: getDocsUrl()
23
+ url: getDocsUrl(__filename)
24
24
  },
25
25
  fixable: 'code'
26
26
  }
@@ -34,7 +34,7 @@ const fix = (context, node) => {
34
34
  const create = context => ({
35
35
  'CallExpression[callee.object.name!="Promise"]': node => {
36
36
  if (isIteratorMethod(node) && hasFunctionArgument(node)) {
37
- const arg = node.arguments[0];
37
+ const [arg] = node.arguments;
38
38
 
39
39
  context.report({
40
40
  node: arg,
@@ -49,7 +49,7 @@ module.exports = {
49
49
  create,
50
50
  meta: {
51
51
  docs: {
52
- url: getDocsUrl()
52
+ url: getDocsUrl(__filename)
53
53
  },
54
54
  fixable: 'code'
55
55
  }
@@ -29,7 +29,7 @@ module.exports = {
29
29
  create,
30
30
  meta: {
31
31
  docs: {
32
- url: getDocsUrl()
32
+ url: getDocsUrl(__filename)
33
33
  },
34
34
  fixable: 'code'
35
35
  }
@@ -25,7 +25,7 @@ module.exports = {
25
25
  create,
26
26
  meta: {
27
27
  docs: {
28
- url: getDocsUrl()
28
+ url: getDocsUrl(__filename)
29
29
  },
30
30
  fixable: 'code'
31
31
  }
@@ -12,7 +12,7 @@ const create = context => {
12
12
 
13
13
  return {
14
14
  CallExpression: node => {
15
- const callee = node.callee;
15
+ const {callee} = node;
16
16
 
17
17
  if (callee.type === 'MemberExpression' && callee.object.name === 'process') {
18
18
  if (callee.property.name === 'on' || callee.property.name === 'once') {
@@ -40,7 +40,7 @@ module.exports = {
40
40
  create,
41
41
  meta: {
42
42
  docs: {
43
- url: getDocsUrl()
43
+ url: getDocsUrl(__filename)
44
44
  }
45
45
  }
46
46
  };
@@ -32,7 +32,7 @@ const create = context => {
32
32
  let flags = null;
33
33
 
34
34
  if (hasRegExp) {
35
- pattern = args[0].regex.pattern;
35
+ ({pattern} = args[0].regex);
36
36
  flags = args[1] && args[1].type === 'Literal' ? args[1].value : args[0].regex.flags;
37
37
  } else {
38
38
  pattern = args[0].value;
@@ -53,7 +53,7 @@ module.exports = {
53
53
  create,
54
54
  meta: {
55
55
  docs: {
56
- url: getDocsUrl()
56
+ url: getDocsUrl(__filename)
57
57
  }
58
58
  }
59
59
  };
@@ -33,7 +33,7 @@ module.exports = {
33
33
  create,
34
34
  meta: {
35
35
  docs: {
36
- url: getDocsUrl()
36
+ url: getDocsUrl(__filename)
37
37
  },
38
38
  fixable: 'code'
39
39
  }
@@ -45,7 +45,7 @@ module.exports = {
45
45
  create,
46
46
  meta: {
47
47
  docs: {
48
- url: getDocsUrl()
48
+ url: getDocsUrl(__filename)
49
49
  },
50
50
  fixable: 'code'
51
51
  }
@@ -0,0 +1,54 @@
1
+ 'use strict';
2
+ const getDocsUrl = require('./utils/get-docs-url');
3
+
4
+ const isMathPow = node => {
5
+ const {callee} = node;
6
+ return (
7
+ callee.type === 'MemberExpression' &&
8
+ callee.object.type === 'Identifier' &&
9
+ callee.object.name === 'Math' &&
10
+ callee.property.type === 'Identifier' &&
11
+ callee.property.name === 'pow'
12
+ );
13
+ };
14
+
15
+ const parseArgument = (context, arg) => {
16
+ if (arg.type === 'Identifier') {
17
+ return arg.name;
18
+ }
19
+
20
+ return context.getSourceCode().getText(arg);
21
+ };
22
+
23
+ const fix = (context, node, fixer) => {
24
+ const base = parseArgument(context, node.arguments[0]);
25
+ const exponent = parseArgument(context, node.arguments[1]);
26
+
27
+ const replacement = `${base} ** ${exponent}`;
28
+
29
+ return fixer.replaceText(node, replacement);
30
+ }
31
+
32
+ const create = context => {
33
+ return {
34
+ CallExpression(node) {
35
+ if (isMathPow(node)) {
36
+ context.report({
37
+ node,
38
+ message: 'Prefer the exponentiation operator over `Math.pow()`.',
39
+ fix: fixer => fix(context, node, fixer),
40
+ });
41
+ }
42
+ }
43
+ };
44
+ };
45
+
46
+ module.exports = {
47
+ create,
48
+ meta: {
49
+ docs: {
50
+ url: getDocsUrl(__filename)
51
+ },
52
+ fixable: 'code'
53
+ }
54
+ };
@@ -2,7 +2,7 @@
2
2
  const getDocsUrl = require('./utils/get-docs-url');
3
3
 
4
4
  const isArrayFrom = node => {
5
- const callee = node.callee;
5
+ const {callee} = node;
6
6
  return (
7
7
  callee.type === 'MemberExpression' &&
8
8
  callee.object.type === 'Identifier' &&
@@ -12,6 +12,8 @@ const isArrayFrom = node => {
12
12
  );
13
13
  };
14
14
 
15
+ const isArrayLike = arg => arg && arg.type !== 'ObjectExpression';
16
+
15
17
  const parseArgument = (context, arg) => {
16
18
  if (arg.type === 'Identifier') {
17
19
  return arg.name;
@@ -23,7 +25,7 @@ const parseArgument = (context, arg) => {
23
25
  const create = context => {
24
26
  return {
25
27
  CallExpression(node) {
26
- if (isArrayFrom(node)) {
28
+ if (isArrayFrom(node) && isArrayLike(node.arguments[0])) {
27
29
  context.report({
28
30
  node,
29
31
  message: 'Prefer the spread operator over `Array.from()`.',
@@ -51,7 +53,7 @@ module.exports = {
51
53
  create,
52
54
  meta: {
53
55
  docs: {
54
- url: getDocsUrl()
56
+ url: getDocsUrl(__filename)
55
57
  },
56
58
  fixable: 'code'
57
59
  }
@@ -11,7 +11,7 @@ const isSimpleString = string => doesNotContain(
11
11
  const create = context => {
12
12
  return {
13
13
  CallExpression(node) {
14
- const callee = node.callee;
14
+ const {callee} = node;
15
15
  const prop = callee.property;
16
16
 
17
17
  if (!(prop && callee.type === 'MemberExpression')) {
@@ -22,9 +22,9 @@ const create = context => {
22
22
 
23
23
  let regex;
24
24
  if (prop.name === 'test' && callee.object.regex) {
25
- regex = callee.object.regex;
25
+ ({regex} = callee.object);
26
26
  } else if (prop.name === 'match' && args && args[0] && args[0].regex) {
27
- regex = args[0].regex;
27
+ ({regex} = args[0]);
28
28
  } else {
29
29
  return;
30
30
  }
@@ -33,7 +33,7 @@ const create = context => {
33
33
  return;
34
34
  }
35
35
 
36
- const pattern = regex.pattern;
36
+ const {pattern} = regex;
37
37
  if (pattern.startsWith('^') && isSimpleString(pattern.slice(1))) {
38
38
  context.report({
39
39
  node,
@@ -53,7 +53,7 @@ module.exports = {
53
53
  create,
54
54
  meta: {
55
55
  docs: {
56
- url: getDocsUrl()
56
+ url: getDocsUrl(__filename)
57
57
  }
58
58
  }
59
59
  };
@@ -120,7 +120,7 @@ module.exports = {
120
120
  create,
121
121
  meta: {
122
122
  docs: {
123
- url: getDocsUrl()
123
+ url: getDocsUrl(__filename)
124
124
  },
125
125
  fixable: 'code'
126
126
  }
@@ -8,7 +8,7 @@ const create = context => {
8
8
  return {
9
9
  'Literal[regex]': node => {
10
10
  const oldPattern = node.regex.pattern;
11
- const flags = node.regex.flags;
11
+ const {flags} = node.regex;
12
12
 
13
13
  const newPattern = cleanRegexp(oldPattern, flags);
14
14
 
@@ -48,10 +48,20 @@ const create = context => {
48
48
  const newPattern = cleanRegexp(oldPattern, flags);
49
49
 
50
50
  if (oldPattern !== newPattern) {
51
+ let fixed;
52
+ if (hasRegExp) {
53
+ fixed = `/${newPattern}/`;
54
+ } else {
55
+ // Escape backslash and apostrophe because we wrap the result in single quotes.
56
+ fixed = (newPattern || '').replace(/\\/, '\\\\');
57
+ fixed = fixed.replace(/'/, '\'');
58
+ fixed = `'${fixed}'`;
59
+ }
60
+
51
61
  context.report({
52
62
  node,
53
63
  message,
54
- fix: fixer => fixer.replaceTextRange(args[0].range, hasRegExp ? `/${newPattern}/` : `'${newPattern}'`)
64
+ fix: fixer => fixer.replaceTextRange(args[0].range, fixed),
55
65
  });
56
66
  }
57
67
  }
@@ -62,7 +72,7 @@ module.exports = {
62
72
  create,
63
73
  meta: {
64
74
  docs: {
65
- url: getDocsUrl()
75
+ url: getDocsUrl(__filename)
66
76
  },
67
77
  fixable: 'code'
68
78
  }
@@ -22,7 +22,7 @@ module.exports = {
22
22
  create,
23
23
  meta: {
24
24
  docs: {
25
- url: getDocsUrl()
25
+ url: getDocsUrl(__filename)
26
26
  },
27
27
  fixable: 'code'
28
28
  }
@@ -4,7 +4,7 @@ const pkg = require('../../package');
4
4
 
5
5
  const repoUrl = 'https://github.com/sindresorhus/eslint-plugin-unicorn';
6
6
 
7
- module.exports = ruleName => {
8
- ruleName = ruleName || path.basename(module.parent.filename, '.js');
7
+ module.exports = filename => {
8
+ const ruleName = path.basename(filename, '.js');
9
9
  return `${repoUrl}/blob/v${pkg.version}/docs/rules/${ruleName}.md`;
10
10
  };