@prantlf/jsonlint 14.0.3 → 15.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 +19 -2
- package/lib/cli.js +75 -14
- package/lib/formatter.js +3 -3
- package/lib/jsonlint.js +85 -77
- package/lib/printer.js +16 -8
- package/lib/sorter.js +22 -5
- package/lib/validator.js +4 -2
- package/package.json +20 -36
- package/web/ajv.min.js +5 -5
- package/web/ajv.min.js.map +1 -1
- package/web/formatter.min.js +4 -4
- package/web/formatter.min.js.map +2 -2
- package/web/jsonlint.html +38 -3
- package/web/jsonlint.min.js +9 -9
- package/web/jsonlint.min.js.map +3 -3
- package/web/printer.min.js +3 -3
- package/web/printer.min.js.map +2 -2
- package/web/sorter.min.js +1 -1
- package/web/sorter.min.js.map +3 -3
- package/web/validator.min.js +3 -3
- package/web/validator.min.js.map +2 -2
package/lib/jsonlint.js
CHANGED
|
@@ -103,6 +103,10 @@ const unescapeMap = {
|
|
|
103
103
|
'/': '/'
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
+
const ownsProperty = Object.prototype.hasOwnProperty
|
|
107
|
+
|
|
108
|
+
const emptyObject = {}
|
|
109
|
+
|
|
106
110
|
function parseInternal (input, options) {
|
|
107
111
|
if (typeof input !== 'string' || !(input instanceof String)) {
|
|
108
112
|
input = String(input)
|
|
@@ -112,6 +116,8 @@ function parseInternal (input, options) {
|
|
|
112
116
|
const ignoreBOM = options.ignoreBOM
|
|
113
117
|
const ignoreComments = options.ignoreComments || options.mode === 'cjson' || json5
|
|
114
118
|
const ignoreTrailingCommas = options.ignoreTrailingCommas || json5
|
|
119
|
+
const ignoreProtoKey = options.ignoreProtoKey
|
|
120
|
+
const ignorePrototypeKeys = options.ignorePrototypeKeys
|
|
115
121
|
const allowSingleQuotedStrings = options.allowSingleQuotedStrings || json5
|
|
116
122
|
const allowDuplicateObjectKeys = options.allowDuplicateObjectKeys
|
|
117
123
|
const reviver = options.reviver
|
|
@@ -176,7 +182,7 @@ function parseInternal (input, options) {
|
|
|
176
182
|
let message
|
|
177
183
|
if (position < inputLength) {
|
|
178
184
|
const token = JSON.stringify(input[position])
|
|
179
|
-
message =
|
|
185
|
+
message = `Unexpected token ${token}`
|
|
180
186
|
} else {
|
|
181
187
|
message = 'Unexpected end of input'
|
|
182
188
|
}
|
|
@@ -220,87 +226,84 @@ function parseInternal (input, options) {
|
|
|
220
226
|
|
|
221
227
|
function parseGeneric () {
|
|
222
228
|
if (position < inputLength) {
|
|
223
|
-
startToken
|
|
229
|
+
startToken?.()
|
|
224
230
|
const char = input[position++]
|
|
225
231
|
if (char === '"' || (char === '\'' && allowSingleQuotedStrings)) {
|
|
226
232
|
const string = parseString(char)
|
|
227
|
-
endToken
|
|
233
|
+
endToken?.('literal', string)
|
|
228
234
|
return string
|
|
229
|
-
}
|
|
230
|
-
endToken
|
|
235
|
+
}if (char === '{') {
|
|
236
|
+
endToken?.('symbol', '{')
|
|
231
237
|
return parseObject()
|
|
232
|
-
}
|
|
233
|
-
endToken
|
|
238
|
+
}if (char === '[') {
|
|
239
|
+
endToken?.('symbol', '[')
|
|
234
240
|
return parseArray()
|
|
235
|
-
}
|
|
241
|
+
}if (char === '-' || char === '.' || isDecDigit(char) ||
|
|
236
242
|
(json5 && (char === '+' || char === 'I' || char === 'N'))) {
|
|
237
243
|
const number = parseNumber()
|
|
238
|
-
endToken
|
|
244
|
+
endToken?.('literal', number)
|
|
239
245
|
return number
|
|
240
|
-
}
|
|
246
|
+
}if (char === 'n') {
|
|
241
247
|
parseKeyword('null')
|
|
242
|
-
endToken
|
|
248
|
+
endToken?.('literal', null)
|
|
243
249
|
return null
|
|
244
|
-
}
|
|
250
|
+
}if (char === 't') {
|
|
245
251
|
parseKeyword('true')
|
|
246
|
-
endToken
|
|
252
|
+
endToken?.('literal', true)
|
|
247
253
|
return true
|
|
248
|
-
}
|
|
254
|
+
}if (char === 'f') {
|
|
249
255
|
parseKeyword('false')
|
|
250
|
-
endToken
|
|
256
|
+
endToken?.('literal', false)
|
|
251
257
|
return false
|
|
252
|
-
}
|
|
258
|
+
}
|
|
253
259
|
--position
|
|
254
|
-
endToken
|
|
260
|
+
endToken?.()
|
|
255
261
|
return undefined
|
|
256
|
-
}
|
|
257
262
|
}
|
|
258
263
|
}
|
|
259
264
|
|
|
260
265
|
function parseKey () {
|
|
261
266
|
let result
|
|
262
267
|
if (position < inputLength) {
|
|
263
|
-
startToken
|
|
268
|
+
startToken?.()
|
|
264
269
|
const char = input[position++]
|
|
265
270
|
if (char === '"' || (char === '\'' && allowSingleQuotedStrings)) {
|
|
266
271
|
const string = parseString(char)
|
|
267
|
-
endToken
|
|
272
|
+
endToken?.('literal', string)
|
|
268
273
|
return string
|
|
269
|
-
}
|
|
270
|
-
endToken
|
|
274
|
+
}if (char === '{') {
|
|
275
|
+
endToken?.('symbol', '{')
|
|
271
276
|
return parseObject()
|
|
272
|
-
}
|
|
273
|
-
endToken
|
|
277
|
+
}if (char === '[') {
|
|
278
|
+
endToken?.('symbol', '[')
|
|
274
279
|
return parseArray()
|
|
275
|
-
}
|
|
280
|
+
}if (char === '.' || isDecDigit(char)) {
|
|
276
281
|
const number = parseNumber(true)
|
|
277
|
-
endToken
|
|
282
|
+
endToken?.('literal', number)
|
|
278
283
|
return number
|
|
279
|
-
}
|
|
284
|
+
}if ((json5 && Uni.isIdentifierStart(char)) ||
|
|
280
285
|
(char === '\\' && input[position] === 'u')) {
|
|
281
286
|
const rollback = position - 1
|
|
282
287
|
result = parseIdentifier()
|
|
283
288
|
if (result === undefined) {
|
|
284
289
|
position = rollback
|
|
285
|
-
endToken
|
|
290
|
+
endToken?.()
|
|
286
291
|
return undefined
|
|
287
|
-
} else {
|
|
288
|
-
endToken && endToken('literal', result)
|
|
289
|
-
return result
|
|
290
292
|
}
|
|
291
|
-
|
|
293
|
+
endToken?.('literal', result)
|
|
294
|
+
return result
|
|
295
|
+
}
|
|
292
296
|
--position
|
|
293
|
-
endToken
|
|
297
|
+
endToken?.()
|
|
294
298
|
return undefined
|
|
295
|
-
}
|
|
296
299
|
}
|
|
297
300
|
}
|
|
298
301
|
|
|
299
302
|
function skipBOM () {
|
|
300
303
|
if (isBOM(input)) {
|
|
301
|
-
startToken
|
|
304
|
+
startToken?.()
|
|
302
305
|
++position
|
|
303
|
-
endToken
|
|
306
|
+
endToken?.('bom')
|
|
304
307
|
}
|
|
305
308
|
}
|
|
306
309
|
|
|
@@ -336,7 +339,7 @@ function parseInternal (input, options) {
|
|
|
336
339
|
++position
|
|
337
340
|
}
|
|
338
341
|
skipComment(input[position++] === '*')
|
|
339
|
-
endToken
|
|
342
|
+
endToken?.('comment')
|
|
340
343
|
} else {
|
|
341
344
|
--position
|
|
342
345
|
break
|
|
@@ -382,40 +385,40 @@ function parseInternal (input, options) {
|
|
|
382
385
|
}
|
|
383
386
|
|
|
384
387
|
function parseObject () {
|
|
385
|
-
|
|
386
|
-
const emptyObject = {}
|
|
388
|
+
let result = {}
|
|
387
389
|
let isNotEmpty = false
|
|
388
390
|
|
|
389
391
|
while (position < inputLength) {
|
|
390
392
|
skipWhiteSpace()
|
|
391
393
|
const key = parseKey()
|
|
392
|
-
if (allowDuplicateObjectKeys === false && result
|
|
393
|
-
fail(
|
|
394
|
+
if (allowDuplicateObjectKeys === false && ownsProperty.call(result, key)) {
|
|
395
|
+
fail(`Duplicate key: "${key}"`)
|
|
394
396
|
}
|
|
395
397
|
skipWhiteSpace()
|
|
396
|
-
startToken
|
|
398
|
+
startToken?.()
|
|
397
399
|
let char = input[position++]
|
|
398
|
-
endToken
|
|
400
|
+
endToken?.('symbol', char)
|
|
399
401
|
if (char === '}' && key === undefined) {
|
|
400
402
|
if (!ignoreTrailingCommas && isNotEmpty) {
|
|
401
403
|
--position
|
|
402
404
|
fail('Trailing comma in object')
|
|
403
405
|
}
|
|
404
406
|
return result
|
|
405
|
-
}
|
|
407
|
+
}if (char === ':' && key !== undefined) {
|
|
406
408
|
skipWhiteSpace()
|
|
407
|
-
tokenPath
|
|
409
|
+
tokenPath?.push(key)
|
|
408
410
|
let value = parseGeneric()
|
|
409
|
-
tokenPath
|
|
411
|
+
tokenPath?.pop()
|
|
410
412
|
|
|
411
|
-
if (value === undefined) fail(
|
|
413
|
+
if (value === undefined) fail(`No value found for key "${key}"`)
|
|
412
414
|
if (typeof key !== 'string') {
|
|
413
415
|
if (!json5 || typeof key !== 'number') {
|
|
414
|
-
fail(
|
|
416
|
+
fail(`Wrong key type: "${key}"`)
|
|
415
417
|
}
|
|
416
418
|
}
|
|
417
419
|
|
|
418
|
-
if (key in emptyObject || emptyObject[key] != null)
|
|
420
|
+
if ((ignorePrototypeKeys && (key in emptyObject || emptyObject[key] != null)) ||
|
|
421
|
+
(ignoreProtoKey && key === '__proto__')) {
|
|
419
422
|
// silently ignore it
|
|
420
423
|
} else {
|
|
421
424
|
if (reviver) {
|
|
@@ -423,16 +426,19 @@ function parseInternal (input, options) {
|
|
|
423
426
|
}
|
|
424
427
|
if (value !== undefined) {
|
|
425
428
|
isNotEmpty = true
|
|
426
|
-
|
|
429
|
+
if (key === '__proto__') {
|
|
430
|
+
result = Object.assign(JSON.parse(`{"__proto__":${JSON.stringify(value)}}`), result)
|
|
431
|
+
} else {
|
|
432
|
+
result[key] = value
|
|
433
|
+
}
|
|
427
434
|
}
|
|
428
435
|
}
|
|
429
436
|
|
|
430
437
|
skipWhiteSpace()
|
|
431
|
-
startToken
|
|
438
|
+
startToken?.()
|
|
432
439
|
char = input[position++]
|
|
433
|
-
endToken
|
|
440
|
+
endToken?.('symbol', char)
|
|
434
441
|
if (char === ',') {
|
|
435
|
-
continue
|
|
436
442
|
} else if (char === '}') {
|
|
437
443
|
return result
|
|
438
444
|
} else {
|
|
@@ -451,13 +457,13 @@ function parseInternal (input, options) {
|
|
|
451
457
|
const result = []
|
|
452
458
|
while (position < inputLength) {
|
|
453
459
|
skipWhiteSpace()
|
|
454
|
-
tokenPath
|
|
460
|
+
tokenPath?.push(result.length)
|
|
455
461
|
let item = parseGeneric()
|
|
456
|
-
tokenPath
|
|
462
|
+
tokenPath?.pop()
|
|
457
463
|
skipWhiteSpace()
|
|
458
|
-
startToken
|
|
464
|
+
startToken?.()
|
|
459
465
|
const char = input[position++]
|
|
460
|
-
endToken
|
|
466
|
+
endToken?.('symbol', char)
|
|
461
467
|
if (item !== undefined) {
|
|
462
468
|
if (reviver) {
|
|
463
469
|
item = reviver(String(result.length), item)
|
|
@@ -498,18 +504,18 @@ function parseInternal (input, options) {
|
|
|
498
504
|
let result
|
|
499
505
|
|
|
500
506
|
if (isOctal) {
|
|
501
|
-
result = parseInt(string.replace(/^0o?/, ''), 8)
|
|
507
|
+
result = Number.parseInt(string.replace(/^0o?/, ''), 8)
|
|
502
508
|
} else {
|
|
503
509
|
result = Number(string)
|
|
504
510
|
}
|
|
505
511
|
|
|
506
512
|
if (Number.isNaN(result)) {
|
|
507
513
|
--position
|
|
508
|
-
fail(
|
|
514
|
+
fail(`Bad numeric literal - "${input.substr(start, position - start + 1)}"`)
|
|
509
515
|
} else if (!json5 && !string.match(/^-?(0|[1-9][0-9]*)(\.[0-9]+)?(e[+-]?[0-9]+)?$/i)) {
|
|
510
516
|
// additional restrictions imposed by json
|
|
511
517
|
--position
|
|
512
|
-
fail(
|
|
518
|
+
fail(`Non-json numeric literal - "${input.substr(start, position - start + 1)}"`)
|
|
513
519
|
} else {
|
|
514
520
|
return result
|
|
515
521
|
}
|
|
@@ -523,7 +529,7 @@ function parseInternal (input, options) {
|
|
|
523
529
|
|
|
524
530
|
if (char === 'N' && json5) {
|
|
525
531
|
parseKeyword('NaN')
|
|
526
|
-
return NaN
|
|
532
|
+
return Number.NaN
|
|
527
533
|
}
|
|
528
534
|
|
|
529
535
|
if (char === 'I' && json5) {
|
|
@@ -608,7 +614,7 @@ function parseInternal (input, options) {
|
|
|
608
614
|
isHexDigit(input[position + 3]) &&
|
|
609
615
|
isHexDigit(input[position + 4])) {
|
|
610
616
|
// UnicodeEscapeSequence
|
|
611
|
-
char = String.fromCharCode(parseInt(input.substr(position + 1, 4), 16))
|
|
617
|
+
char = String.fromCharCode(Number.parseInt(input.substr(position + 1, 4), 16))
|
|
612
618
|
position += 5
|
|
613
619
|
}
|
|
614
620
|
|
|
@@ -639,7 +645,7 @@ function parseInternal (input, options) {
|
|
|
639
645
|
let char = input[position++]
|
|
640
646
|
if (char === endChar) {
|
|
641
647
|
return result
|
|
642
|
-
}
|
|
648
|
+
}if (char === '\\') {
|
|
643
649
|
if (position >= inputLength) {
|
|
644
650
|
fail()
|
|
645
651
|
}
|
|
@@ -662,7 +668,7 @@ function parseInternal (input, options) {
|
|
|
662
668
|
}
|
|
663
669
|
position++
|
|
664
670
|
}
|
|
665
|
-
result += String.fromCharCode(parseInt(input.substr(position - count, count), 16))
|
|
671
|
+
result += String.fromCharCode(Number.parseInt(input.substr(position - count, count), 16))
|
|
666
672
|
} else if (json5 && isOctDigit(char)) {
|
|
667
673
|
let digits
|
|
668
674
|
if (char < '4' && isOctDigit(input[position]) && isOctDigit(input[position + 1])) {
|
|
@@ -675,7 +681,7 @@ function parseInternal (input, options) {
|
|
|
675
681
|
digits = 1
|
|
676
682
|
}
|
|
677
683
|
position += digits - 1
|
|
678
|
-
result += String.fromCharCode(parseInt(input.substr(position - digits, digits), 8))
|
|
684
|
+
result += String.fromCharCode(Number.parseInt(input.substr(position - digits, digits), 8))
|
|
679
685
|
} else if (json5) {
|
|
680
686
|
// \X -> x
|
|
681
687
|
result += char
|
|
@@ -710,9 +716,8 @@ function parseInternal (input, options) {
|
|
|
710
716
|
returnValue = reviver('', returnValue)
|
|
711
717
|
}
|
|
712
718
|
return tokenize ? tokens : returnValue
|
|
713
|
-
} else {
|
|
714
|
-
fail()
|
|
715
719
|
}
|
|
720
|
+
fail()
|
|
716
721
|
} else {
|
|
717
722
|
if (position) {
|
|
718
723
|
fail('No data, only a whitespace')
|
|
@@ -759,9 +764,9 @@ function pathToPointer (tokens) {
|
|
|
759
764
|
if (tokens.length === 0) {
|
|
760
765
|
return ''
|
|
761
766
|
}
|
|
762
|
-
return
|
|
767
|
+
return `/${tokens
|
|
763
768
|
.map(escapePointerToken)
|
|
764
|
-
.join('/')
|
|
769
|
+
.join('/')}`
|
|
765
770
|
}
|
|
766
771
|
|
|
767
772
|
function unescapePointerToken (token) {
|
|
@@ -825,7 +830,7 @@ function upcomingInput (input, offset) {
|
|
|
825
830
|
function getPositionContext (input, offset) {
|
|
826
831
|
const past = pastInput(input, offset)
|
|
827
832
|
const upcoming = upcomingInput(input, offset)
|
|
828
|
-
const pointer = new Array(past.length + 1).join('-')
|
|
833
|
+
const pointer = `${new Array(past.length + 1).join('-')}^`
|
|
829
834
|
return {
|
|
830
835
|
excerpt: past + upcoming,
|
|
831
836
|
pointer
|
|
@@ -889,13 +894,13 @@ function getLocationOnSpiderMonkey (input, reason) {
|
|
|
889
894
|
function getTexts (reason, input, offset, line, column) {
|
|
890
895
|
const position = getPositionContext(input, offset)
|
|
891
896
|
const excerpt = position.excerpt
|
|
892
|
-
let message
|
|
897
|
+
let message
|
|
898
|
+
let pointer
|
|
893
899
|
if (typeof line === 'number') {
|
|
894
900
|
pointer = position.pointer
|
|
895
|
-
message =
|
|
896
|
-
column + ':\n' + excerpt + '\n' + pointer + '\n' + reason
|
|
901
|
+
message = `Parse error on line ${line}, column ${column}:\n${excerpt}\n${pointer}\n${reason}`
|
|
897
902
|
} else {
|
|
898
|
-
message =
|
|
903
|
+
message = `Parse error in JSON input:\n${excerpt}\n${reason}`
|
|
899
904
|
}
|
|
900
905
|
return {
|
|
901
906
|
message,
|
|
@@ -909,7 +914,9 @@ function improveNativeError (input, error) {
|
|
|
909
914
|
const location = getLocationOnV8(input, reason) ||
|
|
910
915
|
checkUnexpectedEndOnV8(input, reason) ||
|
|
911
916
|
getLocationOnSpiderMonkey(input, reason)
|
|
912
|
-
let offset
|
|
917
|
+
let offset
|
|
918
|
+
let line
|
|
919
|
+
let column
|
|
913
920
|
if (location) {
|
|
914
921
|
offset = location.offset
|
|
915
922
|
line = location.line
|
|
@@ -955,13 +962,14 @@ const oldNode = typeof process !== 'undefined' && process.version.startsWith('v4
|
|
|
955
962
|
function needsCustomParser (options) {
|
|
956
963
|
return options.ignoreBOM || options.ignoreComments || options.ignoreTrailingCommas ||
|
|
957
964
|
options.allowSingleQuotedStrings || options.allowDuplicateObjectKeys === false ||
|
|
958
|
-
options.
|
|
965
|
+
options.ignoreProtoKey || options.ignorePrototypeKeys || options.mode === 'cjson' ||
|
|
966
|
+
options.mode === 'json5' || isSafari || oldNode
|
|
959
967
|
}
|
|
960
968
|
|
|
961
969
|
function getReviver (options) {
|
|
962
970
|
if (typeof options === 'function') {
|
|
963
971
|
return options
|
|
964
|
-
}
|
|
972
|
+
}if (options) {
|
|
965
973
|
return options.reviver
|
|
966
974
|
}
|
|
967
975
|
}
|
package/lib/printer.js
CHANGED
|
@@ -22,11 +22,11 @@
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
function print (tokens, options) {
|
|
25
|
-
if (!(tokens
|
|
25
|
+
if (!(tokens?.length)) {
|
|
26
26
|
throw new Error('JSON tokens missing.')
|
|
27
27
|
}
|
|
28
28
|
// Whitespace and comments are available only as raw token content.
|
|
29
|
-
if (!(tokens[0]
|
|
29
|
+
if (!(tokens[0]?.raw)) {
|
|
30
30
|
throw new Error('JSON tokens lack raw values.')
|
|
31
31
|
}
|
|
32
32
|
|
|
@@ -50,14 +50,20 @@
|
|
|
50
50
|
const trimTrailingCommas = options.trimTrailingCommas
|
|
51
51
|
|
|
52
52
|
let outputString = ''
|
|
53
|
-
let foundLineBreak
|
|
54
|
-
let
|
|
53
|
+
let foundLineBreak
|
|
54
|
+
let addedLineBreak
|
|
55
|
+
let needsLineBreak
|
|
56
|
+
let addedSpace
|
|
57
|
+
let needsSpace
|
|
55
58
|
let indentLevel = 0
|
|
56
59
|
const scopes = []
|
|
57
60
|
let scopeType
|
|
58
61
|
let isValue
|
|
59
62
|
const tokenCount = tokens.length
|
|
60
|
-
let tokenIndex
|
|
63
|
+
let tokenIndex
|
|
64
|
+
let token
|
|
65
|
+
let tokenType
|
|
66
|
+
let tokenContent
|
|
61
67
|
|
|
62
68
|
function peekAtNextToken () {
|
|
63
69
|
let nextTokenIndex = tokenIndex
|
|
@@ -80,7 +86,8 @@
|
|
|
80
86
|
addIndent = noop
|
|
81
87
|
}
|
|
82
88
|
|
|
83
|
-
let addLineBreak
|
|
89
|
+
let addLineBreak
|
|
90
|
+
let addDelayedSpaceOrLineBreak
|
|
84
91
|
if (prettyPrint) {
|
|
85
92
|
addLineBreak = function () {
|
|
86
93
|
outputString += '\n'
|
|
@@ -100,7 +107,8 @@
|
|
|
100
107
|
addLineBreak = addDelayedSpaceOrLineBreak = noop
|
|
101
108
|
}
|
|
102
109
|
|
|
103
|
-
let addStandaloneComment
|
|
110
|
+
let addStandaloneComment
|
|
111
|
+
let tryAddingInlineComment
|
|
104
112
|
if (pruneComments) {
|
|
105
113
|
addStandaloneComment = tryAddingInlineComment = noop
|
|
106
114
|
} else {
|
|
@@ -198,7 +206,7 @@
|
|
|
198
206
|
if (enforceDoubleQuotes && tokenContent[0] !== '"') {
|
|
199
207
|
outputString += JSON.stringify(tokenValue)
|
|
200
208
|
} else if (enforceSingleQuotes && tokenContent[0] !== '\'') {
|
|
201
|
-
outputString += '
|
|
209
|
+
outputString += `\'${tokenValue.replace(/'/g, '\\\'')}\'`
|
|
202
210
|
} else {
|
|
203
211
|
outputString += tokenContent
|
|
204
212
|
}
|
package/lib/sorter.js
CHANGED
|
@@ -6,22 +6,39 @@
|
|
|
6
6
|
'use strict'
|
|
7
7
|
|
|
8
8
|
// from http://stackoverflow.com/questions/1359761/sorting-a-json-object-in-javascript
|
|
9
|
-
const
|
|
10
|
-
function sortObject (o) {
|
|
9
|
+
const ownsProperty = Object.prototype.hasOwnProperty
|
|
10
|
+
function sortObject (o, { ignoreCase, locale, caseFirst, numeric } = {}) {
|
|
11
11
|
if (Array.isArray(o)) {
|
|
12
12
|
return o.map(sortObject)
|
|
13
|
-
}
|
|
13
|
+
}if (Object.prototype.toString.call(o) !== '[object Object]') {
|
|
14
14
|
return o
|
|
15
15
|
}
|
|
16
16
|
const sorted = {}
|
|
17
17
|
let key
|
|
18
18
|
const a = []
|
|
19
19
|
for (key in o) {
|
|
20
|
-
if (
|
|
20
|
+
if (ownsProperty.call(o, key)) {
|
|
21
21
|
a.push(key)
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
|
-
|
|
24
|
+
if (locale || caseFirst || numeric) {
|
|
25
|
+
if (locale === 'default') {
|
|
26
|
+
locale = undefined
|
|
27
|
+
}
|
|
28
|
+
const sortOptions = { caseFirst, numeric }
|
|
29
|
+
if (ignoreCase) {
|
|
30
|
+
sortOptions.sensitivity = 'accent'
|
|
31
|
+
}
|
|
32
|
+
a.sort((l, r) => l.localeCompare(r, locale, sortOptions))
|
|
33
|
+
} else if (ignoreCase) {
|
|
34
|
+
a.sort((l, r) => {
|
|
35
|
+
l = l.toLowerCase()
|
|
36
|
+
r = r.toLowerCase()
|
|
37
|
+
return l < r ? -1 : l > r ? 1 : 0
|
|
38
|
+
})
|
|
39
|
+
} else {
|
|
40
|
+
a.sort()
|
|
41
|
+
}
|
|
25
42
|
for (key = 0; key < a.length; key++) {
|
|
26
43
|
sorted[a[key]] = sortObject(o[a[key]])
|
|
27
44
|
}
|
package/lib/validator.js
CHANGED
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
function errorToProblem (error, input, tokens) {
|
|
64
64
|
const dataPath = error.dataPath
|
|
65
65
|
const schemaPath = error.schemaPath
|
|
66
|
-
const reason =
|
|
66
|
+
const reason = `${dataPath || '/'} ${error.message}; see ${schemaPath}`
|
|
67
67
|
const problem = {
|
|
68
68
|
reason,
|
|
69
69
|
dataPath,
|
|
@@ -167,7 +167,9 @@
|
|
|
167
167
|
ignoreComments: options.ignoreComments,
|
|
168
168
|
ignoreTrailingCommas: options.ignoreTrailingCommas,
|
|
169
169
|
allowSingleQuotedStrings: options.allowSingleQuotedStrings,
|
|
170
|
-
allowDuplicateObjectKeys: options.allowDuplicateObjectKeys
|
|
170
|
+
allowDuplicateObjectKeys: options.allowDuplicateObjectKeys,
|
|
171
|
+
ignoreProtoKey: options.ignoreProtoKey,
|
|
172
|
+
ignorePrototypeKeys: options.ignorePrototypeKeys
|
|
171
173
|
}
|
|
172
174
|
const validate = compileSchema(ajv, schema, parseOptions)
|
|
173
175
|
return function (data, input, options) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prantlf/jsonlint",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "15.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": [
|
|
@@ -43,7 +43,8 @@
|
|
|
43
43
|
"compile:jsonlint": "cat-j src/prefix.js.txt src/unicode.js src/custom-parser.js src/pointer.js src/native-parser.js src/configurable-parser.js src/suffix.js.txt > lib/jsonlint.js",
|
|
44
44
|
"minify": "esbuild --minify --sourcemap --outfile=web/jsonlint.min.js lib/jsonlint.js && esbuild --minify --sourcemap --outfile=web/validator.min.js lib/validator.js && esbuild --minify --sourcemap --outfile=web/formatter.min.js lib/formatter.js && esbuild --minify --sourcemap --outfile=web/sorter.min.js lib/sorter.js && esbuild --minify --sourcemap --outfile=web/printer.min.js lib/printer.js",
|
|
45
45
|
"compile:tests": "tsc --moduleResolution node --module es2022 test/types.test.ts && mv-j test/types.test.js test/types.test.mjs",
|
|
46
|
-
"
|
|
46
|
+
"lint": "biome lint *.mjs lib src test/*.js",
|
|
47
|
+
"test": "biome lint *.mjs lib src test/*.js && c8 node test/types.test.mjs && c8 --no-clean node test/parse1 && c8 --no-clean node test/parse1 --native-parser && c8 --no-clean node test/parse2 && c8 --no-clean node test/parse3 && c8 --no-clean node test/parse4 && c8 --no-clean node test/parse5 && c8 --no-clean node test/portable && c8 --no-clean node test/tokenize && c8 --no-clean node test/print && c8 --no-clean node lib/cli package.json test/recursive && c8 --no-clean node lib/cli -sq test/passes/hasOwnProperty.json && c8 --no-clean node lib/cli -s -e json-schema-draft-04 -V test/passes/schema-04.json test/passes/data-04.json && c8 --no-clean node lib/cli -s -e json-schema-draft-07 -V test/passes/schema-07.json test/passes/data-07.json && c8 --no-clean node lib/cli -C test/passes/comments.txt && c8 --no-clean node lib/cli -pS test/passes/strings.txt && c8 --no-clean node lib/cli -M json5 test/passes/json5.text && c8 --no-clean node lib/cli -v && c8 --no-clean node lib/cli -h && c8 --no-clean node lib/cli -Pc test/fails/10.json || c8 --no-clean node lib/cli -f test/.jsonrc.yml 'test/**/*.json' '!**/fails' && c8 report -r text -r lcov",
|
|
47
48
|
"start": "http-server -c 5",
|
|
48
49
|
"web": "npm run web:sync && npm run web:deploy",
|
|
49
50
|
"web:clone": "test ! -d ../jsonlint-pages && git clone --single-branch --branch gh-pages `git remote get-url origin` ../jsonlint-pages",
|
|
@@ -54,48 +55,31 @@
|
|
|
54
55
|
"c8": {
|
|
55
56
|
"reporter": []
|
|
56
57
|
},
|
|
57
|
-
"release": {
|
|
58
|
-
"plugins": [
|
|
59
|
-
"@semantic-release/commit-analyzer",
|
|
60
|
-
"@semantic-release/release-notes-generator",
|
|
61
|
-
"@semantic-release/changelog",
|
|
62
|
-
"@semantic-release/npm",
|
|
63
|
-
[
|
|
64
|
-
"@semantic-release/github",
|
|
65
|
-
{
|
|
66
|
-
"failComment": false
|
|
67
|
-
}
|
|
68
|
-
],
|
|
69
|
-
"@semantic-release/git"
|
|
70
|
-
]
|
|
71
|
-
},
|
|
72
58
|
"dependencies": {
|
|
73
|
-
"ajv": "8.
|
|
59
|
+
"ajv": "8.17.1",
|
|
74
60
|
"ajv-draft-04": "1.0.0",
|
|
75
|
-
"cosmiconfig": "
|
|
76
|
-
"diff": "5.
|
|
77
|
-
"fast-glob": "3.2
|
|
61
|
+
"cosmiconfig": "9.0.0",
|
|
62
|
+
"diff": "5.2.0",
|
|
63
|
+
"fast-glob": "3.3.2"
|
|
78
64
|
},
|
|
79
65
|
"devDependencies": {
|
|
80
|
-
"@
|
|
81
|
-
"@rollup/plugin-
|
|
82
|
-
"@rollup/plugin-
|
|
83
|
-
"@
|
|
84
|
-
"@
|
|
85
|
-
"@types/node": "18.16.1",
|
|
66
|
+
"@biomejs/biome": "^1.8.3",
|
|
67
|
+
"@rollup/plugin-commonjs": "26.0.1",
|
|
68
|
+
"@rollup/plugin-json": "6.1.0",
|
|
69
|
+
"@rollup/plugin-node-resolve": "15.2.3",
|
|
70
|
+
"@types/node": "22.1.0",
|
|
86
71
|
"@unixcompat/cat.js": "2.0.0",
|
|
87
72
|
"@unixcompat/mv.js": "2.0.0",
|
|
88
|
-
"c8": "
|
|
89
|
-
"
|
|
90
|
-
"esbuild": "0.17.18",
|
|
73
|
+
"c8": "10.1.2",
|
|
74
|
+
"esbuild": "0.23.0",
|
|
91
75
|
"http-server": "14.1.1",
|
|
92
76
|
"js-yaml": "4.1.0",
|
|
93
|
-
"rollup": "
|
|
94
|
-
"rollup-plugin-swc-minify": "1.
|
|
77
|
+
"rollup": "4.20.0",
|
|
78
|
+
"rollup-plugin-swc-minify": "1.1.2",
|
|
95
79
|
"tehanu": "1.0.1",
|
|
96
|
-
"tehanu-repo-coco": "1.0.
|
|
97
|
-
"tehanu-teru": "1.0.
|
|
98
|
-
"typescript": "5.
|
|
80
|
+
"tehanu-repo-coco": "1.0.1",
|
|
81
|
+
"tehanu-teru": "1.0.1",
|
|
82
|
+
"typescript": "5.5.4"
|
|
99
83
|
},
|
|
100
84
|
"keywords": [
|
|
101
85
|
"json",
|
|
@@ -103,4 +87,4 @@
|
|
|
103
87
|
"lint",
|
|
104
88
|
"jsonlint"
|
|
105
89
|
]
|
|
106
|
-
}
|
|
90
|
+
}
|