Skip to content

Commit 0e2487d

Browse files
committed
feat: add ** support for folder-naming-convention rule
1 parent cf33913 commit 0e2487d

File tree

4 files changed

+80
-22
lines changed

4 files changed

+80
-22
lines changed

lib/rules/folder-match-with-fex.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
'use strict';
66

77
const micromatch = require('micromatch');
8-
const { getFolder, getFilename } = require('../utils/filename');
8+
const { getFolderPath, getFilename } = require('../utils/filename');
99
const { checkSettings, globPatternValidator } = require('../utils/settings');
1010
const { getDocUrl } = require('../utils/doc');
1111

@@ -57,12 +57,12 @@ module.exports = {
5757

5858
const filenameWithPath = context.getFilename();
5959
const filename = getFilename(filenameWithPath);
60-
const folder = getFolder(filenameWithPath);
60+
const folderPath = getFolderPath(filenameWithPath);
6161

6262
for (const [fexPattern, folderPattern] of Object.entries(rules)) {
6363
if (!micromatch.isMatch(filename, fexPattern)) {
6464
continue;
65-
} else if (micromatch.isMatch(folder, folderPattern)) {
65+
} else if (micromatch.isMatch(folderPath, folderPattern)) {
6666
return;
6767
} else {
6868
context.report({

lib/rules/folder-naming-convention.js

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,11 @@
55
'use strict';
66

77
const micromatch = require('micromatch');
8-
const { getFolder, getSubPaths } = require('../utils/filename');
8+
const {
9+
getFolderPath,
10+
getSubPaths,
11+
getAllFolders,
12+
} = require('../utils/filename');
913
const {
1014
checkSettings,
1115
namingPatternValidator,
@@ -59,29 +63,30 @@ module.exports = {
5963
}
6064

6165
const filenameWithPath = context.getFilename();
62-
const folder = getFolder(filenameWithPath);
63-
const subPaths = getSubPaths(folder);
66+
const folderPath = getFolderPath(filenameWithPath);
67+
const subPaths = getSubPaths(folderPath);
6468

6569
for (const path of subPaths) {
6670
for (const [folderPattern, namingPattern] of Object.entries(rules)) {
6771
if (!micromatch.isMatch(path, folderPattern)) {
6872
continue;
6973
} else {
70-
const matchedValue = micromatch.capture(folderPattern, path);
74+
const matchedPath = micromatch.capture(folderPattern, path)[0]; // only the first matched value is valid
75+
const folders = getAllFolders(matchedPath);
7176

72-
for (const value of matchedValue) {
77+
for (const folder of folders) {
7378
if (
7479
!micromatch.isMatch(
75-
value,
80+
folder,
7681
NAMING_CONVENTION[namingPattern] || namingPattern
7782
)
7883
) {
7984
context.report({
8085
node,
8186
message:
82-
'The folder "{{value}}" does not match the "{{namingPattern}}" style',
87+
'The folder "{{folder}}" does not match the "{{namingPattern}}" style',
8388
data: {
84-
value,
89+
folder,
8590
namingPattern,
8691
},
8792
});

lib/utils/filename.js

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ const getFilename = (path) => path.substring(path.lastIndexOf('/') + 1);
1414
* @type {string} path of folder
1515
* @param {string} path filename concat with path
1616
*/
17-
const getFolder = (path) => path.substring(0, path.lastIndexOf('/') + 1);
17+
const getFolderPath = (path) => path.substring(0, path.lastIndexOf('/') + 1);
1818

1919
/**
2020
* @type {string} base name
@@ -23,12 +23,19 @@ const getFolder = (path) => path.substring(0, path.lastIndexOf('/') + 1);
2323
const getBasename = (filename) =>
2424
filename.substring(0, filename.lastIndexOf('.'));
2525

26+
/**
27+
* @type {string[]} all folders
28+
* @param {string} path path of folder
29+
*/
30+
const getAllFolders = (path) =>
31+
path.split('/').filter((folder) => folder !== '');
32+
2633
/**
2734
* @type {string[]} all sub paths
28-
* @param {string} folder path of folder
35+
* @param {string} path path of folder
2936
*/
3037
const getSubPaths = (path) => {
31-
const folders = path.split('/').filter((folder) => folder !== '');
38+
const folders = getAllFolders(path);
3239
let subPaths = [];
3340

3441
const handler = (array) =>
@@ -49,8 +56,9 @@ const getSubPaths = (path) => {
4956
};
5057

5158
module.exports = {
52-
getFolder,
59+
getFolderPath,
5360
getFilename,
5461
getBasename,
5562
getSubPaths,
63+
getAllFolders,
5664
};

tests/lib/rules/folder-naming-convention.js

Lines changed: 52 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,22 +10,22 @@ const RuleTester = require('eslint').RuleTester;
1010
const ruleTester = new RuleTester();
1111

1212
ruleTester.run(
13-
"folder-naming-convention with option: [{ '*/__tests__/': 'PASCAL_CASE', 'src/*': 'CAMEL_CASE' }]",
13+
"folder-naming-convention with option: [{ '*/__tests__/': 'PASCAL_CASE', 'src/*/': 'CAMEL_CASE' }]",
1414
rule,
1515
{
1616
valid: [
1717
{
1818
code: "var foo = 'bar';",
1919
filename: 'src/components/DisplayLabel/__tests__/displayLabel.test.js',
20-
options: [{ '*/__tests__/': 'PASCAL_CASE', 'src/*': 'CAMEL_CASE' }],
20+
options: [{ '*/__tests__/': 'PASCAL_CASE', 'src/*/': 'CAMEL_CASE' }],
2121
},
2222
],
2323

2424
invalid: [
2525
{
2626
code: "var foo = 'bar';",
2727
filename: 'src/Components/DisplayLabel/__tests__/displayLabel.test.js',
28-
options: [{ '*/__tests__/': 'PASCAL_CASE', 'src/*': 'CAMEL_CASE' }],
28+
options: [{ '*/__tests__/': 'PASCAL_CASE', 'src/*/': 'CAMEL_CASE' }],
2929
errors: [
3030
{
3131
message:
@@ -38,7 +38,7 @@ ruleTester.run(
3838
{
3939
code: "var foo = 'bar';",
4040
filename: 'src/components/displayLabel/__tests__/displayLabel.test.js',
41-
options: [{ '*/__tests__/': 'PASCAL_CASE', 'src/*': 'CAMEL_CASE' }],
41+
options: [{ '*/__tests__/': 'PASCAL_CASE', 'src/*/': 'CAMEL_CASE' }],
4242
errors: [
4343
{
4444
message:
@@ -52,6 +52,51 @@ ruleTester.run(
5252
}
5353
);
5454

55+
ruleTester.run(
56+
"folder-naming-convention with option: [{ 'src/**/': 'CAMEL_CASE' }]",
57+
rule,
58+
{
59+
valid: [
60+
{
61+
code: "var foo = 'bar';",
62+
filename: 'src/components/displayLabel/displayLabel.js',
63+
options: [{ 'src/**/': 'CAMEL_CASE' }],
64+
},
65+
],
66+
67+
invalid: [
68+
{
69+
code: "var foo = 'bar';",
70+
filename: 'src/Components/DisplayLabel/displayLabel.js',
71+
options: [{ 'src/**/': 'CAMEL_CASE' }],
72+
errors: [
73+
{
74+
message:
75+
'The folder "Components" does not match the "CAMEL_CASE" style',
76+
column: 1,
77+
line: 1,
78+
},
79+
],
80+
},
81+
{
82+
code: "var foo = 'bar';",
83+
filename: 'src/components/DisplayLabel/displayLabel.js',
84+
options: [{ 'src/**/': 'CAMEL_CASE' }],
85+
errors: [
86+
{
87+
message:
88+
'The folder "DisplayLabel" does not match the "CAMEL_CASE" style',
89+
column: 1,
90+
line: 1,
91+
},
92+
],
93+
},
94+
],
95+
}
96+
);
97+
98+
// custom rule
99+
55100
ruleTester.run(
56101
'folder-naming-convention with folder that has not been set',
57102
rule,
@@ -60,7 +105,7 @@ ruleTester.run(
60105
{
61106
code: "var foo = 'bar';",
62107
filename: 'scripts/build.js',
63-
options: [{ '*/__tests__/': 'PASCAL_CASE', 'src/*': 'CAMEL_CASE' }],
108+
options: [{ '*/__tests__/': 'PASCAL_CASE', 'src/*/': 'CAMEL_CASE' }],
64109
},
65110
],
66111

@@ -69,7 +114,7 @@ ruleTester.run(
69114
);
70115

71116
ruleTester.run(
72-
"folder-naming-convention with option: [{ '*/__tests__/': 'FOO', 'src/*': 'CAMEL_CASE' }]",
117+
"folder-naming-convention with option: [{ '*/__tests__/': 'FOO', 'src/*/': 'CAMEL_CASE' }]",
73118
rule,
74119
{
75120
valid: [],
@@ -78,7 +123,7 @@ ruleTester.run(
78123
{
79124
code: "var foo = 'bar';",
80125
filename: 'src/utils/calculatePrice.js',
81-
options: [{ '*/__tests__/': 'FOO', 'src/*': 'CAMEL_CASE' }],
126+
options: [{ '*/__tests__/': 'FOO', 'src/*/': 'CAMEL_CASE' }],
82127
errors: [
83128
{
84129
message: 'There is an invalid pattern "FOO", please check it',

0 commit comments

Comments
 (0)