Repository navigation
Conversation
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved serialization and parsing regressions can lose array values, misclassify commented keys, and break the documented alignment option.
3 open issues
What changed in this PR
This PR addresses scalar keys ending in [] being mistaken for arrays during INI stringify/parse round trips.
Changes:
- Quote scalar keys ending in
[]when bracketed-array mode is enabled. - Treat quoted keys literally during parsing.
- Add a round-trip regression case for a scalar key ending in
[].
| File | Description |
|---|---|
test/bar.js |
Adds a scalar-key round-trip regression case. |
lib/ini.js |
Updates key quoting and array-marker detection. |
Review effort: Balanced
| children.push(k) | ||
| } else { | ||
| out += safe(k).padEnd(padToChars, ' ') + separator + safe(val) + eol | ||
| const safeKey = opt.bracketedArray && k.endsWith('[]') ? JSON.stringify(k) : safe(k) |
There was a problem hiding this comment.
Fixed in 673df11. The width now comes from the same encoded key that is written, so stringify({ 'foo[]': 'bar', x: 'y' }, { align: true }) puts both = in one column. Added a test for it.
| if (opt.bracketedArray) { | ||
| isArray = keyRaw.length > 2 && keyRaw.slice(-2) === '[]' | ||
| const rawKey = match[2].trim() | ||
| isArray = !isQuoted(rawKey) && rawKey.length > 2 && rawKey.slice(-2) === '[]' |
There was a problem hiding this comment.
Fixed in 673df11. The array suffix is checked on the decoded key again, as on main, so flag[] # note gives { flag: [true] } and flag # note[] gives { flag: true }. Both are now tests.
| if (opt.bracketedArray) { | ||
| isArray = keyRaw.length > 2 && keyRaw.slice(-2) === '[]' | ||
| const rawKey = match[2].trim() | ||
| isArray = !isQuoted(rawKey) && rawKey.length > 2 && rawKey.slice(-2) === '[]' |
There was a problem hiding this comment.
Fixed in 673df11. Quoted array keys keep the format main writes ("[foo[]"=first) and still parse as arrays. A scalar key ending in [] is now written as "foo[\u005d", which JSON-decodes to foo[] but does not end in []", so the parser can tell the two apart. Added round-trip cases for { '[foo': ['first', 'second'] } and { '[foo[]': 'bar' }.

ini.parse(ini.stringify(obj))turns a scalar key that ends in[]into an array.stringifywrites{ 'foo[]': 'bar' }asfoo[]=bar, which is thebracketedArrayarray marker, soparsereturns{ foo: ['bar'] }.bracketedArrayis on by default.Fix
stringifywrites such a key as"foo[\u005d"=bar. The JSON string decodes tofoo[], but the raw key does not end in[]".parsetreats a quoted key as an array only when the raw key ends in[]"(or[]'). That is the formstringifyalready uses for array keys that need quoting, such as"[foo[]"=first, so those files parse as before.alignwidth uses the same encoded key.[]itself andbracketedArray: falseare unchanged.Compatibility
Text written by main parses the same with this change. I encoded 1824 objects with main (19 keys such as
[a,a=b, quoted keys and keys with[], times 8 values, as scalar, array and section, with 4 option sets) and parsed the output with both versions: 0 differences. The one change on the parse side is that a quoted key whose final[]is written with escapes, such as"foo[\u005d", is now read as a scalar.Tests
{ 'foo[]': 'bar' },{ '[foo[]': 'bar' }and{ '[foo': ['first', 'second'] }.flag[] # noteandflag # note[].alignwith a key ending in[].Breaking any part of the change fails at least one of them (checked with 7 targeted mutations).
npm testpasses with 100% coverage.