diff --git a/lib/ini.js b/lib/ini.js index beb390d..5836ef7 100644 --- a/lib/ini.js +++ b/lib/ini.js @@ -111,7 +111,7 @@ const decode = (str, opt = {}) => { // section |key = value const re = /^\[([^\]]*)\]\s*$|^([^=]+)(=(.*))?$/i const lines = str.split(/[\r\n]+/g) - const duplicates = {} + let duplicates = {} for (const line of lines) { if (!line || line.match(/^\s*[;#]/) || line.match(/^\s*$/)) { @@ -123,6 +123,9 @@ const decode = (str, opt = {}) => { } if (match[1] !== undefined) { section = unsafe(match[1]) + // Reset duplicates counter for each new section + // so keys are only treated as arrays when duplicated within the same section + duplicates = {} if (section === '__proto__') { // not allowed // keep parsing the section, but don't attach it. diff --git a/test/duplicate-properties.js b/test/duplicate-properties.js index 6f47c91..ef57a3c 100644 --- a/test/duplicate-properties.js +++ b/test/duplicate-properties.js @@ -38,3 +38,43 @@ test('encode duplicate properties with bracketedArray=false', function (t) { t.matchSnapshot(e) t.end() }) + +// Regression test for #298 - same key name across different sections +// should NOT be treated as duplicates +test('bracketedArray=false should scope duplicates per section', function (t) { + const content = ` +[section_1] +var = 1 + +[section_2] +var = 2 +` + const d = i.decode(content, { bracketedArray: false }) + // Both values should be scalars, not arrays, since each key appears + // only once within its own section + t.equal(d.section_1.var, '1', 'section_1.var should be a scalar') + t.equal(d.section_2.var, '2', 'section_2.var should be a scalar') + t.notOk(Array.isArray(d.section_1.var), 'section_1.var should not be an array') + t.notOk(Array.isArray(d.section_2.var), 'section_2.var should not be an array') + t.end() +}) + +test('bracketedArray=false still creates arrays for duplicates within same section', function (t) { + const content = ` +[section_1] +var = 1 +var = 2 +var = 3 + +[section_2] +var = single +` + const d = i.decode(content, { bracketedArray: false }) + // section_1.var should be an array since it has duplicates within the section + t.ok(Array.isArray(d.section_1.var), 'section_1.var should be an array') + t.same(d.section_1.var, ['1', '2', '3'], 'section_1.var should have all values') + // section_2.var should be a scalar since it only appears once + t.equal(d.section_2.var, 'single', 'section_2.var should be a scalar') + t.notOk(Array.isArray(d.section_2.var), 'section_2.var should not be an array') + t.end() +})