Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update order-properties to use sort-package-json #55

Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 18 additions & 9 deletions docs/rules/order-properties.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,19 +31,28 @@ Examples of **correct** code for this rule:

### Options

Pass an array of top-level package properties to lint sorting on only those
properties. All properties not in this collection will be ignored.
```js
"package-json/order-properties": ["error", {
order: "sort-package-json"
}]
```

Example:
#### Order

```js
"package-json/order-properties": ["error", [
"name",
"version" // Ensure only that name precedes version
]]
The `order` property specifies the sorting order of package properties. Pass in:

- "legacy" - to order properties specified by [npm documentation](https://docs.npmjs.com/cli/v10/configuring-npm/package-json).
- "sort-package-json" - to order properties by the default order specified in [sort-package-json](https://github.com/keithamus/sort-package-json).
- Array<string> - to specify an array of top-level package properties to lint sorting on only those
JoshuaKGoldberg marked this conversation as resolved.
Show resolved Hide resolved
properties. All properties not in this collection will be sorted by "sort-package-json" specifications.

```tsx
interface {
order?: "legacy" | "sort-package-json" | Array<string>
}
```

Defaults:
Default: `legacy`

```json
[
Expand Down
88 changes: 39 additions & 49 deletions lib/rules/order-properties.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
'use strict';
const disparity = require('disparity');
const sortPackageJson = require('sort-package-json');
const {
isPackageJson,
extractPackageObjectFromAST
Expand Down Expand Up @@ -40,12 +41,6 @@ const standardOrder = [
'cpu'
];

const toIndexMap = (arr) =>
arr.reduce((indexMap, value, index) => {
indexMap[value] = index;
return indexMap;
}, {});

module.exports = {
meta: {
docs: {
Expand All @@ -57,74 +52,69 @@ module.exports = {
fixable: 'code', // or "code" or "whitespace"
schema: [
{
type: 'array',
items: {
type: 'string'
type: 'object',
properties: {
order: {
anyOf: [
{
type: ['string'],
enum: ['legacy', 'sort-package-json']
},
{
type: ['array'],
items: {
type: ['string']
}
}
]
}
}
}
]
},

create(context) {
return {
'Program:exit': (node) => {
'Program:exit': node => {
const options = context.options[0] || { order: 'legacy' };
if (!isPackageJson(context.getFilename())) {
return;
}
const sourceCode = context.getSourceCode();
const packageRoot = extractPackageObjectFromAST(node);
const original = JSON.parse(sourceCode.getText(packageRoot));
const originalIndexMap = toIndexMap(Object.keys(original));
const requiredOrder = context.options[0] || standardOrder;
const requiredIndexMap = toIndexMap(requiredOrder);
const requiredOrder =
options.order === 'legacy' ? standardOrder : options.order;

const orderedSource =
JSON.stringify(
Object.entries(original)
.sort(([a], [b]) => {
const aIndex = requiredIndexMap[a];
const bIndex = requiredIndexMap[b];
const notRequired = {
a: isNaN(aIndex),
b: isNaN(bIndex)
};
if (notRequired.a && notRequired.b) {
// istanbul ignore next: node almost never compares
return originalIndexMap[a] >
originalIndexMap[b]
? 1
: -1;
}
if (notRequired.a) {
return 1;
}
if (notRequired.b) {
return -1;
}
return aIndex > bIndex ? 1 : -1;
})
.reduce((out, [key, value]) => {
out[key] = value;
return out;
}, {}),
null,
2
) + '\n';
const orderedSource = sortPackageJson(
original,
requiredOrder === 'sort-package-json'
? undefined
: {
sortOrder: requiredOrder
}
);

const diff = disparity.unified(
orderedSource,
JSON.stringify(original, null, 2) + '\n'
JSON.stringify(orderedSource, null, 2),
JSON.stringify(original, null, 2)
);
if (diff) {
context.report({
node: packageRoot,
message:
'Package top-level properties are not ordered in the NPM standard way:\n\n{{ diff }}',
data: {
diff: diff.split('\n').slice(3).join('\n')
diff: diff
.split('\n')
.slice(3)
.join('\n')
},
fix(fixer) {
return fixer.replaceText(node, orderedSource);
return fixer.replaceText(
node,
JSON.stringify(orderedSource, null, 2) + `\n`
);
}
});
}
Expand Down
17 changes: 9 additions & 8 deletions lib/rules/sort-collections.js
JoshuaKGoldberg marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ module.exports = {
]
},

create: function (context) {
create: function(context) {
const toSort = context.options[0] || defaultCollections;
return {
'Property:exit': (node) => {
'Property:exit': node => {
if (!isPackageJson(context.getFilename())) {
return;
}
Expand Down Expand Up @@ -63,12 +63,13 @@ module.exports = {
collection,
JSON.stringify(
desiredOrder.reduce((out, property) => {
out[property.key.value] =
JSON.parse(
context
.getSourceCode()
.getText(property.value)
);
out[
property.key.value
] = JSON.parse(
context
.getSourceCode()
.getText(property.value)
);
return out;
}, {}),
null,
Expand Down
10 changes: 5 additions & 5 deletions lib/rules/valid-package-def.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ const unusedErrorPatterns = [
/^author field should have name/i
];

const isUsableError = (errorText) =>
unusedErrorPatterns.every((pattern) => !pattern.test(errorText));
const isUsableError = errorText =>
unusedErrorPatterns.every(pattern => !pattern.test(errorText));

module.exports = {
meta: {
Expand All @@ -32,9 +32,9 @@ module.exports = {
fixable: null // or "code" or "whitespace"
},

create: function (context) {
create: function(context) {
return {
'Program:exit': (node) => {
'Program:exit': node => {
if (!isPackageJson(context.getFilename())) {
return;
}
Expand All @@ -47,7 +47,7 @@ module.exports = {
if (critical || errors) {
const allErrors = [...(critical || []), ...errors];
allErrors.filter(isUsableError).forEach(
(message) =>
message =>
message &&
context.report({
node: packageRoot,
Expand Down
Loading