Skip to content

Commit

Permalink
Replace stripJsonComments() trailing comma regexp
Browse files Browse the repository at this point in the history
I realized after merging #11 that the regular expression at the end of
stripJsonComments() would affect quoted strings. The new
"stripJsonComments > doesn't modify > strings including trailing commas"
test case confirmed this.

The new algorithm took a bit of trial and error, and the existing tests
really helped distill it to its essence. Quite happy with how it turned
out.

Also reorganized the test cases with more `describe` blocks. Added
the new "maintains correct syntax error position info when..." suite to
confirm positional info in JSON.parse errors remains correct.
  • Loading branch information
mbland committed Dec 30, 2023
1 parent 3f64019 commit 40fe838
Show file tree
Hide file tree
Showing 2 changed files with 266 additions and 179 deletions.
31 changes: 16 additions & 15 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -185,14 +185,12 @@ export async function analyzeArgv(argv) {
* @returns {string} jsonStr with comments, trailing commas replaced by space
*/
export function stripJsonComments(jsonStr) {
let inString = false
let escaped = false
let inComment = null
let result = ''
let inString, escaped, inComment, comma, result = []

for (let i = 0; i !== jsonStr.length; ++i) {
const prevChar = i !== 0 ? jsonStr[i-1] : null
const prevChar = jsonStr[i-1]
let curChar = jsonStr[i]
const isNotWhitespace = curChar.trimStart() !== ''

if (inString) {
inString = curChar !== '"' || escaped
Expand All @@ -202,19 +200,22 @@ export function stripJsonComments(jsonStr) {
(inComment === 'block' && prevChar === '*' && curChar === '/')) {
inComment = null
}
if (curChar.trimStart() !== '') curChar = ' '
} else if (curChar === '"') {
if (isNotWhitespace) curChar = ' '
} else if (curChar === '"') { // opening a string
inString = true
} else if (prevChar === '/') {
if (curChar === '/') inComment = 'line'
else if (curChar === '*') inComment = 'block'
if (inComment) curChar = ' ' // otherwise prevChar closed a block comment
} else if (curChar === '/') {
curChar = ' ' // opening a line or block comment
comma = null
} else if (curChar === '/' || curChar === '*') { // maybe opening a comment
if (prevChar === '/') { // definitely opening a comment
inComment = (curChar === '/') ? 'line' : 'block'
curChar = result[i-1] = ' '
}
} else if (isNotWhitespace) { // definitely outside string or comment
if (comma && (curChar === ']' || curChar === '}')) result[comma] = ' '
comma = (curChar === ',') ? i : null
}
result += curChar
result.push(curChar)
}
return result.replaceAll(/,(\s*[\]}])/g, ' $1')
return result.join('')
}

/**
Expand Down

0 comments on commit 40fe838

Please sign in to comment.