@asymmetric-effort/jsonlint 0.0.2 → 0.0.3
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/bin/jsonlint +0 -0
- package/build/index.d.ts +1 -0
- package/build/index.js +236 -0
- package/build/version.d.ts +1 -1
- package/package.json +1 -1
package/bin/jsonlint
CHANGED
|
Binary file
|
package/build/index.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ export type { ParseErrorHash } from "./parser.js";
|
|
|
5
5
|
export { formatJson } from "./formatter.js";
|
|
6
6
|
export { SchemaValidator } from "./schema.js";
|
|
7
7
|
export type { JsonSchema, SchemaError } from "./schema.js";
|
|
8
|
+
export { main } from "./cli.js";
|
|
8
9
|
import { JsonParser } from "./parser.js";
|
|
9
10
|
export declare const parser: JsonParser;
|
|
10
11
|
import { formatJson } from "./formatter.js";
|
package/build/index.js
CHANGED
|
@@ -876,12 +876,248 @@ class SchemaValidator {
|
|
|
876
876
|
}
|
|
877
877
|
}
|
|
878
878
|
}
|
|
879
|
+
// src/cli.ts
|
|
880
|
+
import { readFileSync, writeFileSync } from "fs";
|
|
881
|
+
|
|
882
|
+
// src/version.ts
|
|
883
|
+
var VERSION = "0.0.3";
|
|
884
|
+
|
|
885
|
+
// src/cli.ts
|
|
886
|
+
function printVersion() {
|
|
887
|
+
process.stdout.write(`${VERSION}
|
|
888
|
+
`);
|
|
889
|
+
}
|
|
890
|
+
function printUsage() {
|
|
891
|
+
process.stdout.write(`Usage: jsonlint [OPTIONS] [FILE]
|
|
892
|
+
|
|
893
|
+
Options:
|
|
894
|
+
-v, --version Print version and exit
|
|
895
|
+
-s, --sort-keys Sort object keys in output
|
|
896
|
+
-i, --in-place Overwrite the input file with formatted output
|
|
897
|
+
-t, --indent CHAR Character(s) to use for indentation (default: " ")
|
|
898
|
+
-c, --compact Compact error display
|
|
899
|
+
-V, --validate FILE Validate against a JSON Schema file
|
|
900
|
+
-e, --environment ENV JSON Schema spec version (default: json-schema-draft-03)
|
|
901
|
+
-q, --quiet Do not print parsed JSON to stdout
|
|
902
|
+
-p, --pretty-print Force pretty printing (even if invalid)
|
|
903
|
+
-h, --help Show this help message
|
|
904
|
+
|
|
905
|
+
If FILE is omitted, reads from stdin.
|
|
906
|
+
`);
|
|
907
|
+
}
|
|
908
|
+
function parseArgs(args) {
|
|
909
|
+
const opts = {
|
|
910
|
+
file: null,
|
|
911
|
+
sortKeys: false,
|
|
912
|
+
inPlace: false,
|
|
913
|
+
indent: " ",
|
|
914
|
+
compact: false,
|
|
915
|
+
validate: null,
|
|
916
|
+
environment: "json-schema-draft-03",
|
|
917
|
+
quiet: false,
|
|
918
|
+
prettyPrint: false,
|
|
919
|
+
version: false
|
|
920
|
+
};
|
|
921
|
+
let i = 0;
|
|
922
|
+
while (i < args.length) {
|
|
923
|
+
const arg = args[i];
|
|
924
|
+
switch (arg) {
|
|
925
|
+
case "-v":
|
|
926
|
+
case "--version":
|
|
927
|
+
opts.version = true;
|
|
928
|
+
break;
|
|
929
|
+
case "-s":
|
|
930
|
+
case "--sort-keys":
|
|
931
|
+
opts.sortKeys = true;
|
|
932
|
+
break;
|
|
933
|
+
case "-i":
|
|
934
|
+
case "--in-place":
|
|
935
|
+
opts.inPlace = true;
|
|
936
|
+
break;
|
|
937
|
+
case "-t":
|
|
938
|
+
case "--indent":
|
|
939
|
+
i++;
|
|
940
|
+
opts.indent = args[i] ?? " ";
|
|
941
|
+
break;
|
|
942
|
+
case "-c":
|
|
943
|
+
case "--compact":
|
|
944
|
+
opts.compact = true;
|
|
945
|
+
break;
|
|
946
|
+
case "-V":
|
|
947
|
+
case "--validate":
|
|
948
|
+
i++;
|
|
949
|
+
opts.validate = args[i] ?? null;
|
|
950
|
+
break;
|
|
951
|
+
case "-e":
|
|
952
|
+
case "--environment":
|
|
953
|
+
i++;
|
|
954
|
+
opts.environment = args[i] ?? "json-schema-draft-03";
|
|
955
|
+
break;
|
|
956
|
+
case "-q":
|
|
957
|
+
case "--quiet":
|
|
958
|
+
opts.quiet = true;
|
|
959
|
+
break;
|
|
960
|
+
case "-p":
|
|
961
|
+
case "--pretty-print":
|
|
962
|
+
opts.prettyPrint = true;
|
|
963
|
+
break;
|
|
964
|
+
case "-h":
|
|
965
|
+
case "--help":
|
|
966
|
+
printUsage();
|
|
967
|
+
process.exit(0);
|
|
968
|
+
break;
|
|
969
|
+
default:
|
|
970
|
+
if (arg.startsWith("-")) {
|
|
971
|
+
process.stderr.write(`Unknown option: ${arg}
|
|
972
|
+
`);
|
|
973
|
+
process.exit(1);
|
|
974
|
+
}
|
|
975
|
+
opts.file = arg;
|
|
976
|
+
break;
|
|
977
|
+
}
|
|
978
|
+
i++;
|
|
979
|
+
}
|
|
980
|
+
return opts;
|
|
981
|
+
}
|
|
982
|
+
function sortObject(obj) {
|
|
983
|
+
if (Array.isArray(obj)) {
|
|
984
|
+
return obj.map(sortObject);
|
|
985
|
+
}
|
|
986
|
+
if (obj !== null && typeof obj === "object") {
|
|
987
|
+
const sorted = {};
|
|
988
|
+
const keys = Object.keys(obj).sort();
|
|
989
|
+
for (const key of keys) {
|
|
990
|
+
sorted[key] = sortObject(obj[key]);
|
|
991
|
+
}
|
|
992
|
+
return sorted;
|
|
993
|
+
}
|
|
994
|
+
return obj;
|
|
995
|
+
}
|
|
996
|
+
function readStdin() {
|
|
997
|
+
try {
|
|
998
|
+
return readFileSync("/dev/stdin", "utf-8");
|
|
999
|
+
} catch {
|
|
1000
|
+
process.stderr.write(`Error reading from stdin
|
|
1001
|
+
`);
|
|
1002
|
+
process.exit(1);
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
1005
|
+
function main(args) {
|
|
1006
|
+
const cliArgs = args ?? process.argv.slice(2);
|
|
1007
|
+
const opts = parseArgs(cliArgs);
|
|
1008
|
+
if (opts.version) {
|
|
1009
|
+
printVersion();
|
|
1010
|
+
return;
|
|
1011
|
+
}
|
|
1012
|
+
let input;
|
|
1013
|
+
let filename;
|
|
1014
|
+
if (opts.file) {
|
|
1015
|
+
try {
|
|
1016
|
+
input = readFileSync(opts.file, "utf-8");
|
|
1017
|
+
} catch {
|
|
1018
|
+
process.stderr.write(`Error: could not open file '${opts.file}'
|
|
1019
|
+
`);
|
|
1020
|
+
process.exit(1);
|
|
1021
|
+
return;
|
|
1022
|
+
}
|
|
1023
|
+
filename = opts.file;
|
|
1024
|
+
} else {
|
|
1025
|
+
input = readStdin();
|
|
1026
|
+
filename = "<stdin>";
|
|
1027
|
+
}
|
|
1028
|
+
const parser = new JsonParser;
|
|
1029
|
+
if (opts.compact) {
|
|
1030
|
+
parser.parseError = (str, hash) => {
|
|
1031
|
+
const line = hash.line;
|
|
1032
|
+
const col = hash.loc.last_column;
|
|
1033
|
+
const found = hash.token === "EOF" ? "EOF" : hash.text || hash.token;
|
|
1034
|
+
const expected = hash.expected.join(", ");
|
|
1035
|
+
const msg = `${filename}: line ${line}, col ${col}, found: '${found}' - expected: ${expected}.`;
|
|
1036
|
+
throw new ParseError(msg, hash);
|
|
1037
|
+
};
|
|
1038
|
+
}
|
|
1039
|
+
function formatCompactError(e) {
|
|
1040
|
+
if (opts.compact && e instanceof LexerError) {
|
|
1041
|
+
return `${filename}: line ${e.line}, col ${e.column}, ${e.message.split(`
|
|
1042
|
+
`)[0]}`;
|
|
1043
|
+
}
|
|
1044
|
+
return e instanceof Error ? e.message : String(e);
|
|
1045
|
+
}
|
|
1046
|
+
let parsed;
|
|
1047
|
+
try {
|
|
1048
|
+
parsed = parser.parse(input);
|
|
1049
|
+
} catch (e) {
|
|
1050
|
+
if (opts.prettyPrint) {
|
|
1051
|
+
const formatted = formatJson(input, opts.indent);
|
|
1052
|
+
process.stdout.write(formatted + `
|
|
1053
|
+
`);
|
|
1054
|
+
try {
|
|
1055
|
+
const reformatParser = new JsonParser;
|
|
1056
|
+
if (opts.compact) {
|
|
1057
|
+
reformatParser.parseError = parser.parseError;
|
|
1058
|
+
}
|
|
1059
|
+
reformatParser.parse(formatted);
|
|
1060
|
+
} catch (e2) {
|
|
1061
|
+
process.stderr.write(formatCompactError(e2) + `
|
|
1062
|
+
`);
|
|
1063
|
+
}
|
|
1064
|
+
process.exit(1);
|
|
1065
|
+
return;
|
|
1066
|
+
}
|
|
1067
|
+
process.stderr.write(formatCompactError(e) + `
|
|
1068
|
+
`);
|
|
1069
|
+
process.exit(1);
|
|
1070
|
+
return;
|
|
1071
|
+
}
|
|
1072
|
+
if (opts.validate) {
|
|
1073
|
+
let schemaInput;
|
|
1074
|
+
try {
|
|
1075
|
+
schemaInput = readFileSync(opts.validate, "utf-8");
|
|
1076
|
+
} catch {
|
|
1077
|
+
process.stderr.write(`Error: could not open schema file '${opts.validate}'
|
|
1078
|
+
`);
|
|
1079
|
+
process.exit(1);
|
|
1080
|
+
return;
|
|
1081
|
+
}
|
|
1082
|
+
let schema;
|
|
1083
|
+
try {
|
|
1084
|
+
schema = JSON.parse(schemaInput);
|
|
1085
|
+
} catch {
|
|
1086
|
+
process.stderr.write(`Error: invalid JSON in schema file '${opts.validate}'
|
|
1087
|
+
`);
|
|
1088
|
+
process.exit(1);
|
|
1089
|
+
return;
|
|
1090
|
+
}
|
|
1091
|
+
const validator = new SchemaValidator;
|
|
1092
|
+
const errors = validator.validate(parsed, schema);
|
|
1093
|
+
if (errors.length > 0) {
|
|
1094
|
+
for (const err of errors) {
|
|
1095
|
+
process.stderr.write(`Schema validation error: property '${err.property}': ${err.message}
|
|
1096
|
+
`);
|
|
1097
|
+
}
|
|
1098
|
+
process.exit(1);
|
|
1099
|
+
return;
|
|
1100
|
+
}
|
|
1101
|
+
}
|
|
1102
|
+
if (opts.sortKeys) {
|
|
1103
|
+
parsed = sortObject(parsed);
|
|
1104
|
+
}
|
|
1105
|
+
const output = JSON.stringify(parsed, null, opts.indent);
|
|
1106
|
+
if (opts.inPlace && opts.file) {
|
|
1107
|
+
writeFileSync(opts.file, output + `
|
|
1108
|
+
`, "utf-8");
|
|
1109
|
+
} else if (!opts.quiet) {
|
|
1110
|
+
process.stdout.write(output + `
|
|
1111
|
+
`);
|
|
1112
|
+
}
|
|
1113
|
+
}
|
|
879
1114
|
// src/index.ts
|
|
880
1115
|
var parser = new JsonParser;
|
|
881
1116
|
var formatter = { formatJson };
|
|
882
1117
|
export {
|
|
883
1118
|
parser,
|
|
884
1119
|
parse,
|
|
1120
|
+
main,
|
|
885
1121
|
formatter,
|
|
886
1122
|
formatJson,
|
|
887
1123
|
TokenType,
|
package/build/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const VERSION = "0.0.
|
|
1
|
+
export declare const VERSION = "0.0.3";
|
package/package.json
CHANGED