jsonrepair
Advanced tools
Comparing version 3.8.1 to 3.9.0
@@ -83,3 +83,3 @@ "use strict"; | ||
parseWhitespaceAndSkipComments(); | ||
const processed = parseObject() || parseArray() || parseString() || parseNumber() || parseKeywords() || parseUnquotedString(); | ||
const processed = parseObject() || parseArray() || parseString() || parseNumber() || parseKeywords() || parseUnquotedString(false) || parseRegex(); | ||
parseWhitespaceAndSkipComments(); | ||
@@ -202,3 +202,3 @@ return processed; | ||
skipEllipsis(); | ||
const processedKey = parseString() || parseUnquotedString(); | ||
const processedKey = parseString() || parseUnquotedString(true); | ||
if (!processedKey) { | ||
@@ -317,3 +317,3 @@ if (text.charCodeAt(i) === _stringUtils.codeClosingBrace || text.charCodeAt(i) === _stringUtils.codeOpeningBrace || text.charCodeAt(i) === _stringUtils.codeClosingBracket || text.charCodeAt(i) === _stringUtils.codeOpeningBracket || text[i] === undefined) { | ||
// repair: wrap the output inside array brackets | ||
output = "[\n".concat(output, "\n]"); | ||
output = `[\n${output}\n]`; | ||
} | ||
@@ -399,4 +399,4 @@ | ||
// repair unescaped quote | ||
str = "".concat(str.substring(0, oQuote), "\\").concat(str.substring(oQuote)); | ||
} else if (stopAtDelimiter && (0, _stringUtils.isDelimiter)(text[i])) { | ||
str = `${str.substring(0, oQuote)}\\${str.substring(oQuote)}`; | ||
} else if (stopAtDelimiter && (0, _stringUtils.isUnquotedStringDelimiter)(text[i])) { | ||
// we're in the mode to stop the string at the first delimiter | ||
@@ -443,3 +443,3 @@ // because there is an end quote missing | ||
// repair unescaped double quote | ||
str += "\\".concat(char); | ||
str += `\\${char}`; | ||
i++; | ||
@@ -558,3 +558,3 @@ } else if ((0, _stringUtils.isControlCharacter)(code)) { | ||
const hasInvalidLeadingZero = /^0\d/.test(num); | ||
output += hasInvalidLeadingZero ? "\"".concat(num, "\"") : num; | ||
output += hasInvalidLeadingZero ? `"${num}"` : num; | ||
return true; | ||
@@ -588,14 +588,18 @@ } | ||
*/ | ||
function parseUnquotedString() { | ||
function parseUnquotedString(isKey) { | ||
// note that the symbol can end with whitespaces: we stop at the next delimiter | ||
// also, note that we allow strings to contain a slash / in order to support repairing regular expressions | ||
const start = i; | ||
while (i < text.length && !(0, _stringUtils.isDelimiterExceptSlash)(text[i]) && !(0, _stringUtils.isQuote)(text.charCodeAt(i))) { | ||
i++; | ||
} | ||
if (i > start) { | ||
if (text.charCodeAt(i) === _stringUtils.codeOpenParenthesis && (0, _stringUtils.isFunctionName)(text.slice(start, i).trim())) { | ||
if (_stringUtils.regexFunctionNameCharStart.test(text[i])) { | ||
while (i < text.length && _stringUtils.regexFunctionNameChar.test(text[i])) { | ||
i++; | ||
} | ||
let j = i; | ||
while ((0, _stringUtils.isWhitespace)(text.charCodeAt(j))) { | ||
j++; | ||
} | ||
if (text[j] === '(') { | ||
// repair a MongoDB function call like NumberLong("2") | ||
// repair a JSONP function call like callback({...}); | ||
i++; | ||
i = j + 1; | ||
parseValue(); | ||
@@ -611,21 +615,36 @@ if (text.charCodeAt(i) === _stringUtils.codeCloseParenthesis) { | ||
return true; | ||
// biome-ignore lint/style/noUselessElse: <explanation> | ||
} else { | ||
// repair unquoted string | ||
// also, repair undefined into null | ||
} | ||
} | ||
while (i < text.length && !(0, _stringUtils.isUnquotedStringDelimiter)(text[i]) && !(0, _stringUtils.isQuote)(text.charCodeAt(i)) && (!isKey || text[i] !== ':')) { | ||
i++; | ||
} | ||
if (i > start) { | ||
// repair unquoted string | ||
// also, repair undefined into null | ||
// first, go back to prevent getting trailing whitespaces in the string | ||
while ((0, _stringUtils.isWhitespace)(text.charCodeAt(i - 1)) && i > 0) { | ||
i--; | ||
} | ||
const symbol = text.slice(start, i); | ||
output += symbol === 'undefined' ? 'null' : JSON.stringify(symbol); | ||
if (text.charCodeAt(i) === _stringUtils.codeDoubleQuote) { | ||
// we had a missing start quote, but now we encountered the end quote, so we can skip that one | ||
i++; | ||
} | ||
return true; | ||
// first, go back to prevent getting trailing whitespaces in the string | ||
while ((0, _stringUtils.isWhitespace)(text.charCodeAt(i - 1)) && i > 0) { | ||
i--; | ||
} | ||
const symbol = text.slice(start, i); | ||
output += symbol === 'undefined' ? 'null' : JSON.stringify(symbol); | ||
if (text.charCodeAt(i) === _stringUtils.codeDoubleQuote) { | ||
// we had a missing start quote, but now we encountered the end quote, so we can skip that one | ||
i++; | ||
} | ||
return true; | ||
} | ||
} | ||
function parseRegex() { | ||
if (text[i] === '/') { | ||
const start = i; | ||
i++; | ||
while (i < text.length && (text[i] !== '/' || text[i - 1] === '\\')) { | ||
i++; | ||
} | ||
i++; | ||
output += `"${text.substring(start, i)}"`; | ||
return true; | ||
} | ||
} | ||
function prevNonWhitespaceIndex(start) { | ||
@@ -645,9 +664,9 @@ let prev = start; | ||
// change the number more than it needs to make it valid JSON | ||
output += "".concat(text.slice(start, i), "0"); | ||
output += `${text.slice(start, i)}0`; | ||
} | ||
function throwInvalidCharacter(char) { | ||
throw new _JSONRepairError.JSONRepairError("Invalid character ".concat(JSON.stringify(char)), i); | ||
throw new _JSONRepairError.JSONRepairError(`Invalid character ${JSON.stringify(char)}`, i); | ||
} | ||
function throwUnexpectedCharacter() { | ||
throw new _JSONRepairError.JSONRepairError("Unexpected character ".concat(JSON.stringify(text[i])), i); | ||
throw new _JSONRepairError.JSONRepairError(`Unexpected character ${JSON.stringify(text[i])}`, i); | ||
} | ||
@@ -665,3 +684,3 @@ function throwUnexpectedEnd() { | ||
const chars = text.slice(i, i + 6); | ||
throw new _JSONRepairError.JSONRepairError("Invalid unicode character \"".concat(chars, "\""), i); | ||
throw new _JSONRepairError.JSONRepairError(`Invalid unicode character "${chars}"`, i); | ||
} | ||
@@ -668,0 +687,0 @@ } |
@@ -14,7 +14,7 @@ "use strict"; | ||
if (index < offset) { | ||
throw new Error("".concat(indexOutOfRangeMessage, " (index: ").concat(index, ", offset: ").concat(offset, ")")); | ||
throw new Error(`${indexOutOfRangeMessage} (index: ${index}, offset: ${offset})`); | ||
} | ||
if (index >= currentLength) { | ||
if (!closed) { | ||
throw new Error("".concat(indexOutOfRangeMessage, " (index: ").concat(index, ")")); | ||
throw new Error(`${indexOutOfRangeMessage} (index: ${index})`); | ||
} | ||
@@ -21,0 +21,0 @@ } |
@@ -39,3 +39,3 @@ "use strict"; | ||
if (offset > 0) { | ||
throw new Error("Cannot unshift: ".concat(flushedMessage)); | ||
throw new Error(`Cannot unshift: ${flushedMessage}`); | ||
} | ||
@@ -47,3 +47,3 @@ buffer = text + buffer; | ||
if (start < offset) { | ||
throw new Error("Cannot remove: ".concat(flushedMessage)); | ||
throw new Error(`Cannot remove: ${flushedMessage}`); | ||
} | ||
@@ -58,3 +58,3 @@ if (end !== undefined) { | ||
if (index < offset) { | ||
throw new Error("Cannot insert: ".concat(flushedMessage)); | ||
throw new Error(`Cannot insert: ${flushedMessage}`); | ||
} | ||
@@ -89,3 +89,3 @@ buffer = buffer.substring(0, index - offset) + text + buffer.substring(index - offset); | ||
if (bufferIndex <= 0) { | ||
throw new Error("Cannot insert: ".concat(flushedMessage)); | ||
throw new Error(`Cannot insert: ${flushedMessage}`); | ||
} | ||
@@ -92,0 +92,0 @@ buffer = buffer.substring(0, bufferIndex) + textToInsert + buffer.substring(bufferIndex); |
@@ -132,3 +132,3 @@ "use strict"; | ||
function parseValue() { | ||
return parseObjectStart() || parseArrayStart() || parseString() || parseNumber() || parseKeywords() || parseRepairUnquotedString(); | ||
return parseObjectStart() || parseArrayStart() || parseString() || parseNumber() || parseKeywords() || parseRepairUnquotedString() || parseRepairRegex(); | ||
} | ||
@@ -164,13 +164,23 @@ function parseObjectStart() { | ||
function parseRepairUnquotedString() { | ||
const unquotedStringEnd = findNextDelimiter(); | ||
let j = i; | ||
if (_stringUtils.regexFunctionNameCharStart.test(input.charAt(j))) { | ||
while (!input.isEnd(j) && _stringUtils.regexFunctionNameChar.test(input.charAt(j))) { | ||
j++; | ||
} | ||
let k = j; | ||
while ((0, _stringUtils.isWhitespace)(input.charCodeAt(k))) { | ||
k++; | ||
} | ||
if (input.charCodeAt(k) === _stringUtils.codeOpenParenthesis) { | ||
// repair a MongoDB function call like NumberLong("2") | ||
// repair a JSONP function call like callback({...}); | ||
k++; | ||
i = k; | ||
return stack.push(_stack.StackType.functionCall, _stack.Caret.beforeValue); | ||
} | ||
} | ||
const unquotedStringEnd = findNextDelimiter(false, j); | ||
if (unquotedStringEnd !== null) { | ||
const symbol = input.substring(i, unquotedStringEnd); | ||
i = unquotedStringEnd; | ||
if (skipCharacter(_stringUtils.codeOpenParenthesis) && (0, _stringUtils.isFunctionName)(symbol.trim())) { | ||
// A MongoDB function call like NumberLong("2") | ||
// Or a JSONP function call like callback({...}); | ||
// we strip the function call | ||
return stack.push(_stack.StackType.functionCall, _stack.Caret.beforeValue); | ||
} | ||
output.push(symbol === 'undefined' ? 'null' : JSON.stringify(symbol)); | ||
@@ -185,2 +195,14 @@ if (input.charCodeAt(i) === _stringUtils.codeDoubleQuote) { | ||
} | ||
function parseRepairRegex() { | ||
if (input.charAt(i) === '/') { | ||
const start = i; | ||
i++; | ||
while (!input.isEnd(i) && (input.charAt(i) !== '/' || input.charAt(i - 1) === '\\')) { | ||
i++; | ||
} | ||
i++; | ||
output.push(`"${input.substring(start, i)}"`); | ||
return stack.update(_stack.Caret.afterValue); | ||
} | ||
} | ||
function parseRepairMissingObjectValue() { | ||
@@ -493,3 +515,3 @@ // repair missing object value | ||
output.insertAt(oQuote, '\\'); | ||
} else if (stopAtDelimiter && (0, _stringUtils.isDelimiter)(input.charAt(i))) { | ||
} else if (stopAtDelimiter && (0, _stringUtils.isUnquotedStringDelimiter)(input.charAt(i))) { | ||
// we're in the mode to stop the string at the first delimiter | ||
@@ -535,3 +557,3 @@ // because there is an end quote missing | ||
// repair unescaped double quote | ||
output.push("\\".concat(char)); | ||
output.push(`\\${char}`); | ||
i++; | ||
@@ -650,3 +672,3 @@ } else if ((0, _stringUtils.isControlCharacter)(code)) { | ||
const hasInvalidLeadingZero = /^0\d/.test(num); | ||
output.push(hasInvalidLeadingZero ? "\"".concat(num, "\"") : num); | ||
output.push(hasInvalidLeadingZero ? `"${num}"` : num); | ||
return stack.update(_stack.Caret.afterValue); | ||
@@ -675,3 +697,3 @@ } | ||
function parseUnquotedKey() { | ||
let end = findNextDelimiter(); | ||
let end = findNextDelimiter(true, i); | ||
if (end !== null) { | ||
@@ -693,7 +715,7 @@ // first, go back to prevent getting trailing whitespaces in the string | ||
} | ||
function findNextDelimiter() { | ||
function findNextDelimiter(isKey, start) { | ||
// note that the symbol can end with whitespaces: we stop at the next delimiter | ||
// also, note that we allow strings to contain a slash / in order to support repairing regular expressions | ||
let j = i; | ||
while (!input.isEnd(j) && !(0, _stringUtils.isDelimiterExceptSlash)(input.charAt(j)) && !(0, _stringUtils.isQuote)(input.charCodeAt(j))) { | ||
let j = start; | ||
while (!input.isEnd(j) && !(0, _stringUtils.isUnquotedStringDelimiter)(input.charAt(j)) && !(0, _stringUtils.isQuote)(input.charCodeAt(j)) && (!isKey || input.charAt(j) !== ':')) { | ||
j++; | ||
@@ -717,9 +739,9 @@ } | ||
// change the number more than it needs to make it valid JSON | ||
output.push("".concat(input.substring(start, i), "0")); | ||
output.push(`${input.substring(start, i)}0`); | ||
} | ||
function throwInvalidCharacter(char) { | ||
throw new _JSONRepairError.JSONRepairError("Invalid character ".concat(JSON.stringify(char)), i); | ||
throw new _JSONRepairError.JSONRepairError(`Invalid character ${JSON.stringify(char)}`, i); | ||
} | ||
function throwUnexpectedCharacter() { | ||
throw new _JSONRepairError.JSONRepairError("Unexpected character ".concat(JSON.stringify(input.charAt(i))), i); | ||
throw new _JSONRepairError.JSONRepairError(`Unexpected character ${JSON.stringify(input.charAt(i))}`, i); | ||
} | ||
@@ -737,3 +759,3 @@ function throwUnexpectedEnd() { | ||
const chars = input.substring(i, i + 6); | ||
throw new _JSONRepairError.JSONRepairError("Invalid unicode character \"".concat(chars, "\""), i); | ||
throw new _JSONRepairError.JSONRepairError(`Invalid unicode character "${chars}"`, i); | ||
} | ||
@@ -740,0 +762,0 @@ function atEndOfBlockComment(i) { |
@@ -12,4 +12,4 @@ "use strict"; | ||
onData: chunk => transform.push(chunk), | ||
bufferSize: options === null || options === void 0 ? void 0 : options.bufferSize, | ||
chunkSize: options === null || options === void 0 ? void 0 : options.chunkSize | ||
bufferSize: options?.bufferSize, | ||
chunkSize: options?.chunkSize | ||
}); | ||
@@ -16,0 +16,0 @@ const transform = new _nodeStream.Transform({ |
@@ -9,3 +9,3 @@ "use strict"; | ||
constructor(message, position) { | ||
super("".concat(message, " at position ").concat(position)); | ||
super(`${message} at position ${position}`); | ||
this.position = position; | ||
@@ -12,0 +12,0 @@ } |
@@ -11,7 +11,5 @@ "use strict"; | ||
exports.isDelimiter = isDelimiter; | ||
exports.isDelimiterExceptSlash = isDelimiterExceptSlash; | ||
exports.isDigit = isDigit; | ||
exports.isDoubleQuote = isDoubleQuote; | ||
exports.isDoubleQuoteLike = isDoubleQuoteLike; | ||
exports.isFunctionName = isFunctionName; | ||
exports.isHex = isHex; | ||
@@ -23,4 +21,6 @@ exports.isQuote = isQuote; | ||
exports.isStartOfValue = isStartOfValue; | ||
exports.isUnquotedStringDelimiter = isUnquotedStringDelimiter; | ||
exports.isValidStringCharacter = isValidStringCharacter; | ||
exports.isWhitespace = isWhitespace; | ||
exports.regexFunctionNameCharStart = exports.regexFunctionNameChar = void 0; | ||
exports.removeAtIndex = removeAtIndex; | ||
@@ -85,4 +85,7 @@ exports.stripLastOccurrence = stripLastOccurrence; | ||
const regexDelimiter = /^[,:[\]/{}()\n+]$/; | ||
function isDelimiterExceptSlash(char) { | ||
return isDelimiter(char) && char !== '/'; | ||
const regexUnquotedStringDelimiter = /^[,[\]/{}\n+]$/; | ||
const regexFunctionNameCharStart = exports.regexFunctionNameCharStart = /^[a-zA-Z_$]$/; | ||
const regexFunctionNameChar = exports.regexFunctionNameChar = /^[a-zA-Z_$0-9]$/; | ||
function isUnquotedStringDelimiter(char) { | ||
return regexUnquotedStringDelimiter.test(char); | ||
} | ||
@@ -186,5 +189,2 @@ function isStartOfValue(char) { | ||
} | ||
function isFunctionName(text) { | ||
return /^\w+$/.test(text); | ||
} | ||
//# sourceMappingURL=stringUtils.js.map |
import { JSONRepairError } from '../utils/JSONRepairError.js'; | ||
import { codeAsterisk, codeBackslash, codeCloseParenthesis, codeClosingBrace, codeClosingBracket, codeColon, codeComma, codeDot, codeDoubleQuote, codeLowercaseE, codeMinus, codeNewline, codeOpenParenthesis, codeOpeningBrace, codeOpeningBracket, codePlus, codeSemicolon, codeSlash, codeUppercaseE, endsWithCommaOrNewline, insertBeforeLastWhitespace, isControlCharacter, isDelimiter, isDelimiterExceptSlash, isDigit, isDoubleQuote, isDoubleQuoteLike, isFunctionName, isHex, isQuote, isSingleQuote, isSingleQuoteLike, isSpecialWhitespace, isStartOfValue, isValidStringCharacter, isWhitespace, removeAtIndex, stripLastOccurrence } from '../utils/stringUtils.js'; | ||
import { codeAsterisk, codeBackslash, codeCloseParenthesis, codeClosingBrace, codeClosingBracket, codeColon, codeComma, codeDot, codeDoubleQuote, codeLowercaseE, codeMinus, codeNewline, codeOpeningBrace, codeOpeningBracket, codePlus, codeSemicolon, codeSlash, codeUppercaseE, endsWithCommaOrNewline, insertBeforeLastWhitespace, isControlCharacter, isDelimiter, isDigit, isDoubleQuote, isDoubleQuoteLike, isHex, isQuote, isSingleQuote, isSingleQuoteLike, isSpecialWhitespace, isStartOfValue, isUnquotedStringDelimiter, isValidStringCharacter, isWhitespace, regexFunctionNameChar, regexFunctionNameCharStart, removeAtIndex, stripLastOccurrence } from '../utils/stringUtils.js'; | ||
const controlCharacters = { | ||
@@ -77,3 +77,3 @@ '\b': '\\b', | ||
parseWhitespaceAndSkipComments(); | ||
const processed = parseObject() || parseArray() || parseString() || parseNumber() || parseKeywords() || parseUnquotedString(); | ||
const processed = parseObject() || parseArray() || parseString() || parseNumber() || parseKeywords() || parseUnquotedString(false) || parseRegex(); | ||
parseWhitespaceAndSkipComments(); | ||
@@ -196,3 +196,3 @@ return processed; | ||
skipEllipsis(); | ||
const processedKey = parseString() || parseUnquotedString(); | ||
const processedKey = parseString() || parseUnquotedString(true); | ||
if (!processedKey) { | ||
@@ -311,3 +311,3 @@ if (text.charCodeAt(i) === codeClosingBrace || text.charCodeAt(i) === codeOpeningBrace || text.charCodeAt(i) === codeClosingBracket || text.charCodeAt(i) === codeOpeningBracket || text[i] === undefined) { | ||
// repair: wrap the output inside array brackets | ||
output = "[\n".concat(output, "\n]"); | ||
output = `[\n${output}\n]`; | ||
} | ||
@@ -393,4 +393,4 @@ | ||
// repair unescaped quote | ||
str = "".concat(str.substring(0, oQuote), "\\").concat(str.substring(oQuote)); | ||
} else if (stopAtDelimiter && isDelimiter(text[i])) { | ||
str = `${str.substring(0, oQuote)}\\${str.substring(oQuote)}`; | ||
} else if (stopAtDelimiter && isUnquotedStringDelimiter(text[i])) { | ||
// we're in the mode to stop the string at the first delimiter | ||
@@ -437,3 +437,3 @@ // because there is an end quote missing | ||
// repair unescaped double quote | ||
str += "\\".concat(char); | ||
str += `\\${char}`; | ||
i++; | ||
@@ -552,3 +552,3 @@ } else if (isControlCharacter(code)) { | ||
const hasInvalidLeadingZero = /^0\d/.test(num); | ||
output += hasInvalidLeadingZero ? "\"".concat(num, "\"") : num; | ||
output += hasInvalidLeadingZero ? `"${num}"` : num; | ||
return true; | ||
@@ -582,14 +582,18 @@ } | ||
*/ | ||
function parseUnquotedString() { | ||
function parseUnquotedString(isKey) { | ||
// note that the symbol can end with whitespaces: we stop at the next delimiter | ||
// also, note that we allow strings to contain a slash / in order to support repairing regular expressions | ||
const start = i; | ||
while (i < text.length && !isDelimiterExceptSlash(text[i]) && !isQuote(text.charCodeAt(i))) { | ||
i++; | ||
} | ||
if (i > start) { | ||
if (text.charCodeAt(i) === codeOpenParenthesis && isFunctionName(text.slice(start, i).trim())) { | ||
if (regexFunctionNameCharStart.test(text[i])) { | ||
while (i < text.length && regexFunctionNameChar.test(text[i])) { | ||
i++; | ||
} | ||
let j = i; | ||
while (isWhitespace(text.charCodeAt(j))) { | ||
j++; | ||
} | ||
if (text[j] === '(') { | ||
// repair a MongoDB function call like NumberLong("2") | ||
// repair a JSONP function call like callback({...}); | ||
i++; | ||
i = j + 1; | ||
parseValue(); | ||
@@ -605,21 +609,36 @@ if (text.charCodeAt(i) === codeCloseParenthesis) { | ||
return true; | ||
// biome-ignore lint/style/noUselessElse: <explanation> | ||
} else { | ||
// repair unquoted string | ||
// also, repair undefined into null | ||
} | ||
} | ||
while (i < text.length && !isUnquotedStringDelimiter(text[i]) && !isQuote(text.charCodeAt(i)) && (!isKey || text[i] !== ':')) { | ||
i++; | ||
} | ||
if (i > start) { | ||
// repair unquoted string | ||
// also, repair undefined into null | ||
// first, go back to prevent getting trailing whitespaces in the string | ||
while (isWhitespace(text.charCodeAt(i - 1)) && i > 0) { | ||
i--; | ||
} | ||
const symbol = text.slice(start, i); | ||
output += symbol === 'undefined' ? 'null' : JSON.stringify(symbol); | ||
if (text.charCodeAt(i) === codeDoubleQuote) { | ||
// we had a missing start quote, but now we encountered the end quote, so we can skip that one | ||
i++; | ||
} | ||
return true; | ||
// first, go back to prevent getting trailing whitespaces in the string | ||
while (isWhitespace(text.charCodeAt(i - 1)) && i > 0) { | ||
i--; | ||
} | ||
const symbol = text.slice(start, i); | ||
output += symbol === 'undefined' ? 'null' : JSON.stringify(symbol); | ||
if (text.charCodeAt(i) === codeDoubleQuote) { | ||
// we had a missing start quote, but now we encountered the end quote, so we can skip that one | ||
i++; | ||
} | ||
return true; | ||
} | ||
} | ||
function parseRegex() { | ||
if (text[i] === '/') { | ||
const start = i; | ||
i++; | ||
while (i < text.length && (text[i] !== '/' || text[i - 1] === '\\')) { | ||
i++; | ||
} | ||
i++; | ||
output += `"${text.substring(start, i)}"`; | ||
return true; | ||
} | ||
} | ||
function prevNonWhitespaceIndex(start) { | ||
@@ -639,9 +658,9 @@ let prev = start; | ||
// change the number more than it needs to make it valid JSON | ||
output += "".concat(text.slice(start, i), "0"); | ||
output += `${text.slice(start, i)}0`; | ||
} | ||
function throwInvalidCharacter(char) { | ||
throw new JSONRepairError("Invalid character ".concat(JSON.stringify(char)), i); | ||
throw new JSONRepairError(`Invalid character ${JSON.stringify(char)}`, i); | ||
} | ||
function throwUnexpectedCharacter() { | ||
throw new JSONRepairError("Unexpected character ".concat(JSON.stringify(text[i])), i); | ||
throw new JSONRepairError(`Unexpected character ${JSON.stringify(text[i])}`, i); | ||
} | ||
@@ -659,3 +678,3 @@ function throwUnexpectedEnd() { | ||
const chars = text.slice(i, i + 6); | ||
throw new JSONRepairError("Invalid unicode character \"".concat(chars, "\""), i); | ||
throw new JSONRepairError(`Invalid unicode character "${chars}"`, i); | ||
} | ||
@@ -662,0 +681,0 @@ } |
@@ -8,7 +8,7 @@ export function createInputBuffer() { | ||
if (index < offset) { | ||
throw new Error("".concat(indexOutOfRangeMessage, " (index: ").concat(index, ", offset: ").concat(offset, ")")); | ||
throw new Error(`${indexOutOfRangeMessage} (index: ${index}, offset: ${offset})`); | ||
} | ||
if (index >= currentLength) { | ||
if (!closed) { | ||
throw new Error("".concat(indexOutOfRangeMessage, " (index: ").concat(index, ")")); | ||
throw new Error(`${indexOutOfRangeMessage} (index: ${index})`); | ||
} | ||
@@ -15,0 +15,0 @@ } |
@@ -33,3 +33,3 @@ import { isWhitespace } from '../../utils/stringUtils.js'; | ||
if (offset > 0) { | ||
throw new Error("Cannot unshift: ".concat(flushedMessage)); | ||
throw new Error(`Cannot unshift: ${flushedMessage}`); | ||
} | ||
@@ -41,3 +41,3 @@ buffer = text + buffer; | ||
if (start < offset) { | ||
throw new Error("Cannot remove: ".concat(flushedMessage)); | ||
throw new Error(`Cannot remove: ${flushedMessage}`); | ||
} | ||
@@ -52,3 +52,3 @@ if (end !== undefined) { | ||
if (index < offset) { | ||
throw new Error("Cannot insert: ".concat(flushedMessage)); | ||
throw new Error(`Cannot insert: ${flushedMessage}`); | ||
} | ||
@@ -83,3 +83,3 @@ buffer = buffer.substring(0, index - offset) + text + buffer.substring(index - offset); | ||
if (bufferIndex <= 0) { | ||
throw new Error("Cannot insert: ".concat(flushedMessage)); | ||
throw new Error(`Cannot insert: ${flushedMessage}`); | ||
} | ||
@@ -86,0 +86,0 @@ buffer = buffer.substring(0, bufferIndex) + textToInsert + buffer.substring(bufferIndex); |
import { JSONRepairError } from '../utils/JSONRepairError.js'; | ||
import { codeAsterisk, codeBackslash, codeCloseParenthesis, codeClosingBrace, codeClosingBracket, codeColon, codeComma, codeDot, codeDoubleQuote, codeLowercaseE, codeMinus, codeNewline, codeOpenParenthesis, codeOpeningBrace, codeOpeningBracket, codePlus, codeSemicolon, codeSlash, codeUppercaseE, isControlCharacter, isDelimiter, isDelimiterExceptSlash, isDigit, isDoubleQuote, isDoubleQuoteLike, isFunctionName, isHex, isQuote, isSingleQuote, isSingleQuoteLike, isSpecialWhitespace, isStartOfValue, isValidStringCharacter, isWhitespace } from '../utils/stringUtils.js'; | ||
import { codeAsterisk, codeBackslash, codeCloseParenthesis, codeClosingBrace, codeClosingBracket, codeColon, codeComma, codeDot, codeDoubleQuote, codeLowercaseE, codeMinus, codeNewline, codeOpenParenthesis, codeOpeningBrace, codeOpeningBracket, codePlus, codeSemicolon, codeSlash, codeUppercaseE, isControlCharacter, isDelimiter, isDigit, isDoubleQuote, isDoubleQuoteLike, isHex, isQuote, isSingleQuote, isSingleQuoteLike, isSpecialWhitespace, isStartOfValue, isUnquotedStringDelimiter, isValidStringCharacter, isWhitespace, regexFunctionNameChar, regexFunctionNameCharStart } from '../utils/stringUtils.js'; | ||
import { createInputBuffer } from './buffer/InputBuffer.js'; | ||
@@ -126,3 +126,3 @@ import { createOutputBuffer } from './buffer/OutputBuffer.js'; | ||
function parseValue() { | ||
return parseObjectStart() || parseArrayStart() || parseString() || parseNumber() || parseKeywords() || parseRepairUnquotedString(); | ||
return parseObjectStart() || parseArrayStart() || parseString() || parseNumber() || parseKeywords() || parseRepairUnquotedString() || parseRepairRegex(); | ||
} | ||
@@ -158,13 +158,23 @@ function parseObjectStart() { | ||
function parseRepairUnquotedString() { | ||
const unquotedStringEnd = findNextDelimiter(); | ||
let j = i; | ||
if (regexFunctionNameCharStart.test(input.charAt(j))) { | ||
while (!input.isEnd(j) && regexFunctionNameChar.test(input.charAt(j))) { | ||
j++; | ||
} | ||
let k = j; | ||
while (isWhitespace(input.charCodeAt(k))) { | ||
k++; | ||
} | ||
if (input.charCodeAt(k) === codeOpenParenthesis) { | ||
// repair a MongoDB function call like NumberLong("2") | ||
// repair a JSONP function call like callback({...}); | ||
k++; | ||
i = k; | ||
return stack.push(StackType.functionCall, Caret.beforeValue); | ||
} | ||
} | ||
const unquotedStringEnd = findNextDelimiter(false, j); | ||
if (unquotedStringEnd !== null) { | ||
const symbol = input.substring(i, unquotedStringEnd); | ||
i = unquotedStringEnd; | ||
if (skipCharacter(codeOpenParenthesis) && isFunctionName(symbol.trim())) { | ||
// A MongoDB function call like NumberLong("2") | ||
// Or a JSONP function call like callback({...}); | ||
// we strip the function call | ||
return stack.push(StackType.functionCall, Caret.beforeValue); | ||
} | ||
output.push(symbol === 'undefined' ? 'null' : JSON.stringify(symbol)); | ||
@@ -179,2 +189,14 @@ if (input.charCodeAt(i) === codeDoubleQuote) { | ||
} | ||
function parseRepairRegex() { | ||
if (input.charAt(i) === '/') { | ||
const start = i; | ||
i++; | ||
while (!input.isEnd(i) && (input.charAt(i) !== '/' || input.charAt(i - 1) === '\\')) { | ||
i++; | ||
} | ||
i++; | ||
output.push(`"${input.substring(start, i)}"`); | ||
return stack.update(Caret.afterValue); | ||
} | ||
} | ||
function parseRepairMissingObjectValue() { | ||
@@ -487,3 +509,3 @@ // repair missing object value | ||
output.insertAt(oQuote, '\\'); | ||
} else if (stopAtDelimiter && isDelimiter(input.charAt(i))) { | ||
} else if (stopAtDelimiter && isUnquotedStringDelimiter(input.charAt(i))) { | ||
// we're in the mode to stop the string at the first delimiter | ||
@@ -529,3 +551,3 @@ // because there is an end quote missing | ||
// repair unescaped double quote | ||
output.push("\\".concat(char)); | ||
output.push(`\\${char}`); | ||
i++; | ||
@@ -644,3 +666,3 @@ } else if (isControlCharacter(code)) { | ||
const hasInvalidLeadingZero = /^0\d/.test(num); | ||
output.push(hasInvalidLeadingZero ? "\"".concat(num, "\"") : num); | ||
output.push(hasInvalidLeadingZero ? `"${num}"` : num); | ||
return stack.update(Caret.afterValue); | ||
@@ -669,3 +691,3 @@ } | ||
function parseUnquotedKey() { | ||
let end = findNextDelimiter(); | ||
let end = findNextDelimiter(true, i); | ||
if (end !== null) { | ||
@@ -687,7 +709,7 @@ // first, go back to prevent getting trailing whitespaces in the string | ||
} | ||
function findNextDelimiter() { | ||
function findNextDelimiter(isKey, start) { | ||
// note that the symbol can end with whitespaces: we stop at the next delimiter | ||
// also, note that we allow strings to contain a slash / in order to support repairing regular expressions | ||
let j = i; | ||
while (!input.isEnd(j) && !isDelimiterExceptSlash(input.charAt(j)) && !isQuote(input.charCodeAt(j))) { | ||
let j = start; | ||
while (!input.isEnd(j) && !isUnquotedStringDelimiter(input.charAt(j)) && !isQuote(input.charCodeAt(j)) && (!isKey || input.charAt(j) !== ':')) { | ||
j++; | ||
@@ -711,9 +733,9 @@ } | ||
// change the number more than it needs to make it valid JSON | ||
output.push("".concat(input.substring(start, i), "0")); | ||
output.push(`${input.substring(start, i)}0`); | ||
} | ||
function throwInvalidCharacter(char) { | ||
throw new JSONRepairError("Invalid character ".concat(JSON.stringify(char)), i); | ||
throw new JSONRepairError(`Invalid character ${JSON.stringify(char)}`, i); | ||
} | ||
function throwUnexpectedCharacter() { | ||
throw new JSONRepairError("Unexpected character ".concat(JSON.stringify(input.charAt(i))), i); | ||
throw new JSONRepairError(`Unexpected character ${JSON.stringify(input.charAt(i))}`, i); | ||
} | ||
@@ -731,3 +753,3 @@ function throwUnexpectedEnd() { | ||
const chars = input.substring(i, i + 6); | ||
throw new JSONRepairError("Invalid unicode character \"".concat(chars, "\""), i); | ||
throw new JSONRepairError(`Invalid unicode character "${chars}"`, i); | ||
} | ||
@@ -734,0 +756,0 @@ function atEndOfBlockComment(i) { |
@@ -6,4 +6,4 @@ import { Transform } from 'node:stream'; | ||
onData: chunk => transform.push(chunk), | ||
bufferSize: options === null || options === void 0 ? void 0 : options.bufferSize, | ||
chunkSize: options === null || options === void 0 ? void 0 : options.chunkSize | ||
bufferSize: options?.bufferSize, | ||
chunkSize: options?.chunkSize | ||
}); | ||
@@ -10,0 +10,0 @@ const transform = new Transform({ |
export class JSONRepairError extends Error { | ||
constructor(message, position) { | ||
super("".concat(message, " at position ").concat(position)); | ||
super(`${message} at position ${position}`); | ||
this.position = position; | ||
@@ -5,0 +5,0 @@ } |
@@ -58,4 +58,7 @@ export const codeBackslash = 0x5c; // "\" | ||
const regexDelimiter = /^[,:[\]/{}()\n+]$/; | ||
export function isDelimiterExceptSlash(char) { | ||
return isDelimiter(char) && char !== '/'; | ||
const regexUnquotedStringDelimiter = /^[,[\]/{}\n+]$/; | ||
export const regexFunctionNameCharStart = /^[a-zA-Z_$]$/; | ||
export const regexFunctionNameChar = /^[a-zA-Z_$0-9]$/; | ||
export function isUnquotedStringDelimiter(char) { | ||
return regexUnquotedStringDelimiter.test(char); | ||
} | ||
@@ -159,5 +162,2 @@ export function isStartOfValue(char) { | ||
} | ||
export function isFunctionName(text) { | ||
return /^\w+$/.test(text); | ||
} | ||
//# sourceMappingURL=stringUtils.js.map |
@@ -36,3 +36,5 @@ export declare const codeBackslash = 92; | ||
export declare function isDelimiter(char: string): boolean; | ||
export declare function isDelimiterExceptSlash(char: string): boolean; | ||
export declare const regexFunctionNameCharStart: RegExp; | ||
export declare const regexFunctionNameChar: RegExp; | ||
export declare function isUnquotedStringDelimiter(char: string): boolean; | ||
export declare function isStartOfValue(char: string): boolean; | ||
@@ -85,3 +87,2 @@ export declare function isControlCharacter(code: number): code is 8 | 10 | 12 | 9 | 13; | ||
export declare function endsWithCommaOrNewline(text: string): boolean; | ||
export declare function isFunctionName(text: string): boolean; | ||
//# sourceMappingURL=stringUtils.d.ts.map |
@@ -9,3 +9,3 @@ (function (global, factory) { | ||
constructor(message, position) { | ||
super("".concat(message, " at position ").concat(position)); | ||
super(`${message} at position ${position}`); | ||
this.position = position; | ||
@@ -22,3 +22,2 @@ } | ||
const codeClosingBracket = 0x5d; // "]" | ||
const codeOpenParenthesis = 0x28; // "(" | ||
const codeCloseParenthesis = 0x29; // ")" | ||
@@ -73,4 +72,7 @@ const codeSpace = 0x20; // " " | ||
const regexDelimiter = /^[,:[\]/{}()\n+]$/; | ||
function isDelimiterExceptSlash(char) { | ||
return isDelimiter(char) && char !== '/'; | ||
const regexUnquotedStringDelimiter = /^[,[\]/{}\n+]$/; | ||
const regexFunctionNameCharStart = /^[a-zA-Z_$]$/; | ||
const regexFunctionNameChar = /^[a-zA-Z_$0-9]$/; | ||
function isUnquotedStringDelimiter(char) { | ||
return regexUnquotedStringDelimiter.test(char); | ||
} | ||
@@ -174,5 +176,2 @@ function isStartOfValue(char) { | ||
} | ||
function isFunctionName(text) { | ||
return /^\w+$/.test(text); | ||
} | ||
@@ -253,3 +252,3 @@ const controlCharacters = { | ||
parseWhitespaceAndSkipComments(); | ||
const processed = parseObject() || parseArray() || parseString() || parseNumber() || parseKeywords() || parseUnquotedString(); | ||
const processed = parseObject() || parseArray() || parseString() || parseNumber() || parseKeywords() || parseUnquotedString(false) || parseRegex(); | ||
parseWhitespaceAndSkipComments(); | ||
@@ -372,3 +371,3 @@ return processed; | ||
skipEllipsis(); | ||
const processedKey = parseString() || parseUnquotedString(); | ||
const processedKey = parseString() || parseUnquotedString(true); | ||
if (!processedKey) { | ||
@@ -487,3 +486,3 @@ if (text.charCodeAt(i) === codeClosingBrace || text.charCodeAt(i) === codeOpeningBrace || text.charCodeAt(i) === codeClosingBracket || text.charCodeAt(i) === codeOpeningBracket || text[i] === undefined) { | ||
// repair: wrap the output inside array brackets | ||
output = "[\n".concat(output, "\n]"); | ||
output = `[\n${output}\n]`; | ||
} | ||
@@ -569,4 +568,4 @@ | ||
// repair unescaped quote | ||
str = "".concat(str.substring(0, oQuote), "\\").concat(str.substring(oQuote)); | ||
} else if (stopAtDelimiter && isDelimiter(text[i])) { | ||
str = `${str.substring(0, oQuote)}\\${str.substring(oQuote)}`; | ||
} else if (stopAtDelimiter && isUnquotedStringDelimiter(text[i])) { | ||
// we're in the mode to stop the string at the first delimiter | ||
@@ -613,3 +612,3 @@ // because there is an end quote missing | ||
// repair unescaped double quote | ||
str += "\\".concat(char); | ||
str += `\\${char}`; | ||
i++; | ||
@@ -728,3 +727,3 @@ } else if (isControlCharacter(code)) { | ||
const hasInvalidLeadingZero = /^0\d/.test(num); | ||
output += hasInvalidLeadingZero ? "\"".concat(num, "\"") : num; | ||
output += hasInvalidLeadingZero ? `"${num}"` : num; | ||
return true; | ||
@@ -758,14 +757,18 @@ } | ||
*/ | ||
function parseUnquotedString() { | ||
function parseUnquotedString(isKey) { | ||
// note that the symbol can end with whitespaces: we stop at the next delimiter | ||
// also, note that we allow strings to contain a slash / in order to support repairing regular expressions | ||
const start = i; | ||
while (i < text.length && !isDelimiterExceptSlash(text[i]) && !isQuote(text.charCodeAt(i))) { | ||
i++; | ||
} | ||
if (i > start) { | ||
if (text.charCodeAt(i) === codeOpenParenthesis && isFunctionName(text.slice(start, i).trim())) { | ||
if (regexFunctionNameCharStart.test(text[i])) { | ||
while (i < text.length && regexFunctionNameChar.test(text[i])) { | ||
i++; | ||
} | ||
let j = i; | ||
while (isWhitespace(text.charCodeAt(j))) { | ||
j++; | ||
} | ||
if (text[j] === '(') { | ||
// repair a MongoDB function call like NumberLong("2") | ||
// repair a JSONP function call like callback({...}); | ||
i++; | ||
i = j + 1; | ||
parseValue(); | ||
@@ -781,21 +784,36 @@ if (text.charCodeAt(i) === codeCloseParenthesis) { | ||
return true; | ||
// biome-ignore lint/style/noUselessElse: <explanation> | ||
} else { | ||
// repair unquoted string | ||
// also, repair undefined into null | ||
} | ||
} | ||
while (i < text.length && !isUnquotedStringDelimiter(text[i]) && !isQuote(text.charCodeAt(i)) && (!isKey || text[i] !== ':')) { | ||
i++; | ||
} | ||
if (i > start) { | ||
// repair unquoted string | ||
// also, repair undefined into null | ||
// first, go back to prevent getting trailing whitespaces in the string | ||
while (isWhitespace(text.charCodeAt(i - 1)) && i > 0) { | ||
i--; | ||
} | ||
const symbol = text.slice(start, i); | ||
output += symbol === 'undefined' ? 'null' : JSON.stringify(symbol); | ||
if (text.charCodeAt(i) === codeDoubleQuote) { | ||
// we had a missing start quote, but now we encountered the end quote, so we can skip that one | ||
i++; | ||
} | ||
return true; | ||
// first, go back to prevent getting trailing whitespaces in the string | ||
while (isWhitespace(text.charCodeAt(i - 1)) && i > 0) { | ||
i--; | ||
} | ||
const symbol = text.slice(start, i); | ||
output += symbol === 'undefined' ? 'null' : JSON.stringify(symbol); | ||
if (text.charCodeAt(i) === codeDoubleQuote) { | ||
// we had a missing start quote, but now we encountered the end quote, so we can skip that one | ||
i++; | ||
} | ||
return true; | ||
} | ||
} | ||
function parseRegex() { | ||
if (text[i] === '/') { | ||
const start = i; | ||
i++; | ||
while (i < text.length && (text[i] !== '/' || text[i - 1] === '\\')) { | ||
i++; | ||
} | ||
i++; | ||
output += `"${text.substring(start, i)}"`; | ||
return true; | ||
} | ||
} | ||
function prevNonWhitespaceIndex(start) { | ||
@@ -815,9 +833,9 @@ let prev = start; | ||
// change the number more than it needs to make it valid JSON | ||
output += "".concat(text.slice(start, i), "0"); | ||
output += `${text.slice(start, i)}0`; | ||
} | ||
function throwInvalidCharacter(char) { | ||
throw new JSONRepairError("Invalid character ".concat(JSON.stringify(char)), i); | ||
throw new JSONRepairError(`Invalid character ${JSON.stringify(char)}`, i); | ||
} | ||
function throwUnexpectedCharacter() { | ||
throw new JSONRepairError("Unexpected character ".concat(JSON.stringify(text[i])), i); | ||
throw new JSONRepairError(`Unexpected character ${JSON.stringify(text[i])}`, i); | ||
} | ||
@@ -835,3 +853,3 @@ function throwUnexpectedEnd() { | ||
const chars = text.slice(i, i + 6); | ||
throw new JSONRepairError("Invalid unicode character \"".concat(chars, "\""), i); | ||
throw new JSONRepairError(`Invalid unicode character "${chars}"`, i); | ||
} | ||
@@ -838,0 +856,0 @@ } |
@@ -1,1 +0,3 @@ | ||
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).JSONRepair={})}(this,function(t){class x extends Error{constructor(t,e){super("".concat(t," at position ").concat(e)),this.position=e}}let h=125,e=32,y=10,O=9,N=13,J=8,S=12,j=34,r=39,$=48,k=57,d=44,m=65,I=97,T=70,E=102,l=160,R=8192,U=8202,F=8239,q=8287,z=12288,n=8220,o=8221,c=8216,i=8217,a=96,f=180;function B(t){return t>=$&&t<=k}function D(t){return u.test(t)}let u=/^[,:[\]/{}()\n+]$/;function G(t){return s.test(t)||t&&K(t.charCodeAt(0))}let s=/^[[{\w-]$/;function H(t){return t===e||t===y||t===O||t===N}function K(t){return L(t)||P(t)}function L(t){return t===j||t===n||t===o}function M(t){return t===j}function P(t){return t===r||t===c||t===i||t===a||t===f}function Q(t){return t===r}function V(t,e,r){r=2<arguments.length&&void 0!==r&&r,e=t.lastIndexOf(e);return-1!==e?t.substring(0,e)+(r?"":t.substring(e+1)):t}function W(t,e){let r=t.length;if(!H(t.charCodeAt(r-1)))return t+e;for(;H(t.charCodeAt(r-1));)r--;return t.substring(0,r)+e+t.substring(r)}let X={"\b":"\\b","\f":"\\f","\n":"\\n","\r":"\\r","\t":"\\t"},Y={'"':'"',"\\":"\\","/":"/",b:"\b",f:"\f",n:"\n",r:"\r",t:"\t"};t.JSONRepairError=x,t.jsonrepair=function(s){let A=0,C="";if(!c())throw new x("Unexpected end of json string",s.length);var t=i(d);if(t&&g(),G(s[A])&&/[,\n][ \t\r]*$/.test(C)){t||(C=W(C,","));{let t=!0,e=!0;for(;e;)t?t=!1:i(d)||(C=W(C,",")),e=c();e||(C=V(C,","));C="[\n".concat(C,"\n]")}}else t&&(C=V(C,","));for(;s.charCodeAt(A)===h||93===s.charCodeAt(A);)A++,g();if(A>=s.length)return C;throw new x("Unexpected character ".concat(JSON.stringify(s[A])),A);function c(){g();var t=function(){if(123!==s.charCodeAt(A))return!1;{C+="{",A++,g(),v(d)&&g();let e=!0;for(;A<s.length&&s.charCodeAt(A)!==h;){let t;if(e?(t=!0,e=!1):((t=i(d))||(C=W(C,",")),g()),a(),!(b()||f())){s.charCodeAt(A)===h||123===s.charCodeAt(A)||93===s.charCodeAt(A)||91===s.charCodeAt(A)||void 0===s[A]?C=V(C,","):function(){throw new x("Object key expected",A)}();break}g();var r=i(58),n=A>=s.length,o=(r||(G(s[A])||n?C=W(C,":"):u()),c());o||(r||n?C+="null":u())}return s.charCodeAt(A)===h?(C+="}",A++):C=W(C,"}"),!0}}()||function(){if(91!==s.charCodeAt(A))return!1;{C+="[",A++,g(),v(d)&&g();let t=!0;for(;A<s.length&&93!==s.charCodeAt(A);){t?t=!1:i(d)||(C=W(C,",")),a();var e=c();if(!e){C=V(C,",");break}}return 93===s.charCodeAt(A)?(C+="]",A++):C=W(C,"]"),!0}}()||b()||function(){var t=A;if(45===s.charCodeAt(A)){if(A++,n())return o(t),!0;if(!B(s.charCodeAt(A)))return A=t,!1}for(;B(s.charCodeAt(A));)A++;if(46===s.charCodeAt(A)){if(A++,n())return o(t),!0;if(!B(s.charCodeAt(A)))return A=t,!1;for(;B(s.charCodeAt(A));)A++}if(101===s.charCodeAt(A)||69===s.charCodeAt(A)){if(A++,45!==s.charCodeAt(A)&&43!==s.charCodeAt(A)||A++,n())return o(t),!0;if(!B(s.charCodeAt(A)))return A=t,!1;for(;B(s.charCodeAt(A));)A++}var e,r;if(n()){if(A>t)return e=s.slice(t,A),r=/^0\d/.test(e),C+=r?'"'.concat(e,'"'):e,!0}else A=t;return!1}()||r("true","true")||r("false","false")||r("null","null")||r("True","true")||r("False","false")||r("None","null")||f();return g(),t}function g(){A;let t=e();for(;t=(t=function(){if(47===s.charCodeAt(A)&&42===s.charCodeAt(A+1)){for(;A<s.length&&!function(t,e){return"*"===t[e]&&"/"===t[e+1]}(s,A);)A++;A+=2}else{if(47!==s.charCodeAt(A)||47!==s.charCodeAt(A+1))return!1;for(;A<s.length&&s.charCodeAt(A)!==y;)A++}return!0}())&&e(););A}function e(){let t="";for(var e,r;(e=H(s.charCodeAt(A)))||(r=s.charCodeAt(A))===l||r>=R&&r<=U||r===F||r===q||r===z;)t+=e?s[A]:" ",A++;return 0<t.length&&(C+=t,!0)}function i(t){return s.charCodeAt(A)===t&&(C+=s[A],A++,!0)}function v(t){return s.charCodeAt(A)===t&&(A++,!0)}function a(){g(),46===s.charCodeAt(A)&&46===s.charCodeAt(A+1)&&46===s.charCodeAt(A+2)&&(A+=3,g(),v(d))}function b(t){var r,n,o=0<arguments.length&&void 0!==t&&t;let c=92===s.charCodeAt(A);if(c&&(A++,c=!0),K(s.charCodeAt(A))){var i=M(s.charCodeAt(A))?M:Q(s.charCodeAt(A))?Q:P(s.charCodeAt(A))?P:L,a=A,f=C.length;let e='"';for(A++;;){if(A>=s.length)return u=w(A-1),!o&&D(s.charAt(u))?(A=a,C=C.substring(0,f),b(!0)):(e=W(e,'"'),C+=e,!0);if(i(s.charCodeAt(A))){var u=A,h=e.length;if(e+='"',A++,C+=e,g(),o||A>=s.length||D(s.charAt(A))||K(s.charCodeAt(A))||B(s.charCodeAt(A)))return p(),!0;if(D(s.charAt(w(u-1))))return A=a,C=C.substring(0,f),b(!0);C=C.substring(0,f),A=u+1,e="".concat(e.substring(0,h),"\\").concat(e.substring(h))}else{if(o&&D(s[A]))return e=W(e,'"'),C+=e,p(),!0;if(92===s.charCodeAt(A)){h=s.charAt(A+1);if(void 0!==Y[h])e+=s.slice(A,A+2),A+=2;else if("u"===h){let t=2;for(;t<6&&((n=s.charCodeAt(A+t))>=$&&n<=k||n>=m&&n<=T||n>=I&&n<=E);)t++;if(6===t)e+=s.slice(A,A+6),A+=6;else{if(!(A+t>=s.length))throw d=void 0,d=s.slice(A,A+6),new x('Invalid unicode character "'.concat(d,'"'),A);A=s.length}}else e+=h,A+=2}else{var d=s.charAt(A),l=s.charCodeAt(A);if(l===j&&92!==s.charCodeAt(A-1))e+="\\".concat(d);else if((r=l)===y||r===N||r===O||r===J||r===S)e+=X[d];else{if(!(32<=(r=l)&&r<=1114111))throw l=void 0,l=d,new x("Invalid character ".concat(JSON.stringify(l)),A);e+=d}A++}}c&&v(92)}}return!1}function p(){let t=!1;for(g();43===s.charCodeAt(A);){t=!0,A++,g();var e=(C=V(C,'"',!0)).length,r=b();C=r?(r=C,e=e,n=1,r.substring(0,e)+r.substring(e+n)):W(C,'"')}var n;t}function r(t,e){return s.slice(A,A+t.length)===t&&(C+=e,A+=t.length,!0)}function f(){for(var t,e=A;A<s.length&&(!D(t=s[A])||"/"===t)&&!K(s.charCodeAt(A));)A++;if(A>e){if(40===s.charCodeAt(A)&&/^\w+$/.test(s.slice(e,A).trim()))A++,c(),41===s.charCodeAt(A)&&(A++,59===s.charCodeAt(A))&&A++;else{for(;H(s.charCodeAt(A-1))&&0<A;)A--;e=s.slice(e,A);C+="undefined"===e?"null":JSON.stringify(e),s.charCodeAt(A)===j&&A++}return!0}}function w(t){let e=t;for(;0<e&&H(s.charCodeAt(e));)e--;return e}function n(){return A>=s.length||D(s[A])||H(s.charCodeAt(A))}function o(t){C+="".concat(s.slice(t,A),"0")}function u(){throw new x("Colon expected",A)}}}); | ||
((t,e)=>{"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).JSONRepair={})})(this,function(t){class $ extends Error{constructor(t,e){super(t+" at position "+e),this.position=e}}let u=125,e=32,x=10,y=9,O=13,N=8,J=12,S=34,r=39,j=48,k=57,d=44,I=65,T=97,m=70,z=102,l=160,E=8192,R=8202,U=8239,Z=8287,_=12288,n=8220,o=8221,i=8216,c=8217,f=96,a=180;function F(t){return t>=j&&t<=k}function q(t){return h.test(t)}let h=/^[,:[\]/{}()\n+]$/,s=/^[,[\]/{}\n+]$/,W=/^[a-zA-Z_$]$/,X=/^[a-zA-Z_$0-9]$/;function B(t){return s.test(t)}function D(t){return A.test(t)||t&&H(t.charCodeAt(0))}let A=/^[[{\w-]$/;function G(t){return t===e||t===x||t===y||t===O}function H(t){return K(t)||M(t)}function K(t){return t===S||t===n||t===o}function L(t){return t===S}function M(t){return t===r||t===i||t===c||t===f||t===a}function P(t){return t===r}function Q(t,e,r){r=2<arguments.length&&void 0!==r&&r,e=t.lastIndexOf(e);return-1!==e?t.substring(0,e)+(r?"":t.substring(e+1)):t}function V(t,e){let r=t.length;if(!G(t.charCodeAt(r-1)))return t+e;for(;G(t.charCodeAt(r-1));)r--;return t.substring(0,r)+e+t.substring(r)}let Y={"\b":"\\b","\f":"\\f","\n":"\\n","\r":"\\r","\t":"\\t"},tt={'"':'"',"\\":"\\","/":"/",b:"\b",f:"\f",n:"\n",r:"\r",t:"\t"};t.JSONRepairError=$,t.jsonrepair=function(s){let A=0,C="";if(!i())throw new $("Unexpected end of json string",s.length);var t=c(d);if(t&&g(),D(s[A])&&/[,\n][ \t\r]*$/.test(C)){t||(C=V(C,","));{let t=!0,e=!0;for(;e;)t?t=!1:c(d)||(C=V(C,",")),e=i();C=`[ | ||
${C=e?C:Q(C,",")} | ||
]`}}else t&&(C=Q(C,","));for(;s.charCodeAt(A)===u||93===s.charCodeAt(A);)A++,g();if(A>=s.length)return C;throw new $("Unexpected character "+JSON.stringify(s[A]),A);function i(){g();var t=(()=>{if(123!==s.charCodeAt(A))return!1;{C+="{",A++,g(),b(d)&&g();let e=!0;for(;A<s.length&&s.charCodeAt(A)!==u;){let t;if(e?(t=!0,e=!1):((t=c(d))||(C=V(C,",")),g()),f(),!(v()||a(!0))){s.charCodeAt(A)===u||123===s.charCodeAt(A)||93===s.charCodeAt(A)||91===s.charCodeAt(A)||void 0===s[A]?C=Q(C,","):(()=>{throw new $("Object key expected",A)})();break}g();var r=c(58),n=A>=s.length,o=(r||(D(s[A])||n?C=V(C,":"):h()),i());o||(r||n?C+="null":h())}return s.charCodeAt(A)===u?(C+="}",A++):C=V(C,"}"),!0}})()||(()=>{if(91!==s.charCodeAt(A))return!1;{C+="[",A++,g(),b(d)&&g();let t=!0;for(;A<s.length&&93!==s.charCodeAt(A);){t?t=!1:c(d)||(C=V(C,",")),f();var e=i();if(!e){C=Q(C,",");break}}return 93===s.charCodeAt(A)?(C+="]",A++):C=V(C,"]"),!0}})()||v()||(()=>{var t,e,r=A;if(45===s.charCodeAt(A)){if(A++,n())return o(r),!0;if(!F(s.charCodeAt(A)))return A=r,!1}for(;F(s.charCodeAt(A));)A++;if(46===s.charCodeAt(A)){if(A++,n())return o(r),!0;if(!F(s.charCodeAt(A)))return A=r,!1;for(;F(s.charCodeAt(A));)A++}if(101===s.charCodeAt(A)||69===s.charCodeAt(A)){if(A++,45!==s.charCodeAt(A)&&43!==s.charCodeAt(A)||A++,n())return o(r),!0;if(!F(s.charCodeAt(A)))return A=r,!1;for(;F(s.charCodeAt(A));)A++}if(n()){if(A>r)return t=s.slice(r,A),e=/^0\d/.test(t),C+=e?`"${t}"`:t,!0}else A=r;return!1})()||r("true","true")||r("false","false")||r("null","null")||r("True","true")||r("False","false")||r("None","null")||a(!1)||(()=>{if("/"===s[A]){var t=A;for(A++;A<s.length&&("/"!==s[A]||"\\"===s[A-1]);)A++;return A++,C+=`"${s.substring(t,A)}"`,!0}})();return g(),t}function g(){A;let t=e();for(;t=(t=(()=>{if(47===s.charCodeAt(A)&&42===s.charCodeAt(A+1)){for(;A<s.length&&!((t,e)=>"*"===t[e]&&"/"===t[e+1])(s,A);)A++;A+=2}else{if(47!==s.charCodeAt(A)||47!==s.charCodeAt(A+1))return!1;for(;A<s.length&&s.charCodeAt(A)!==x;)A++}return!0})())&&e(););A}function e(){let t="";for(var e,r;(e=G(s.charCodeAt(A)))||(r=s.charCodeAt(A))===l||r>=E&&r<=R||r===U||r===Z||r===_;)t+=e?s[A]:" ",A++;return 0<t.length&&(C+=t,!0)}function c(t){return s.charCodeAt(A)===t&&(C+=s[A],A++,!0)}function b(t){return s.charCodeAt(A)===t&&(A++,!0)}function f(){g(),46===s.charCodeAt(A)&&46===s.charCodeAt(A+1)&&46===s.charCodeAt(A+2)&&(A+=3,g(),b(d))}function v(t){var r,n,o=0<arguments.length&&void 0!==t&&t;let i=92===s.charCodeAt(A);if(i&&(A++,i=!0),H(s.charCodeAt(A))){var c=L(s.charCodeAt(A))?L:P(s.charCodeAt(A))?P:M(s.charCodeAt(A))?M:K,f=A,a=C.length;let e='"';for(A++;;){if(A>=s.length)return h=w(A-1),!o&&q(s.charAt(h))?(A=f,C=C.substring(0,a),v(!0)):(e=V(e,'"'),C+=e,!0);if(c(s.charCodeAt(A))){var h=A,u=e.length;if(e+='"',A++,C+=e,g(),o||A>=s.length||q(s.charAt(A))||H(s.charCodeAt(A))||F(s.charCodeAt(A)))return p(),!0;if(q(s.charAt(w(h-1))))return A=f,C=C.substring(0,a),v(!0);C=C.substring(0,a),A=h+1,e=e.substring(0,u)+"\\"+e.substring(u)}else{if(o&&B(s[A]))return e=V(e,'"'),C+=e,p(),!0;if(92===s.charCodeAt(A)){u=s.charAt(A+1);if(void 0!==tt[u])e+=s.slice(A,A+2),A+=2;else if("u"===u){let t=2;for(;t<6&&((n=s.charCodeAt(A+t))>=j&&n<=k||n>=I&&n<=m||n>=T&&n<=z);)t++;if(6===t)e+=s.slice(A,A+6),A+=6;else{if(!(A+t>=s.length))throw d=void 0,d=s.slice(A,A+6),new $(`Invalid unicode character "${d}"`,A);A=s.length}}else e+=u,A+=2}else{var d=s.charAt(A),l=s.charCodeAt(A);if(l===S&&92!==s.charCodeAt(A-1))e+="\\"+d;else if((r=l)===x||r===O||r===y||r===N||r===J)e+=Y[d];else{if(!(32<=(r=l)&&r<=1114111))throw l=void 0,l=d,new $("Invalid character "+JSON.stringify(l),A);e+=d}A++}}i&&b(92)}}return!1}function p(){let t=!1;for(g();43===s.charCodeAt(A);){t=!0,A++,g();var e=(C=Q(C,'"',!0)).length,r=v();C=r?(r=C,e=e,n=1,r.substring(0,e)+r.substring(e+n)):V(C,'"')}var n;t}function r(t,e){return s.slice(A,A+t.length)===t&&(C+=e,A+=t.length,!0)}function a(t){var e=A;if(W.test(s[A])){for(;A<s.length&&X.test(s[A]);)A++;let t=A;for(;G(s.charCodeAt(t));)t++;if("("===s[t])return A=t+1,i(),41===s.charCodeAt(A)&&(A++,59===s.charCodeAt(A))&&A++,!0}for(;A<s.length&&!B(s[A])&&!H(s.charCodeAt(A))&&(!t||":"!==s[A]);)A++;if(A>e){for(;G(s.charCodeAt(A-1))&&0<A;)A--;e=s.slice(e,A);return C+="undefined"===e?"null":JSON.stringify(e),s.charCodeAt(A)===S&&A++,!0}}function w(t){let e=t;for(;0<e&&G(s.charCodeAt(e));)e--;return e}function n(){return A>=s.length||q(s[A])||G(s.charCodeAt(A))}function o(t){C+=s.slice(t,A)+"0"}function h(){throw new $("Colon expected",A)}}}); |
{ | ||
"name": "jsonrepair", | ||
"version": "3.8.1", | ||
"version": "3.9.0", | ||
"description": "Repair broken JSON documents", | ||
@@ -70,23 +70,23 @@ "repository": { | ||
"devDependencies": { | ||
"@babel/cli": "7.24.7", | ||
"@babel/core": "7.24.7", | ||
"@babel/plugin-transform-typescript": "7.24.7", | ||
"@babel/preset-env": "7.24.7", | ||
"@babel/preset-typescript": "7.24.7", | ||
"@biomejs/biome": "1.9.1", | ||
"@commitlint/cli": "19.3.0", | ||
"@commitlint/config-conventional": "19.2.2", | ||
"@types/node": "20.14.9", | ||
"@babel/cli": "7.25.7", | ||
"@babel/core": "7.25.8", | ||
"@babel/plugin-transform-typescript": "7.25.7", | ||
"@babel/preset-env": "7.25.8", | ||
"@babel/preset-typescript": "7.25.7", | ||
"@biomejs/biome": "1.9.4", | ||
"@commitlint/cli": "19.5.0", | ||
"@commitlint/config-conventional": "19.5.0", | ||
"@types/node": "22.7.7", | ||
"benchmark": "2.1.4", | ||
"cpy-cli": "5.0.0", | ||
"del-cli": "5.1.0", | ||
"husky": "9.0.11", | ||
"del-cli": "6.0.0", | ||
"husky": "9.1.6", | ||
"npm-run-all": "4.1.5", | ||
"rollup": "4.18.0", | ||
"rollup": "4.24.0", | ||
"standard-version": "9.5.0", | ||
"ts-node": "10.9.2", | ||
"typescript": "5.5.3", | ||
"uglify-js": "3.18.0", | ||
"vitest": "1.6.0" | ||
"typescript": "5.6.3", | ||
"uglify-js": "3.19.3", | ||
"vitest": "2.1.3" | ||
} | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
508444
4819