@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 CHANGED
@@ -1,7 +1,7 @@
1
1
  MIT License
2
2
 
3
3
  Copyright (c) 2012-2018 Zachary Carter
4
- Copyright (c) 2019 Ferdinand Prantl
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
- [![NPM version](https://badge.fury.io/js/%40prantlf%2Fjsonlint.svg)](https://badge.fury.io/js/%40prantlf%2Fjsonlint)
4
- [![Build Status](https://travis-ci.com/prantlf/jsonlint.svg?branch=master)](https://travis-ci.com/prantlf/jsonlint)
5
- [![codecov](https://codecov.io/gh/prantlf/jsonlint/branch/master/graph/badge.svg)](https://codecov.io/gh/prantlf/jsonlint)
6
- [![Dependency Status](https://david-dm.org/prantlf/jsonlint.svg)](https://david-dm.org/prantlf/jsonlint)
7
- [![devDependency Status](https://david-dm.org/prantlf/jsonlint/dev-status.svg)](https://david-dm.org/prantlf/jsonlint#info=devDependencies)
8
- [![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com)
3
+ [![Latest version](https://img.shields.io/npm/v/@prantlf/jsonlint)
4
+ ![Dependency status](https://img.shields.io/librariesio/release/npm/@prantlf/jsonlint)
5
+ ](https://www.npmjs.com/package/@prantlf/jsonlint)
6
+ [![Code coverage](https://codecov.io/gh/prantlf/jsonlint/branch/master/graph/badge.svg)](https://codecov.io/gh/prantlf/jsonlint)
9
7
 
10
- A [JSON]/[JSON5] parser and validator with a command-line client. A [pure JavaScript version] of the service provided at [jsonlint.com].
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 package with the following enhancements:
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 tripping comments, for example. (Raw token values must be enabled when tokenizing the JSON input.)
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` | will not print quotes around object keys which are JavaScript identifier names |
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 */}', { ignoreComments: true }))
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 10.15.3:
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
- the built-in parser x 68,212 ops/sec ±0.86% (87 runs sampled)
273
- the pure jju parser x 10,234 ops/sec ±1.08% (89 runs sampled)
274
- the extended jju parser x 10,210 ops/sec ±1.26% (88 runs sampled)
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. Extending the parser with the support for comments and single-quoted strings does not affect the performance. Making the parser collect tokens and their locations decreases the performance a bit.
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-2019 Zachary Carter, Ferdinand Prantl
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
- var fs = require('fs')
4
- var path = require('path')
5
- var parser = require('./jsonlint')
6
- var formatter = require('./formatter')
7
- var printer = require('./printer')
8
- var sorter = require('./sorter')
9
- var validator = require('./validator')
10
- var pkg = require('../package')
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
- var options = require('commander')
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
- var parserOptions, parsed, formatted
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
- var validate
75
+ let validate
72
76
  try {
73
- var schema = fs.readFileSync(path.normalize(options.validate), 'utf8')
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
- var message = 'Loading the JSON schema failed: "' +
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
- var tokens = parser.tokenize(source, parserOptions)
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
- var source = parse(fs.readFileSync(file, 'utf8'), file)
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
- var extensions = options.extensions.map(function (extension) {
157
+ const extensions = options.extensions.map(function (extension) {
147
158
  return '.' + extension
148
159
  })
149
- var srcStat
160
+ let srcStat
150
161
  try {
151
162
  srcStat = fs.statSync(src)
152
163
  if (srcStat.isFile()) {
153
164
  if (checkExtension) {
154
- var ext = path.extname(src)
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
- var sources = fs.readdirSync(src)
162
- for (var i = 0; i < sources.length; i++) {
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
- var files = options.args
173
- var source = ''
183
+ const files = commander.args
184
+ let source = ''
174
185
  if (files.length) {
175
- for (var i = 0; i < files.length; i++) {
186
+ for (let i = 0; i < files.length; i++) {
176
187
  processSources(files[i], false)
177
188
  }
178
189
  } else {
179
- var stdin = process.openStdin()
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
- var parsed = parse(source, '<stdin>')
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
- var i = 0
25
- var length = 0
26
- var indentString = indent !== undefined
24
+ let i = 0
25
+ let length = 0
26
+ const indentString = indent !== undefined
27
27
  ? typeof indent === 'number'
28
- ? new Array(indent + 1).join(' ') : indent : ' '
29
- var outputString = ''
30
- var indentLevel = 0
31
- var inString
32
- var currentChar
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)