Skip to content

Commit

Permalink
Merge e4e13ea into 6512110
Browse files Browse the repository at this point in the history
  • Loading branch information
Mairu committed Jul 14, 2019
2 parents 6512110 + e4e13ea commit 179e948
Show file tree
Hide file tree
Showing 4 changed files with 346 additions and 8 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Expand Up @@ -5,6 +5,8 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel

## [Unreleased]

### Added
- [`order`]: Adds support for pathGroups to allow ordering by defined patterns ([#795], thanks [@Mairu]

## [2.18.0] - 2019-06-24

Expand Down
26 changes: 26 additions & 0 deletions docs/rules/order.md
Expand Up @@ -94,6 +94,32 @@ You can set the options like this:
"import/order": ["error", {"groups": ["index", "sibling", "parent", "internal", "external", "builtin"]}]
```

### `pathGroups: [array of objects]`:

To be able so group by paths mostly needed with aliases pathGroups can be defined.

Properties of the objects

| property | required | type | description |
|----------------|:--------:|--------|---------------|
| pattern | x | string | minimatch pattern for the paths to be in this group (will not be used for builtins or externals) |
| patternOptions | | object | options for minimatch, default: { nocomment: true } |
| group | x | string | one of the allowed groups, the pathGroup will be positioned relative to this group |
| position | | string | defines where around the group the pathGroup will be positioned, can be 'after' or 'before', if not provided pathGroup will be positioned like the group |

```json
{
"import/order": ["error", {
"pathGroups": [
{
"pattern": "~/**",
"group": "external"
}
]
}]
}
```

### `newlines-between: [ignore|always|always-and-inside-groups|never]`:


Expand Down
98 changes: 95 additions & 3 deletions src/rules/order.js
@@ -1,5 +1,6 @@
'use strict'

import minimatch from 'minimatch'
import importType from '../core/importType'
import isStaticRequire from '../core/staticRequire'
import docsUrl from '../docsUrl'
Expand Down Expand Up @@ -242,9 +243,29 @@ function makeOutOfOrderReport(context, imported) {

// DETECTING

function computePathRank(ranks, pathGroups, path, maxPosition) {
for (let i = 0, l = pathGroups.length; i < l; i++) {
const { pattern, patternOptions, group, position = 1 } = pathGroups[i]
if (minimatch(path, pattern, patternOptions || { nocomment: true })) {
return ranks[group] + (position / maxPosition)
}
}
}

function computeRank(context, ranks, name, type) {
return ranks[importType(name, context)] +
(type === 'import' ? 0 : 100)
const impType = importType(name, context)
let rank
if (impType !== 'builtin' && impType !== 'external') {
rank = computePathRank(ranks.groups, ranks.pathGroups, name, ranks.maxPosition)
}
if (!rank) {
rank = ranks.groups[impType]
}
if (type !== 'import') {
rank += 100
}

return rank
}

function registerNode(context, node, name, type, ranks, imported) {
Expand Down Expand Up @@ -292,6 +313,49 @@ function convertGroupsToRanks(groups) {
}, rankObject)
}

function convertPathGroupsForRanks(pathGroups) {
const after = {}
const before = {}

const transformed = pathGroups.map((pathGroup, index) => {
const { group, position: positionString } = pathGroup
let position = 0
if (positionString === 'after') {
if (!after[group]) {
after[group] = 1
}
position = after[group]++
} else if (positionString === 'before') {
if (!before[group]) {
before[group] = []
}
before[group].push(index)
}

return Object.assign({}, pathGroup, { position })
})

let maxPosition = 1

Object.keys(before).forEach((group) => {
const groupLength = before[group].length
before[group].forEach((groupIndex, index) => {
transformed[groupIndex].position = -1 * (groupLength - index)
})
maxPosition = Math.max(maxPosition, groupLength)
})

Object.keys(after).forEach((key) => {
const groupNextPosition = after[key]
maxPosition = Math.max(maxPosition, groupNextPosition - 1)
})

return {
pathGroups: transformed,
maxPosition: maxPosition > 10 ? Math.pow(10, Math.ceil(Math.log10(maxPosition))) : 10,
}
}

function fixNewLineAfterImport(context, previousImport) {
const prevRoot = findRootNode(previousImport.node)
const tokensToEndOfLine = takeTokensAfterWhile(
Expand Down Expand Up @@ -376,6 +440,29 @@ module.exports = {
groups: {
type: 'array',
},
pathGroups: {
type: 'array',
items: {
type: 'object',
properties: {
pattern: {
type: 'string',
},
patternOptions: {
type: 'object',
},
group: {
type: 'string',
enum: types,
},
position: {
type: 'string',
enum: ['after', 'before'],
},
},
required: ['pattern', 'group'],
},
},
'newlines-between': {
enum: [
'ignore',
Expand All @@ -396,7 +483,12 @@ module.exports = {
let ranks

try {
ranks = convertGroupsToRanks(options.groups || defaultGroups)
const { pathGroups, maxPosition } = convertPathGroupsForRanks(options.pathGroups || [])
ranks = {
groups: convertGroupsToRanks(options.groups || defaultGroups),
pathGroups,
maxPosition,
}
} catch (error) {
// Malformed configuration
return {
Expand Down

0 comments on commit 179e948

Please sign in to comment.