From 11ba2c097cd10bffe7960a11544aad781afdd3ee Mon Sep 17 00:00:00 2001 From: Devansh Jethmalani Date: Sun, 21 Jul 2019 07:14:28 +0530 Subject: [PATCH 1/3] Fix issue #31 - add a RegEx in the condition to allow `(` and `)` inside `{` and `}` - add corresponding tests --- src/emmetHelper.ts | 4 ++-- src/test/emmetHelper.test.ts | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/emmetHelper.ts b/src/emmetHelper.ts index 8524eb0..fb3b45b 100644 --- a/src/emmetHelper.ts +++ b/src/emmetHelper.ts @@ -490,8 +490,8 @@ export function isAbbreviationValid(syntax: string, abbreviation: string): boole return parseInt(multipleMatch[1], 10) <= 100 } // Its common for users to type (sometextinsidebrackets), this should not be treated as an abbreviation - // Grouping in abbreviation is valid only if preceeded/succeeded with one of the symbols for nesting, sibling, repeater or climb up - if (!/\(.*\)[>\+\*\^]/.test(abbreviation) && !/[>\+\*\^]\(.*\)/.test(abbreviation) && /\(/.test(abbreviation) && /\)/.test(abbreviation)) { + // Grouping in abbreviation is valid only if it's inside a text node or preceeded/succeeded with one of the symbols for nesting, sibling, repeater or climb up + if (!/\{[^\}]*\(.*\)[^\{]*\}/.test(abbreviation) && !/\(.*\)[>\+\*\^]/.test(abbreviation) && !/[>\+\*\^]\(.*\)/.test(abbreviation) && /\(/.test(abbreviation) && /\)/.test(abbreviation)) { return false; } diff --git a/src/test/emmetHelper.test.ts b/src/test/emmetHelper.test.ts index 7ad0f88..85f0b00 100644 --- a/src/test/emmetHelper.test.ts +++ b/src/test/emmetHelper.test.ts @@ -33,7 +33,7 @@ const expectedBemCommentFilterOutputDocs = expectedBemCommentFilterOutput.replac describe('Validate Abbreviations', () => { it('should return true for valid abbreviations', () => { - const htmlAbbreviations = ['ul>li', 'ul', 'h1', 'ul>li*3', '(ul>li)+div', '.hello', '!', '#hello', '.item[id=ok]', '.', '.foo']; + const htmlAbbreviations = ['ul>li', 'ul', 'h1', 'ul>li*3', '(ul>li)+div', '.hello', '!', '#hello', '.item[id=ok]', '.', '.foo', 'div{ foo (bar) baz }']; const cssAbbreviations = ['#123', '#abc']; htmlAbbreviations.forEach(abbr => { assert(isAbbreviationValid('html', abbr)); @@ -61,6 +61,7 @@ describe('Validate Abbreviations', () => { 'if(!ok)', 'while(!ok)', '(!ok)', + 'div{ foo }(bar){ baz }' ]; const cssAbbreviations = ['123', '#xyz']; htmlAbbreviations.forEach(abbr => { From c86069b1c348eb4874229818585a9ff0d3c94806 Mon Sep 17 00:00:00 2001 From: Devansh Jethmalani Date: Sun, 21 Jul 2019 07:27:12 +0530 Subject: [PATCH 2/3] Use more permissive RegEx for fixing #31, minor fixes & refactor --- src/emmetHelper.ts | 2 +- src/test/emmetHelper.test.ts | 13 +++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/emmetHelper.ts b/src/emmetHelper.ts index fb3b45b..11addaa 100644 --- a/src/emmetHelper.ts +++ b/src/emmetHelper.ts @@ -491,7 +491,7 @@ export function isAbbreviationValid(syntax: string, abbreviation: string): boole } // Its common for users to type (sometextinsidebrackets), this should not be treated as an abbreviation // Grouping in abbreviation is valid only if it's inside a text node or preceeded/succeeded with one of the symbols for nesting, sibling, repeater or climb up - if (!/\{[^\}]*\(.*\)[^\{]*\}/.test(abbreviation) && !/\(.*\)[>\+\*\^]/.test(abbreviation) && !/[>\+\*\^]\(.*\)/.test(abbreviation) && /\(/.test(abbreviation) && /\)/.test(abbreviation)) { + if ((/\(/.test(abbreviation) || /\)/.test(abbreviation)) && !/\{[^\}\{]*[\(\)]+[^\}\{]*\}(?:[>\+\*\^]|$)/.test(abbreviation) && !/\(.*\)[>\+\*\^]/.test(abbreviation) && !/[>\+\*\^]\(.*\)/.test(abbreviation)) { return false; } diff --git a/src/test/emmetHelper.test.ts b/src/test/emmetHelper.test.ts index 85f0b00..2e8a4f9 100644 --- a/src/test/emmetHelper.test.ts +++ b/src/test/emmetHelper.test.ts @@ -33,13 +33,13 @@ const expectedBemCommentFilterOutputDocs = expectedBemCommentFilterOutput.replac describe('Validate Abbreviations', () => { it('should return true for valid abbreviations', () => { - const htmlAbbreviations = ['ul>li', 'ul', 'h1', 'ul>li*3', '(ul>li)+div', '.hello', '!', '#hello', '.item[id=ok]', '.', '.foo', 'div{ foo (bar) baz }']; + const htmlAbbreviations = ['ul>li', 'ul', 'h1', 'ul>li*3', '(ul>li)+div', '.hello', '!', '#hello', '.item[id=ok]', '.', '.foo', 'div{ foo (bar) baz }', 'div{ foo ((( abc }', 'div{()}', 'div{ a (b) c}', 'div{ a (b) c}+div{ a (( }']; const cssAbbreviations = ['#123', '#abc']; htmlAbbreviations.forEach(abbr => { - assert(isAbbreviationValid('html', abbr)); + assert(isAbbreviationValid('html', abbr), `${abbr} should be treated as valid abbreviation`); }); htmlAbbreviations.forEach(abbr => { - assert(isAbbreviationValid('haml', abbr)); + assert(isAbbreviationValid('haml', abbr), `${abbr} should be treated as valid abbreviation`); }); cssAbbreviations.forEach(abbr => { assert(isAbbreviationValid('css', abbr), `${abbr} should be treated as valid abbreviation`); @@ -61,7 +61,12 @@ describe('Validate Abbreviations', () => { 'if(!ok)', 'while(!ok)', '(!ok)', - 'div{ foo }(bar){ baz }' + 'div{ foo }(bar){ baz }', + 'div{ foo ((}( abc }', + 'div{ a}(b) c}', + 'div{ a (b){c}', + 'div{ a}(b){c}', + 'div{ a (( dsf} d (( sf )) }' ]; const cssAbbreviations = ['123', '#xyz']; htmlAbbreviations.forEach(abbr => { From 52b2a1dec3a9429abb47876a6ccfe814b16cfdd8 Mon Sep 17 00:00:00 2001 From: Devansh Jethmalani <30295578+devanshj@users.noreply.github.com> Date: Thu, 26 Sep 2019 22:46:14 +0530 Subject: [PATCH 3/3] Formatting Co-Authored-By: Pine --- src/test/emmetHelper.test.ts | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/test/emmetHelper.test.ts b/src/test/emmetHelper.test.ts index 2e8a4f9..6a5a348 100644 --- a/src/test/emmetHelper.test.ts +++ b/src/test/emmetHelper.test.ts @@ -33,7 +33,24 @@ const expectedBemCommentFilterOutputDocs = expectedBemCommentFilterOutput.replac describe('Validate Abbreviations', () => { it('should return true for valid abbreviations', () => { - const htmlAbbreviations = ['ul>li', 'ul', 'h1', 'ul>li*3', '(ul>li)+div', '.hello', '!', '#hello', '.item[id=ok]', '.', '.foo', 'div{ foo (bar) baz }', 'div{ foo ((( abc }', 'div{()}', 'div{ a (b) c}', 'div{ a (b) c}+div{ a (( }']; + const htmlAbbreviations = [ + 'ul>li', + 'ul', + 'h1', + 'ul>li*3', + '(ul>li)+div', + '.hello', + '!', + '#hello', + '.item[id=ok]', + '.', + '.foo', + 'div{ foo (bar) baz }', + 'div{ foo ((( abc }', + 'div{()}', + 'div{ a (b) c}', + 'div{ a (b) c}+div{ a (( }' + ]; const cssAbbreviations = ['#123', '#abc']; htmlAbbreviations.forEach(abbr => { assert(isAbbreviationValid('html', abbr), `${abbr} should be treated as valid abbreviation`); @@ -1132,4 +1149,4 @@ describe('Test completions', () => { assert.equal(completionList.items[0].label, 'abbr'); }); }); -}) \ No newline at end of file +})