Skip to content

Commit

Permalink
feat: keep comment-hack keys above preceding key
Browse files Browse the repository at this point in the history
  • Loading branch information
forivall committed Nov 26, 2020
1 parent 78f1110 commit cc1cee5
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 1 deletion.
37 changes: 36 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const uniqAndSortArray = pipe([uniq, sortArray])
const onObject = (fn) => (x) => (isPlainObject(x) ? fn(x) : x)
const sortObjectBy = (comparator, deep) => {
const over = onObject((object) => {
// TODO: check for comments and update comparator accordingly
object = sortObjectKeys(object, comparator)
if (deep) {
for (const [key, value] of Object.entries(object)) {
Expand Down Expand Up @@ -132,6 +133,7 @@ const defaultNpmScripts = new Set([
])

const sortScripts = onObject((scripts) => {
// TODO: apply comments extraction and re-application here.
const names = Object.keys(scripts)
const prefixable = new Set()

Expand Down Expand Up @@ -309,6 +311,7 @@ function editStringJSON(json, over) {
}

const isPrivateKey = (key) => key[0] === '_'
const isCommentKey = (key) => key.trim().startsWith('//')
const partition = (array, predicate) =>
array.reduce(
(result, value) => {
Expand All @@ -317,21 +320,53 @@ const partition = (array, predicate) =>
},
[[], []],
)
const removeAndGatherComments = (keys, predicate) =>
keys.reduceRight(
(result, key) => {
const prev = result[0][0]
;(predicate(key)
? result[0].length > 0
? result[1][prev] || (result[1][prev] = [])
: result[2]
: result[0]
).unshift(key)
return result
},
// 0: non-comment keys and trailing comments
// 1: comments that precede a key
// 2: trailing comments
[[], {}, []],
)
function sortPackageJson(jsonIsh, options = {}) {
return editStringJSON(
jsonIsh,
onObject((json) => {
/** @type {string[]} */
let sortOrder = options.sortOrder ? options.sortOrder : defaultSortOrder

if (Array.isArray(sortOrder)) {
const keys = Object.keys(json)
const allKeys = Object.keys(json)
const [keys, comments, trailing] = removeAndGatherComments(
allKeys,
isCommentKey,
)
const [privateKeys, publicKeys] = partition(keys, isPrivateKey)
sortOrder = [
...sortOrder,
...defaultSortOrder,
...publicKeys.sort(),
...trailing,
...privateKeys.sort(),
]
if (allKeys.length !== keys.length) {
// re-add comment keys
for (let i = sortOrder.length - 1; i >= 0; i--) {
const c = comments[sortOrder[i]]
if (c) {
sortOrder.splice(i, 0, ...c)
}
}
}
}

return overFields(sortObjectKeys(json, sortOrder))
Expand Down
6 changes: 6 additions & 0 deletions tests/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,9 @@ test('private keys', macro.sortObject, {
expect: keysToObject(['name', 'a', 'z', '_a', '_z']),
message: 'Should put private keys at bottom',
})

test('comment keys', macro.sortObject, {
value: keysToObject(['//z', '//x', 'z', ' //name', 'name', 'a', '// end']),
expect: keysToObject([' //name', 'name', 'a', '//z', '//x', 'z', '// end']),
message: 'Should keep comment keys above preceding key',
})

0 comments on commit cc1cee5

Please sign in to comment.