Skip to content

Commit

Permalink
Merge pull request #38 from epaew/feature/pluralize_dictionary
Browse files Browse the repository at this point in the history
Change where to get the dictionaries of the `pluralize`
  • Loading branch information
epaew authored Jun 9, 2020
2 parents 247108b + 945a68e commit 3644dde
Show file tree
Hide file tree
Showing 9 changed files with 119 additions and 115 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
* [#12](https://github.com/epaew/eslint-plugin-filenames-simple/pull/12) Add new rule `pluralize`
* [#37](https://github.com/epaew/eslint-plugin-filenames-simple/pull/37)
Add options for the rule `named-export` to limit the filenames to which this rule applies.
* [#38](https://github.com/epaew/eslint-plugin-filenames-simple/pull/38)
Change where to get the dictionaries for the rule `pluralize`.

# 0.3.1
## Bugfix
Expand Down
3 changes: 3 additions & 0 deletions docs/rules/named-export.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,3 +104,6 @@ Specify one of the following as the file naming convention to which this rule ap
```typescript
export type ClassExpression = { id: Identifier }
```

## See also
* [settings/pluralize](../settings/pluralize.md)
18 changes: 2 additions & 16 deletions docs/rules/pluralize.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,6 @@ This rule ensures that filenames are plural (or singular).
{
"parentDir": "plural",
"file": "singular"
},
{
"uncountable": ["water"]
}
]
}
Expand All @@ -30,16 +27,5 @@ Specify one of the following naming conventions for each `parentDir` or `file`.
* singular
* plural

### dictionaries: (the second option)
Specify the dictionary to pass to the `pluralize` library.
See also: https://github.com/blakeembrey/pluralize#usage

#### Keys and examples
* irregular: array of arguments for `pluralize.addIrregularRule()`
* e.g. `[["singular", "plural"], ["person", "people"]]`
* plural: array of arguments for `pluralize.addPluralRule()`
* e.g. `[["plural", "singular"]]`
* singular: array of arguments for `pluralize.addSingularRule()`
* e.g. `[["singular", "plural"]]`
* uncountable: array of arguments for `pluralize.addUncountableRule()`
* e.g. `["uncountable", "water"]`
## See also
* [settings/pluralize](../settings/pluralize.md)
30 changes: 30 additions & 0 deletions docs/settings/pluralize.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# filenames-simple/pluralize
Specify the dictionary to pass to the `pluralize` library.
See also: https://github.com/blakeembrey/pluralize#usage

## Acceptable keys
* irregular: array of arguments for `pluralize.addIrregularRule()`
* plural: array of arguments for `pluralize.addPluralRule()`
* singular: array of arguments for `pluralize.addSingularRule()`
* uncountable: array of arguments for `pluralize.addUncountableRule()`

## Configuration example
```json
{
"plugins": [
"filenames-simple"
],
"rules": {
"filenames-simple/named-export": ["error", "singular"],
"filenames-simple/pluralize": ["error", { "parentDir": "plural", "file": "singular" }]
},
"settings": {
"filenames-simple": {
"pluralize": {
"irregular": [["singular", "plural"], ["index", "indices"]],
"uncountable": ["water"]
}
}
}
}
```
6 changes: 4 additions & 2 deletions src/rules/named-export.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import '../utils/polyfill.node10';
import { Identifier, Program, ESTreeParser } from '../utils/estree-parser';
import { isSameName } from '../utils/is-same-name';
import { presetCaseConverters } from '../utils/preset-case-converters';
import { isValidName } from '../utils/pluralize';
import { initPluralize, isValidName } from '../utils/pluralize';

type Pluralize = 'always' | 'singular' | 'plural';

Expand Down Expand Up @@ -37,9 +37,11 @@ export const namedExport: Rule.RuleModule = {
schema: [{ enum: ['always', 'singular', 'plural'] }],
},
create: context => {
initPluralize(context);
const pluralize: Pluralize = context.options[0] ?? 'always';

return {
Program: node => {
const pluralize: Pluralize = context.options[0] ?? 'always';
const filename = fetchFilename(context);

if (!(pluralize === 'always' || isValidName(filename, pluralize))) return;
Expand Down
44 changes: 3 additions & 41 deletions src/rules/pluralize.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,11 @@
import path from 'path';
import { Rule } from 'eslint';
import { correct, Dictionaries, isValidName, setDictionaries } from '../utils/pluralize';
import { correct, initPluralize, isValidName } from '../utils/pluralize';

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

const irregular = {
type: 'array',
items: {
type: 'array',
items: [{ type: 'string' }, { type: 'string' }],
maxItems: 2,
minItems: 2,
},
minItems: 1,
uniqueItems: true,
};
const plural = irregular;
const singular = irregular;

const fetchFilename = (context: Rule.RuleContext): [string, string[]] => {
const absolutePath = path.resolve(context.getFilename());
Expand All @@ -33,11 +15,6 @@ const fetchFilename = (context: Rule.RuleContext): [string, string[]] => {
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',
Expand All @@ -50,26 +27,11 @@ export const pluralize: Rule.RuleModule = {
},
minProperties: 1,
},
{
type: 'object',
properties: {
irregular,
plural,
singular,
uncountable: {
type: 'array',
items: { type: 'string' },
minItems: 1,
uniqueItems: true,
},
},
minProperties: 1,
},
],
},
create: context => {
const { rules, dictionaries } = parseOptions(context);
dictionaries && setDictionaries(dictionaries);
initPluralize(context);
const rules: Rules = context.options[0] ?? {};

return {
Program: node => {
Expand Down
38 changes: 21 additions & 17 deletions src/utils/pluralize.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,18 @@
import { Rule } from 'eslint';
import pluralize from 'pluralize';

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

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

export const isValidName = (name: string, rule?: Rule) => {
const validator = {
singular: pluralize.isSingular,
plural: pluralize.isPlural,
};
return rule ? validator[rule](name) : true;
};
export const initPluralize = (context: Pick<Rule.RuleContext, 'settings'>) => {
const dictionaries: Dictionaries | undefined = context.settings?.['filenames-simple']?.pluralize;
if (!dictionaries) return;

export const setDictionaries = (dictionaries: Dictionaries) => {
const keys: Array<keyof Dictionaries> = ['irregular', 'plural', 'singular', 'uncountable'];
const dictionarySetter = {
irregular: ([singular, plural]: [string, string]) =>
Expand All @@ -42,3 +30,19 @@ export const setDictionaries = (dictionaries: Dictionaries) => {
dictionaries[key] && dictionaries[key].forEach(dictionarySetter[key]);
});
};

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

export const isValidName = (name: string, rule?: PluralizeRule) => {
const validator = {
singular: pluralize.isSingular,
plural: pluralize.isPlural,
};
return rule ? validator[rule](name) : true;
};
33 changes: 17 additions & 16 deletions tests/rules/pluralize.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { RuleTester } from 'eslint';
import { pluralize } from '#/rules/pluralize';
import { Dictionaries } from '#/utils/pluralize';

const ruleTester = new RuleTester();

Expand Down Expand Up @@ -39,24 +40,8 @@ ruleTester.run('pluralize', pluralize, {
filename: 'src/controllers/indices.js',
options: [{ parentDir: 'plural', file: 'plural' }],
},
{
code: '',
filename: 'src/lib/index.js',
options: [
{ parentDir: 'plural', file: 'singular' },
{ irregular: [['person', 'people']], uncountable: ['lib'] },
],
},
],
invalid: [
{
code: '',
filename: 'src/controller/index.js',
options: [{ parentDir: 'plural', file: 'singular' }],
errors: [
'The filename must follow the pluralize rule. Should rename to controllers/index.js',
],
},
{
code: '',
filename: 'src/controller/index.js',
Expand All @@ -75,3 +60,19 @@ ruleTester.run('pluralize', pluralize, {
},
],
});

const dictonaries: Dictionaries = { irregular: [['person', 'people']], uncountable: ['lib'] };
const ruleTesterWithDictonaries = new RuleTester({
settings: { 'filenames-simple': { pluralize: dictonaries } },
});

ruleTesterWithDictonaries.run('pluralize', pluralize, {
valid: [
{
code: '',
filename: 'src/lib/index.js',
options: [{ parentDir: 'plural', file: 'singular' }],
},
],
invalid: [],
});
60 changes: 37 additions & 23 deletions tests/utils/pluralize.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Rule } from 'eslint';
import * as pluralize from '#/utils/pluralize';

describe('pluralize.correct', () => {
Expand Down Expand Up @@ -62,28 +63,41 @@ describe('pluralize.isValidName', () => {
});
});

describe('pluralize.setDictionaries', () => {
const dictionaries = {
irregular: [['regular', 'irregular']] as [string, string][],
plural: [['index', 'indexes']] as [string, string][],
singular: [['shoes', 'shoes']] as [string, string][],
uncountable: ['test'],
};
const subject = () => pluralize.setDictionaries(dictionaries);

it('returns true when the name is plural', () => {
// before setDictionaries()
expect(pluralize.correct('regular', 'plural')).toBe('regulars');
expect(pluralize.correct('index', 'plural')).toBe('indices');
expect(pluralize.correct('shoes', 'singular')).toBe('shoe');
expect(pluralize.correct('test', 'plural')).toBe('tests');

subject();

// after setDictionaries()
expect(pluralize.correct('regular', 'plural')).toBe('irregular');
expect(pluralize.correct('index', 'plural')).toBe('indexes');
expect(pluralize.correct('shoes', 'singular')).toBe('shoes');
expect(pluralize.correct('test', 'plural')).toBe('test');
// NOTE: This test affects other tests because the instance of `pluralize` is a singleton.
describe('pluralize.initPluralize', () => {
const subject = (context: Pick<Rule.RuleContext, 'settings'>) => pluralize.initPluralize(context);

describe('when dictionaries are empty', () => {
const context = { settings: {} };

it('does not throw error', () => {
subject(context);
});
});

describe('when dictionaries are present', () => {
const dictionaries = {
irregular: [['regular', 'irregular']] as [string, string][],
plural: [['index', 'indexes']] as [string, string][],
singular: [['shoes', 'shoes']] as [string, string][],
uncountable: ['test'],
};
const context = { settings: { 'filenames-simple': { pluralize: dictionaries } } };

it('set the dictionaries of pluralize', () => {
// before setDictionaries()
expect(pluralize.correct('regular', 'plural')).toBe('regulars');
expect(pluralize.correct('index', 'plural')).toBe('indices');
expect(pluralize.correct('shoes', 'singular')).toBe('shoe');
expect(pluralize.correct('test', 'plural')).toBe('tests');

subject(context);

// after setDictionaries()
expect(pluralize.correct('regular', 'plural')).toBe('irregular');
expect(pluralize.correct('index', 'plural')).toBe('indexes');
expect(pluralize.correct('shoes', 'singular')).toBe('shoes');
expect(pluralize.correct('test', 'plural')).toBe('test');
});
});
});

0 comments on commit 3644dde

Please sign in to comment.