Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions src/app/converter/converter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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', () => {
Expand Down
52 changes: 52 additions & 0 deletions src/app/parser/parser.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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', () => {
Expand Down Expand Up @@ -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: (
Expand Down Expand Up @@ -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');
});
});
});
20 changes: 12 additions & 8 deletions src/app/parser/parser.ts
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -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);

Expand All @@ -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*;(?![^\\{]*\\}))`;
}
}
2 changes: 1 addition & 1 deletion src/app/utils/utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
4 changes: 2 additions & 2 deletions src/app/utils/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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})}";}`;
Copy link
Copy Markdown
Contributor Author

@davidsmith2 davidsmith2 Jun 20, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The underscore is required to avoid errors like the following:

Error: Expected identifier.
   ╷
46 │ #sass-export-id.100{content:"#{inspect(80%)}";}
   │                 ^
   ╵

}
return `${WRAPPER_CSS_ID}.${cssDeclaration.name}{content:"#{${cssDeclaration.value}}";}`;
return `${WRAPPER_CSS_ID}._${cssDeclaration.name}{content:"#{${cssDeclaration.value}}";}`;
}

public static removeDoubleQuotes(wrappedContent: string): string {
Expand Down
7 changes: 7 additions & 0 deletions test/scss/_maps.scss
Original file line number Diff line number Diff line change
Expand Up @@ -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%
);