diff --git a/src/app/converter/converter.test.ts b/src/app/converter/converter.test.ts index c540df5..e752571 100644 --- a/src/app/converter/converter.test.ts +++ b/src/app/converter/converter.test.ts @@ -213,6 +213,24 @@ describe('Converter class', () => { expect(map[ix].compiledValue).to.be.equal(compiled); }); }); + + it('should allow maps with numeric keys', () => { + let result = structured['levels'][0]; + expect(result).to.have.property('mapValue'); + let map = result.mapValue; + + let expected = [ + { name: '100', value: '80%', compiledValue: '80%' }, + { name: '500', value: '0', compiledValue: '0' }, + { name: '900', value: '80%', compiledValue: '80%' }, + ]; + + expected.forEach(({name, value, compiledValue}, ix) => { + expect(map[ix].name).to.be.equal(name); + expect(map[ix].value).to.be.equal(value); + expect(map[ix].compiledValue).to.be.equal(compiledValue); + }); + }); }); describe('mixins support', () => { diff --git a/src/app/parser/parser.test.ts b/src/app/parser/parser.test.ts index 80fa816..ab28a05 100644 --- a/src/app/parser/parser.test.ts +++ b/src/app/parser/parser.test.ts @@ -47,6 +47,12 @@ describe('Parser class', () => { expect(parser.parse()).that.is.an('array'); expect(parser.parse()).to.be.empty; + + rawContent = '$0: test;'; + parser = new Parser(rawContent); + + expect(parser.parse()).that.is.an('array'); + expect(parser.parse()).to.be.empty; }); describe('parseStructured Validations', () => { @@ -228,6 +234,26 @@ describe('Parser class', () => { expect(parsedArray[0].mapValue[1].value).be.equal('$bp-medium'); }); + it('should parse map with numeric keys', () => { + let content = `$levels: ( + 100: 80%, + 500: 0, + 900: 80% + );`; + + let parser = new Parser(content); + let parsedArray = parser.parse(); + + expect(parsedArray[0].mapValue[0].name).be.equal('100'); + expect(parsedArray[0].mapValue[0].value).be.equal('80%'); + + expect(parsedArray[0].mapValue[1].name).be.equal('500'); + expect(parsedArray[0].mapValue[1].value).be.equal('0'); + + expect(parsedArray[0].mapValue[2].name).be.equal('900'); + expect(parsedArray[0].mapValue[2].value).be.equal('80%'); + }); + it('should ignore comments inline', () => { let content = ` $font-size: ( @@ -398,5 +424,31 @@ describe('Parser class', () => { expect(parsedArray[0].mapValue[2].mapValue[1].value).be.equal('$bp-xl'); }); + + it('should parse map with numeric keys', () => { + let content = `$content: ( + 0: 0, + 1: 1, + 2: ( + 0: 0, + 1: 1, + 2: 2 + ) + );`; + + let parser = new Parser(content); + let parsedArray = parser.parse(); + + expect(parsedArray[0].mapValue[2].name).be.equal('2'); + + expect(parsedArray[0].mapValue[2].mapValue[0].name).be.equal('0'); + expect(parsedArray[0].mapValue[2].mapValue[0].value).be.equal('0'); + + expect(parsedArray[0].mapValue[2].mapValue[1].name).be.equal('1'); + expect(parsedArray[0].mapValue[2].mapValue[1].value).be.equal('1'); + + expect(parsedArray[0].mapValue[2].mapValue[2].name).be.equal('2'); + expect(parsedArray[0].mapValue[2].mapValue[2].value).be.equal('2'); + }); }); }); diff --git a/src/app/parser/parser.ts b/src/app/parser/parser.ts index f45b37f..e6e09ae 100644 --- a/src/app/parser/parser.ts +++ b/src/app/parser/parser.ts @@ -1,9 +1,8 @@ const VARIABLE_PATERN = '(?!\\d)[\\w_-][\\w\\d_-]*'; +const MAP_KEY_PATTERN = '[\\w-]+'; const VALUE_PATERN = '[^;]+|"(?:[^"]+|(?:\\\\"|[^"])*)"'; -const DECLARATION_PATTERN = - `\\$['"]?(${VARIABLE_PATERN})['"]?\\s*:\\s*(${VALUE_PATERN})(?:\\s*!(global|default)\\s*;|\\s*;(?![^\\{]*\\}))`; -const MAP_DECLARATIOM_REGEX = /['"]?((?!\d)[\w_-][\w\d_-]*)['"]?\s*:\s*([a-z\-]+\([^\)]+\)|[^\)\(,\/]+|\([^\)]+\))/gi; +const MAP_DECLARATIOM_REGEX = /['"]?([\w_-][\w\d_-]*)['"]?\s*:\s*([a-z\-]+\([^\)]+\)|[^\)\(,\/]+|\([^\)]+\))/gi; const QUOTES_PATTERN = /^(['"]).*\1$/; const QUOTES_REPLACE = /^(['"])|(['"])$/g; @@ -77,7 +76,7 @@ export class Parser { private extractDeclarationsStructured(content: string): [any] { - const matches = content.match(new RegExp(`${DECLARATION_PATTERN}|${SECTION_PATTERN}|${END_SECTION_PATTERN}`, 'g')); + const matches = content.match(new RegExp(`${this.getDeclarationPattern()}|${SECTION_PATTERN}|${END_SECTION_PATTERN}`, 'g')); if (!matches) { return [] as any; @@ -88,7 +87,7 @@ export class Parser { private extractDeclarations(content: string): [any] { - const matches = content.match(new RegExp(DECLARATION_PATTERN, 'g')); + const matches = content.match(new RegExp(this.getDeclarationPattern(), 'g')); if (!matches) { return [] as any; @@ -108,10 +107,10 @@ export class Parser { } - private parseSingleDeclaration(matchDeclaration: string): IDeclaration { + private parseSingleDeclaration(matchDeclaration: string, isMap: boolean = false): IDeclaration { let matches = matchDeclaration .replace(/\s*!(default|global)\s*;/, ';') - .match(new RegExp(DECLARATION_PATTERN)); + .match(new RegExp(this.getDeclarationPattern(isMap))); if (!matches) { return; @@ -132,7 +131,8 @@ export class Parser { if (map.length) { parsedDeclaration.mapValue = map.map((declaration) => { const singleDeclaration = this.parseSingleDeclaration( - `$${declaration};` + `$${declaration};`, + true ); this.parseMapDeclarations(singleDeclaration); @@ -148,4 +148,8 @@ export class Parser { private checkIsSectionEnd(content: string): boolean { return (new RegExp(END_SECTION_PATTERN, 'gi')).test(content); } + + private getDeclarationPattern(isMap: boolean = false): string { + return `\\$['"]?(${isMap ? MAP_KEY_PATTERN : VARIABLE_PATERN})['"]?\\s*:\\s*(${VALUE_PATERN})(?:\\s*!(global|default)\\s*;|\\s*;(?![^\\{]*\\}))`; + } } diff --git a/src/app/utils/utils.test.ts b/src/app/utils/utils.test.ts index 4c6f9b1..f7983fb 100644 --- a/src/app/utils/utils.test.ts +++ b/src/app/utils/utils.test.ts @@ -33,7 +33,7 @@ describe('Utils class', () => { it('should wrap a variable', () => { let declaration = { name: 'var', value: '$the-value', compiledValue: '' }; - let expectedResult = '#sass-export-id.var{content:"#{$the-value}";}'; + let expectedResult = '#sass-export-id._var{content:"#{$the-value}";}'; let wrapped = Utils.wrapCss(declaration, false); expect(wrapped).to.be.equal(expectedResult); diff --git a/src/app/utils/utils.ts b/src/app/utils/utils.ts index ea25e47..1259d9e 100644 --- a/src/app/utils/utils.ts +++ b/src/app/utils/utils.ts @@ -17,9 +17,9 @@ export class Utils { public static wrapCss(cssDeclaration: IDeclaration, useInspect: boolean): string { if (useInspect) { - return `${WRAPPER_CSS_ID}.${cssDeclaration.name}{content:"#{inspect(${cssDeclaration.value})}";}`; + return `${WRAPPER_CSS_ID}._${cssDeclaration.name}{content:"#{inspect(${cssDeclaration.value})}";}`; } - return `${WRAPPER_CSS_ID}.${cssDeclaration.name}{content:"#{${cssDeclaration.value}}";}`; + return `${WRAPPER_CSS_ID}._${cssDeclaration.name}{content:"#{${cssDeclaration.value}}";}`; } public static removeDoubleQuotes(wrappedContent: string): string { diff --git a/test/scss/_maps.scss b/test/scss/_maps.scss index f8218b2..d220474 100644 --- a/test/scss/_maps.scss +++ b/test/scss/_maps.scss @@ -35,3 +35,10 @@ $funcs: ( 'rgba': rgba(255, 0, 0, .5), 'darken': darken(#b37399, 20%) ); + +// @sass-export-section="levels" +$levels: ( + 100: 80%, + 500: 0, + 900: 80% +);