44 lines
1.3 KiB
JavaScript
44 lines
1.3 KiB
JavaScript
module.exports = (txt, reviver, context = 20) => {
|
|
try {
|
|
return JSON.parse(txt, reviver);
|
|
} catch (e) {
|
|
handleJsonNotString(txt);
|
|
const syntaxErr = e.message.match(/^Unexpected token.*position\s+(\d+)/i);
|
|
const errIdxBrokenJson = e.message.match(/^Unexpected end of JSON.*/i) ? txt.length - 1 : null;
|
|
const errIdx = syntaxErr ? +syntaxErr[1] : errIdxBrokenJson;
|
|
handleErrIdxNotNull(e, txt, errIdx, context);
|
|
e.offset = errIdx;
|
|
const lines = txt.substr(0, errIdx).split('\n');
|
|
e.startLine = lines.length;
|
|
e.startColumn = lines[lines.length - 1].length;
|
|
throw e;
|
|
}
|
|
};
|
|
|
|
function handleJsonNotString(txt) {
|
|
if (typeof txt !== 'string') {
|
|
const isEmptyArray = Array.isArray(txt) && txt.length === 0;
|
|
const errorMessage = `Cannot parse ${
|
|
isEmptyArray ? 'an empty array' : String(txt)}`;
|
|
throw new TypeError(errorMessage);
|
|
}
|
|
}
|
|
|
|
function handleErrIdxNotNull(e, txt, errIdx, context) {
|
|
if (errIdx !== null) {
|
|
const start = errIdx <= context
|
|
? 0
|
|
: errIdx - context;
|
|
const end = errIdx + context >= txt.length
|
|
? txt.length
|
|
: errIdx + context;
|
|
e.message += ` while parsing near '${
|
|
start === 0 ? '' : '...'
|
|
}${txt.slice(start, end)}${
|
|
end === txt.length ? '' : '...'
|
|
}'`;
|
|
} else {
|
|
e.message += ` while parsing '${txt.slice(0, context * 2)}'`;
|
|
}
|
|
}
|