UNPKG

ai-json-fixer

Version:

A simple JSON parser designed to handle malformed JSON from Large Language Models

123 lines 4.39 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.removeTrailingContent = removeTrailingContent; /** * Removes trailing content after valid JSON */ function removeTrailingContent(input) { // Track string state and bracket counts let inString = false; let escapeNext = false; let depth = 0; let lastValidJsonEnd = -1; let jsonStarted = false; let currentQuoteChar = ''; for (let i = 0; i < input.length; i++) { const char = input[i]; // Handle escape sequences if (escapeNext) { escapeNext = false; continue; } if (char === '\\' && inString) { escapeNext = true; continue; } // Handle string boundaries if ((char === '"' || char === "'") && !escapeNext) { if (!inString) { inString = true; currentQuoteChar = char; if (!jsonStarted && char === '"') { jsonStarted = true; } } else if (char === currentQuoteChar) { inString = false; currentQuoteChar = ''; // If this was a standalone string (primitive JSON), mark end if (depth === 0 && jsonStarted && char === '"') { lastValidJsonEnd = i + 1; } } continue; } // Skip characters inside strings if (inString) { continue; } // Track depth for objects and arrays if (char === '{' || char === '[') { depth++; jsonStarted = true; } else if (char === '}' || char === ']') { depth--; // If we've returned to depth 0, we might have a complete JSON structure if (depth === 0 && jsonStarted) { lastValidJsonEnd = i + 1; // Check if there are more JSON objects following let j = i + 1; while (j < input.length && /\s/.test(input[j])) { j++; } // If the next non-whitespace character starts a new JSON structure, continue if (j < input.length && (input[j] === '{' || input[j] === '[' || input[j] === '"')) { lastValidJsonEnd = -1; // Reset and continue parsing } } } // Handle primitive JSON values (strings already handled above) if (!jsonStarted && depth === 0) { // Check for numbers if (/\d/.test(char) || (char === '-' && i + 1 < input.length && /\d/.test(input[i + 1]))) { jsonStarted = true; // Find end of number let j = i + 1; while (j < input.length && /[\d.eE+-]/.test(input[j])) { j++; } lastValidJsonEnd = j; i = j - 1; // Skip to end of number continue; } // Check for boolean values and null const remaining = input.substring(i); if (remaining.startsWith('true')) { jsonStarted = true; lastValidJsonEnd = i + 4; i += 3; // Skip to end of 'true' continue; } else if (remaining.startsWith('false')) { jsonStarted = true; lastValidJsonEnd = i + 5; i += 4; // Skip to end of 'false' continue; } else if (remaining.startsWith('null')) { jsonStarted = true; lastValidJsonEnd = i + 4; i += 3; // Skip to end of 'null' continue; } } } // If we found valid JSON, trim to that point if (lastValidJsonEnd > 0) { return input.substring(0, lastValidJsonEnd).trimEnd(); } // If no valid JSON end was found but we're at depth 0, the whole input might be valid if (depth === 0 && jsonStarted) { // Try to parse it to verify try { JSON.parse(input.trim()); return input.trimEnd(); } catch { // Not valid JSON, return as is } } return input; } //# sourceMappingURL=trailing-content-removal.js.map