Skip to content

Commit b70cb64

Browse files
authored
filename-case: Allow acronyms in pascal case (#3125)
1 parent e097996 commit b70cb64

3 files changed

Lines changed: 80 additions & 1 deletion

File tree

docs/rules/filename-case.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ Set the `checkDirectories` option to `false` to only check filenames.
4444
### `pascalCase`
4545

4646
- `FooBar.js`
47+
- `FAQPage.js`
4748
- `FooBar.Test.js`
4849
- `FooBar.TestUtils.js`
4950

rules/filename-case.js

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,21 @@ const isIgnoredChar = char => !/^[\w-]$/.test(char);
2222
const ignoredByDefault = new Set(['index.js', 'index.mjs', 'index.cjs', 'index.ts', 'index.tsx', 'index.vue']);
2323
const isLowerCase = string => string === string.toLowerCase();
2424
const disjunctionListFormat = new Intl.ListFormat('en-US', {type: 'disjunction'});
25+
const alphanumericRegex = /^[\da-z]+$/i;
26+
const leadingAcronymRegex = /^[A-Z]{3,}(?=\d*[A-Z](?:[a-z]|\d+[a-z]))/;
27+
28+
function pascalCaseWithLeadingAcronym(string) {
29+
if (alphanumericRegex.test(string)) {
30+
const leadingAcronym = leadingAcronymRegex.exec(string)?.[0];
31+
const suffix = leadingAcronym && string.slice(leadingAcronym.length);
32+
33+
if (suffix && pascalCase(suffix) === suffix) {
34+
return string;
35+
}
36+
}
37+
38+
return pascalCase(string);
39+
}
2540

2641
const cases = {
2742
camelCase: {
@@ -37,7 +52,7 @@ const cases = {
3752
name: 'snake case',
3853
},
3954
pascalCase: {
40-
fn: pascalCase,
55+
fn: pascalCaseWithLeadingAcronym,
4156
name: 'pascal case',
4257
},
4358
};

test/filename-case.js

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,14 @@ ruleTest({
140140
testCase('src/foo/.test_utils.js', 'kebabCase'),
141141
testCase('Src/Foo/Foo.js', 'pascalCase'),
142142
testCase('Src/Foo/FooBar.js', 'pascalCase'),
143+
testCase('Src/Foo/FAQPage.js', 'pascalCase'),
144+
testCase('Src/Foo/DIYWidget.js', 'pascalCase'),
145+
testCase('Src/Foo/URL2Path.js', 'pascalCase'),
146+
testCase('Src/Foo/FAQI18n.js', 'pascalCase'),
147+
testCase('Src/Foo/URL2I18n.js', 'pascalCase'),
148+
testCase('Src/FAQPage/Foo.js', 'pascalCase'),
149+
testCase('Src/URL2Path/Foo.js', 'pascalCase'),
150+
testCase('Src/URL2I18n/Foo.js', 'pascalCase'),
143151
testCase('Src/Foo/Foo.test.js', 'pascalCase'),
144152
testCase('Src/Foo/FooBar.test.js', 'pascalCase'),
145153
testCase('Src/Foo/FooBar.test-utils.js', 'pascalCase'),
@@ -464,6 +472,61 @@ ruleTest({
464472
'pascalCase',
465473
'Filename is not in pascal case. Rename it to `FooBar.test-utils.js`.',
466474
),
475+
testCase(
476+
'Src/Foo/PageFAQ.js',
477+
'pascalCase',
478+
'Filename is not in pascal case. Rename it to `PageFaq.js`.',
479+
),
480+
testCase(
481+
'Src/Foo/FAQ-Page.js',
482+
'pascalCase',
483+
'Filename is not in pascal case. Rename it to `FaqPage.js`.',
484+
),
485+
testCase(
486+
'Src/Foo/FAQpage.js',
487+
'pascalCase',
488+
'Filename is not in pascal case. Rename it to `FaQpage.js`.',
489+
),
490+
testCase(
491+
'Src/Foo/FAQPageFOO.js',
492+
'pascalCase',
493+
'Filename is not in pascal case. Rename it to `FaqPageFoo.js`.',
494+
),
495+
testCase(
496+
'Src/FAQpage/Foo.js',
497+
'pascalCase',
498+
'Directory name `FAQpage` is not in pascal case. Rename it to `FaQpage`.',
499+
),
500+
testCase(
501+
'Src/Foo/URL2path.js',
502+
'pascalCase',
503+
'Filename is not in pascal case. Rename it to `Url2path.js`.',
504+
),
505+
testCase(
506+
'Src/Foo/UIPath.js',
507+
'pascalCase',
508+
'Filename is not in pascal case. Rename it to `UiPath.js`.',
509+
),
510+
testCase(
511+
'Src/Foo/UI2Path.js',
512+
'pascalCase',
513+
'Filename is not in pascal case. Rename it to `Ui2Path.js`.',
514+
),
515+
testCase(
516+
'Src/Foo/FOO2.js',
517+
'pascalCase',
518+
'Filename is not in pascal case. Rename it to `Foo2.js`.',
519+
),
520+
testCase(
521+
'src/foo/FAQPage.js',
522+
'camelCase',
523+
'Filename is not in camel case. Rename it to `faqPage.js`.',
524+
),
525+
testCase(
526+
'src/foo/FAQPage.js',
527+
undefined,
528+
'Filename is not in kebab case. Rename it to `faq-page.js`.',
529+
),
467530
testCase(
468531
'src/foo/_FOO-BAR.js',
469532
'camelCase',

0 commit comments

Comments
 (0)