Skip to content

Fix stringify producing unparseable output for quoted multiline strings - #70

Open
afonsojanu wants to merge 1 commit into
hjson:masterfrom
afonsojanu:fix-mlstring-quote-boundary
Open

afonsojanu wants to merge 1 commit into
hjson:masterfrom
afonsojanu:fix-mlstring-quote-boundary

Conversation

@afonsojanu

Copy link
Copy Markdown

Closes #68

When a string needs quoting and ends up written with the single-line ''' shortcut (used to avoid escaping backslashes, e.g. for regexes), a leading or trailing single quote in the content lands directly against the ''' delimiter with nothing in between. That produces a run of four quote characters at the boundary, and the parser can no longer tell where the content ends and the closing delimiter begins.

const Hjson = require('hjson');
Hjson.stringify({ test: "'Hello,\\nWorld!'" });

currently produces:

{
  test: ''''Hello,\nWorld!''''
}

which throws Bad string containing newline when parsed back.

mlString() now only takes the compact single-line form when the content doesn't start or end with a quote character. When it does, it falls back to the existing block form, where the opening and closing ''' sit on their own line and can never merge with the content.

Added a stringify fixture (mlStrQuote1) with a string that starts with a quote, one that ends with a quote, one with quotes on both sides, and a plain string to confirm the compact form still gets used when there's no boundary issue. All four round-trip correctly through parse -> stringify -> parse now, and the full existing suite still passes.

When a string needs quoting and gets written as a single-line ''' block
(the compact form used to avoid escaping backslashes), a leading or
trailing single quote in the content runs straight into the ''' delimiter
with nothing separating them. That leaves a run of four quote characters
at the boundary, which the parser can't tell apart from the closing
delimiter, so the round trip breaks.

For example, stringifying { test: "'Hello,\nWorld!'" } (backslash
escaped, not a real newline) currently produces:

  { test: ''''Hello,\nWorld!'''' }

which fails to parse back with "Bad string containing newline".

mlString() now only takes the compact single-line shortcut when the
line doesn't start or end with a quote. Otherwise it falls back to the
block form, where the delimiters sit on their own line and can't merge
with the content.

Added a stringify fixture (mlStrQuote1) covering a string that starts
with a quote, one that ends with a quote, and one with quotes on both
ends, plus a plain string to confirm the compact form is unaffected.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Encoder produces broken output for strings starting with a single quote that require escaping

1 participant