index.js 1.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. 'use strict';
  2. const errorEx = require('error-ex');
  3. const fallback = require('json-parse-even-better-errors');
  4. const {default: LinesAndColumns} = require('lines-and-columns');
  5. const {codeFrameColumns} = require('@babel/code-frame');
  6. const JSONError = errorEx('JSONError', {
  7. fileName: errorEx.append('in %s'),
  8. codeFrame: errorEx.append('\n\n%s\n')
  9. });
  10. const parseJson = (string, reviver, filename) => {
  11. if (typeof reviver === 'string') {
  12. filename = reviver;
  13. reviver = null;
  14. }
  15. try {
  16. try {
  17. return JSON.parse(string, reviver);
  18. } catch (error) {
  19. fallback(string, reviver);
  20. throw error;
  21. }
  22. } catch (error) {
  23. error.message = error.message.replace(/\n/g, '');
  24. const indexMatch = error.message.match(/in JSON at position (\d+) while parsing/);
  25. const jsonError = new JSONError(error);
  26. if (filename) {
  27. jsonError.fileName = filename;
  28. }
  29. if (indexMatch && indexMatch.length > 0) {
  30. const lines = new LinesAndColumns(string);
  31. const index = Number(indexMatch[1]);
  32. const location = lines.locationForIndex(index);
  33. const codeFrame = codeFrameColumns(
  34. string,
  35. {start: {line: location.line + 1, column: location.column + 1}},
  36. {highlightCode: true}
  37. );
  38. jsonError.codeFrame = codeFrame;
  39. }
  40. throw jsonError;
  41. }
  42. };
  43. parseJson.JSONError = JSONError;
  44. module.exports = parseJson;