Skip to content

Commit f37e271

Browse files
authored
#50 and Fixed #53 - Update prefer-property-order (#54)
* #50 and Fixed #53 - Update prefer-property-order Add defaults if an empty array is passed. Prevent the rule from failing if package.json file is missing a node that exists in the preferred property list. * Revert from array includes to indexOf for Node 4 and 5 support
1 parent 89d8422 commit f37e271

File tree

6 files changed

+251
-42
lines changed

6 files changed

+251
-42
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ This project adheres to [Semantic Versioning](http://semver.org/).
1111

1212
### Removed
1313

14+
## [2.8.1] - 2017-08-21
15+
### Changed/Fixed
16+
- Updated rule: [prefer-property-order](https://github.com/tclindner/npm-package-json-lint/wiki/prefer-property-order) based on discussion with @moshest in [issue #50](https://github.com/tclindner/npm-package-json-lint/issues/50) and @evilebottnawi in [issue #53](https://github.com/tclindner/npm-package-json-lint/issues/53).
17+
1418
## [2.8.0] - 2017-08-16
1519
### Added
1620
- New rule: [prefer-property-order](https://github.com/tclindner/npm-package-json-lint/wiki/prefer-property-order)

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "npm-package-json-lint",
3-
"version": "2.8.0",
3+
"version": "2.8.1",
44
"description": "CLI app for linting package.json files.",
55
"keywords": [
66
"lint",

src/rules/prefer-property-order.js

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,7 @@ const lint = function(packageJsonData, lintType, preferredOrder) {
1111
const result = isInPreferredOrder(packageJsonData, preferredOrder);
1212

1313
if (!result.status) {
14-
let helpTip = '';
15-
16-
if (result.data.actualNode === null) {
17-
helpTip = `Please add ${result.data.desiredNode} at the end of the file.`;
18-
} else {
19-
helpTip = `Please move ${result.data.actualNode} after ${result.data.desiredNode}.`;
20-
}
21-
22-
return new LintIssue(lintId, lintType, nodeName, `${message} ${helpTip}`);
14+
return new LintIssue(lintId, lintType, nodeName, `${message} ${result.msg}`);
2315
}
2416

2517
return true;

src/validators/property-order.js

Lines changed: 73 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,95 @@
11
'use strict';
22

3+
/* eslint max-statements: 'off' */
4+
5+
const notFound = -1;
6+
const empty = 0;
37
const increment = 1;
8+
const defaultPreferredNodeOrder = [
9+
'name',
10+
'version',
11+
'description',
12+
'keywords',
13+
'homepage',
14+
'bugs',
15+
'license',
16+
'author',
17+
'contributors',
18+
'files',
19+
'main',
20+
'module',
21+
'jsnext:main',
22+
'types',
23+
'typings',
24+
'style',
25+
'example',
26+
'examplestyle',
27+
'assets',
28+
'bin',
29+
'man',
30+
'directories',
31+
'repository',
32+
'scripts',
33+
'config',
34+
'pre-commit',
35+
'browser',
36+
'browserify',
37+
'babel',
38+
'eslintConfig',
39+
'stylelint',
40+
'npmPackageJsonLintConfig',
41+
'dependencies',
42+
'devDependencies',
43+
'peerDependencies',
44+
'bundledDependencies',
45+
'bundleDependencies',
46+
'optionalDependencies',
47+
'engines',
48+
'engineStrict',
49+
'os',
50+
'cpu',
51+
'preferGlobal',
52+
'private',
53+
'publishConfig'
54+
];
455

556
/**
657
* Determines whether an array is in the specified order
7-
* @param {Object} packageJsonData Valid JSON
8-
* @param {Array} preferredNodeOrder Preferred order of nodes
9-
* @return {Object} Object containing the status and the node that is out of order, if applicable
58+
* @param {Object} packageJsonData Valid JSON
59+
* @param {Array} userPreferredNodeOrder Preferred order of nodes
60+
* @return {Object} Object containing the status and the node that is out of order, if applicable
1061
*/
11-
const isInPreferredOrder = function(packageJsonData, preferredNodeOrder) {
62+
const isInPreferredOrder = function(packageJsonData, userPreferredNodeOrder) {
1263
let isValid = true;
13-
let data = {
14-
actualNode: null,
15-
desiredNode: null
16-
};
64+
let msg = null;
1765
const actualNodeList = Object.keys(packageJsonData);
66+
const preferredNodeOrder = userPreferredNodeOrder.length === empty ? Array.from(defaultPreferredNodeOrder) : Array.from(userPreferredNodeOrder);
67+
const preferredNodeOrderCopy = Array.from(preferredNodeOrder);
1868

19-
for (let keyIndex = 0;keyIndex < preferredNodeOrder.length;keyIndex += increment) {
20-
if (typeof actualNodeList[keyIndex] === 'undefined') {
69+
for (let keyIndex = 0;keyIndex < actualNodeList.length;keyIndex += increment) {
70+
let preferredNodeOrderItem = null;
71+
72+
if (preferredNodeOrder.indexOf(actualNodeList[keyIndex]) === notFound) {
2173
isValid = false;
22-
data = {
23-
actualNode: null,
24-
desiredNode: preferredNodeOrder[keyIndex]
25-
};
74+
msg = `${actualNodeList[keyIndex]} is not in the preferred property list.`;
2675
break;
27-
} else if (actualNodeList[keyIndex] !== preferredNodeOrder[keyIndex]) {
76+
}
77+
78+
if (preferredNodeOrderCopy.indexOf(actualNodeList[keyIndex]) === notFound) {
2879
isValid = false;
29-
data = {
30-
actualNode: actualNodeList[keyIndex],
31-
desiredNode: preferredNodeOrder[keyIndex]
32-
};
80+
msg = `Please move ${actualNodeList[keyIndex]} before ${actualNodeList[keyIndex - increment]}.`;
3381
break;
3482
}
83+
84+
do {
85+
preferredNodeOrderItem = preferredNodeOrderCopy.shift();
86+
87+
} while (actualNodeList[keyIndex] !== preferredNodeOrderItem);
3588
}
3689

3790
return {
3891
status: isValid,
39-
data
92+
msg
4093
};
4194
};
4295

tests/unit/rules/prefer-property-order.test.js

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,7 @@ describe('prefer-property-order Unit Tests', function() {
3737
];
3838
const response = lint(packageJsonData, 'error', preferredOrder);
3939

40-
response.lintId.should.equal('prefer-property-order');
41-
response.lintType.should.equal('error');
42-
response.node.should.equal('');
43-
response.lintMessage.should.equal('Your package.json properties are not in the desired order. Please add description at the end of the file.');
40+
response.should.be.true;
4441
});
4542
});
4643

@@ -61,7 +58,7 @@ describe('prefer-property-order Unit Tests', function() {
6158
response.lintId.should.equal('prefer-property-order');
6259
response.lintType.should.equal('error');
6360
response.node.should.equal('');
64-
response.lintMessage.should.equal('Your package.json properties are not in the desired order. Please move description after version.');
61+
response.lintMessage.should.equal('Your package.json properties are not in the desired order. Please move version before description.');
6562
});
6663
});
6764
});

tests/unit/validators/property-order.test.js

Lines changed: 170 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,22 @@ describe('property-order Unit Tests', function() {
2222
const response = propertyOrder.isInPreferredOrder(packageJson, preferredOrder);
2323

2424
response.status.should.be.true;
25-
(response.data.actualNode === null).should.be.true;
26-
(response.data.desiredNode === null).should.be.true;
25+
(response.msg === null).should.be.true;
26+
});
27+
});
28+
29+
context('when the properties in the package.json file are in the desired order, but the defaults are used', function() {
30+
it('true should be returned', function() {
31+
const packageJson = {
32+
name: 'awesome-module',
33+
version: '1.0.0',
34+
description: 'description'
35+
};
36+
const preferredOrder = [];
37+
const response = propertyOrder.isInPreferredOrder(packageJson, preferredOrder);
38+
39+
response.status.should.be.true;
40+
(response.msg === null).should.be.true;
2741
});
2842
});
2943

@@ -40,9 +54,8 @@ describe('property-order Unit Tests', function() {
4054
];
4155
const response = propertyOrder.isInPreferredOrder(packageJson, preferredOrder);
4256

43-
response.status.should.be.false;
44-
(response.data.actualNode === null).should.be.true;
45-
response.data.desiredNode.should.equal('description');
57+
response.status.should.be.true;
58+
(response.msg === null).should.be.true;
4659
});
4760
});
4861

@@ -61,8 +74,158 @@ describe('property-order Unit Tests', function() {
6174
const response = propertyOrder.isInPreferredOrder(packageJson, preferredOrder);
6275

6376
response.status.should.be.false;
64-
response.data.actualNode.should.equal('description');
65-
response.data.desiredNode.should.equal('version');
77+
response.msg.should.equal('Please move version before description.');
78+
});
79+
});
80+
81+
context('when the actual node list is in a different order than desired', function() {
82+
it('false should be returned', function() {
83+
const packageJson = {
84+
version: '1.0.0',
85+
name: 'awesome-module',
86+
description: 'description'
87+
};
88+
const preferredOrder = [
89+
'name',
90+
'version',
91+
'description'
92+
];
93+
const response = propertyOrder.isInPreferredOrder(packageJson, preferredOrder);
94+
95+
response.status.should.be.false;
96+
response.msg.should.equal('Please move name before version.');
97+
});
98+
});
99+
100+
context('when the actual node list is in a different order than desired', function() {
101+
it('false should be returned', function() {
102+
const packageJson = {
103+
name: 'awesome-module',
104+
version: '1.0.0',
105+
description: 'description'
106+
};
107+
const preferredOrder = [
108+
'name',
109+
'version',
110+
'homepage',
111+
'description'
112+
];
113+
const response = propertyOrder.isInPreferredOrder(packageJson, preferredOrder);
114+
115+
response.status.should.be.true;
116+
(response.msg === null).should.be.true;
117+
});
118+
});
119+
120+
context('when the actual node list is in a different order than desired', function() {
121+
it('false should be returned', function() {
122+
const packageJson = {
123+
name: 'awesome-module',
124+
version: '1.0.0',
125+
description: 'description',
126+
homepage: 'https://github.com/tclindner/npm-package-json-lint'
127+
};
128+
const preferredOrder = [
129+
'name',
130+
'version',
131+
'description',
132+
'keywords',
133+
'homepage'
134+
];
135+
const response = propertyOrder.isInPreferredOrder(packageJson, preferredOrder);
136+
137+
response.status.should.be.true;
138+
(response.msg === null).should.be.true;
139+
});
140+
});
141+
142+
context('when the actual node list is in correct order, but has extra values in preferred order', function() {
143+
it('true should be returned', function() {
144+
const packageJson = {
145+
name: 'awesome-module',
146+
version: '1.0.0',
147+
description: 'description',
148+
homepage: 'https://github.com/tclindner/npm-package-json-lint'
149+
};
150+
const preferredOrder = [
151+
'name',
152+
'version',
153+
'description',
154+
'scripts',
155+
'bin',
156+
'keywords',
157+
'homepage'
158+
];
159+
const response = propertyOrder.isInPreferredOrder(packageJson, preferredOrder);
160+
161+
response.status.should.be.true;
162+
(response.msg === null).should.be.true;
163+
});
164+
});
165+
166+
context('when the actual node list is not in correct order and also has extra values in preferred order', function() {
167+
it('true should be returned', function() {
168+
const packageJson = {
169+
name: 'awesome-module',
170+
version: '1.0.0',
171+
description: 'description',
172+
homepage: 'https://github.com/tclindner/npm-package-json-lint',
173+
keywords: ['word']
174+
};
175+
const preferredOrder = [
176+
'name',
177+
'version',
178+
'description',
179+
'scripts',
180+
'bin',
181+
'keywords',
182+
'homepage'
183+
];
184+
const response = propertyOrder.isInPreferredOrder(packageJson, preferredOrder);
185+
186+
response.status.should.be.false;
187+
response.msg.should.equal('Please move keywords before homepage.');
188+
});
189+
});
190+
191+
context('when node is not in the preferred node list', function() {
192+
it('false should be returned', function() {
193+
const packageJson = {
194+
name: 'awesome-module',
195+
version: '1.0.0',
196+
description: 'description',
197+
homepage: 'https://github.com/tclindner/npm-package-json-lint'
198+
};
199+
const preferredOrder = [
200+
'name',
201+
'version',
202+
'keywords',
203+
'homepage'
204+
];
205+
const response = propertyOrder.isInPreferredOrder(packageJson, preferredOrder);
206+
207+
response.status.should.be.false;
208+
response.msg.should.equal('description is not in the preferred property list.');
209+
});
210+
});
211+
212+
context('when node is not in the preferred node list', function() {
213+
it('false should be returned', function() {
214+
const packageJson = {
215+
name: 'awesome-module',
216+
version: '1.0.0',
217+
description: 'description',
218+
homepage: 'https://github.com/tclindner/npm-package-json-lint'
219+
};
220+
const preferredOrder = [
221+
'version',
222+
'keywords',
223+
'homepage'
224+
];
225+
const response = propertyOrder.isInPreferredOrder(packageJson, preferredOrder);
226+
227+
response.status.should.be.false;
228+
response.msg.should.equal('name is not in the preferred property list.');
66229
});
67230
});
68231
});

0 commit comments

Comments
 (0)