diff --git a/lib/parse.js b/lib/parse.js index a577a22..6fca2e0 100644 --- a/lib/parse.js +++ b/lib/parse.js @@ -32,7 +32,6 @@ module.exports = function (input) { code = value.charCodeAt(next); } while (code <= 32); token = value.slice(pos, next); - pos = next; prev = tokens[tokens.length - 1]; if (code === closeParentheses && balanced) { @@ -42,14 +41,16 @@ module.exports = function (input) { } else if (code === slash || code === comma || code === colon) { before = token; } else { - tokens.push({ type: 'space', value: token }); + tokens.push({ type: 'space', sourceIndex: pos, value: token }); } + pos = next; + // Quotes } else if (code === singleQuote || code === doubleQuote) { next = pos; quote = code === singleQuote ? '\'' : '"'; - token = { type: 'string', quote: quote }; + token = { type: 'string', sourceIndex: pos, quote: quote }; do { escape = false; next = value.indexOf(quote, next + 1); @@ -74,12 +75,13 @@ module.exports = function (input) { // Dividers } else if (code === slash || code === comma || code === colon) { token = value[pos]; - pos += 1; - code = value.charCodeAt(pos); - tokens.push({ type: 'div', value: token, before: before, after: '' }); + tokens.push({ type: 'div', sourceIndex: pos - before.length, value: token, before: before, after: '' }); before = ''; + pos += 1; + code = value.charCodeAt(pos); + // Open parentheses } else if (openParentheses === code) { // Whitespaces after open parentheses @@ -88,7 +90,7 @@ module.exports = function (input) { next += 1; code = value.charCodeAt(next); } while (code <= 32); - token = { type: 'function', value: name, before: value.slice(pos + 1, next) }; + token = { type: 'function', sourceIndex: pos - name.length, value: name, before: value.slice(pos + 1, next) }; pos = next; if (name === 'url' && code !== singleQuote && code !== doubleQuote) { @@ -113,10 +115,10 @@ module.exports = function (input) { whitespacePos -= 1; code = value.charCodeAt(whitespacePos); } while (code <= 32); - token.nodes = [{ type: 'word', value: value.slice(pos, whitespacePos + 1) }]; + token.nodes = [{ type: 'word', sourceIndex: pos, value: value.slice(pos, whitespacePos + 1) }]; if (token.unclosed && whitespacePos + 1 !== next) { token.after = ''; - token.nodes.push({ type: 'space', value: value.slice(whitespacePos + 1, next) }); + token.nodes.push({ type: 'space', sourceIndex: whitespacePos + 1, value: value.slice(whitespacePos + 1, next) }); } else { token.after = value.slice(whitespacePos + 1, next); } @@ -161,13 +163,14 @@ module.exports = function (input) { code === openParentheses || code === closeParentheses && balanced )); token = value.slice(pos, next); - pos = next; if (openParentheses === code) { name = token; } else { - tokens.push({ type: 'word', value: token }); + tokens.push({ type: 'word', sourceIndex: pos, value: token }); } + + pos = next; } } diff --git a/test/index.js b/test/index.js index b7afad5..cba2523 100644 --- a/test/index.js +++ b/test/index.js @@ -28,11 +28,11 @@ test('ValueParser', function (t) { }); t.deepEqual(result, [ - { type: 'function', value: 'fn', before: ' ', after: '', nodes: [] }, - { type: 'function', value: 'fn2', before: ' ', after: '', nodes: [ - { type: 'function', value: 'fn3', before: '', after: '', nodes: [] } + { type: 'function', sourceIndex: 0, value: 'fn', before: ' ', after: '', nodes: [] }, + { type: 'function', sourceIndex: 6, value: 'fn2', before: ' ', after: '', nodes: [ + { type: 'function', sourceIndex: 11, value: 'fn3', before: '', after: '', nodes: [] } ] }, - { type: 'function', value: 'fn3', before: '', after: '', nodes: [] }, + { type: 'function', sourceIndex: 11, value: 'fn3', before: '', after: '', nodes: [] }, ], 'should process all functions'); @@ -48,9 +48,9 @@ test('ValueParser', function (t) { }); t.deepEqual(result, [ - { type: 'function', value: 'fn', before: ' ', after: '', nodes: [] }, - { type: 'function', value: 'fn2', before: ' ', after: '', nodes: [ - { type: 'function', value: 'fn3', before: '', after: '', nodes: [] } + { type: 'function', sourceIndex: 0, value: 'fn', before: ' ', after: '', nodes: [] }, + { type: 'function', sourceIndex: 6, value: 'fn2', before: ' ', after: '', nodes: [ + { type: 'function', sourceIndex: 11, value: 'fn3', before: '', after: '', nodes: [] } ] }, ], 'shouldn\'t process functions after falsy callback'); @@ -65,10 +65,10 @@ test('ValueParser', function (t) { }); t.deepEqual(result, [ - { type: 'function', value: 'fn', before: ' ', after: '', nodes: [] }, - { type: 'space', value: ' '}, - { type: 'word', value: 'fn2', before: ' ', after: '', nodes: [ - { type: 'function', value: 'fn3', before: '', after: '', nodes: [] } + { type: 'function', sourceIndex: 0, value: 'fn', before: ' ', after: '', nodes: [] }, + { type: 'space', sourceIndex: 5, value: ' '}, + { type: 'word', sourceIndex: 6, value: 'fn2', before: ' ', after: '', nodes: [ + { type: 'function', sourceIndex: 11, value: 'fn3', before: '', after: '', nodes: [] } ] }, ], 'shouldn\'t process nodes with defined non-function type'); @@ -82,9 +82,9 @@ test('ValueParser', function (t) { }, true); t.deepEqual(result, [ - { type: 'function', value: 'fn3', before: '', after: '', nodes: [] }, - { type: 'function', value: 'fn2', before: ' ', after: '', nodes: [ - { type: 'function', value: 'fn3', before: '', after: '', nodes: [] } + { type: 'function', sourceIndex: 5, value: 'fn3', before: '', after: '', nodes: [] }, + { type: 'function', sourceIndex: 0, value: 'fn2', before: ' ', after: '', nodes: [ + { type: 'function', sourceIndex: 5, value: 'fn3', before: '', after: '', nodes: [] } ] }, ], 'should process all functions with reverse mode'); }); diff --git a/test/parse.js b/test/parse.js index 01f5d57..5989448 100644 --- a/test/parse.js +++ b/test/parse.js @@ -9,63 +9,63 @@ var tests = [{ message: 'should process escaped parentheses (open)', fixture: '\\(', expected: [ - { type: 'word', value: '\\(' } + { type: 'word', sourceIndex: 0, value: '\\(' } ] }, { message: 'should process escaped parentheses (close)', fixture: '\\)', expected: [ - { type: 'word', value: '\\)' } + { type: 'word', sourceIndex: 0, value: '\\)' } ] }, { message: 'should process escaped parentheses (both)', fixture: '\\(\\)', expected: [ - { type: 'word', value: '\\(\\)' } + { type: 'word', sourceIndex: 0, value: '\\(\\)' } ] }, { message: 'should process escaped parentheses (both)', fixture: '\\( \\)', expected: [ - { type: 'word', value: '\\(' }, - { type: 'space', value: ' ' }, - { type: 'word', value: '\\)' } + { type: 'word', sourceIndex: 0, value: '\\(' }, + { type: 'space', sourceIndex: 2, value: ' ' }, + { type: 'word', sourceIndex: 3, value: '\\)' } ] }, { message: 'should process unopened parentheses as word', fixture: '() )wo)rd)', expected: [ - { type: 'function', value: '', before: '', after: '', nodes: [] }, - { type: 'space', value: ' ' }, - { type: 'word', value: ')wo)rd)' } + { type: 'function', sourceIndex: 0, value: '', before: '', after: '', nodes: [] }, + { type: 'space', sourceIndex: 2, value: ' ' }, + { type: 'word', sourceIndex: 3, value: ')wo)rd)' } ] }, { message: 'should add before prop', fixture: '( )', expected: [ - { type: 'function', value: '', before: ' ', after: '', nodes: [] } + { type: 'function', sourceIndex: 0, value: '', before: ' ', after: '', nodes: [] } ] }, { message: 'should add before and after prop', fixture: '( | )', expected: [ - { type: 'function', value: '', before: ' ', after: ' ', nodes: [ - { type: 'word', value: '|' } + { type: 'function', sourceIndex: 0, value: '', before: ' ', after: ' ', nodes: [ + { type: 'word', sourceIndex: 2, value: '|' } ] } ] }, { message: 'should add value prop', fixture: 'name()', expected: [ - { type: 'function', value: 'name', before: '', after: '', nodes: [] } + { type: 'function', sourceIndex: 0, value: 'name', before: '', after: '', nodes: [] } ] }, { message: 'should process nested functions', fixture: '((()))', expected: [ - { type: 'function', value: '', before: '', after: '', nodes: [ - { type: 'function', value: '', before: '', after: '', nodes: [ - { type: 'function', value: '', before: '', after: '', nodes: [] } + { type: 'function', sourceIndex: 0, value: '', before: '', after: '', nodes: [ + { type: 'function', sourceIndex: 1, value: '', before: '', after: '', nodes: [ + { type: 'function', sourceIndex: 2, value: '', before: '', after: '', nodes: [] } ] } ] } ] @@ -73,282 +73,282 @@ var tests = [{ message: 'should process advanced nested functions', fixture: '( calc(( ) ))word', expected: [ - { type: 'function', value: '', before: ' ', after: '', nodes: [ - { type: 'function', value: 'calc', before: '', after: ' ', nodes: [ - { type: 'function', value: '', before: ' ', after: '', nodes: [] } + { type: 'function', sourceIndex: 0, value: '', before: ' ', after: '', nodes: [ + { type: 'function', sourceIndex: 2, value: 'calc', before: '', after: ' ', nodes: [ + { type: 'function', sourceIndex: 7, value: '', before: ' ', after: '', nodes: [] } ] } ] }, - { type: 'word', value: 'word' } + { type: 'word', sourceIndex: 13, value: 'word' } ] }, { message: 'should process divider (/)', fixture: '/', expected: [ - { type: 'div', value: '/', before: '', after: '' } + { type: 'div', sourceIndex: 0, value: '/', before: '', after: '' } ] }, { message: 'should process divider (:)', fixture: ':', expected: [ - { type: 'div', value: ':', before: '', after: '' } + { type: 'div', sourceIndex: 0, value: ':', before: '', after: '' } ] }, { message: 'should process divider (,)', fixture: ',', expected: [ - { type: 'div', value: ',', before: '', after: '' } + { type: 'div', sourceIndex: 0, value: ',', before: '', after: '' } ] }, { message: 'should process complex divider', fixture: ' , ', expected: [ - { type: 'div', value: ',', before: ' ', after: ' ' } + { type: 'div', sourceIndex: 0, value: ',', before: ' ', after: ' ' } ] }, { message: 'should process divider in function', fixture: '( , )', expected: [ - { type: 'function', value: '', before: ' ', after: ' ', nodes: [ - { type: 'div', value: ',', before: '', after: '' } + { type: 'function', sourceIndex: 0, value: '', before: ' ', after: ' ', nodes: [ + { type: 'div', sourceIndex: 2, value: ',', before: '', after: '' } ] } ] }, { message: 'should process two spaced divider', fixture: ' , : ', expected: [ - { type: 'div', value: ',', before: ' ', after: ' ' }, - { type: 'div', value: ':', before: '', after: ' ' } + { type: 'div', sourceIndex: 0, value: ',', before: ' ', after: ' ' }, + { type: 'div', sourceIndex: 3, value: ':', before: '', after: ' ' } ] }, { message: 'should process empty quoted strings (")', fixture: '""', expected: [ - { type: 'string', value: '', quote: '"' } + { type: 'string', sourceIndex: 0, value: '', quote: '"' } ] }, { message: 'should process empty quoted strings (\')', fixture: '\'\'', expected: [ - { type: 'string', value: '', quote: '\'' } + { type: 'string', sourceIndex: 0, value: '', quote: '\'' } ] }, { message: 'should process escaped quotes (\')', fixture: '\'word\\\'word\'', expected: [ - { type: 'string', value: 'word\\\'word', quote: '\'' } + { type: 'string', sourceIndex: 0, value: 'word\\\'word', quote: '\'' } ] }, { message: 'should process escaped quotes (\')', fixture: '"word\\"word"', expected: [ - { type: 'string', value: 'word\\"word', quote: '"' } + { type: 'string', sourceIndex: 0, value: 'word\\"word', quote: '"' } ] }, { message: 'should process single quotes inside double quotes (\')', fixture: '"word\'word"', expected: [ - { type: 'string', value: 'word\'word', quote: '"' } + { type: 'string', sourceIndex: 0, value: 'word\'word', quote: '"' } ] }, { message: 'should process double quotes inside single quotes (\')', fixture: '\'word"word\'', expected: [ - { type: 'string', value: 'word"word', quote: '\'' } + { type: 'string', sourceIndex: 0, value: 'word"word', quote: '\'' } ] }, { message: 'should process unclosed quotes', fixture: '"word', expected: [ - { type: 'string', value: 'word', quote: '"', unclosed: true } + { type: 'string', sourceIndex: 0, value: 'word', quote: '"', unclosed: true } ] }, { message: 'should process unclosed quotes with ended backslash', fixture: '"word\\', expected: [ - { type: 'string', value: 'word\\', quote: '"', unclosed: true } + { type: 'string', sourceIndex: 0, value: 'word\\', quote: '"', unclosed: true } ] }, { message: 'should process quoted strings', fixture: '"string"', expected: [ - { type: 'string', value: 'string', quote: '"' } + { type: 'string', sourceIndex: 0, value: 'string', quote: '"' } ] }, { message: 'should process quoted strings and words', fixture: 'word1"string"word2', expected: [ - { type: 'word', value: 'word1' }, - { type: 'string', value: 'string', quote: '"' }, - { type: 'word', value: 'word2' } + { type: 'word', sourceIndex: 0, value: 'word1' }, + { type: 'string', sourceIndex: 5, value: 'string', quote: '"' }, + { type: 'word', sourceIndex: 13, value: 'word2' } ] }, { message: 'should process quoted strings and spaces', fixture: ' "string" ', expected: [ - { type: 'space', value: ' ' }, - { type: 'string', value: 'string', quote: '"' }, - { type: 'space', value: ' ' } + { type: 'space', sourceIndex: 0, value: ' ' }, + { type: 'string', sourceIndex: 1, value: 'string', quote: '"' }, + { type: 'space', sourceIndex: 9, value: ' ' } ] }, { message: 'should process escaped symbols as words', fixture: ' \\"word\\\'\\ \\\t ', expected: [ - { type: 'space', value: ' ' }, - { type: 'word', value: '\\"word\\\'\\ \\\t'}, - { type: 'space', value: ' ' } + { type: 'space', sourceIndex: 0, value: ' ' }, + { type: 'word', sourceIndex: 1, value: '\\"word\\\'\\ \\\t'}, + { type: 'space', sourceIndex: 13, value: ' ' } ] }, { message: 'should correctly proceess font value', fixture: 'bold italic 12px \t /3 \'Open Sans\', Arial, "Helvetica Neue", sans-serif', expected: [ - { type: 'word', value: 'bold' }, - { type: 'space', value: ' ' }, - { type: 'word', value: 'italic' }, - { type: 'space', value: ' ' }, - { type: 'word', value: '12px' }, - { type: 'div', value: '/' , before: ' \t ', after: '' }, - { type: 'word', value: '3' }, - { type: 'space', value: ' ' }, - { type: 'string', value: 'Open Sans', quote: '\'' }, - { type: 'div', value: ',', before: '', after: ' ' }, - { type: 'word', value: 'Arial' }, - { type: 'div', value: ',', before: '', after: ' ' }, - { type: 'string', value: 'Helvetica Neue', quote: '"' }, - { type: 'div', value: ',', before: '', after: ' ' }, - { type: 'word', value: 'sans-serif' }, + { type: 'word', sourceIndex: 0, value: 'bold' }, + { type: 'space', sourceIndex: 4, value: ' ' }, + { type: 'word', sourceIndex: 5, value: 'italic' }, + { type: 'space', sourceIndex: 11, value: ' ' }, + { type: 'word', sourceIndex: 12, value: '12px' }, + { type: 'div', sourceIndex: 16, value: '/' , before: ' \t ', after: '' }, + { type: 'word', sourceIndex: 20, value: '3' }, + { type: 'space', sourceIndex: 21, value: ' ' }, + { type: 'string', sourceIndex: 22, value: 'Open Sans', quote: '\'' }, + { type: 'div', sourceIndex: 33, value: ',', before: '', after: ' ' }, + { type: 'word', sourceIndex: 35, value: 'Arial' }, + { type: 'div', sourceIndex: 40, value: ',', before: '', after: ' ' }, + { type: 'string', sourceIndex: 42, value: 'Helvetica Neue', quote: '"' }, + { type: 'div', sourceIndex: 58, value: ',', before: '', after: ' ' }, + { type: 'word', sourceIndex: 60, value: 'sans-serif' }, ] }, { message: 'should correctly proceess color value', fixture: 'rgba( 29, 439 , 29 )', expected: [ - { type: 'function', value: 'rgba', before: ' ', after: ' ', nodes: [ - { type: 'word', value: '29' }, - { type: 'div', value: ',', before: '', after: ' ' }, - { type: 'word', value: '439' }, - { type: 'div', value: ',', before: ' ', after: ' ' }, - { type: 'word', value: '29' }, + { type: 'function', sourceIndex: 0, value: 'rgba', before: ' ', after: ' ', nodes: [ + { type: 'word', sourceIndex: 6, value: '29' }, + { type: 'div', sourceIndex: 8, value: ',', before: '', after: ' ' }, + { type: 'word', sourceIndex: 10, value: '439' }, + { type: 'div', sourceIndex: 13, value: ',', before: ' ', after: ' ' }, + { type: 'word', sourceIndex: 16, value: '29' }, ] } ] }, { message: 'should correctly process url function', fixture: 'url( /gfx/img/bg.jpg )', expected: [ - { type: 'function', value: 'url', before: ' ', after: ' ', nodes: [ - { type: 'word', value: '/gfx/img/bg.jpg' } + { type: 'function', sourceIndex: 0, value: 'url', before: ' ', after: ' ', nodes: [ + { type: 'word', sourceIndex: 5, value: '/gfx/img/bg.jpg' } ] } ] }, { message: 'should add unclosed: true prop for url function', fixture: 'url( /gfx/img/bg.jpg ', expected: [ - { type: 'function', value: 'url', before: ' ', after: '', unclosed: true, nodes: [ - { type: 'word', value: '/gfx/img/bg.jpg' }, - { type: 'space', value: ' ' } + { type: 'function', sourceIndex: 0, value: 'url', before: ' ', after: '', unclosed: true, nodes: [ + { type: 'word', sourceIndex: 5, value: '/gfx/img/bg.jpg' }, + { type: 'space', sourceIndex: 20, value: ' ' } ] } ] }, { message: 'should correctly process url function with quoted first argument', fixture: 'url( "/gfx/img/bg.jpg" hello )', expected: [ - { type: 'function', value: 'url', before: ' ', after: ' ', nodes: [ - { type: 'string', quote: '"', value: '/gfx/img/bg.jpg' }, - { type: 'space', value: ' ' }, - { type: 'word', value: 'hello' } + { type: 'function', sourceIndex: 0, value: 'url', before: ' ', after: ' ', nodes: [ + { type: 'string', sourceIndex: 5, quote: '"', value: '/gfx/img/bg.jpg' }, + { type: 'space', sourceIndex: 22, value: ' ' }, + { type: 'word', sourceIndex: 23, value: 'hello' } ] } ] }, { message: 'should correctly process nested calc functions', fixture: 'calc(((768px - 100vw) / 2) - 15px)', expected: [ - {type: 'function', value: 'calc', before: '', after: '', nodes: [ - { type: 'function', value: '', before: '', after: '', nodes: [ - { type: 'function', value: '', before: '', after: '', nodes: [ - { type: 'word', value: '768px' }, - { type: 'space', value: ' ' }, - { type: 'word', value: '-' }, - { type: 'space', value: ' ' }, - { type: 'word', value: '100vw' } + {type: 'function', sourceIndex: 0, value: 'calc', before: '', after: '', nodes: [ + { type: 'function', sourceIndex: 5, value: '', before: '', after: '', nodes: [ + { type: 'function', sourceIndex: 6, value: '', before: '', after: '', nodes: [ + { type: 'word', sourceIndex: 7, value: '768px' }, + { type: 'space', sourceIndex: 12, value: ' ' }, + { type: 'word', sourceIndex: 13, value: '-' }, + { type: 'space', sourceIndex: 14, value: ' ' }, + { type: 'word', sourceIndex: 15, value: '100vw' } ] }, - { type: 'div', value: '/', before: ' ', after: ' ' }, - { type: 'word', value: '2' } + { type: 'div', sourceIndex: 21, value: '/', before: ' ', after: ' ' }, + { type: 'word', sourceIndex: 24, value: '2' } ] }, - { type: 'space', value: ' ' }, - { type: 'word', value: '-' }, - { type: 'space', value: ' ' }, - { type: 'word', value: '15px' } + { type: 'space', sourceIndex: 26, value: ' ' }, + { type: 'word', sourceIndex: 27, value: '-' }, + { type: 'space', sourceIndex: 28, value: ' ' }, + { type: 'word', sourceIndex: 29, value: '15px' } ] } ] }, { message: 'should process colons with params', fixture: '(min-width: 700px) and (orientation: \\$landscape)', expected: [ - { type: 'function', value: '', before: '', after: '', nodes: [ - { type: 'word', value: 'min-width' }, - { type: 'div', value: ':', before: '', after: ' ' }, - { type: 'word', value: '700px' } + { type: 'function', sourceIndex: 0, value: '', before: '', after: '', nodes: [ + { type: 'word', sourceIndex: 1, value: 'min-width' }, + { type: 'div', sourceIndex: 10, value: ':', before: '', after: ' ' }, + { type: 'word', sourceIndex: 12, value: '700px' } ] }, - { type: 'space', value: ' ' }, - { type: 'word', value: 'and' }, - { type: 'space', value: ' ' }, - { type: 'function', value: '', before: '', after: '', nodes: [ - { type: 'word', value: 'orientation' }, - { type: 'div', value: ':', before: '', after: ' ' }, - { type: 'word', value: '\\$landscape' } + { type: 'space', sourceIndex: 18, value: ' ' }, + { type: 'word', sourceIndex: 19, value: 'and' }, + { type: 'space', sourceIndex: 22, value: ' ' }, + { type: 'function', sourceIndex: 23, value: '', before: '', after: '', nodes: [ + { type: 'word', sourceIndex: 24, value: 'orientation' }, + { type: 'div', sourceIndex: 35, value: ':', before: '', after: ' ' }, + { type: 'word', sourceIndex: 37, value: '\\$landscape' } ] } ] }, { message: 'should escape parentheses with backslash', fixture: 'url( http://website.com/assets\\)_test )', expected: [ - { type: 'function', value: 'url', before: ' ', after: ' ', nodes: [ - { type: 'word', value: 'http://website.com/assets\\)_test' } + { type: 'function', sourceIndex: 0, value: 'url', before: ' ', after: ' ', nodes: [ + { type: 'word', sourceIndex: 5, value: 'http://website.com/assets\\)_test' } ] } ] }, { message: 'should parse parentheses correctly', fixture: 'fn1(fn2(255), fn3(.2)), fn4(fn5(255,.2), fn6)', expected: [ - { type: 'function', value: 'fn1', before: '', after: '', nodes: [ - { type: 'function', value: 'fn2', before: '', after: '', nodes: [ - { type: 'word', value: '255' } + { type: 'function', sourceIndex: 0, value: 'fn1', before: '', after: '', nodes: [ + { type: 'function', sourceIndex: 4, value: 'fn2', before: '', after: '', nodes: [ + { type: 'word', sourceIndex: 8, value: '255' } ] }, - { type: 'div', value: ',', before: '', after: ' ' }, - { type: 'function', value: 'fn3', before: '', after: '', nodes: [ - { type: 'word', value: '.2' } + { type: 'div', sourceIndex: 12, value: ',', before: '', after: ' ' }, + { type: 'function', sourceIndex: 14, value: 'fn3', before: '', after: '', nodes: [ + { type: 'word', sourceIndex: 18, value: '.2' } ] }, ] }, - { type: 'div', value: ',', before: '', after: ' ' }, - { type: 'function', value: 'fn4', before: '', after: '', nodes: [ - { type: 'function', value: 'fn5', before: '', after: '', nodes: [ - { type: 'word', value: '255' }, - { type: 'div', value: ',', before: '', after: '' }, - { type: 'word', value: '.2' } + { type: 'div', sourceIndex: 22, value: ',', before: '', after: ' ' }, + { type: 'function', sourceIndex: 24, value: 'fn4', before: '', after: '', nodes: [ + { type: 'function', sourceIndex: 28, value: 'fn5', before: '', after: '', nodes: [ + { type: 'word', sourceIndex: 32, value: '255' }, + { type: 'div', sourceIndex: 35, value: ',', before: '', after: '' }, + { type: 'word', sourceIndex: 36, value: '.2' } ] }, - { type: 'div', value: ',', before: '', after: ' '}, - { type: 'word', value: 'fn6' } + { type: 'div', sourceIndex: 39, value: ',', before: '', after: ' '}, + { type: 'word', sourceIndex: 41, value: 'fn6' } ] } ] }, { message: 'shouldn\'t throw an error on unclosed function', fixture: '(0 32 word ', expected: [ - { type: 'function', value: '', before: '', after: '', unclosed: true, nodes: [ - { type: 'word', value: '0' }, - { type: 'space', value: ' ' }, - { type: 'word', value: '32' }, - { type: 'space', value: ' ' }, - { type: 'word', value: 'word' }, - { type: 'space', value: ' ' } + { type: 'function', sourceIndex: 0, value: '', before: '', after: '', unclosed: true, nodes: [ + { type: 'word', sourceIndex: 1, value: '0' }, + { type: 'space', sourceIndex: 2, value: ' ' }, + { type: 'word', sourceIndex: 3, value: '32' }, + { type: 'space', sourceIndex: 5, value: ' ' }, + { type: 'word', sourceIndex: 6, value: 'word' }, + { type: 'space', sourceIndex: 10, value: ' ' } ] } ] }, { message: 'should add unclosed: true prop for every unclosed function', fixture: '( ( ( ) ', expected: [ - { type: 'function', value: '', before: ' ', after: '', unclosed: true, nodes: [ - { type: 'function', value: '', before: ' ', after: '', unclosed: true, nodes: [ - { type: 'function', value: '', before: ' ', after: '', nodes: [] }, - { type: 'space', value: ' ' } + { type: 'function', sourceIndex: 0, value: '', before: ' ', after: '', unclosed: true, nodes: [ + { type: 'function', sourceIndex: 2, value: '', before: ' ', after: '', unclosed: true, nodes: [ + { type: 'function', sourceIndex: 4, value: '', before: ' ', after: '', nodes: [] }, + { type: 'space', sourceIndex: 7, value: ' ' } ] } ] } ] @@ -356,31 +356,31 @@ var tests = [{ message: 'shouldn\'t throw an error on unopened function', fixture: '0 32 word ) ', expected: [ - { type: 'word', value: '0' }, - { type: 'space', value: ' ' }, - { type: 'word', value: '32' }, - { type: 'space', value: ' ' }, - { type: 'word', value: 'word' }, - { type: 'space', value: ' ' }, - { type: 'word', value: ')' }, - { type: 'space', value: ' ' } + { type: 'word', sourceIndex: 0, value: '0' }, + { type: 'space', sourceIndex: 1, value: ' ' }, + { type: 'word', sourceIndex: 2, value: '32' }, + { type: 'space', sourceIndex: 4, value: ' ' }, + { type: 'word', sourceIndex: 5, value: 'word' }, + { type: 'space', sourceIndex: 9, value: ' ' }, + { type: 'word', sourceIndex: 10, value: ')' }, + { type: 'space', sourceIndex: 11, value: ' ' } ] }, { message: 'should process escaped spaces as word in fonts', fixture: 'Bond\\ 007', expected: [ - { type: 'word', value: 'Bond\\ 007' } + { type: 'word', sourceIndex: 0, value: 'Bond\\ 007' } ] }, { message: 'should parse double url and comma', fixture: 'url(foo/bar.jpg), url(http://website.com/img.jpg)', expected: [ - { type: 'function', value: 'url', before: '', after: '', nodes: [ - { type: 'word', value: 'foo/bar.jpg' } + { type: 'function', sourceIndex: 0, value: 'url', before: '', after: '', nodes: [ + { type: 'word', sourceIndex: 4, value: 'foo/bar.jpg' } ] }, - { type: 'div', value: ',', before: '', after: ' ' }, - { type: 'function', value: 'url', before: '', after: '', nodes: [ - { type: 'word', value: 'http://website.com/img.jpg' } + { type: 'div', sourceIndex: 16, value: ',', before: '', after: ' ' }, + { type: 'function', sourceIndex: 18, value: 'url', before: '', after: '', nodes: [ + { type: 'word', sourceIndex: 22, value: 'http://website.com/img.jpg' } ] }, ] }];