From 438c22aba661584f8ade2583a6192e18d0686dbc Mon Sep 17 00:00:00 2001 From: Aleks Hudochenkov Date: Wed, 27 Dec 2023 19:04:57 +0100 Subject: [PATCH] Fix parsing for two interpolations before rule selector. Fixes #24 --- lib/__tests__/parse.test.js | 51 +++++++++++++++++++++++++++++++++++++ lib/parser.js | 16 ++++++++---- 2 files changed, 62 insertions(+), 5 deletions(-) diff --git a/lib/__tests__/parse.test.js b/lib/__tests__/parse.test.js index d1ca2be..96cf2aa 100644 --- a/lib/__tests__/parse.test.js +++ b/lib/__tests__/parse.test.js @@ -540,6 +540,31 @@ describe('simple interpolations', () => { expect(firstNode.nodes).toHaveLength(1); }); + test('two interpolations in selector (whole selector)', () => { + let document = parse( + 'let Component = styled.div`${Component} ${Component1} { color: red; }`;', + ); + + expect(document.nodes).toHaveLength(1); + expect(document.first.nodes).toHaveLength(1); + expect(document.first.raws).toEqual({ + isRuleLike: true, + styledSyntaxIsComponent: true, + styledSyntaxRangeStart: 27, + styledSyntaxRangeEnd: 69, + codeBefore: 'let Component = styled.div`', + codeAfter: '`;', + after: '', + semicolon: false, + }); + + let firstNode = document.first.first; + + expect(firstNode.type).toBe('rule'); + expect(firstNode.selector).toBe('${Component} ${Component1}'); + expect(firstNode.nodes).toHaveLength(1); + }); + test('in selector (whole selector starts with a dot)', () => { let document = parse('let Component = styled.div`.${Component} { color: red; }`;'); @@ -703,6 +728,32 @@ describe('simple interpolations', () => { expect(firstNode.raws.before).toBe('${hello}\n\t'); }); + test('two interpolations on a new line before selector', () => { + let document = parse( + 'let Component = styled.div`${hello}\n\t${hello}\n\ta { color: red; }`;', + ); + + expect(document.nodes).toHaveLength(1); + expect(document.first.nodes).toHaveLength(1); + expect(document.first.raws).toEqual({ + isRuleLike: true, + styledSyntaxIsComponent: true, + styledSyntaxRangeStart: 27, + styledSyntaxRangeEnd: 64, + codeBefore: 'let Component = styled.div`', + codeAfter: '`;', + after: '', + semicolon: false, + }); + + let firstNode = document.first.first; + + expect(firstNode.type).toBe('rule'); + expect(firstNode.selector).toBe('a'); + expect(firstNode.nodes).toHaveLength(1); + expect(firstNode.raws.before).toBe('${hello}\n\t${hello}\n\t'); + }); + test('comment in selector with interpolation', () => { let document = parse( 'let Component = styled.div`${Card}:hover, /* hello */ b { color: red; }`;', diff --git a/lib/parser.js b/lib/parser.js index 393a36b..22cfa23 100644 --- a/lib/parser.js +++ b/lib/parser.js @@ -387,16 +387,22 @@ class Parser extends PostCSSParser { let index; for (index = 0; index < tokensLength; index++) { - let next = tokens.shift(); + let current = tokens.shift(); - spaces += next[1]; - removedTokens.push(next); + spaces += current[1]; + removedTokens.push(current); - if (index === 0 && this.isInterpolation(next)) { + if (index === 0 && this.isInterpolation(current)) { hasInterpolation = true; } - if (next[0] === 'space' && next[1].includes('\n')) { + if (current[0] === 'space' && current[1].includes('\n')) { + const nextToken = tokens[0]; + + if (nextToken && this.isInterpolation(nextToken)) { + continue; + } + break; } }