Skip to content

Commit 136ea99

Browse files
committed
feat: Allow trimming trailing commas in arrays and objects (JSON5)
1 parent 321e4d3 commit 136ea99

File tree

7 files changed

+46
-5
lines changed

7 files changed

+46
-5
lines changed

README.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,11 @@ By default, `jsonlint` will either report a syntax error with details or pretty-
103103
--prune-comments omit comments from the prettified output
104104
--strip-object-keys strip quotes from object keys if possible
105105
(JSON5)
106+
--enforce-double-quotes surrounds all strings with double quotes
107+
--enforce-single-quotes surrounds all strings with single quotes
108+
(JSON5)
109+
--trim-trailing-commas omit trailing commas from objects and arrays
110+
(JSON5)
106111
-v, --version output the version number
107112
-h, --help output usage information
108113

@@ -204,6 +209,7 @@ The [`print`](#pretty-printing) method accepts an object `options` as the second
204209
| `stripObjectKeys` | will not print quotes around object keys which are JavaScript identifier names |
205210
| `enforceDoubleQuotes` | will surround all strings with double quotes |
206211
| `enforceSingleQuotes` | will surround all strings with single quotes |
212+
| `trimTrailingCommas` | will omit all trailing commas after the last object entry or array item |
207213

208214
```js
209215
// Just concatenate the tokens to produce the same output as was the input.
@@ -223,7 +229,11 @@ print(tokens, { indent: ' ', pruneComments: true })
223229
// Print to multiple lines with indentation enabled and JSON5 object keys.
224230
print(tokens, { indent: '\t', stripObjectKeys: true })
225231
// Print to multiple lines with indentation enabled, unify JSON5 formatting.
226-
print(tokens, { indent: ' ', enforceDoubleQuotes: true })
232+
print(tokens, {
233+
indent: ' ',
234+
enforceDoubleQuotes: true,
235+
trimTrailingCommas: true
236+
})
227237
```
228238

229239
### Tokenizing

lib/cli.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ var options = require('commander')
3636
.option('--strip-object-keys', 'strip quotes from object keys if possible (JSON5)')
3737
.option('--enforce-double-quotes', 'surrounds all strings with double quotes')
3838
.option('--enforce-single-quotes', 'surrounds all strings with single quotes (JSON5)')
39+
.option('--trim-trailing-commas', 'omit trailing commas from objects and arrays (JSON5)')
3940
.version(pkg.version, '-v, --version')
4041
.on('--help', () => {
4142
console.log()
@@ -90,7 +91,8 @@ function parse (source, file) {
9091
pruneComments: options.pruneComments,
9192
stripObjectKeys: options.stripObjectKeys,
9293
enforceDoubleQuotes: options.enforceDoubleQuotes,
93-
enforceSingleQuotes: options.enforceSingleQuotes
94+
enforceSingleQuotes: options.enforceSingleQuotes,
95+
trimTrailingCommas: options.trimTrailingCommas
9496
})
9597
}
9698
if (options.sortKeys) {

lib/jsonlint.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ declare module '@prantlf/jsonlint/lib/printer' {
9292
stripObjectKeys?: boolean
9393
enforceDoubleQuotes?: boolean
9494
enforceSingleQuotes?: boolean
95+
trimTrailingCommas?: boolean
9596
}
9697

9798
/**

lib/printer.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
var stripObjectKeys = options.stripObjectKeys
5151
var enforceDoubleQuotes = options.enforceDoubleQuotes
5252
var enforceSingleQuotes = options.enforceSingleQuotes
53+
var trimTrailingCommas = options.trimTrailingCommas
5354

5455
var outputString = ''
5556
var foundLineBreak, addedLineBreak, needsLineBreak
@@ -61,6 +62,16 @@
6162
var tokenCount = tokens.length
6263
var tokenIndex, token, tokenType, tokenContent
6364

65+
function peekAtNextToken () {
66+
var nextTokenIndex = tokenIndex
67+
var nextToken
68+
do {
69+
nextToken = tokens[++nextTokenIndex]
70+
} while (nextToken && (nextToken.type === 'whitespace' ||
71+
nextToken.type === 'comment'))
72+
return nextToken
73+
}
74+
6475
var addIndent
6576
if (prettyPrint && indentString) {
6677
addIndent = function () {
@@ -222,6 +233,12 @@
222233
}
223234

224235
function addComma () {
236+
if (trimTrailingCommas) {
237+
var nextToken = peekAtNextToken()
238+
if (nextToken && nextToken.type === 'symbol') {
239+
return tryAddingInlineComment()
240+
}
241+
}
225242
addDelayedSpaceOrLineBreak()
226243
outputString += ','
227244
tryAddingInlineComment()

test/print.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,4 +161,9 @@ addTest('enforce double quotes, but strip quotes from object keys', function ()
161161
assert.equal(output, '{/* String parameter */key:"value",}')
162162
})
163163

164+
addTest('trim trailing commas', function () {
165+
var output = print(stringTokens, { trimTrailingCommas: true })
166+
assert.equal(output, '{/* String parameter */"key":\'value\'}')
167+
})
168+
164169
if (require.main === module) { require('test').run(exports) }

test/typings.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ addTest('print', () => {
6767
print(tokens, { stripObjectKeys: true })
6868
print(tokens, { enforceDoubleQuotes: true })
6969
print(tokens, { enforceSingleQuotes: true })
70+
print(tokens, { trimTrailingCommas: true })
7071
assert.ok(true)
7172
})
7273

web/jsonlint.html

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,10 @@ <h1>JSON Lint</h1>
144144
<input type="checkbox" id="enforce-single-quotes">
145145
<label for="enforce-single-quotes">Enforce single quotes</label>
146146
</div>
147+
<div style="display: none">
148+
<input type="checkbox" id="trim-trailing-commas">
149+
<label for="trim-trailing-commas">Trim trailing commas</label>
150+
</div>
147151
</div>
148152
<div>
149153
<span>Standard:</span>
@@ -231,8 +235,8 @@ <h2>Result</h2>
231235
ensureOneSelected(selected, other)
232236
var forFormat = ['sort-object-keys']
233237
var forPrettyPrint = [
234-
'prune-comments', 'strip-object-keys',
235-
'enforce-double-quotes', 'enforce-single-quotes'
238+
'prune-comments', 'strip-object-keys', 'enforce-double-quotes',
239+
'enforce-single-quotes', 'trim-trailing-commas'
236240
]
237241
swapWrapperVisibility(document.getElementById('pretty-print').checked,
238242
forPrettyPrint, forFormat)
@@ -304,7 +308,8 @@ <h2>Result</h2>
304308
pruneComments: document.getElementById('prune-comments').checked,
305309
stripObjectKeys: document.getElementById('strip-object-keys').checked,
306310
enforceDoubleQuotes: document.getElementById('enforce-double-quotes').checked,
307-
enforceSingleQuotes: document.getElementById('enforce-single-quotes').checked
311+
enforceSingleQuotes: document.getElementById('enforce-single-quotes').checked,
312+
trimTrailingCommas: document.getElementById('trim-trailing-commas').checked
308313
})
309314
}
310315

0 commit comments

Comments
 (0)