Skip to content

Commit

Permalink
Add rule pluralize
Browse files Browse the repository at this point in the history
  • Loading branch information
epaew committed Jun 8, 2020
1 parent b89ba61 commit b3768fd
Show file tree
Hide file tree
Showing 5 changed files with 144 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/configs/all.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ export const all: Linter.BaseConfig = {
'filenames-simple/named-export': 'error',
'filenames-simple/naming-convention': 'error',
'filenames-simple/no-index': 'error',
'filenames-simple/pluralize': ['error', { parentDir: 'plural', file: 'singular' }],
},
};
1 change: 1 addition & 0 deletions src/configs/recommended.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export const recommended: Linter.BaseConfig = {
'filenames-simple/named-export': 'warn',
'filenames-simple/naming-convention': 'error',
'filenames-simple/no-index': 'off',
'filenames-simple/pluralize': 'off',
},
};

Expand Down
2 changes: 2 additions & 0 deletions src/rules/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { extname } from './extname';
import { namedExport } from './named-export';
import { namingConvention } from './naming-convention';
import { noIndex } from './no-index';
import { pluralize } from './pluralize';

type Rules = { [key: string]: Rule.RuleModule | undefined };

Expand All @@ -14,4 +15,5 @@ export const rules: Rules = {
'named-export': namedExport,
'naming-convention': namingConvention,
'no-index': noIndex,
pluralize,
};
97 changes: 97 additions & 0 deletions src/rules/pluralize.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import path from 'path';
import { Rule } from 'eslint';
import { correct, Dictionaries, isValidName, setDictionaries } from '../utils/pluralize';

type Rules = {
parentDir?: 'singular' | 'plural';
file?: 'singular' | 'plural';
};
type Options = {
dictionaries?: Dictionaries;
rules: Rules;
};

const fetchFilename = (context: Rule.RuleContext) => {
const absolutePath = path.resolve(context.getFilename());
const [dirname, basename] = absolutePath.split(path.sep).slice(-2);
const [filename] = basename.split('.');

return [dirname, filename];
};

const parseOptions = (context: Rule.RuleContext): Options => {
const [rules = {}, dictionaries = {}] = context.options;
return { rules, dictionaries };
};

export const pluralize: Rule.RuleModule = {
meta: {
type: 'suggestion',
schema: [
{
type: 'object',
properties: {
parentDir: { enum: ['singular', 'plural'] },
file: { enum: ['singular', 'plural'] },
},
minProperties: 1,
},
{
type: 'object',
properties: {
irregular: {
type: 'object',
additionalProperties: { type: 'string' },
minProperties: 1,
},
plural: {
type: 'object',
additionalProperties: { type: 'string' },
minProperties: 1,
},
singular: {
type: 'object',
additionalProperties: { type: 'string' },
minProperties: 1,
},
uncountable: {
type: 'array',
items: { type: 'string' },
minItems: 1,
uniqueItems: true,
},
},
minProperties: 1,
},
],
},
create: context => {
const { rules, dictionaries } = parseOptions(context);
dictionaries && setDictionaries(dictionaries);

return {
Program: node => {
const [dirname, filename] = fetchFilename(context);

if (
rules.parentDir &&
isValidName(dirname, rules.parentDir) &&
rules.file &&
isValidName(filename, rules.file)
) {
return;
}

context.report({
node: node,
message:
'The filename must follow the pluralize rule. Should rename to {{ dirname }}/{{ filename }}',
data: {
dirname: rules.parentDir ? correct(dirname, rules.parentDir) : dirname,
filename: rules.file ? correct(filename, rules.file) : filename,
},
});
},
};
},
};
43 changes: 43 additions & 0 deletions src/utils/pluralize.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import pluralize from 'pluralize';

export type Dictionaries = {
irregular?: [string, string][];
plural?: [string, string][];
singular?: [string, string][];
uncountable?: string[];
};

export const correct = (name: string, rule: 'singular' | 'plural') => {
const corrector = {
singular: pluralize.singular,
plural: pluralize.plural,
};
return corrector[rule](name);
};

export const isValidName = (name: string, rule?: 'singular' | 'plural') => {
const validator = {
singular: pluralize.isSingular,
plural: pluralize.isPlural,
};
return rule ? validator[rule](name) : true;
};

export const setDictionaries = (dictionaries: Dictionaries) => {
const keys: Array<keyof Dictionaries> = ['irregular', 'plural', 'singular', 'uncountable'];
const dictionarySetter = {
irregular: ([singular, plural]: [string, string]) =>
pluralize.addIrregularRule(singular, plural),
plural: ([plural, singular]: [string, string]) =>
pluralize.addPluralRule(new RegExp(plural), singular),
singular: ([singular, plural]: [string, string]) =>
pluralize.addSingularRule(new RegExp(singular), plural),
uncountable: (uncountable: string) => pluralize.addUncountableRule(uncountable),
};

keys.forEach(key => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
dictionaries[key] && dictionaries[key].forEach(dictionarySetter[key]);
});
};

0 comments on commit b3768fd

Please sign in to comment.