json-lint.js 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662
  1. /* Jison generated parser */
  2. let jsonlint = (function () {
  3. var parser = {
  4. trace: function trace() {
  5. },
  6. yy: {},
  7. symbols_: {
  8. "error": 2,
  9. "JSONString": 3,
  10. "STRING": 4,
  11. "JSONNumber": 5,
  12. "NUMBER": 6,
  13. "JSONNullLiteral": 7,
  14. "NULL": 8,
  15. "JSONBooleanLiteral": 9,
  16. "TRUE": 10,
  17. "FALSE": 11,
  18. "JSONText": 12,
  19. "JSONValue": 13,
  20. "EOF": 14,
  21. "JSONObject": 15,
  22. "JSONArray": 16,
  23. "{": 17,
  24. "}": 18,
  25. "JSONMemberList": 19,
  26. "JSONMember": 20,
  27. ":": 21,
  28. ",": 22,
  29. "[": 23,
  30. "]": 24,
  31. "JSONElementList": 25,
  32. "$accept": 0,
  33. "$end": 1
  34. },
  35. terminals_: {
  36. 2: "error",
  37. 4: "STRING",
  38. 6: "NUMBER",
  39. 8: "NULL",
  40. 10: "TRUE",
  41. 11: "FALSE",
  42. 14: "EOF",
  43. 17: "{",
  44. 18: "}",
  45. 21: ":",
  46. 22: ",",
  47. 23: "[",
  48. 24: "]"
  49. },
  50. productions_: [0, [3, 1], [5, 1], [7, 1], [9, 1], [9, 1], [12, 2], [13, 1], [13, 1], [13, 1], [13, 1], [13, 1], [13, 1], [15, 2], [15, 3], [20, 3], [19, 1], [19, 3], [16, 2], [16, 3], [25, 1], [25, 3]],
  51. performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, $$, _$) {
  52. var $0 = $$.length - 1;
  53. switch (yystate) {
  54. case 1: // replace escaped characters with actual character
  55. this.$ = yytext.replace(/\\(\\|")/g, "$" + "1")
  56. .replace(/\\n/g, '\n')
  57. .replace(/\\r/g, '\r')
  58. .replace(/\\t/g, '\t')
  59. .replace(/\\v/g, '\v')
  60. .replace(/\\f/g, '\f')
  61. .replace(/\\b/g, '\b');
  62. break;
  63. case 2:
  64. this.$ = Number(yytext);
  65. break;
  66. case 3:
  67. this.$ = null;
  68. break;
  69. case 4:
  70. this.$ = true;
  71. break;
  72. case 5:
  73. this.$ = false;
  74. break;
  75. case 6:
  76. return this.$ = $$[$0 - 1];
  77. break;
  78. case 13:
  79. this.$ = {};
  80. break;
  81. case 14:
  82. this.$ = $$[$0 - 1];
  83. break;
  84. case 15:
  85. this.$ = [$$[$0 - 2], $$[$0]];
  86. break;
  87. case 16:
  88. this.$ = {};
  89. this.$[$$[$0][0]] = $$[$0][1];
  90. break;
  91. case 17:
  92. this.$ = $$[$0 - 2];
  93. $$[$0 - 2][$$[$0][0]] = $$[$0][1];
  94. break;
  95. case 18:
  96. this.$ = [];
  97. break;
  98. case 19:
  99. this.$ = $$[$0 - 1];
  100. break;
  101. case 20:
  102. this.$ = [$$[$0]];
  103. break;
  104. case 21:
  105. this.$ = $$[$0 - 2];
  106. $$[$0 - 2].push($$[$0]);
  107. break;
  108. }
  109. },
  110. table: [{
  111. 3: 5,
  112. 4: [1, 12],
  113. 5: 6,
  114. 6: [1, 13],
  115. 7: 3,
  116. 8: [1, 9],
  117. 9: 4,
  118. 10: [1, 10],
  119. 11: [1, 11],
  120. 12: 1,
  121. 13: 2,
  122. 15: 7,
  123. 16: 8,
  124. 17: [1, 14],
  125. 23: [1, 15]
  126. }, {1: [3]}, {14: [1, 16]}, {14: [2, 7], 18: [2, 7], 22: [2, 7], 24: [2, 7]}, {
  127. 14: [2, 8],
  128. 18: [2, 8],
  129. 22: [2, 8],
  130. 24: [2, 8]
  131. }, {14: [2, 9], 18: [2, 9], 22: [2, 9], 24: [2, 9]}, {
  132. 14: [2, 10],
  133. 18: [2, 10],
  134. 22: [2, 10],
  135. 24: [2, 10]
  136. }, {14: [2, 11], 18: [2, 11], 22: [2, 11], 24: [2, 11]}, {
  137. 14: [2, 12],
  138. 18: [2, 12],
  139. 22: [2, 12],
  140. 24: [2, 12]
  141. }, {14: [2, 3], 18: [2, 3], 22: [2, 3], 24: [2, 3]}, {
  142. 14: [2, 4],
  143. 18: [2, 4],
  144. 22: [2, 4],
  145. 24: [2, 4]
  146. }, {14: [2, 5], 18: [2, 5], 22: [2, 5], 24: [2, 5]}, {
  147. 14: [2, 1],
  148. 18: [2, 1],
  149. 21: [2, 1],
  150. 22: [2, 1],
  151. 24: [2, 1]
  152. }, {14: [2, 2], 18: [2, 2], 22: [2, 2], 24: [2, 2]}, {3: 20, 4: [1, 12], 18: [1, 17], 19: 18, 20: 19}, {
  153. 3: 5,
  154. 4: [1, 12],
  155. 5: 6,
  156. 6: [1, 13],
  157. 7: 3,
  158. 8: [1, 9],
  159. 9: 4,
  160. 10: [1, 10],
  161. 11: [1, 11],
  162. 13: 23,
  163. 15: 7,
  164. 16: 8,
  165. 17: [1, 14],
  166. 23: [1, 15],
  167. 24: [1, 21],
  168. 25: 22
  169. }, {1: [2, 6]}, {14: [2, 13], 18: [2, 13], 22: [2, 13], 24: [2, 13]}, {18: [1, 24], 22: [1, 25]}, {
  170. 18: [2, 16],
  171. 22: [2, 16]
  172. }, {21: [1, 26]}, {14: [2, 18], 18: [2, 18], 22: [2, 18], 24: [2, 18]}, {
  173. 22: [1, 28],
  174. 24: [1, 27]
  175. }, {22: [2, 20], 24: [2, 20]}, {14: [2, 14], 18: [2, 14], 22: [2, 14], 24: [2, 14]}, {
  176. 3: 20,
  177. 4: [1, 12],
  178. 20: 29
  179. }, {
  180. 3: 5,
  181. 4: [1, 12],
  182. 5: 6,
  183. 6: [1, 13],
  184. 7: 3,
  185. 8: [1, 9],
  186. 9: 4,
  187. 10: [1, 10],
  188. 11: [1, 11],
  189. 13: 30,
  190. 15: 7,
  191. 16: 8,
  192. 17: [1, 14],
  193. 23: [1, 15]
  194. }, {14: [2, 19], 18: [2, 19], 22: [2, 19], 24: [2, 19]}, {
  195. 3: 5,
  196. 4: [1, 12],
  197. 5: 6,
  198. 6: [1, 13],
  199. 7: 3,
  200. 8: [1, 9],
  201. 9: 4,
  202. 10: [1, 10],
  203. 11: [1, 11],
  204. 13: 31,
  205. 15: 7,
  206. 16: 8,
  207. 17: [1, 14],
  208. 23: [1, 15]
  209. }, {18: [2, 17], 22: [2, 17]}, {18: [2, 15], 22: [2, 15]}, {22: [2, 21], 24: [2, 21]}],
  210. defaultActions: {16: [2, 6]},
  211. parseError: function parseError(str, hash) {
  212. throw new Error(str);
  213. },
  214. parse: function parse(input) {
  215. var self = this,
  216. stack = [0],
  217. vstack = [null], // semantic value stack
  218. lstack = [], // location stack
  219. table = this.table,
  220. yytext = '',
  221. yylineno = 0,
  222. yyleng = 0,
  223. recovering = 0,
  224. TERROR = 2,
  225. EOF = 1;
  226. //this.reductionCount = this.shiftCount = 0;
  227. this.lexer.setInput(input);
  228. this.lexer.yy = this.yy;
  229. this.yy.lexer = this.lexer;
  230. if (typeof this.lexer.yylloc == 'undefined')
  231. this.lexer.yylloc = {};
  232. var yyloc = this.lexer.yylloc;
  233. lstack.push(yyloc);
  234. if (typeof this.yy.parseError === 'function')
  235. this.parseError = this.yy.parseError;
  236. function popStack(n) {
  237. stack.length = stack.length - 2 * n;
  238. vstack.length = vstack.length - n;
  239. lstack.length = lstack.length - n;
  240. }
  241. function lex() {
  242. var token;
  243. token = self.lexer.lex() || 1; // $end = 1
  244. // if token isn't its numeric value, convert
  245. if (typeof token !== 'number') {
  246. token = self.symbols_[token] || token;
  247. }
  248. return token;
  249. }
  250. var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected;
  251. while (true) {
  252. // retreive state number from top of stack
  253. state = stack[stack.length - 1];
  254. // use default actions if available
  255. if (this.defaultActions[state]) {
  256. action = this.defaultActions[state];
  257. } else {
  258. if (symbol == null)
  259. symbol = lex();
  260. // read action for current state and first input
  261. action = table[state] && table[state][symbol];
  262. }
  263. // handle parse error
  264. _handle_error:
  265. if (typeof action === 'undefined' || !action.length || !action[0]) {
  266. if (!recovering) {
  267. // Report error
  268. expected = [];
  269. for (p in table[state]) if (this.terminals_[p] && p > 2) {
  270. expected.push("'" + this.terminals_[p] + "'");
  271. }
  272. var errStr = '';
  273. if (this.lexer.showPosition) {
  274. errStr = 'Parse error on line ' + (yylineno + 1) + ":\n" + this.lexer.showPosition() + "\nExpecting " + expected.join(', ') + ", got '" + this.terminals_[symbol] + "'";
  275. } else {
  276. errStr = 'Parse error on line ' + (yylineno + 1) + ": Unexpected " +
  277. (symbol == 1 /*EOF*/ ? "end of input" :
  278. ("'" + (this.terminals_[symbol] || symbol) + "'"));
  279. }
  280. this.parseError(errStr,
  281. {
  282. text: this.lexer.match,
  283. token: this.terminals_[symbol] || symbol,
  284. lineText: this.lexer._sLine,
  285. line: this.lexer.yylineno,
  286. pos: this.lexer._pre,
  287. loc: yyloc,
  288. expected: expected
  289. });
  290. }
  291. // just recovered from another error
  292. if (recovering == 3) {
  293. if (symbol == EOF) {
  294. throw new Error(errStr || 'Parsing halted.');
  295. }
  296. // discard current lookahead and grab another
  297. yyleng = this.lexer.yyleng;
  298. yytext = this.lexer.yytext;
  299. yylineno = this.lexer.yylineno;
  300. yyloc = this.lexer.yylloc;
  301. symbol = lex();
  302. }
  303. // try to recover from error
  304. while (1) {
  305. // check for error recovery rule in this state
  306. if ((TERROR.toString()) in table[state]) {
  307. break;
  308. }
  309. if (state == 0) {
  310. throw new Error(errStr || 'Parsing halted.');
  311. }
  312. popStack(1);
  313. state = stack[stack.length - 1];
  314. }
  315. preErrorSymbol = symbol; // save the lookahead token
  316. symbol = TERROR; // insert generic error symbol as new lookahead
  317. state = stack[stack.length - 1];
  318. action = table[state] && table[state][TERROR];
  319. recovering = 3; // allow 3 real symbols to be shifted before reporting a new error
  320. }
  321. // this shouldn't happen, unless resolve defaults are off
  322. if (action[0] instanceof Array && action.length > 1) {
  323. throw new Error('Parse Error: multiple actions possible at state: ' + state + ', token: ' + symbol);
  324. }
  325. switch (action[0]) {
  326. case 1: // shift
  327. //this.shiftCount++;
  328. stack.push(symbol);
  329. vstack.push(this.lexer.yytext);
  330. lstack.push(this.lexer.yylloc);
  331. stack.push(action[1]); // push state
  332. symbol = null;
  333. if (!preErrorSymbol) { // normal execution/no error
  334. yyleng = this.lexer.yyleng;
  335. yytext = this.lexer.yytext;
  336. yylineno = this.lexer.yylineno;
  337. yyloc = this.lexer.yylloc;
  338. if (recovering > 0)
  339. recovering--;
  340. } else { // error just occurred, resume old lookahead f/ before error
  341. symbol = preErrorSymbol;
  342. preErrorSymbol = null;
  343. }
  344. break;
  345. case 2: // reduce
  346. //this.reductionCount++;
  347. len = this.productions_[action[1]][1];
  348. // perform semantic action
  349. yyval.$ = vstack[vstack.length - len]; // default to $$ = $1
  350. // default location, uses first token for firsts, last for lasts
  351. yyval._$ = {
  352. first_line: lstack[lstack.length - (len || 1)].first_line,
  353. last_line: lstack[lstack.length - 1].last_line,
  354. first_column: lstack[lstack.length - (len || 1)].first_column,
  355. last_column: lstack[lstack.length - 1].last_column
  356. };
  357. r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack);
  358. if (typeof r !== 'undefined') {
  359. return r;
  360. }
  361. // pop off stack
  362. if (len) {
  363. stack = stack.slice(0, -1 * len * 2);
  364. vstack = vstack.slice(0, -1 * len);
  365. lstack = lstack.slice(0, -1 * len);
  366. }
  367. stack.push(this.productions_[action[1]][0]); // push nonterminal (reduce)
  368. vstack.push(yyval.$);
  369. lstack.push(yyval._$);
  370. // goto new state = table[STATE][NONTERMINAL]
  371. newState = table[stack[stack.length - 2]][stack[stack.length - 1]];
  372. stack.push(newState);
  373. break;
  374. case 3: // accept
  375. return true;
  376. }
  377. }
  378. return true;
  379. }
  380. };
  381. /* Jison generated lexer */
  382. var lexer = (function () {
  383. var lexer = ({
  384. EOF: 1,
  385. parseError: function parseError(str, hash) {
  386. if (this.yy.parseError) {
  387. this.yy.parseError(str, hash);
  388. } else {
  389. throw new Error(str);
  390. }
  391. },
  392. setInput: function (input) {
  393. this._input = input;
  394. this._more = this._less = this.done = false;
  395. this.yylineno = this.yyleng = 0;
  396. this.yytext = this.matched = this.match = '';
  397. this.conditionStack = ['INITIAL'];
  398. this.yylloc = {first_line: 1, first_column: 0, last_line: 1, last_column: 0};
  399. return this;
  400. },
  401. input: function () {
  402. var ch = this._input[0];
  403. this.yytext += ch;
  404. this.yyleng++;
  405. this.match += ch;
  406. this.matched += ch;
  407. var lines = ch.match(/\n/);
  408. if (lines) this.yylineno++;
  409. this._input = this._input.slice(1);
  410. return ch;
  411. },
  412. unput: function (ch) {
  413. this._input = ch + this._input;
  414. return this;
  415. },
  416. more: function () {
  417. this._more = true;
  418. return this;
  419. },
  420. less: function (n) {
  421. this._input = this.match.slice(n) + this._input;
  422. },
  423. pastInput: function () {
  424. var past = this.matched.substr(0, this.matched.length - this.match.length);
  425. this._pre = past.slice(past.lastIndexOf('\n')).length - 1;
  426. return (past.length > 20 ? '...' : '') + past.substr(-20).replace(/\n/g, "");
  427. },
  428. upcomingInput: function () {
  429. var next = this.match;
  430. if (next.length < 20) {
  431. next += this._input.substr(0, 20 - next.length);
  432. }
  433. var s = (next.substr(0, 20) + (next.length > 20 ? '...' : '')).replace(/\n/g, "");
  434. return s;
  435. },
  436. showPosition: function () {
  437. var pre = this.pastInput();
  438. var c = new Array(pre.length + 1).join("-");
  439. var sW = this.upcomingInput();
  440. var s = pre + sW;
  441. this._sLine = s;
  442. return s + "\n" + c + "^";
  443. },
  444. next: function () {
  445. if (this.done) {
  446. return this.EOF;
  447. }
  448. if (!this._input) this.done = true;
  449. var token,
  450. match,
  451. tempMatch,
  452. index,
  453. col,
  454. lines;
  455. if (!this._more) {
  456. this.yytext = '';
  457. this.match = '';
  458. }
  459. var rules = this._currentRules();
  460. for (var i = 0; i < rules.length; i++) {
  461. tempMatch = this._input.match(this.rules[rules[i]]);
  462. if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {
  463. match = tempMatch;
  464. index = i;
  465. if (!this.options.flex) break;
  466. }
  467. }
  468. if (match) {
  469. lines = match[0].match(/\n.*/g);
  470. if (lines) this.yylineno += lines.length;
  471. this.yylloc = {
  472. first_line: this.yylloc.last_line,
  473. last_line: this.yylineno + 1,
  474. first_column: this.yylloc.last_column,
  475. last_column: lines ? lines[lines.length - 1].length - 1 : this.yylloc.last_column + match[0].length
  476. }
  477. this.yytext += match[0];
  478. this.match += match[0];
  479. this.yyleng = this.yytext.length;
  480. this._more = false;
  481. this._input = this._input.slice(match[0].length);
  482. this.matched += match[0];
  483. token = this.performAction.call(this, this.yy, this, rules[index], this.conditionStack[this.conditionStack.length - 1]);
  484. if (this.done && this._input) this.done = false;
  485. if (token) return token;
  486. else return;
  487. }
  488. if (this._input === "") {
  489. return this.EOF;
  490. } else {
  491. this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. Unrecognized text.\n' + this.showPosition(),
  492. {
  493. text: "",
  494. token: null,
  495. lineText: this.lexer._sLine,
  496. line: this.yylineno,
  497. pos: this.lexer._pre
  498. });
  499. }
  500. },
  501. lex: function lex() {
  502. var r = this.next();
  503. if (typeof r !== 'undefined') {
  504. return r;
  505. } else {
  506. return this.lex();
  507. }
  508. },
  509. begin: function begin(condition) {
  510. this.conditionStack.push(condition);
  511. },
  512. popState: function popState() {
  513. return this.conditionStack.pop();
  514. },
  515. _currentRules: function _currentRules() {
  516. return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules;
  517. },
  518. topState: function () {
  519. return this.conditionStack[this.conditionStack.length - 2];
  520. },
  521. pushState: function begin(condition) {
  522. this.begin(condition);
  523. }
  524. });
  525. lexer.options = {};
  526. lexer.performAction = function anonymous(yy, yy_, $avoiding_name_collisions, YY_START) {
  527. var YYSTATE = YY_START
  528. switch ($avoiding_name_collisions) {
  529. case 0:/* skip whitespace */
  530. break;
  531. case 1:
  532. return 6
  533. break;
  534. case 2:
  535. yy_.yytext = yy_.yytext.substr(1, yy_.yyleng - 2);
  536. return 4
  537. break;
  538. case 3:
  539. return 17
  540. break;
  541. case 4:
  542. return 18
  543. break;
  544. case 5:
  545. return 23
  546. break;
  547. case 6:
  548. return 24
  549. break;
  550. case 7:
  551. return 22
  552. break;
  553. case 8:
  554. return 21
  555. break;
  556. case 9:
  557. return 10
  558. break;
  559. case 10:
  560. return 11
  561. break;
  562. case 11:
  563. return 8
  564. break;
  565. case 12:
  566. return 14
  567. break;
  568. case 13:
  569. return 'INVALID'
  570. break;
  571. }
  572. };
  573. lexer.rules = [/^(?:\s+)/, /^(?:(-?([0-9]|[1-9][0-9]+))(\.[0-9]+)?([eE][-+]?[0-9]+)?\b)/, /^(?:"(?:\\[\\"bfnrt/]|\\u[a-fA-F0-9]{4}|[^\\\0-\x09\x0a-\x1f"])*")/, /^(?:\{)/, /^(?:\})/, /^(?:\[)/, /^(?:\])/, /^(?:,)/, /^(?::)/, /^(?:true\b)/, /^(?:false\b)/, /^(?:null\b)/, /^(?:$)/, /^(?:.)/];
  574. lexer.conditions = {"INITIAL": {"rules": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13], "inclusive": true}};
  575. return lexer;
  576. })();
  577. parser.lexer = lexer;
  578. return parser;
  579. })();
  580. /**
  581. * json lint entry
  582. * @param sJson
  583. * @returns {{}}
  584. */
  585. let lintDetect = function (sJson) {
  586. let result = {};
  587. let insertErrorFlag = function (s) {
  588. s = s.replace(/^(\s*){([^\s])/, ($0, $1, $2) => ($1 + '{ ' + $2));
  589. s = s.replace(/([\s,]+)([^,:\{\}\[\]\s'"]+)(\s*:)/gm, ($0, $1, $2, $3) => ($1 + '"' + $2 + '"' + $3));
  590. s = s.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
  591. let aLine = s.split('\n');
  592. jsonlint.yy.parseError = function (sError, oError) {
  593. let theLineNum = oError.line === oError.loc.first_line ? oError.line - 1 : oError.line;
  594. let sLine = aLine[theLineNum];
  595. result.line = theLineNum;
  596. result.col = oError.loc.first_column;
  597. aLine[theLineNum] = sLine.slice(0, oError.loc.first_column) +
  598. '@◆$#errorEm#$◆@' + sLine.slice(oError.loc.first_column, oError.loc.last_column) + '@◆$#/errorEm#$◆@' +
  599. sLine.slice(oError.loc.last_column);
  600. };
  601. try {
  602. jsonlint.parse(s);
  603. } catch (e) {
  604. result["hasError"] = true;
  605. }
  606. return aLine.join('\n');
  607. };
  608. let escape = function (s) {
  609. s = s || '';
  610. return s.replace(/\&/g, '&amp;').replace(/\</g, '&lt;').replace(/\>/g, '&gt;').replace(/\"/g, '&quot;').replace(/ /g, '&nbsp;');
  611. };
  612. sJson = insertErrorFlag(sJson);
  613. sJson = escape(sJson);
  614. let placeholder = '<span class="x-ph"><<<<</span>';
  615. sJson = sJson.replace('@◆$#errorEm#$◆@', '<span class="errorEm">').replace('@◆$#/errorEm#$◆@', '</span>' + placeholder);
  616. sJson = '<ol><li><div>' + sJson.split('\n').join('</div></li><li><div>') + '</div></li></ol>';
  617. result["dom"] = '<div class="line-code">' + sJson + '</div>';
  618. return result;
  619. };
  620. window.JsonLint = {
  621. lintDetect: lintDetect
  622. };