Skip to content

Commit efa8868

Browse files
committed
feat: keep comment-hack keys above preceding key
1 parent 78f1110 commit efa8868

File tree

2 files changed

+41
-1
lines changed

2 files changed

+41
-1
lines changed

index.js

+35-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ const uniqAndSortArray = pipe([uniq, sortArray])
1616
const onObject = (fn) => (x) => (isPlainObject(x) ? fn(x) : x)
1717
const sortObjectBy = (comparator, deep) => {
1818
const over = onObject((object) => {
19+
// TODO: check for comments and update comparator accordingly
1920
object = sortObjectKeys(object, comparator)
2021
if (deep) {
2122
for (const [key, value] of Object.entries(object)) {
@@ -132,6 +133,7 @@ const defaultNpmScripts = new Set([
132133
])
133134

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

@@ -309,6 +311,7 @@ function editStringJSON(json, over) {
309311
}
310312

311313
const isPrivateKey = (key) => key[0] === '_'
314+
const isCommentKey = (key) => key.trim().startsWith('//')
312315
const partition = (array, predicate) =>
313316
array.reduce(
314317
(result, value) => {
@@ -317,21 +320,52 @@ const partition = (array, predicate) =>
317320
},
318321
[[], []],
319322
)
323+
const removeAndGatherComments = (keys, predicate) =>
324+
keys.reduceRight(
325+
(result, key) => {
326+
const prev = result[0][0]
327+
;(predicate(key)
328+
? result[0].length > 0
329+
? result[1][prev] || (result[1][prev] = [])
330+
: result[2]
331+
: result[0]
332+
).unshift(key)
333+
return result
334+
},
335+
// 0: non-comment keys and trailing comments
336+
// 1: comments that precede a key
337+
// 2: trailing comments
338+
[[], {}, []],
339+
)
320340
function sortPackageJson(jsonIsh, options = {}) {
321341
return editStringJSON(
322342
jsonIsh,
323343
onObject((json) => {
324344
let sortOrder = options.sortOrder ? options.sortOrder : defaultSortOrder
325345

326346
if (Array.isArray(sortOrder)) {
327-
const keys = Object.keys(json)
347+
const allKeys = Object.keys(json)
348+
const [keys, comments, trailing] = removeAndGatherComments(
349+
allKeys,
350+
isCommentKey,
351+
)
328352
const [privateKeys, publicKeys] = partition(keys, isPrivateKey)
329353
sortOrder = [
330354
...sortOrder,
331355
...defaultSortOrder,
332356
...publicKeys.sort(),
333357
...privateKeys.sort(),
358+
...trailing,
334359
]
360+
if (allKeys.length !== keys.length) {
361+
// re-add comment keys
362+
for (let i = sortOrder.length - 1; i >= 0; i--) {
363+
const c = comments[sortOrder[i]]
364+
if (c) {
365+
sortOrder.splice(i, 0, ...c)
366+
}
367+
}
368+
}
335369
}
336370

337371
return overFields(sortObjectKeys(json, sortOrder))

tests/main.js

+6
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,9 @@ test('private keys', macro.sortObject, {
3939
expect: keysToObject(['name', 'a', 'z', '_a', '_z']),
4040
message: 'Should put private keys at bottom',
4141
})
42+
43+
test('comment keys', macro.sortObject, {
44+
value: keysToObject(['//z', '//x', 'z', ' //name', 'name', 'a', '// end']),
45+
expect: keysToObject([' //name', 'name', 'a', '//z', '//x', 'z', '// end']),
46+
message: 'Should keep comment keys above preceding key',
47+
})

0 commit comments

Comments
 (0)