@prantlf/jsonlint 16.0.0 → 17.0.0
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 +47 -3
- package/lib/cli.js +104 -33
- package/lib/index.d.ts +17 -0
- package/lib/jsonlint.js +8 -8
- package/lib/printer.js +16 -8
- package/lib/validator.js +27 -9
- package/package.json +17 -14
- package/web/ajv.min.js +6 -6
- package/web/ajv.min.js.map +1 -1
- package/web/jsonlint.html +10 -3
- package/web/jsonlint.min.js.map +1 -1
- package/web/printer.min.js +5 -4
- package/web/printer.min.js.map +3 -3
- package/web/validator.min.js +3 -3
- package/web/validator.min.js.map +3 -3
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-2026 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
|
@@ -157,12 +157,16 @@ Usage: `jsonlint [options] [--] [<file, directory, pattern> ...]`
|
|
|
157
157
|
-P, --pretty-print-invalid force pretty-printing even for invalid input
|
|
158
158
|
-r, --trailing-newline ensure a line break at the end of the output
|
|
159
159
|
-R, --no-trailing-newline ensure no line break at the end of the output
|
|
160
|
+
--no-strict disable the strict schema validation mode
|
|
160
161
|
--prune-comments omit comments from the prettified output
|
|
161
162
|
--strip-object-keys strip quotes from object keys if possible
|
|
162
163
|
--enforce-double-quotes surrounds all strings with double quotes
|
|
163
164
|
--enforce-single-quotes surrounds all strings with single quotes
|
|
164
165
|
--trim-trailing-commas omit trailing commas from objects and arrays
|
|
166
|
+
--no-compact-empty-objects insert line break between empty {} and []
|
|
167
|
+
--force-crlf make sure all line breaks are CRLF
|
|
165
168
|
--succeed-with-no-files succeed (exit code 0) if no files were found
|
|
169
|
+
--[no-]color force or disable colourful output of the diff
|
|
166
170
|
-v, --version output the version number
|
|
167
171
|
-h, --help display help for command
|
|
168
172
|
|
|
@@ -177,8 +181,8 @@ for JSON Schema validation are "draft-04", "draft-06", "draft-07",
|
|
|
177
181
|
with "json-schema-". JSON Type Definition can be selected by "rfc8927",
|
|
178
182
|
"json-type-definition" or "jtd". If not specified, it will be "draft-07".
|
|
179
183
|
|
|
180
|
-
If you specify schemas
|
|
181
|
-
|
|
184
|
+
If you specify multiple schemas, either separate them by comma (,) or
|
|
185
|
+
use the "-V" parameter multiple times.
|
|
182
186
|
|
|
183
187
|
### Configuration
|
|
184
188
|
|
|
@@ -222,6 +226,8 @@ The configuration is an object with the following properties, described above, w
|
|
|
222
226
|
| duplicate-keys | duplicateKeys |
|
|
223
227
|
| validate | |
|
|
224
228
|
| environment | |
|
|
229
|
+
| strict | |
|
|
230
|
+
| color | |
|
|
225
231
|
| log-files | logFiles |
|
|
226
232
|
| quiet | |
|
|
227
233
|
| continue | |
|
|
@@ -233,6 +239,8 @@ The configuration is an object with the following properties, described above, w
|
|
|
233
239
|
| enforce-double-quotes | enforceDoubleQuotes |
|
|
234
240
|
| enforce-single-quotes | enforceSingleQuotes |
|
|
235
241
|
| trim-trailing-commas | trimTrailingCommas |
|
|
242
|
+
| compact-empty-objects | compactEmptyObjects |
|
|
243
|
+
| force-crlf | forceCrlf |
|
|
236
244
|
|
|
237
245
|
The parameter `config` will be ignored in configuration files. The extra parameter `patterns` can be set to an array of strings with paths or patterns instead of putting them to the command line.
|
|
238
246
|
|
|
@@ -314,6 +322,12 @@ If you use external definitions in multiple schemas, you have to pass an array o
|
|
|
314
322
|
const validate = compile(['string with main schema', 'string with a sub-schema'])
|
|
315
323
|
```
|
|
316
324
|
|
|
325
|
+
The schema is parsed in the *strict mode* by default. It'll fail with unknown schema keywords, string formats, conflicting property definitions, union types etc. You may need to relax the schema compilation by disabling the strict mode under circumstances:
|
|
326
|
+
|
|
327
|
+
```js
|
|
328
|
+
const validate = compile('string with JSON Schema', { environment: 'draft-2020-12', strict: false })
|
|
329
|
+
```
|
|
330
|
+
|
|
317
331
|
### Pretty-Printing
|
|
318
332
|
|
|
319
333
|
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.)
|
|
@@ -337,6 +351,8 @@ The [`print`](#pretty-printing) method accepts an object `options` as the second
|
|
|
337
351
|
| `enforceDoubleQuotes` | will surround all strings with double quotes |
|
|
338
352
|
| `enforceSingleQuotes` | will surround all strings with single quotes |
|
|
339
353
|
| `trimTrailingCommas` | will omit all trailing commas after the last object entry or array item |
|
|
354
|
+
| `compactEmptyObjects` | if set to `false`, will insert a line break between empty `{}` and `[]` |
|
|
355
|
+
| `forceCrlf` | make sure all line breaks are CRLF |
|
|
340
356
|
|
|
341
357
|
```js
|
|
342
358
|
// Just concatenate the tokens to produce the same output as was the input.
|
|
@@ -361,6 +377,34 @@ print(tokens, {
|
|
|
361
377
|
enforceDoubleQuotes: true,
|
|
362
378
|
trimTrailingCommas: true
|
|
363
379
|
})
|
|
380
|
+
// Same as `print(tokens, {})`, but uses \r\n for line breaks.
|
|
381
|
+
print(tokens, { forceCrlf: true })
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
Pretty-printing can be also used to preserve the contents of string literal in the output. For example, the following input:
|
|
385
|
+
|
|
386
|
+
```json
|
|
387
|
+
{ "pattern": "^(?:\\\\x[0-9A-F]{2}|[\u0020-\u007E])+$" }
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
will be validated and printed out by default:
|
|
391
|
+
|
|
392
|
+
```json
|
|
393
|
+
{
|
|
394
|
+
"pattern": "^(?:\\\\x[0-9A-F]{2}|[ -~])+$"
|
|
395
|
+
}
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
As you see, the escape Unicode sequences were replaced by the corresponding UTF-8 characters. While this saves space and is arguably more readable, you may have a coding standard which requires to represent some characters always by the escaped Unicode sequences. Yu can achieve it by enabling pretty-printing, which preserves the string literals in the input form. Apart from the programmatic way above, it's possible on the command line too:
|
|
399
|
+
|
|
400
|
+
jsonlint -p pattern.json
|
|
401
|
+
|
|
402
|
+
resulting in the following output:
|
|
403
|
+
|
|
404
|
+
```json
|
|
405
|
+
{
|
|
406
|
+
"pattern": "^(?:\\\\x[0-9A-F]{2}|[\u0020-\u007E])+$"
|
|
407
|
+
}
|
|
364
408
|
```
|
|
365
409
|
|
|
366
410
|
### Tokenizing
|
|
@@ -445,7 +489,7 @@ ${reason}`)
|
|
|
445
489
|
|
|
446
490
|
## License
|
|
447
491
|
|
|
448
|
-
Copyright (C) 2012-
|
|
492
|
+
Copyright (C) 2012-2026 Zachary Carter, Ferdinand Prantl
|
|
449
493
|
|
|
450
494
|
Licensed under the [MIT License].
|
|
451
495
|
|
package/lib/cli.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
const { readdirSync, readFileSync,
|
|
3
|
+
const { globSync, readdirSync, readFileSync, writeFileSync } = require('node:fs')
|
|
4
4
|
const { extname, join } = require('node:path')
|
|
5
|
-
const
|
|
5
|
+
const pico = require('picocolors')
|
|
6
6
|
const { parse, tokenize } = require('./jsonlint')
|
|
7
7
|
const { format } = require('./formatter')
|
|
8
8
|
const { print } = require('./printer')
|
|
@@ -54,20 +54,39 @@ Options:
|
|
|
54
54
|
-P, --pretty-print-invalid force pretty-printing even for invalid input
|
|
55
55
|
-r, --trailing-newline ensure a line break at the end of the output
|
|
56
56
|
-R, --no-trailing-newline ensure no line break at the end of the output
|
|
57
|
+
--no-strict disable the strict schema validation mode
|
|
57
58
|
--prune-comments omit comments from the prettified output
|
|
58
59
|
--strip-object-keys strip quotes from object keys if possible
|
|
59
|
-
--enforce-double-quotes
|
|
60
|
-
--enforce-single-quotes
|
|
60
|
+
--enforce-double-quotes surround all strings with double quotes
|
|
61
|
+
--enforce-single-quotes surround all strings with single quotes
|
|
61
62
|
--trim-trailing-commas omit trailing commas from objects and arrays
|
|
63
|
+
--no-compact-empty-objects insert line break between empty {} and []
|
|
64
|
+
--force-crlf make sure all line breaks are CRLF
|
|
62
65
|
--succeed-with-no-files succeed (exit code 0) if no files were found
|
|
66
|
+
--[no-]color force or disable colourful output of the diff
|
|
63
67
|
-v, --version output the version number
|
|
64
68
|
-h, --help display help for command
|
|
65
69
|
|
|
70
|
+
You can use BASH patterns for including and excluding files (only files).
|
|
71
|
+
Patterns are case-sensitive and have to use slashes as directory separators.
|
|
72
|
+
A pattern to exclude from processing starts with "!".
|
|
73
|
+
|
|
74
|
+
Parsing mode can be "cjson" or "json5" to enable other flags automatically.
|
|
75
|
+
If no files or directories are specified, stdin will be parsed. Environments
|
|
76
|
+
for JSON Schema validation are "draft-04", "draft-06", "draft-07",
|
|
77
|
+
"draft-2019-09" or "draft-2020-12". The environment may be prefixed
|
|
78
|
+
with "json-schema-". JSON Type Definition can be selected by "rfc8927",
|
|
79
|
+
"json-type-definition" or "jtd". If not specified, it will be "draft-07".
|
|
80
|
+
|
|
81
|
+
If you specify multiple schemas, either separate them by comma (,) or
|
|
82
|
+
use the "-V" parameter multiple times.
|
|
83
|
+
|
|
66
84
|
Examples:
|
|
67
85
|
$ jsonlint myfile.json
|
|
68
86
|
$ jsonlint --in-place --pretty-print mydir
|
|
69
87
|
$ jsonlint --comments --trailing-commas --no-duplicate-keys \\
|
|
70
|
-
--log-files --compact --continue '**/*.json' '!**/node_modules'
|
|
88
|
+
--log-files --compact --continue '**/*.json' '!**/node_modules'
|
|
89
|
+
$ jsonlint --validate openapi-schema.json --environment draft-07 myapi.json`)
|
|
71
90
|
}
|
|
72
91
|
|
|
73
92
|
const { argv } = process
|
|
@@ -174,6 +193,12 @@ for (let i = 2, l = argv.length; i < l; ++i) {
|
|
|
174
193
|
}
|
|
175
194
|
params.environment = arg
|
|
176
195
|
return
|
|
196
|
+
case 'strict':
|
|
197
|
+
params.strict = flag
|
|
198
|
+
return
|
|
199
|
+
case 'color':
|
|
200
|
+
params.color = flag
|
|
201
|
+
return
|
|
177
202
|
case 'x': case 'context':
|
|
178
203
|
arg = match[4] || argv[++i]
|
|
179
204
|
if (Number.isNaN(+arg)) {
|
|
@@ -217,6 +242,12 @@ for (let i = 2, l = argv.length; i < l; ++i) {
|
|
|
217
242
|
case 'trim-trailing-commas':
|
|
218
243
|
params.trimTrailingCommas = flag
|
|
219
244
|
return
|
|
245
|
+
case 'compact-empty-objects':
|
|
246
|
+
params.compactEmptyObjects = flag
|
|
247
|
+
return
|
|
248
|
+
case 'force-crlf':
|
|
249
|
+
params.forceCrlf = flag
|
|
250
|
+
return
|
|
220
251
|
case 'succeed-with-no-files':
|
|
221
252
|
params.succeedWithNoFiles = flag
|
|
222
253
|
return
|
|
@@ -257,6 +288,8 @@ const paramNames = {
|
|
|
257
288
|
'enforce-double-quotes': 'enforceDoubleQuotes',
|
|
258
289
|
'enforce-single-quotes': 'enforceSingleQuotes',
|
|
259
290
|
'trim-trailing-commas': 'trimTrailingCommas',
|
|
291
|
+
'compact-empty-objects': 'compactEmptyObjects',
|
|
292
|
+
'force-crlf': 'forceCrlf',
|
|
260
293
|
'sort-keys': 'sortKeys',
|
|
261
294
|
'sort-keys-ignore-case': 'sortKeysIgnoreCase',
|
|
262
295
|
'sort-keys-locale': 'sortKeysLocale',
|
|
@@ -346,6 +379,7 @@ function processContents (source, file) {
|
|
|
346
379
|
}
|
|
347
380
|
})
|
|
348
381
|
parserOptions.environment = params.environment
|
|
382
|
+
parserOptions.strict = params.strict
|
|
349
383
|
try {
|
|
350
384
|
validate = compile(schemas, parserOptions)
|
|
351
385
|
} catch (error) {
|
|
@@ -365,7 +399,9 @@ function processContents (source, file) {
|
|
|
365
399
|
stripObjectKeys: params.stripObjectKeys,
|
|
366
400
|
enforceDoubleQuotes: params.enforceDoubleQuotes,
|
|
367
401
|
enforceSingleQuotes: params.enforceSingleQuotes,
|
|
368
|
-
trimTrailingCommas: params.trimTrailingCommas
|
|
402
|
+
trimTrailingCommas: params.trimTrailingCommas,
|
|
403
|
+
compactEmptyObjects: params.compactEmptyObjects,
|
|
404
|
+
forceCrlf: params.forceCrlf
|
|
369
405
|
})
|
|
370
406
|
}
|
|
371
407
|
const sortOptions = {}
|
|
@@ -433,11 +469,41 @@ function ensureLineBreak (parsed, source) {
|
|
|
433
469
|
const newLine = !lines[lines.length - 1]
|
|
434
470
|
if (params.trailingNewline === true ||
|
|
435
471
|
(params.trailingNewline !== false && newLine)) {
|
|
436
|
-
parsed +=
|
|
472
|
+
parsed += params.forceCrlf === true ? "\r\n" : "\n"
|
|
437
473
|
}
|
|
438
474
|
return parsed
|
|
439
475
|
}
|
|
440
476
|
|
|
477
|
+
function printDiff (diff) {
|
|
478
|
+
const { env } = process
|
|
479
|
+
const isColorSupported =
|
|
480
|
+
!(env.NO_COLOR || params.color === false || env.CI || env.TERM === 'dumb') &&
|
|
481
|
+
(env.FORCE_COLOR || params.color === true || process.platform === "win32" || process.stdout.isTTY)
|
|
482
|
+
if (isColorSupported) {
|
|
483
|
+
const lines = diff.split(/\r?\n/)
|
|
484
|
+
for (const line of lines) {
|
|
485
|
+
if (/^@@ +-\d+,\d+ +\+\d+,\d+ +@@/.test(line) ||
|
|
486
|
+
/^@@ +-\d+ +\+\d+,\d+ +@@/.test(line) ||
|
|
487
|
+
/^@@ +-\d+,\d+ +\+\d+ +@@/.test(line) ||
|
|
488
|
+
/^@@ +-\d+ +\+\d+ +@@/.test(line)) {
|
|
489
|
+
console.log(pico.blue(line)) // meta
|
|
490
|
+
} else if (/={3,}/.test(line) ||
|
|
491
|
+
/^-{3}/.test(line) ||
|
|
492
|
+
/^\+{3}/.test(line)) {
|
|
493
|
+
console.log(pico.gray(line)) // comment
|
|
494
|
+
} else if (/^\+/.test(line)) {
|
|
495
|
+
console.log(pico.green(line)) // addition
|
|
496
|
+
} else if (/^-/.test(line)) {
|
|
497
|
+
console.log(pico.red(line)) // deletion
|
|
498
|
+
} else {
|
|
499
|
+
console.log(line)
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
} else {
|
|
503
|
+
console.log(diff)
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
|
|
441
507
|
function checkContents (file, source, parsed) {
|
|
442
508
|
const { createTwoFilesPatch, structuredPatch } = require('diff')
|
|
443
509
|
const structured = structuredPatch(`${file}.orig`, file, source, parsed, '', '', { context: params.context })
|
|
@@ -454,7 +520,7 @@ function checkContents (file, source, parsed) {
|
|
|
454
520
|
}
|
|
455
521
|
if (!params.quiet) {
|
|
456
522
|
const diff = createTwoFilesPatch(`${file}.orig`, file, source, parsed, '', '', { context: params.context })
|
|
457
|
-
|
|
523
|
+
printDiff(diff)
|
|
458
524
|
}
|
|
459
525
|
if (params.continue) {
|
|
460
526
|
process.exitCode = 1
|
|
@@ -522,22 +588,26 @@ function processFile (file) {
|
|
|
522
588
|
}
|
|
523
589
|
}
|
|
524
590
|
|
|
525
|
-
function processSource (
|
|
591
|
+
function processSource (path, isFile, isDirectory, checkExtension) {
|
|
526
592
|
try {
|
|
527
|
-
|
|
528
|
-
if (srcStat.isFile()) {
|
|
593
|
+
if (isFile) {
|
|
529
594
|
if (checkExtension) {
|
|
530
|
-
const ext = extname(
|
|
595
|
+
const ext = extname(path)
|
|
531
596
|
if (extensions.indexOf(ext) < 0) {
|
|
532
597
|
return
|
|
533
598
|
}
|
|
534
599
|
}
|
|
535
|
-
processFile(
|
|
536
|
-
} else if (
|
|
537
|
-
const sources = readdirSync(
|
|
600
|
+
processFile(path)
|
|
601
|
+
} else if (isDirectory) {
|
|
602
|
+
const sources = readdirSync(path, { withFileTypes: true })
|
|
538
603
|
for (const source of sources) {
|
|
539
|
-
|
|
604
|
+
const subpath = join(path, source.name)
|
|
605
|
+
const isFile = source.isFile()
|
|
606
|
+
const isDirectory = source.isDirectory()
|
|
607
|
+
processSource(subpath, isFile, isDirectory, false)
|
|
540
608
|
}
|
|
609
|
+
} else {
|
|
610
|
+
console.warn('WARN', 'Not a file or directory:', path)
|
|
541
611
|
}
|
|
542
612
|
} catch ({ message }) {
|
|
543
613
|
console.warn('WARN', message)
|
|
@@ -545,31 +615,32 @@ function processSource (src, checkExtension) {
|
|
|
545
615
|
}
|
|
546
616
|
|
|
547
617
|
function processPatterns (patterns) {
|
|
548
|
-
const
|
|
549
|
-
|
|
550
|
-
|
|
618
|
+
const include = []
|
|
619
|
+
const exclude = []
|
|
620
|
+
for (const pattern of patterns) {
|
|
621
|
+
if (pattern.startsWith('!')) {
|
|
622
|
+
exclude.push(pattern.slice(1))
|
|
623
|
+
} else {
|
|
624
|
+
include.push(pattern)
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
const sources = globSync(include, { exclude, withFileTypes: true })
|
|
628
|
+
if (!sources.length) {
|
|
629
|
+
console.error('no files or directories found for the input patterns')
|
|
551
630
|
process.exit(params.succeedWithNoFiles ? 0 : 1)
|
|
552
631
|
}
|
|
553
|
-
for (const
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
}
|
|
632
|
+
for (const source of sources) {
|
|
633
|
+
const path = join(source.parentPath, source.name)
|
|
634
|
+
const isFile = source.isFile()
|
|
635
|
+
const isDirectory = source.isDirectory()
|
|
636
|
+
processSource(path, isFile, isDirectory, false)
|
|
559
637
|
}
|
|
560
638
|
}
|
|
561
639
|
|
|
562
640
|
function main () {
|
|
563
641
|
const files = args.length && args || params.patterns || []
|
|
564
642
|
if (files.length) {
|
|
565
|
-
|
|
566
|
-
if (dynamic) {
|
|
567
|
-
processPatterns(files)
|
|
568
|
-
} else {
|
|
569
|
-
for (const file of files) {
|
|
570
|
-
processSource(file, false)
|
|
571
|
-
}
|
|
572
|
-
}
|
|
643
|
+
processPatterns(files)
|
|
573
644
|
} else {
|
|
574
645
|
let source = ''
|
|
575
646
|
const stdin = process.openStdin()
|
package/lib/index.d.ts
CHANGED
|
@@ -425,6 +425,13 @@ declare module '@prantlf/jsonlint/lib/validator' {
|
|
|
425
425
|
* 'json-type-definition' | 'jtd' | 'rfc8927'`
|
|
426
426
|
*/
|
|
427
427
|
environment?: Environment
|
|
428
|
+
|
|
429
|
+
/**
|
|
430
|
+
* Enable or disable the strict schema validation mode.
|
|
431
|
+
*
|
|
432
|
+
* The default is `true`. You may need to set it to `false` to ignore some schema extensions.
|
|
433
|
+
*/
|
|
434
|
+
strict?: boolean
|
|
428
435
|
}
|
|
429
436
|
|
|
430
437
|
/**
|
|
@@ -499,6 +506,16 @@ declare module '@prantlf/jsonlint/lib/printer' {
|
|
|
499
506
|
* Remove trailing commas after the last item in objects and arrays.
|
|
500
507
|
*/
|
|
501
508
|
trimTrailingCommas?: boolean
|
|
509
|
+
|
|
510
|
+
/**
|
|
511
|
+
* If set to `false`, will insert a line break between empty `{}` and `[]`.
|
|
512
|
+
*/
|
|
513
|
+
compactEmptyObjects?: boolean
|
|
514
|
+
|
|
515
|
+
/**
|
|
516
|
+
* Make sure all line breaks are CRLF.
|
|
517
|
+
*/
|
|
518
|
+
forceCrlf?: boolean
|
|
502
519
|
}
|
|
503
520
|
|
|
504
521
|
/**
|
package/lib/jsonlint.js
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
// This is autogenerated with esprima tools, see:
|
|
10
10
|
// https://github.com/ariya/esprima/blob/master/esprima.js
|
|
11
11
|
|
|
12
|
-
//
|
|
12
|
+
// biome-ignore lint/correctness/noUnusedVariables: generated code
|
|
13
13
|
const Uni = {
|
|
14
14
|
isWhiteSpace: function isWhiteSpace (x) {
|
|
15
15
|
// section 7.2, table 2
|
|
@@ -727,7 +727,7 @@ function parseInternal (input, options) {
|
|
|
727
727
|
}
|
|
728
728
|
}
|
|
729
729
|
|
|
730
|
-
//
|
|
730
|
+
// biome-ignore lint/correctness/noUnusedVariables: concatenated with other files
|
|
731
731
|
function parseCustom (input, options) {
|
|
732
732
|
if (typeof options === 'function') {
|
|
733
733
|
options = {
|
|
@@ -739,7 +739,7 @@ function parseCustom (input, options) {
|
|
|
739
739
|
return parseInternal(input, options)
|
|
740
740
|
}
|
|
741
741
|
|
|
742
|
-
//
|
|
742
|
+
// biome-ignore lint/correctness/noUnusedVariables: concatenated with other files
|
|
743
743
|
function tokenize (input, options) {
|
|
744
744
|
if (!options) {
|
|
745
745
|
options = {}
|
|
@@ -759,7 +759,7 @@ function escapePointerToken (token) {
|
|
|
759
759
|
.replace(/\//g, '~1')
|
|
760
760
|
}
|
|
761
761
|
|
|
762
|
-
//
|
|
762
|
+
// biome-ignore lint/correctness/noUnusedVariables: concatenated with other files
|
|
763
763
|
function pathToPointer (tokens) {
|
|
764
764
|
if (tokens.length === 0) {
|
|
765
765
|
return ''
|
|
@@ -775,7 +775,7 @@ function unescapePointerToken (token) {
|
|
|
775
775
|
.replace(/~0/g, '~')
|
|
776
776
|
}
|
|
777
777
|
|
|
778
|
-
//
|
|
778
|
+
// biome-ignore lint/correctness/noUnusedVariables: concatenated with other files
|
|
779
779
|
function pointerToPath (pointer) {
|
|
780
780
|
if (pointer === '') {
|
|
781
781
|
return []
|
|
@@ -881,7 +881,7 @@ function getLocationOnSpiderMonkey (input, reason) {
|
|
|
881
881
|
if (match) {
|
|
882
882
|
const line = +match[1]
|
|
883
883
|
const column = +match[2]
|
|
884
|
-
const offset = getOffset(input, line, column)
|
|
884
|
+
const offset = getOffset(input, line, column)
|
|
885
885
|
return {
|
|
886
886
|
offset,
|
|
887
887
|
line,
|
|
@@ -942,7 +942,7 @@ function improveNativeError (input, error) {
|
|
|
942
942
|
return error
|
|
943
943
|
}
|
|
944
944
|
|
|
945
|
-
//
|
|
945
|
+
// biome-ignore lint/correctness/noUnusedVariables: concatenated with other files
|
|
946
946
|
function parseNative (input, reviver) {
|
|
947
947
|
try {
|
|
948
948
|
return JSON.parse(input, reviver)
|
|
@@ -974,7 +974,7 @@ function getReviver (options) {
|
|
|
974
974
|
}
|
|
975
975
|
}
|
|
976
976
|
|
|
977
|
-
//
|
|
977
|
+
// biome-ignore lint/correctness/noUnusedVariables: concatenated with other files
|
|
978
978
|
function parse (input, options) {
|
|
979
979
|
options || (options = {})
|
|
980
980
|
return needsCustomParser(options)
|
package/lib/printer.js
CHANGED
|
@@ -48,6 +48,8 @@
|
|
|
48
48
|
const enforceDoubleQuotes = options.enforceDoubleQuotes
|
|
49
49
|
const enforceSingleQuotes = options.enforceSingleQuotes
|
|
50
50
|
const trimTrailingCommas = options.trimTrailingCommas
|
|
51
|
+
const compactEmptyObjects = options.compactEmptyObjects !== false
|
|
52
|
+
const newLineChar = options.forceCrlf === true ? "\r\n" : "\n"
|
|
51
53
|
|
|
52
54
|
let outputString = ''
|
|
53
55
|
let foundLineBreak
|
|
@@ -90,7 +92,7 @@
|
|
|
90
92
|
let addDelayedSpaceOrLineBreak
|
|
91
93
|
if (prettyPrint) {
|
|
92
94
|
addLineBreak = function () {
|
|
93
|
-
outputString +=
|
|
95
|
+
outputString += newLineChar
|
|
94
96
|
}
|
|
95
97
|
|
|
96
98
|
addDelayedSpaceOrLineBreak = function () {
|
|
@@ -206,7 +208,7 @@
|
|
|
206
208
|
if (enforceDoubleQuotes && tokenContent[0] !== '"') {
|
|
207
209
|
outputString += JSON.stringify(tokenValue)
|
|
208
210
|
} else if (enforceSingleQuotes && tokenContent[0] !== '\'') {
|
|
209
|
-
outputString +=
|
|
211
|
+
outputString += `'${tokenValue.replace(/'/g, '\\\'')}'`
|
|
210
212
|
} else {
|
|
211
213
|
outputString += tokenContent
|
|
212
214
|
}
|
|
@@ -216,6 +218,8 @@
|
|
|
216
218
|
tryAddingInlineComment()
|
|
217
219
|
}
|
|
218
220
|
|
|
221
|
+
let justOpenedScope
|
|
222
|
+
|
|
219
223
|
function openScope () {
|
|
220
224
|
addDelayedSpaceOrLineBreak()
|
|
221
225
|
scopes.push(scopeType)
|
|
@@ -224,15 +228,17 @@
|
|
|
224
228
|
outputString += tokenContent
|
|
225
229
|
tryAddingInlineComment()
|
|
226
230
|
++indentLevel
|
|
227
|
-
needsLineBreak = true
|
|
231
|
+
needsLineBreak = justOpenedScope = true
|
|
228
232
|
}
|
|
229
233
|
|
|
230
234
|
function closeScope () {
|
|
231
235
|
scopeType = scopes.pop()
|
|
232
|
-
addLineBreak()
|
|
233
236
|
--indentLevel
|
|
234
|
-
|
|
235
|
-
|
|
237
|
+
if (!compactEmptyObjects || !justOpenedScope) {
|
|
238
|
+
addLineBreak()
|
|
239
|
+
addIndent()
|
|
240
|
+
}
|
|
241
|
+
needsSpace = needsLineBreak = justOpenedScope = false
|
|
236
242
|
outputString += tokenContent
|
|
237
243
|
tryAddingInlineComment()
|
|
238
244
|
}
|
|
@@ -278,11 +284,11 @@
|
|
|
278
284
|
case '{':
|
|
279
285
|
case '[':
|
|
280
286
|
openScope()
|
|
281
|
-
|
|
287
|
+
continue
|
|
282
288
|
case '}':
|
|
283
289
|
case ']':
|
|
284
290
|
closeScope()
|
|
285
|
-
|
|
291
|
+
continue
|
|
286
292
|
case ',':
|
|
287
293
|
addComma()
|
|
288
294
|
break
|
|
@@ -292,7 +298,9 @@
|
|
|
292
298
|
break
|
|
293
299
|
default: // whitespace
|
|
294
300
|
foundLineBreak = tokenContent.indexOf('\n') >= 0
|
|
301
|
+
continue
|
|
295
302
|
}
|
|
303
|
+
justOpenedScope = false
|
|
296
304
|
}
|
|
297
305
|
|
|
298
306
|
return outputString
|
package/lib/validator.js
CHANGED
|
@@ -7,7 +7,10 @@
|
|
|
7
7
|
AjvJTD: 'ajv/dist/jtd',
|
|
8
8
|
Ajv2019: 'ajv/dist/2019',
|
|
9
9
|
Ajv2020: 'ajv/dist/2020',
|
|
10
|
-
Schema06: 'ajv/dist/refs/json-schema-draft-06.json'
|
|
10
|
+
Schema06: 'ajv/dist/refs/json-schema-draft-06.json',
|
|
11
|
+
Keywords: 'ajv-keywords',
|
|
12
|
+
Formats: 'ajv-formats',
|
|
13
|
+
Formats2019: 'ajv-formats-draft2019'
|
|
11
14
|
}
|
|
12
15
|
const requireAjv = name => {
|
|
13
16
|
const exported = require(ajv[name])
|
|
@@ -101,27 +104,38 @@
|
|
|
101
104
|
return error
|
|
102
105
|
}
|
|
103
106
|
|
|
104
|
-
function createAjv (environment) {
|
|
107
|
+
function createAjv (environment, ajvOptions) {
|
|
105
108
|
let ajv
|
|
106
109
|
if (!environment || environment === 'json-schema-draft-06' || environment === 'draft-06') {
|
|
107
110
|
const Ajv = requireAjv('Ajv07')
|
|
108
|
-
ajv = new Ajv()
|
|
111
|
+
ajv = new Ajv(ajvOptions)
|
|
109
112
|
ajv.addMetaSchema(requireAjv('Schema06'))
|
|
113
|
+
requireAjv('Formats')(ajv)
|
|
114
|
+
requireAjv('Keywords')(ajv)
|
|
110
115
|
} else if (environment === 'json-schema-draft-07' || environment === 'draft-07') {
|
|
111
116
|
const Ajv = requireAjv('Ajv07')
|
|
112
|
-
ajv = new Ajv()
|
|
117
|
+
ajv = new Ajv(ajvOptions)
|
|
118
|
+
requireAjv('Formats')(ajv)
|
|
119
|
+
requireAjv('Formats2019')(ajv)
|
|
120
|
+
requireAjv('Keywords')(ajv)
|
|
113
121
|
} else if (environment === 'json-schema-draft-04' || environment === 'draft-04') {
|
|
114
122
|
const Ajv = requireAjv('Ajv04')
|
|
115
|
-
ajv = new Ajv()
|
|
123
|
+
ajv = new Ajv(ajvOptions)
|
|
116
124
|
} else if (environment === 'json-schema-draft-2019-09' || environment === 'draft-2019-09') {
|
|
117
125
|
const Ajv = requireAjv('Ajv2019')
|
|
118
|
-
ajv = new Ajv()
|
|
126
|
+
ajv = new Ajv(ajvOptions)
|
|
127
|
+
requireAjv('Formats')(ajv)
|
|
128
|
+
requireAjv('Formats2019')(ajv)
|
|
129
|
+
requireAjv('Keywords')(ajv)
|
|
119
130
|
} else if (environment === 'json-schema-draft-2020-12' || environment === 'draft-2020-12') {
|
|
120
131
|
const Ajv = requireAjv('Ajv2020')
|
|
121
|
-
ajv = new Ajv()
|
|
132
|
+
ajv = new Ajv(ajvOptions)
|
|
133
|
+
requireAjv('Formats')(ajv)
|
|
134
|
+
requireAjv('Formats2019')(ajv)
|
|
135
|
+
requireAjv('Keywords')(ajv)
|
|
122
136
|
} else if (environment === 'json-type-definition' || environment === 'jtd' || environment === 'rfc8927') {
|
|
123
137
|
const Ajv = requireAjv('AjvJTD')
|
|
124
|
-
ajv = new Ajv()
|
|
138
|
+
ajv = new Ajv(ajvOptions)
|
|
125
139
|
} else {
|
|
126
140
|
throw new RangeError(`Unsupported environment for the JSON Schema validation: "${environment}".`)
|
|
127
141
|
}
|
|
@@ -160,7 +174,11 @@
|
|
|
160
174
|
options = environment
|
|
161
175
|
environment = options.environment
|
|
162
176
|
}
|
|
163
|
-
const
|
|
177
|
+
const ajvOptions = {}
|
|
178
|
+
if (options.strict === false) {
|
|
179
|
+
ajvOptions.strict = false
|
|
180
|
+
}
|
|
181
|
+
const ajv = createAjv(environment, ajvOptions)
|
|
164
182
|
const parseOptions = {
|
|
165
183
|
mode: options.mode,
|
|
166
184
|
ignoreBOM: options.ignoreBOM,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prantlf/jsonlint",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "17.0.0",
|
|
4
4
|
"description": "JSON/CJSON/JSON5 parser, syntax and schema validator and pretty-printer.",
|
|
5
5
|
"author": "Ferdinand Prantl <prantlf@gmail.com> (http://prantl.tk)",
|
|
6
6
|
"contributors": [
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"web"
|
|
37
37
|
],
|
|
38
38
|
"engines": {
|
|
39
|
-
"node": ">=
|
|
39
|
+
"node": ">=22.2"
|
|
40
40
|
},
|
|
41
41
|
"scripts": {
|
|
42
42
|
"build": "npm run compile:jsonlint && rollup -c && npm run minify && npm run compile:tests",
|
|
@@ -58,28 +58,31 @@
|
|
|
58
58
|
"dependencies": {
|
|
59
59
|
"ajv": "8.17.1",
|
|
60
60
|
"ajv-draft-04": "1.0.0",
|
|
61
|
+
"ajv-formats": "^3.0.1",
|
|
62
|
+
"ajv-formats-draft2019": "^1.6.1",
|
|
63
|
+
"ajv-keywords": "^5.1.0",
|
|
61
64
|
"cosmiconfig": "9.0.0",
|
|
62
|
-
"diff": "
|
|
63
|
-
"
|
|
65
|
+
"diff": "8.0.2",
|
|
66
|
+
"picocolors": "^1.1.1"
|
|
64
67
|
},
|
|
65
68
|
"devDependencies": {
|
|
66
|
-
"@biomejs/biome": "^
|
|
67
|
-
"@rollup/plugin-commonjs": "
|
|
69
|
+
"@biomejs/biome": "^2.3.11",
|
|
70
|
+
"@rollup/plugin-commonjs": "29.0.0",
|
|
68
71
|
"@rollup/plugin-json": "6.1.0",
|
|
69
|
-
"@rollup/plugin-node-resolve": "
|
|
70
|
-
"@types/node": "
|
|
72
|
+
"@rollup/plugin-node-resolve": "16.0.3",
|
|
73
|
+
"@types/node": "25.0.3",
|
|
71
74
|
"@unixcompat/cat.js": "2.0.0",
|
|
72
75
|
"@unixcompat/mv.js": "2.0.0",
|
|
73
|
-
"c8": "10.1.
|
|
74
|
-
"esbuild": "0.
|
|
76
|
+
"c8": "10.1.3",
|
|
77
|
+
"esbuild": "0.27.2",
|
|
75
78
|
"http-server": "14.1.1",
|
|
76
|
-
"js-yaml": "4.1.
|
|
77
|
-
"rollup": "4.
|
|
78
|
-
"rollup-plugin-swc-minify": "1.
|
|
79
|
+
"js-yaml": "4.1.1",
|
|
80
|
+
"rollup": "4.54.0",
|
|
81
|
+
"rollup-plugin-swc-minify": "1.3.0",
|
|
79
82
|
"tehanu": "1.0.1",
|
|
80
83
|
"tehanu-repo-coco": "1.0.1",
|
|
81
84
|
"tehanu-teru": "1.0.1",
|
|
82
|
-
"typescript": "5.
|
|
85
|
+
"typescript": "5.9.3"
|
|
83
86
|
},
|
|
84
87
|
"keywords": [
|
|
85
88
|
"json",
|