Skip to content

Commit ee0a03e

Browse files
committed
feat: add support of glob match pattern for filename-naming-convention
1 parent 238cd78 commit ee0a03e

File tree

5 files changed

+161
-19
lines changed

5 files changed

+161
-19
lines changed

lib/constants/naming-convention.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,32 +7,32 @@
77
/**
88
* @example hello, helloWorld
99
*/
10-
const CAMEL_CASE = /^([a-z]+){1}([A-Z][a-z0-9]*)*$/;
10+
const CAMEL_CASE = '+([a-z])*([A-Z]*([a-z0-9]))';
1111

1212
/**
1313
* @example Hello, HelloWorld
1414
*/
15-
const PASCAL_CASE = /^([A-Z][a-z0-9]*)*$/;
15+
const PASCAL_CASE = '*([A-Z]*([a-z0-9]))';
1616

1717
/**
1818
* @example hello, hello_world
1919
*/
20-
const SNAKE_CASE = /^([a-z]+_?)([a-z0-9]+_)*[a-z0-9]+$/;
20+
const SNAKE_CASE = '+([a-z])*(_+([a-z0-9]))';
2121

2222
/**
2323
* @example hello, hello-world
2424
*/
25-
const KEBAB_CASE = /^([a-z]+-?)([a-z0-9]+-)*[a-z0-9]+$/;
25+
const KEBAB_CASE = '+([a-z])*(-+([a-z0-9]))';
2626

2727
/**
2828
* @example HELLO, HELLO_WORLD
2929
*/
30-
const SCREAMING_SNAKE_CASE = /^([A-Z]+_?)([A-Z0-9]+_)*[A-Z0-9]+$/;
30+
const SCREAMING_SNAKE_CASE = '+([A-Z])*(_+([A-Z0-9]))';
3131

3232
/**
3333
* @example hello, helloworld
3434
*/
35-
const FLAT_CASE = /^[a-z0-9]+$/;
35+
const FLAT_CASE = '+([a-z0-9])';
3636

3737
module.exports = {
3838
CAMEL_CASE,

lib/rules/filename-naming-convention.js

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

77
const micromatch = require('micromatch');
8+
const isGlob = require('is-glob');
89
const { getFilename, getBasename } = require('../utils/filename');
910
const NAMING_CONVENTION = require('../constants/naming-convention');
1011

1112
/**
1213
* @type {string} invalid naming pattern
13-
* @param {string} rules naming pattern configurated by user
14+
* @param rules naming pattern configurated by user
1415
*/
1516
const checkNamingConfig = (rules) => {
1617
const buildInPatterns = Object.keys(NAMING_CONVENTION);
17-
const isValidPattern = (pattern) =>
18-
(typeof pattern === 'string' && buildInPatterns.includes(pattern)) ||
19-
pattern instanceof RegExp;
2018

21-
return Object.values(rules).find((pattern) => !isValidPattern(pattern));
19+
for (const [fexPattern, namingPattern] of Object.entries(rules)) {
20+
if (!isGlob(fexPattern)) {
21+
return fexPattern;
22+
} else if (
23+
!isGlob(namingPattern) &&
24+
!buildInPatterns.includes(namingPattern)
25+
) {
26+
return namingPattern;
27+
}
28+
}
2229
};
2330

2431
/**
@@ -53,7 +60,7 @@ module.exports = {
5360
context.report({
5461
node,
5562
message:
56-
'There is an unsupported naming style "{{invalidPattern}}", please check it.',
63+
'There is an invalid pattern "{{invalidPattern}}", please check it',
5764
data: {
5865
invalidPattern,
5966
},
@@ -64,21 +71,24 @@ module.exports = {
6471
const filenameWithPath = context.getFilename();
6572
const filename = getFilename(filenameWithPath);
6673

67-
for (const [fexPattern, pattern] of Object.entries(rules)) {
74+
for (const [fexPattern, namingPattern] of Object.entries(rules)) {
6875
if (!micromatch.isMatch(filename, fexPattern)) {
6976
continue;
7077
} else if (
71-
(NAMING_CONVENTION[pattern] || pattern).test(getBasename(filename))
78+
micromatch.isMatch(
79+
getBasename(filename),
80+
NAMING_CONVENTION[namingPattern] || namingPattern
81+
)
7282
) {
7383
return;
7484
} else {
7585
context.report({
7686
node,
7787
message:
78-
'The filename "{{filename}}" does not match the "{{pattern}}" style',
88+
'The filename "{{filename}}" does not match the "{{namingPattern}}" style',
7989
data: {
8090
filename,
81-
pattern,
91+
namingPattern,
8292
},
8393
});
8494
return;

package-lock.json

Lines changed: 1 addition & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
"test": "mocha tests --recursive"
1919
},
2020
"dependencies": {
21+
"is-glob": "^4.0.3",
2122
"micromatch": "^4.0.4",
2223
"requireindex": "^1.2.0"
2324
},

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

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -504,3 +504,136 @@ ruleTester.run(
504504
],
505505
}
506506
);
507+
508+
ruleTester.run(
509+
"filename-naming-convention with option: [{ '*.js': '__+([a-z])', '*.jsx': '__+([a-z])' }]",
510+
rule,
511+
{
512+
valid: [
513+
{
514+
code: "var foo = 'bar';",
515+
filename: 'src/components/__login.jsx',
516+
options: [{ '*.js': '__+([a-z])', '*.jsx': '__+([a-z])' }],
517+
},
518+
{
519+
code: "var foo = 'bar';",
520+
filename: 'src/utils/__calculateprice.js',
521+
options: [{ '*.js': '__+([a-z])', '*.jsx': '__+([a-z])' }],
522+
},
523+
],
524+
525+
invalid: [
526+
{
527+
code: "var foo = 'bar';",
528+
filename: 'src/utils/calculatePrice.js',
529+
options: [{ '*.js': '__+([a-z])', '*.jsx': '__+([a-z])' }],
530+
errors: [
531+
{
532+
message:
533+
'The filename "calculatePrice.js" does not match the "__+([a-z])" style',
534+
column: 1,
535+
line: 1,
536+
},
537+
],
538+
},
539+
{
540+
code: "var foo = 'bar';",
541+
filename: 'src/utils/CalculatePrice.js',
542+
options: [{ '*.js': '__+([a-z])', '*.jsx': '__+([a-z])' }],
543+
errors: [
544+
{
545+
message:
546+
'The filename "CalculatePrice.js" does not match the "__+([a-z])" style',
547+
column: 1,
548+
line: 1,
549+
},
550+
],
551+
},
552+
{
553+
code: "var foo = 'bar';",
554+
filename: 'src/utils/calculate_price.js',
555+
options: [{ '*.js': '__+([a-z])', '*.jsx': '__+([a-z])' }],
556+
errors: [
557+
{
558+
message:
559+
'The filename "calculate_price.js" does not match the "__+([a-z])" style',
560+
column: 1,
561+
line: 1,
562+
},
563+
],
564+
},
565+
{
566+
code: "var foo = 'bar';",
567+
filename: 'src/utils/calculate-price.js',
568+
options: [{ '*.js': '__+([a-z])', '*.jsx': '__+([a-z])' }],
569+
errors: [
570+
{
571+
message:
572+
'The filename "calculate-price.js" does not match the "__+([a-z])" style',
573+
column: 1,
574+
line: 1,
575+
},
576+
],
577+
},
578+
{
579+
code: "var foo = 'bar';",
580+
filename: 'src/utils/CALCULATE_PRICE.js',
581+
options: [{ '*.js': '__+([a-z])', '*.jsx': '__+([a-z])' }],
582+
errors: [
583+
{
584+
message:
585+
'The filename "CALCULATE_PRICE.js" does not match the "__+([a-z])" style',
586+
column: 1,
587+
line: 1,
588+
},
589+
],
590+
},
591+
],
592+
}
593+
);
594+
595+
ruleTester.run(
596+
"filename-naming-convention with option: [{ '*.js': 'FOO', '.jsx': 'FLAT_CASE' }]",
597+
rule,
598+
{
599+
valid: [],
600+
601+
invalid: [
602+
{
603+
code: "var foo = 'bar';",
604+
filename: 'src/utils/calculatePrice.js',
605+
options: [{ '*.js': 'FOO', '.jsx': 'FLAT_CASE' }],
606+
errors: [
607+
{
608+
message: 'There is an invalid pattern "FOO", please check it',
609+
column: 1,
610+
line: 1,
611+
},
612+
],
613+
},
614+
],
615+
}
616+
);
617+
618+
ruleTester.run(
619+
"filename-naming-convention with option: [{ '*.js': 'CAMEL_CASE', '.jsx': 'FLAT_CASE' }]",
620+
rule,
621+
{
622+
valid: [],
623+
624+
invalid: [
625+
{
626+
code: "var foo = 'bar';",
627+
filename: 'src/utils/calculatePrice.js',
628+
options: [{ '*.js': 'CAMEL_CASE', '.jsx': 'FLAT_CASE' }],
629+
errors: [
630+
{
631+
message: 'There is an invalid pattern ".jsx", please check it',
632+
column: 1,
633+
line: 1,
634+
},
635+
],
636+
},
637+
],
638+
}
639+
);

0 commit comments

Comments
 (0)