From 3b3f9954cf89c679cd34a25e47df6c75e1441662 Mon Sep 17 00:00:00 2001 From: shellscape Date: Sun, 6 Oct 2019 19:56:03 -0400 Subject: [PATCH 1/2] chore: setup framework for custom sorting --- lib/index.js | 25 +++++++++--- lib/rules/custom.js | 40 ++++++++++++++++++ lib/rules/dependencies.js | 32 --------------- lib/rules/sort.js | 74 ---------------------------------- test/custom.js | 26 ++++++++++++ test/fixtures/fixture.json | 20 ++++----- test/snapshots/custom.js.md | 19 +++++++++ test/snapshots/custom.js.snap | Bin 0 -> 189 bytes test/snapshots/test.js.md | 16 ++++---- test/snapshots/test.js.snap | Bin 916 -> 922 bytes 10 files changed, 119 insertions(+), 133 deletions(-) create mode 100644 lib/rules/custom.js delete mode 100644 lib/rules/dependencies.js delete mode 100644 lib/rules/sort.js create mode 100644 test/custom.js create mode 100644 test/snapshots/custom.js.md create mode 100644 test/snapshots/custom.js.snap diff --git a/lib/index.js b/lib/index.js index 9997f32..e7a99dc 100644 --- a/lib/index.js +++ b/lib/index.js @@ -10,28 +10,39 @@ */ const { parsers } = require('prettier/parser-babylon'); -const { dependencies } = require('./rules/dependencies'); +const { custom } = require('./rules/custom'); const { engines } = require('./rules/engines'); const { files } = require('./rules/files'); const { scripts } = require('./rules/scripts'); -const { sort } = require('./rules/sort'); +const { sort: sortProps } = require('./rules/props'); const { 'json-stringify': parser } = parsers; const { parse } = parser; const rePkg = /package\.json$/; -const format = (properties) => { - let props = sort(properties); +const format = (properties, { sort = null }) => { + let props = sortProps(properties); props = engines(props); props = files(props); props = scripts(props); - props = dependencies(props); + + if (sort) { + props = custom(props, sort); + } return props; }; module.exports = { name: 'prettier-plugin-package', + options: { + sort: { + type: 'object', + category: 'prettier-plugin-package', + default: null, + description: 'Specify custom sorting for one or more package properties' + } + }, parsers: { 'json-stringify': { ...parser, @@ -40,9 +51,11 @@ module.exports = { const { filepath } = options; const ast = parse(...args); + console.log(options); + if (rePkg.test(filepath)) { const { properties } = ast; - ast.properties = format(properties); + ast.properties = format(properties, options); } return ast; diff --git a/lib/rules/custom.js b/lib/rules/custom.js new file mode 100644 index 0000000..6b500bb --- /dev/null +++ b/lib/rules/custom.js @@ -0,0 +1,40 @@ +/* + Copyright © 2019 Andrew Powell + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of this Source Code Form. +*/ + +const alpha = (a, b) => (a.key.value > b.key.value ? 1 : a.key.value < b.key.value ? -1 : 0); + +const methods = { alpha }; +const { log } = console; + +const process = (props, sort) => { + const declaredMethods = Object.keys(sort); + let result = props; + + log('declaredMethods', declaredMethods); + + for (const methodName of declaredMethods) { + const method = methods[methodName]; + const propertyNames = declaredMethods[methodName]; + + if (method) { + result = result.map((prop) => { + if (propertyNames.includes(prop.key.value)) { + prop.value.properties.sort(method); + } + return prop; + }); + } + } + + return result; +}; + +module.exports = { custom: process }; diff --git a/lib/rules/dependencies.js b/lib/rules/dependencies.js deleted file mode 100644 index 61b9488..0000000 --- a/lib/rules/dependencies.js +++ /dev/null @@ -1,32 +0,0 @@ -/* - Copyright © 2019 Andrew Powell - - This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of this Source Code Form. -*/ - -const dependencyNames = [ - // dependencies - 'bundledDependencies', - 'optionalDependencies', - 'peerDependencies', - 'dependencies', - 'devDependencies', - 'resolutions' -]; - -const process = (props) => - props.map((prop) => { - if (dependencyNames.includes(prop.key.value)) { - prop.value.properties.sort((a, b) => - a.key.value > b.key.value ? 1 : a.key.value < b.key.value ? -1 : 0 - ); - } - return prop; - }); - -module.exports = { dependencies: process }; diff --git a/lib/rules/sort.js b/lib/rules/sort.js deleted file mode 100644 index c16a7ec..0000000 --- a/lib/rules/sort.js +++ /dev/null @@ -1,74 +0,0 @@ -/* - Copyright © 2019 Andrew Powell - - This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of this Source Code Form. -*/ -const primary = [ - // meta - 'name', - 'version', - 'flat', - 'private', - 'publishConfig', - 'description', - 'license', - 'repository', - 'author', - 'homepage', - 'bugs', - - // entry - 'main', - 'bin', - 'module', - - // constraints - 'engines', - 'cpu', - 'os', - - // content and util - 'scripts', - 'files', - 'keywords', - - // dependencies - 'bundledDependencies', - 'optionalDependencies', - 'peerDependencies', - 'dependencies', - 'devDependencies', - 'resolutions', - - // types - 'types', - 'typings' -]; - -const sort = (props) => { - const unknown = []; - const known = props.filter((prop) => { - if (primary.includes(prop.key.value)) { - return true; - } - unknown.push(prop); - return false; - }); - - known.sort((a, b) => { - const aIndex = primary.indexOf(a.key.value); - const bIndex = primary.indexOf(b.key.value); - - return aIndex > bIndex ? 1 : aIndex < bIndex ? -1 : 0; - }); - unknown.sort((a, b) => (a.key.value > b.key.value ? 1 : a.key.value < b.key.value ? -1 : 0)); - - return known.concat(unknown); -}; - -module.exports = { sort }; diff --git a/test/custom.js b/test/custom.js new file mode 100644 index 0000000..c4c4a22 --- /dev/null +++ b/test/custom.js @@ -0,0 +1,26 @@ +const test = require('ava'); +const prettier = require('prettier'); + +test('default', (t) => { + const options = { + filepath: 'package.json', + parser: 'json-stringify', + plugins: ['.'], + sort: { + alpha: ['dependencies'] + } + }; + const fixture = { + dependencies: { + nyc: '^14.1.0', + 'eslint-config-shellscape': '^2.0.2', + ava: '^2.2.0', + execa: '^2.0.3' + } + }; + + const input = JSON.stringify(fixture, null, 2); + const output = prettier.format(input, options); + + t.snapshot(output); +}); diff --git a/test/fixtures/fixture.json b/test/fixtures/fixture.json index 7df7e7e..01f2c6e 100644 --- a/test/fixtures/fixture.json +++ b/test/fixtures/fixture.json @@ -41,12 +41,6 @@ "prettier": "^1.18.2", "eslint-config-shellscape": "^2.0.2" }, - "dependencies": { - "nyc": "^14.1.0", - "eslint-config-shellscape": "^2.0.2", - "ava": "^2.2.0", - "execa": "^2.0.3" - }, "typings": "dist/index.d.ts", "dependencies": {}, "devDependencies": { @@ -60,17 +54,18 @@ "pre-commit": "^1.2.2", "prettier": "^1.18.2" }, - "ava": { - "files": [ - "!**/fixtures/**" - ] - }, + "pre-commit": "lint-staged", "lint-staged": { "*.js": [ "eslint --fix", "git add" ] }, + "ava": { + "files": [ + "!**/fixtures/**" + ] + }, "nyc": { "include": [ "lib/*.js" @@ -78,6 +73,5 @@ "exclude": [ "test/" ] - }, - "pre-commit": "lint-staged" + } } diff --git a/test/snapshots/custom.js.md b/test/snapshots/custom.js.md new file mode 100644 index 0000000..8bdd3b9 --- /dev/null +++ b/test/snapshots/custom.js.md @@ -0,0 +1,19 @@ +# Snapshot report for `test/custom.js` + +The actual snapshot is saved in `custom.js.snap`. + +Generated by [AVA](https://ava.li). + +## default + +> Snapshot 1 + + `{␊ + "dependencies": {␊ + "nyc": "^14.1.0",␊ + "eslint-config-shellscape": "^2.0.2",␊ + "ava": "^2.2.0",␊ + "execa": "^2.0.3"␊ + }␊ + }␊ + ` diff --git a/test/snapshots/custom.js.snap b/test/snapshots/custom.js.snap new file mode 100644 index 0000000000000000000000000000000000000000..b68f88b92a475e19c36d0c46880101b5654cd2b9 GIT binary patch literal 189 zcmV;u07CykRzVATSMxnHku@Y(`cFL8f+wYAyu@rIgfy)V!3` zyyVQ(VkIjDkQh)juQD0PQHnD((KFODP||^jrWWU9=9TCs=jWwmrt21Gq~_!lCnpx9 rf|VNS8R!|oR3?@sLIsVGv{$4iC&JYlD*;7oxoWup`H%0jwg3PC5JOMi literal 0 HcmV?d00001 diff --git a/test/snapshots/test.js.md b/test/snapshots/test.js.md index a874853..bdb798f 100644 --- a/test/snapshots/test.js.md +++ b/test/snapshots/test.js.md @@ -48,18 +48,18 @@ Generated by [AVA](https://ava.li). "prettier"␊ ],␊ "peerDependencies": {␊ - "eslint-config-shellscape": "^2.0.2",␊ - "prettier": "^1.18.2"␊ + "prettier": "^1.18.2",␊ + "eslint-config-shellscape": "^2.0.2"␊ },␊ "dependencies": {},␊ "devDependencies": {␊ - "@commitlint/cli": "^8.1.0",␊ "@commitlint/config-conventional": "^8.1.0",␊ + "lint-staged": "^9.2.0",␊ "ava": "^2.2.0",␊ "eslint-config-shellscape": "^2.0.2",␊ "execa": "^2.0.3",␊ - "lint-staged": "^9.2.0",␊ "nyc": "^14.1.0",␊ + "@commitlint/cli": "^8.1.0",␊ "pre-commit": "^1.2.2",␊ "prettier": "^1.18.2"␊ },␊ @@ -131,18 +131,18 @@ Generated by [AVA](https://ava.li). "prettier"␊ ],␊ "peerDependencies": {␊ - "eslint-config-shellscape": "^2.0.2",␊ - "prettier": "^1.18.2"␊ + "prettier": "^1.18.2",␊ + "eslint-config-shellscape": "^2.0.2"␊ },␊ "dependencies": {},␊ "devDependencies": {␊ - "@commitlint/cli": "^8.1.0",␊ "@commitlint/config-conventional": "^8.1.0",␊ + "lint-staged": "^9.2.0",␊ "ava": "^2.2.0",␊ "eslint-config-shellscape": "^2.0.2",␊ "execa": "^2.0.3",␊ - "lint-staged": "^9.2.0",␊ "nyc": "^14.1.0",␊ + "@commitlint/cli": "^8.1.0",␊ "pre-commit": "^1.2.2",␊ "prettier": "^1.18.2"␊ },␊ diff --git a/test/snapshots/test.js.snap b/test/snapshots/test.js.snap index afac647a227f721bbba7263ab62f321fcd1778e5..1fd1288573a16cc19bdbf0b3a6ff3c02957d8f1f 100644 GIT binary patch delta 877 zcmV-z1Csod2bu>WK~_N^Q*L2!b7*gLAa*he0s!?%_um=v@8vZI&MC7d@!pXlBNNwE z3$2#6U_siFOo%@ERH zK?03M(ntj;MM1b}ob@Pk(;z$udeFG8gAPGR%9)Ov_2#@eYmGpLf~G3>f3z6kDP_0{ z6htHk@SaJ|$UYZIpcDvV;kALR=SNz!n1;Zl;j*^A>dt$!)-E9Bk}58S+9mrC$1)63 z@c+m-$W)(;`VQ;q^8`{IhrYg2sa*8^9##FU>xDe=|Mq}x)|3AX;ZrFykQONksL?N` zU7xZD1}ItX;ZYVFq7jwKf8VDucp#I~4-7Fu)6l8Z$>fm0-z+uelOz7!sByL}ZMhOMz76+BKrhIsrlv*R>xYmJ|$>8{>AeObQTBuMI5=9#f_a za1N^11~Fet2s1&|aBK^bN)l>_HteU_=(_uYCrek4+AACF)z04Ce~s3o_QPYeD?YMr zK5We$R{-@bsvOL%To-?lbC*jfW6P83=hpp+?2Xd`a`nN=*4}z+qqVkKL>D+93+{A) zf5RZ`1M1Kvg}Oy`pz}Fu0kt<%MRTP>b7ZSzw9F$ACe6ArmHo#o9*&D%M3sW){veBJ z=`55A4uet6=z7zMe|TzRYPCshy%ygaoz}gzj+d02R#)1cN1GiDwqw8!VECMisDf90 zPNQY*?)KGG?rHl)37P_kdyoP$VA`0@h0o z4Of~??0W;136OrX*)aB<61=Wo4${;`TEVEk!<;f&v0;-SipCMGJV!;zhjC_FY6+&R z-W*`}m0F((E7VWQA4jjNSY3lkq$m&y(>y8PAjPJQ>gb-FW^9=Ia0Bcn<&o D%q_65 delta 871 zcmV-t1DO1p2b2dQK~_N^Q*L2!b7*gLAa*he0sz+T{B3-{>A4d12r7W;qMdB<@sIO6i-pLbsEzW(~{ z$s7LQ^y7r1f8I|z&gbu68apTNPJT>2`SkL1=fi}tE?#k*i_WBpnz-a#z3_JOXo`>q z3leC|lSV2)DGI_(L8f|K)OT1=RYlE1tC4`xvYA~_|NhJw2L>u3^_5gM0kV4&}I?#EDT0rg1RMA|i&>Yz+87}h(gh{hbOl9v8iwC2k7g43)xj)Dv zS~?4*f`edKGrHdNe?>gCF}2zxwqA?xt#)g9z3n9>r?u6k_QrNwgFQ1~`!G1%s3&y*I24Ka8n?oWq7WT^v>mu-x$90WjS}gZS(Qe|;gA^6b!f{^Xz!VNjZH z{h_9I?^ePJf6qn`M(>_zW~D7&Kh_R0092BvTXnW From 98f9ce5b9c460cf4fce6358c8348bf4da494a830 Mon Sep 17 00:00:00 2001 From: shellscape Date: Sun, 6 Oct 2019 20:16:32 -0400 Subject: [PATCH 2/2] feat: plugin options, custom sorting --- lib/index.js | 33 +++++++++++++++++++++------------ lib/rules/custom.js | 5 +---- package-lock.json | 6 +++--- package.json | 2 +- test/custom.js | 8 +++++--- test/snapshots/custom.js.md | 6 +++--- test/snapshots/custom.js.snap | Bin 189 -> 190 bytes 7 files changed, 34 insertions(+), 26 deletions(-) diff --git a/lib/index.js b/lib/index.js index e7a99dc..14fba52 100644 --- a/lib/index.js +++ b/lib/index.js @@ -20,14 +20,25 @@ const { 'json-stringify': parser } = parsers; const { parse } = parser; const rePkg = /package\.json$/; -const format = (properties, { sort = null }) => { +const safe = (json) => { + try { + return JSON.parse(json); + } catch (_) { + return null; + } +}; + +const format = (properties, options) => { let props = sortProps(properties); props = engines(props); props = files(props); props = scripts(props); - if (sort) { - props = custom(props, sort); + if (options) { + const { sort } = safe(options); + if (sort) { + props = custom(props, sort); + } } return props; @@ -36,11 +47,11 @@ const format = (properties, { sort = null }) => { module.exports = { name: 'prettier-plugin-package', options: { - sort: { - type: 'object', - category: 'prettier-plugin-package', - default: null, - description: 'Specify custom sorting for one or more package properties' + pluginPackage: { + type: 'path', + category: 'Plugins', + default: '', + description: 'Specify options for the package plugin' } }, parsers: { @@ -48,14 +59,12 @@ module.exports = { ...parser, parse(...args) { const [, , options] = args; - const { filepath } = options; + const { filepath, pluginPackage } = options; const ast = parse(...args); - console.log(options); - if (rePkg.test(filepath)) { const { properties } = ast; - ast.properties = format(properties, options); + ast.properties = format(properties, pluginPackage); } return ast; diff --git a/lib/rules/custom.js b/lib/rules/custom.js index 6b500bb..f117bf4 100644 --- a/lib/rules/custom.js +++ b/lib/rules/custom.js @@ -12,17 +12,14 @@ const alpha = (a, b) => (a.key.value > b.key.value ? 1 : a.key.value < b.key.value ? -1 : 0); const methods = { alpha }; -const { log } = console; const process = (props, sort) => { const declaredMethods = Object.keys(sort); let result = props; - log('declaredMethods', declaredMethods); - for (const methodName of declaredMethods) { const method = methods[methodName]; - const propertyNames = declaredMethods[methodName]; + const propertyNames = sort[methodName]; if (method) { result = result.map((prop) => { diff --git a/package-lock.json b/package-lock.json index 3a0b6e0..c81c9c9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3133,9 +3133,9 @@ "dev": true }, "handlebars": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.2.0.tgz", - "integrity": "sha512-Kb4xn5Qh1cxAKvQnzNWZ512DhABzyFNmsaJf3OAkWNa4NkaqWcNI8Tao8Tasi0/F4JD9oyG0YxuFyvyR57d+Gw==", + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.4.2.tgz", + "integrity": "sha512-cIv17+GhL8pHHnRJzGu2wwcthL5sb8uDKBHvZ2Dtu5s1YNt0ljbzKbamnc+gr69y7bzwQiBdr5+hOpRd5pnOdg==", "dev": true, "requires": { "neo-async": "^2.6.0", diff --git a/package.json b/package.json index 0522bec..56675fb 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "eslint-config-shellscape": "^2.0.2", "execa": "^2.0.3", "lint-staged": "^9.2.0", - "nyc": "^14.1.0", + "nyc": "^14.1.1", "pre-commit": "^1.2.2", "prettier": "^1.18.2" }, diff --git a/test/custom.js b/test/custom.js index c4c4a22..16e7571 100644 --- a/test/custom.js +++ b/test/custom.js @@ -6,9 +6,11 @@ test('default', (t) => { filepath: 'package.json', parser: 'json-stringify', plugins: ['.'], - sort: { - alpha: ['dependencies'] - } + pluginPackage: JSON.stringify({ + sort: { + alpha: ['dependencies'] + } + }) }; const fixture = { dependencies: { diff --git a/test/snapshots/custom.js.md b/test/snapshots/custom.js.md index 8bdd3b9..f015e5d 100644 --- a/test/snapshots/custom.js.md +++ b/test/snapshots/custom.js.md @@ -10,10 +10,10 @@ Generated by [AVA](https://ava.li). `{␊ "dependencies": {␊ - "nyc": "^14.1.0",␊ - "eslint-config-shellscape": "^2.0.2",␊ "ava": "^2.2.0",␊ - "execa": "^2.0.3"␊ + "eslint-config-shellscape": "^2.0.2",␊ + "execa": "^2.0.3",␊ + "nyc": "^14.1.0"␊ }␊ }␊ ` diff --git a/test/snapshots/custom.js.snap b/test/snapshots/custom.js.snap index b68f88b92a475e19c36d0c46880101b5654cd2b9..e7fd47d0bc3ec9ceba1372e52239e71237c1bccb 100644 GIT binary patch delta 104 zcmV-u0GI#00lonuK~_N^Q*L2!b7*gLAa*he0s#C(DYhS?dAEsyEhI#;d18?wOAoOu z5y(-BGtx8CGf>ij2$6jlDneBn=o!IPR-`5;!i9}t!g-a+U_nC@Jwu?eK*3tBS}p*y Kn4P4y0002;J}5>2 delta 103 zcmV-t0GR*20lfhtK~_N^Q*L2!b7*gLAa*he0syNnz5%HuAcjbO_j~>O