|
| 1 | +import * as fs from 'fs'; |
| 2 | +import * as path from 'path'; |
| 3 | +import * as coreModules from 'resolve/lib/core'; |
1 | 4 | import * as tslint from 'tslint';
|
2 | 5 | import * as tslintAirbnb from 'tslint-config-airbnb';
|
3 | 6 | const tslintReact = require('tslint-react');
|
4 | 7 |
|
5 | 8 | const rulesAirbnb = tslintAirbnb.rules;
|
6 | 9 | const rulesReact = tslintReact.rules;
|
7 | 10 |
|
| 11 | +// prepare regex for node core modules for 'ordered-imports' rule |
| 12 | +const modules = Object.entries(coreModules as Record<string, boolean>).reduce( |
| 13 | + (acc: string[], [module, enabled]) => { |
| 14 | + enabled && !module.startsWith('_') && acc.push(module); |
| 15 | + return acc; |
| 16 | + }, |
| 17 | + [] |
| 18 | +); |
| 19 | +const coreModulesRegex = '^(' + modules.join('|') + ')$'; |
| 20 | + |
| 21 | +// prepare import groups for 'ordered-imports' rule |
| 22 | +const projectPackageJson = path.join(process.cwd(), 'package.json'); |
| 23 | +let dependenciesRegex; |
| 24 | +if (fs.existsSync(projectPackageJson)) { |
| 25 | + const packageJson = require(projectPackageJson); |
| 26 | + const dependencies = [ |
| 27 | + ...Object.keys(packageJson.dependencies || {}), |
| 28 | + ...Object.keys(packageJson.devDependencies || {}), |
| 29 | + ]; |
| 30 | + |
| 31 | + if (dependencies.length) { |
| 32 | + dependenciesRegex = '^(' + dependencies.join('|').replace(/\./g, '\\\\.') + ')(/|$)'; |
| 33 | + } |
| 34 | +} |
| 35 | + |
| 36 | +const importGroups = [ |
| 37 | + { |
| 38 | + name: 'aliased paths, which begin with tilde in our convention', |
| 39 | + match: '^~', |
| 40 | + order: 30, |
| 41 | + }, |
| 42 | + { |
| 43 | + name: 'parent directories', |
| 44 | + match: '^\\.\\.', |
| 45 | + order: 50, |
| 46 | + }, |
| 47 | + { |
| 48 | + name: 'current directory', |
| 49 | + match: '^\\.', |
| 50 | + order: 60, |
| 51 | + }, |
| 52 | + { |
| 53 | + name: 'built-in node modules', |
| 54 | + match: coreModulesRegex, |
| 55 | + order: 10, |
| 56 | + }, |
| 57 | + dependenciesRegex && { |
| 58 | + name: 'dependencies', |
| 59 | + match: dependenciesRegex, |
| 60 | + order: 20, |
| 61 | + }, |
| 62 | + { |
| 63 | + name: 'the rest, incl. typescript absolute imports', |
| 64 | + match: '\\.*', |
| 65 | + order: 40, |
| 66 | + }, |
| 67 | +].filter(Boolean); // filter out empty dependencies group |
| 68 | + |
8 | 69 | const rules : tslint.Configuration.RawRulesConfig = Object.assign({}, rulesAirbnb, rulesReact, {
|
9 | 70 | // differences from airbnb ruleset
|
10 | 71 | 'prefer-array-literal': [true, {'allow-size-argument': true}],
|
@@ -87,6 +148,11 @@ const rules : tslint.Configuration.RawRulesConfig = Object.assign({}, rulesAirbn
|
87 | 148 | 'no-for-in-array': true,
|
88 | 149 | 'no-return-await': true,
|
89 | 150 | 'no-unused': [true, 'ignore-parameters'], // instead of "noUnusedLocals" in typescript
|
| 151 | + 'ordered-imports': [true, { |
| 152 | + 'named-imports-order': 'lowercase-last', |
| 153 | + 'grouped-imports': true, |
| 154 | + groups: importGroups, |
| 155 | + }], |
90 | 156 |
|
91 | 157 | // comments
|
92 | 158 | /**
|
|
0 commit comments