@prantlf/jsonlint 10.2.0 → 11.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +24 -21
- package/lib/cli.js +36 -25
- package/lib/formatter.js +12 -10
- package/lib/jsonlint.js +134 -121
- package/lib/printer.js +32 -32
- package/lib/schema-drafts.js +6 -3
- package/lib/sorter.js +6 -6
- package/lib/validator.js +31 -31
- package/package.json +53 -32
- package/web/ajv.min.js +3 -1
- package/web/ajv.min.js.map +1 -1
- package/web/formatter.min.js +1 -1
- package/web/formatter.min.js.map +1 -1
- package/web/jsonlint.html +333 -0
- package/web/jsonlint.min.js +1 -1
- package/web/jsonlint.min.js.map +1 -1
- package/web/printer.min.js +1 -1
- package/web/printer.min.js.map +1 -1
- package/web/schema-drafts.min.js +1 -1
- package/web/schema-drafts.min.js.map +1 -1
- package/web/sorter.min.js +1 -1
- package/web/sorter.min.js.map +1 -1
- package/web/validator.min.js +1 -1
- package/web/validator.min.js.map +1 -1
- package/CHANGELOG.md +0 -271
package/LICENSE
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
MIT License
|
|
2
2
|
|
|
3
3
|
Copyright (c) 2012-2018 Zachary Carter
|
|
4
|
-
Copyright (c) 2019
|
|
4
|
+
Copyright (c) 2019-2022 Ferdinand Prantl
|
|
5
5
|
|
|
6
6
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
7
|
of this software and associated documentation files (the "Software"), to deal
|
package/README.md
CHANGED
|
@@ -1,20 +1,18 @@
|
|
|
1
1
|
# JSON Lint
|
|
2
2
|
|
|
3
|
-
[](https://david-dm.org/prantlf/jsonlint#info=devDependencies)
|
|
8
|
-
[](https://standardjs.com)
|
|
3
|
+
[
|
|
4
|
+

|
|
5
|
+
](https://www.npmjs.com/package/@prantlf/jsonlint)
|
|
6
|
+
[](https://codecov.io/gh/prantlf/jsonlint)
|
|
9
7
|
|
|
10
|
-
A [JSON]/[JSON5] parser and
|
|
8
|
+
A [JSON]/CJSON/[JSON5] parser, validator and pretty-printer with a command-line client. See it in action at https://prantlf.github.io/jsonlint/.
|
|
11
9
|
|
|
12
|
-
This is a fork of the original
|
|
10
|
+
This is a fork of the original project ([zaach/jsonlint](https://github.com/zaach/jsonlint)) with the following enhancements:
|
|
13
11
|
|
|
14
12
|
* Handles multiple files on the command line (by Greg Inman).
|
|
15
13
|
* Walks directories recursively (by Paul Vollmer).
|
|
16
14
|
* Provides 100% compatible interface to the native `JSON.parse` method.
|
|
17
|
-
* Optionally recognizes JavaScript-style comments and single quoted strings.
|
|
15
|
+
* Optionally recognizes JavaScript-style comments (CJSON) and single quoted strings (JSON5).
|
|
18
16
|
* Optionally ignores trailing commas and reports duplicate object keys as an error.
|
|
19
17
|
* Supports [JSON Schema] drafts 04, 06 and 07.
|
|
20
18
|
* Offers pretty-printing including comment-stripping and object keys without quotes (JSON5).
|
|
@@ -30,6 +28,7 @@ Integration to the favourite task loaders for JSON file validation is provided b
|
|
|
30
28
|
|
|
31
29
|
* [`Grunt`] - see [`@prantlf/grunt-jsonlint`]
|
|
32
30
|
* [`Gulp`] - see [`@prantlf/gulp-jsonlint`]
|
|
31
|
+
* [`Rollup`] - see [`rollup-plugin-jsonlint`]
|
|
33
32
|
|
|
34
33
|
## Synopsis
|
|
35
34
|
|
|
@@ -100,6 +99,8 @@ By default, `jsonlint` will either report a syntax error with details or pretty-
|
|
|
100
99
|
-p, --pretty-print prettify the input instead of stringifying
|
|
101
100
|
the parsed object
|
|
102
101
|
-P, --pretty-print-invalid force pretty-printing even for invalid input
|
|
102
|
+
-r, --trailing-newline ensure a line break at the end of the output
|
|
103
|
+
-R, --no-trailing-newline ensure no line break at the end of the output
|
|
103
104
|
--prune-comments omit comments from the prettified output
|
|
104
105
|
--strip-object-keys strip quotes from object keys if possible
|
|
105
106
|
(JSON5)
|
|
@@ -189,7 +190,7 @@ const validate = compile('string with JSON schema', {
|
|
|
189
190
|
|
|
190
191
|
### Pretty-Printing
|
|
191
192
|
|
|
192
|
-
You can parse a JSON string to an array of tokens and print it back to a string with some changes applied. It can be unification of whitespace or
|
|
193
|
+
You can parse a JSON string to an array of tokens and print it back to a string with some changes applied. It can be unification of whitespace, reformatting or stripping comments, for example. (Raw token values must be enabled when tokenizing the JSON input.)
|
|
193
194
|
|
|
194
195
|
```js
|
|
195
196
|
const { tokenize } = require('@prantlf/jsonlint')
|
|
@@ -206,7 +207,7 @@ The [`print`](#pretty-printing) method accepts an object `options` as the second
|
|
|
206
207
|
| --------------------------- | ------------------------------------------------------- |
|
|
207
208
|
| `indent` | count of spaces or the specific characters to be used as an indentation unit |
|
|
208
209
|
| `pruneComments` | will omit all tokens with comments |
|
|
209
|
-
| `stripObjectKeys`
|
|
210
|
+
| `stripObjectKeys` | will not print quotes around object keys which are JavaScript identifier names |
|
|
210
211
|
| `enforceDoubleQuotes` | will surround all strings with double quotes |
|
|
211
212
|
| `enforceSingleQuotes` | will surround all strings with single quotes |
|
|
212
213
|
| `trimTrailingCommas` | will omit all trailing commas after the last object entry or array item |
|
|
@@ -242,7 +243,10 @@ The method `tokenize` has the same prototype as the method [`parse`](#module-int
|
|
|
242
243
|
|
|
243
244
|
```js
|
|
244
245
|
const { tokenize } = require('@prantlf/jsonlint')
|
|
245
|
-
const tokens = tokenize('{"flag":true /* default */}', {
|
|
246
|
+
const tokens = tokenize('{"flag":true /* default */}', {
|
|
247
|
+
ignoreComments: true,
|
|
248
|
+
rawTokens: true
|
|
249
|
+
}))
|
|
246
250
|
// Returns the following array:
|
|
247
251
|
// [
|
|
248
252
|
// { type: 'symbol', raw: '{', value: '{' },
|
|
@@ -267,15 +271,13 @@ If you want to retain comments or whitespace for pretty-printing, for example, s
|
|
|
267
271
|
|
|
268
272
|
### Performance
|
|
269
273
|
|
|
270
|
-
This is a part of an output from the [parser benchmark], when parsing a 4.2 KB formatted string ([package.json](./package.json)) with Node.js
|
|
274
|
+
This is a part of an output from the [parser benchmark], when parsing a 4.2 KB formatted string ([package.json](./package.json)) with Node.js 12.14.0:
|
|
271
275
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
the tokenizable jju parser x 8,832 ops/sec ±0.92% (89 runs sampled)
|
|
276
|
-
the tokenizing jju parser x 7,911 ops/sec ±1.05% (86 runs sampled)
|
|
276
|
+
jsonlint using native JSON.parse x 97,109 ops/sec ±0.81% (93 runs sampled)
|
|
277
|
+
jsonlint using hand-coded parser x 7,256 ops/sec ±0.54% (90 runs sampled)
|
|
278
|
+
jsonlint using tokenising parser x 6,387 ops/sec ±0.44% (88 runs sampled)
|
|
277
279
|
|
|
278
|
-
A custom JSON parser is [a lot slower] than the built-in one. However, it is more important to have a [clear error reporting] than the highest speed in scenarios like parsing configuration files.
|
|
280
|
+
A custom JSON parser is [a lot slower] than the built-in one. However, it is more important to have a [clear error reporting] than the highest speed in scenarios like parsing configuration files. (For better error-reporting, the speed can be preserved by using the native parser initially and re-parsing with another parser only in case of failure.) Features like comments or JSON5 are also helpful in configuration files. Tokens preserve the complete input and can be used for pretty-printing without losing the comments.
|
|
279
281
|
|
|
280
282
|
### Error Handling
|
|
281
283
|
|
|
@@ -317,21 +319,22 @@ ${reason}`)
|
|
|
317
319
|
|
|
318
320
|
## License
|
|
319
321
|
|
|
320
|
-
Copyright (C) 2012-
|
|
322
|
+
Copyright (C) 2012-2022 Zachary Carter, Ferdinand Prantl
|
|
321
323
|
|
|
322
324
|
Licensed under the [MIT License].
|
|
323
325
|
|
|
324
326
|
[MIT License]: http://en.wikipedia.org/wiki/MIT_License
|
|
325
327
|
[pure JavaScript version]: http://prantlf.github.com/jsonlint/
|
|
326
|
-
[jsonlint.com]: http://jsonlint.com
|
|
327
328
|
[JSON]: https://tools.ietf.org/html/rfc8259
|
|
328
329
|
[JSON5]: https://spec.json5.org
|
|
329
330
|
[JSON Schema]: https://json-schema.org
|
|
330
331
|
[UMD]: https://github.com/umdjs/umd
|
|
331
332
|
[`Grunt`]: https://gruntjs.com/
|
|
332
333
|
[`Gulp`]: http://gulpjs.com/
|
|
334
|
+
[`Rollup`]: https://rollupjs.org/
|
|
333
335
|
[`@prantlf/grunt-jsonlint`]: https://www.npmjs.com/package/@prantlf/grunt-jsonlint
|
|
334
336
|
[`@prantlf/gulp-jsonlint`]: https://www.npmjs.com/package/@prantlf/gulp-jsonlint
|
|
337
|
+
[`rollup-plugin-jsonlint`]: https://www.npmjs.com/package/rollup-plugin-jsonlint
|
|
335
338
|
[7x faster than the custom parser]: ./benchmarks/results/performance.md#results
|
|
336
339
|
[parser benchmark]: ./benchmarks#json-parser-comparison
|
|
337
340
|
[a lot slower]: ./benchmarks/results/performance.md#results
|
package/lib/cli.js
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
3
|
+
const fs = require('fs')
|
|
4
|
+
const path = require('path')
|
|
5
|
+
const parser = require('./jsonlint')
|
|
6
|
+
const formatter = require('./formatter')
|
|
7
|
+
const printer = require('./printer')
|
|
8
|
+
const sorter = require('./sorter')
|
|
9
|
+
const validator = require('./validator')
|
|
10
|
+
const pkg = require('../package')
|
|
11
11
|
|
|
12
12
|
function collectExtensions (extension) {
|
|
13
13
|
return extension.split(',')
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
const commander = require('commander')
|
|
17
17
|
.name('jsonlint')
|
|
18
18
|
.usage('[options] [<file or directory> ...]')
|
|
19
19
|
.description(pkg.description)
|
|
@@ -32,6 +32,8 @@ var options = require('commander')
|
|
|
32
32
|
.option('-q, --quiet', 'do not print the parsed json to stdin')
|
|
33
33
|
.option('-p, --pretty-print', 'prettify the input instead of stringifying the parsed object')
|
|
34
34
|
.option('-P, --pretty-print-invalid', 'force pretty-printing even for invalid input')
|
|
35
|
+
.option('-r, --trailing-newline', 'ensure a line break at the end of the output')
|
|
36
|
+
.option('-R, --no-trailing-newline', 'ensure no line break at the end of the output')
|
|
35
37
|
.option('--prune-comments', 'omit comments from the prettified output')
|
|
36
38
|
.option('--strip-object-keys', 'strip quotes from object keys if possible (JSON5)')
|
|
37
39
|
.option('--enforce-double-quotes', 'surrounds all strings with double quotes')
|
|
@@ -47,6 +49,8 @@ var options = require('commander')
|
|
|
47
49
|
})
|
|
48
50
|
.parse(process.argv)
|
|
49
51
|
|
|
52
|
+
const options = commander.opts()
|
|
53
|
+
|
|
50
54
|
function logNormalError (error, file) {
|
|
51
55
|
console.log('File:', file)
|
|
52
56
|
console.error(error.message)
|
|
@@ -58,7 +62,7 @@ function logCompactError (error, file) {
|
|
|
58
62
|
}
|
|
59
63
|
|
|
60
64
|
function parse (source, file) {
|
|
61
|
-
|
|
65
|
+
let parserOptions, parsed, formatted
|
|
62
66
|
try {
|
|
63
67
|
parserOptions = {
|
|
64
68
|
mode: options.mode,
|
|
@@ -68,13 +72,13 @@ function parse (source, file) {
|
|
|
68
72
|
allowDuplicateObjectKeys: options.duplicateKeys
|
|
69
73
|
}
|
|
70
74
|
if (options.validate) {
|
|
71
|
-
|
|
75
|
+
let validate
|
|
72
76
|
try {
|
|
73
|
-
|
|
77
|
+
const schema = fs.readFileSync(path.normalize(options.validate), 'utf8')
|
|
74
78
|
parserOptions.environment = options.environment
|
|
75
79
|
validate = validator.compile(schema, parserOptions)
|
|
76
80
|
} catch (error) {
|
|
77
|
-
|
|
81
|
+
const message = 'Loading the JSON schema failed: "' +
|
|
78
82
|
options.validate + '".\n' + error.message
|
|
79
83
|
throw new Error(message)
|
|
80
84
|
}
|
|
@@ -84,7 +88,7 @@ function parse (source, file) {
|
|
|
84
88
|
}
|
|
85
89
|
if (options.prettyPrint) {
|
|
86
90
|
parserOptions.rawTokens = true
|
|
87
|
-
|
|
91
|
+
const tokens = parser.tokenize(source, parserOptions)
|
|
88
92
|
// TODO: Support sorting tor the tokenized input too.
|
|
89
93
|
return printer.print(tokens, {
|
|
90
94
|
indent: options.indent,
|
|
@@ -132,8 +136,15 @@ function parse (source, file) {
|
|
|
132
136
|
|
|
133
137
|
function processFile (file) {
|
|
134
138
|
file = path.normalize(file)
|
|
135
|
-
|
|
139
|
+
const original = fs.readFileSync(file, 'utf8')
|
|
140
|
+
let source = parse(original, file)
|
|
136
141
|
if (options.inPlace) {
|
|
142
|
+
const lines = original.split(/\?r\n/)
|
|
143
|
+
const newLine = !lines[lines.length - 1]
|
|
144
|
+
if (options.trailingNewline === true ||
|
|
145
|
+
(options.trailingNewline !== false && newLine)) {
|
|
146
|
+
source += '\n'
|
|
147
|
+
}
|
|
137
148
|
fs.writeFileSync(file, source)
|
|
138
149
|
} else {
|
|
139
150
|
if (!options.quiet) {
|
|
@@ -143,23 +154,23 @@ function processFile (file) {
|
|
|
143
154
|
}
|
|
144
155
|
|
|
145
156
|
function processSources (src, checkExtension) {
|
|
146
|
-
|
|
157
|
+
const extensions = options.extensions.map(function (extension) {
|
|
147
158
|
return '.' + extension
|
|
148
159
|
})
|
|
149
|
-
|
|
160
|
+
let srcStat
|
|
150
161
|
try {
|
|
151
162
|
srcStat = fs.statSync(src)
|
|
152
163
|
if (srcStat.isFile()) {
|
|
153
164
|
if (checkExtension) {
|
|
154
|
-
|
|
165
|
+
const ext = path.extname(src)
|
|
155
166
|
if (extensions.indexOf(ext) < 0) {
|
|
156
167
|
return
|
|
157
168
|
}
|
|
158
169
|
}
|
|
159
170
|
processFile(src)
|
|
160
171
|
} else if (srcStat.isDirectory()) {
|
|
161
|
-
|
|
162
|
-
for (
|
|
172
|
+
const sources = fs.readdirSync(src)
|
|
173
|
+
for (let i = 0; i < sources.length; i++) {
|
|
163
174
|
processSources(path.join(src, sources[i]), true)
|
|
164
175
|
}
|
|
165
176
|
}
|
|
@@ -169,20 +180,20 @@ function processSources (src, checkExtension) {
|
|
|
169
180
|
}
|
|
170
181
|
|
|
171
182
|
function main () {
|
|
172
|
-
|
|
173
|
-
|
|
183
|
+
const files = commander.args
|
|
184
|
+
let source = ''
|
|
174
185
|
if (files.length) {
|
|
175
|
-
for (
|
|
186
|
+
for (let i = 0; i < files.length; i++) {
|
|
176
187
|
processSources(files[i], false)
|
|
177
188
|
}
|
|
178
189
|
} else {
|
|
179
|
-
|
|
190
|
+
const stdin = process.openStdin()
|
|
180
191
|
stdin.setEncoding('utf8')
|
|
181
192
|
stdin.on('data', function (chunk) {
|
|
182
193
|
source += chunk.toString('utf8')
|
|
183
194
|
})
|
|
184
195
|
stdin.on('end', function () {
|
|
185
|
-
|
|
196
|
+
const parsed = parse(source, '<stdin>')
|
|
186
197
|
if (!options.quiet) {
|
|
187
198
|
console.log(parsed)
|
|
188
199
|
}
|
package/lib/formatter.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
(function (global, factory) {
|
|
2
|
-
// eslint-disable-next-line no-unused-expressions
|
|
2
|
+
// eslint-disable-next-line no-unused-expressions, multiline-ternary
|
|
3
3
|
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports)
|
|
4
|
-
// eslint-disable-next-line no-undef
|
|
4
|
+
// eslint-disable-next-line no-undef, multiline-ternary
|
|
5
5
|
: typeof define === 'function' && define.amd ? define('jsonlint-formatter', ['exports'], factory)
|
|
6
6
|
// eslint-disable-next-line no-undef
|
|
7
7
|
: (global = global || self, factory(global.jsonlintFormatter = {}))
|
|
@@ -21,15 +21,17 @@
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
function format (json, indent) {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
let i = 0
|
|
25
|
+
let length = 0
|
|
26
|
+
const indentString = indent !== undefined
|
|
27
27
|
? typeof indent === 'number'
|
|
28
|
-
? new Array(indent + 1).join(' ')
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
28
|
+
? new Array(indent + 1).join(' ')
|
|
29
|
+
: indent
|
|
30
|
+
: ' '
|
|
31
|
+
let outputString = ''
|
|
32
|
+
let indentLevel = 0
|
|
33
|
+
let inString
|
|
34
|
+
let currentChar
|
|
33
35
|
|
|
34
36
|
for (i = 0, length = json.length; i < length; i += 1) {
|
|
35
37
|
currentChar = json.charAt(i)
|