diff --git a/lib/stringToParts.js b/lib/stringToParts.js index a34daa1..f70f333 100644 --- a/lib/stringToParts.js +++ b/lib/stringToParts.js @@ -4,28 +4,45 @@ module.exports = function stringToParts(str) { const result = []; let curPropertyName = ''; - let inSquareBrackets = false; + let state = 'DEFAULT'; for (let i = 0; i < str.length; ++i) { - if (inSquareBrackets && !/\d/.test(str[i]) && str[i] !== ']') { - throw new Error('Can only use numbers in square bracket path notation, got ' + - 'character "' + str[i] + '" in path "' + str + '"'); + // Fall back to treating as property name rather than bracket notation if + // square brackets contains something other than a number. + if (state === 'IN_SQUARE_BRACKETS' && !/\d/.test(str[i]) && str[i] !== ']') { + state = 'DEFAULT'; + curPropertyName = result[result.length - 1] + '[' + curPropertyName; + result.splice(result.length - 1, 1); } - if (str[i] === '.' || str[i] === '[' || str[i] === ']') { - if (str[i] === '[') { - inSquareBrackets = true; - } else if (str[i] === ']') { - inSquareBrackets = false; + if (str[i] === '[') { + if (state !== 'IMMEDIATELY_AFTER_SQUARE_BRACKETS') { + result.push(curPropertyName); + curPropertyName = ''; + } + state = 'IN_SQUARE_BRACKETS'; + } else if (str[i] === ']') { + if (state === 'IN_SQUARE_BRACKETS') { + state = 'IMMEDIATELY_AFTER_SQUARE_BRACKETS'; + result.push(curPropertyName); + curPropertyName = ''; + } else { + state = 'DEFAULT'; + curPropertyName += str[i]; } - if (curPropertyName.length > 0) { + } else if (str[i] === '.') { + if (state !== 'IMMEDIATELY_AFTER_SQUARE_BRACKETS') { result.push(curPropertyName); + curPropertyName = ''; } - curPropertyName = ''; + state = 'DEFAULT'; } else { curPropertyName += str[i]; } } - result.push(curPropertyName); + + if (state !== 'IMMEDIATELY_AFTER_SQUARE_BRACKETS') { + result.push(curPropertyName); + } return result; }; \ No newline at end of file diff --git a/test/stringToParts.js b/test/stringToParts.js index 3758d10..09940df 100644 --- a/test/stringToParts.js +++ b/test/stringToParts.js @@ -11,11 +11,13 @@ describe('stringToParts', function() { it('handles dot notation', function() { assert.deepEqual(stringToParts('a.b.c'), ['a', 'b', 'c']); - assert.deepEqual(stringToParts('a..b.d'), ['a', 'b', 'd']); + assert.deepEqual(stringToParts('a..b.d'), ['a', '', 'b', 'd']); }); - it('throws for invalid numbers in square brackets', function() { - assert.throws(() => stringToParts('foo[1mystring]'), /1mystring/); + it('ignores invalid numbers in square brackets', function() { + assert.deepEqual(stringToParts('foo[1mystring]'), ['foo[1mystring]']); + assert.deepEqual(stringToParts('foo[1mystring].bar[1]'), ['foo[1mystring]', 'bar', '1']); + assert.deepEqual(stringToParts('foo[1mystring][2]'), ['foo[1mystring]', '2']); }); it('handles empty string', function() {