diff --git a/exporters/variables-scss/.eslintrc.cjs b/exporters/variables-scss/.eslintrc.cjs index 81cadc8386..0e13d2b0b4 100644 --- a/exporters/variables-scss/.eslintrc.cjs +++ b/exporters/variables-scss/.eslintrc.cjs @@ -5,4 +5,16 @@ module.exports = { ecmaVersion: 'latest', project: './tsconfig.eslint.json', }, + + rules: { + // Conflicting with the Prettier configuration fo the line length + // We are leaving this up to developer to decide where to use braces and where implicit return + // @see { @link https://eslint.org/docs/latest/rules/arrow-body-style } + 'arrow-body-style': 'off', + + // Better handling quotes with escaped strings inside + // Double and backticks quotes are allowed when needed + // @see { @link https://eslint.org/docs/latest/rules/quotes } + quotes: ['warn', 'single', { avoidEscape: true }], + }, }; diff --git a/exporters/variables-scss/src/generators/__tests__/fileGenerator.test.ts b/exporters/variables-scss/src/generators/__tests__/fileGenerator.test.ts index 3bbf805850..5b3e2e9a3d 100644 --- a/exporters/variables-scss/src/generators/__tests__/fileGenerator.test.ts +++ b/exporters/variables-scss/src/generators/__tests__/fileGenerator.test.ts @@ -1,9 +1,12 @@ +import { Supernova, Token, TokenGroup, TokenTheme } from '@supernovaio/sdk-exporters'; import fs from 'fs'; import path from 'path'; -import { Supernova, Token, TokenGroup, TokenTheme } from '@supernovaio/sdk-exporters'; +import { exampleDimensionAndStringTokens } from '../../../tests/fixtures/exampleDimensionAndStringTokens'; +import { exampleGroups } from '../../../tests/fixtures/exampleGroups'; +import { nonThemedFilesData } from '../../config/fileConfig'; import { - generateFiles, generateBarrelFile, + generateFiles, generateOutputFilesByThemes, generateRootThemesFileContent, generateRootThemesFileImports, @@ -11,9 +14,6 @@ import { jsImportStatement, scssImportStatement, } from '../fileGenerator'; -import { exampleDimensionAndStringTokens } from '../../../tests/fixtures/exampleDimensionAndStringTokens'; -import { nonThemedFilesData } from '../../config/fileConfig'; -import { exampleGroups } from '../../../tests/fixtures/exampleGroups'; const mockedExpectedResult = fs.readFileSync( path.join(__dirname, '../../../tests/fixtures/exampleFileContent.scss'), @@ -21,9 +21,9 @@ const mockedExpectedResult = fs.readFileSync( ); const mappedTokens: Map = new Map([]); const tokenGroups: Array = exampleGroups; -const emptyFile = `/* This file was generated by Supernova, don't change manually */\n\n`; +const emptyFile = "/* This file was generated by Supernova, don't change manually */\n\n"; const barrelFile = fs.readFileSync(path.join(__dirname, '../__fixtures__/barrelFileMock.scss'), 'utf-8'); -const barrelColorFile = `@forward 'colors';\n`; +const barrelColorFile = "@forward 'colors';\n"; const barrelJsFile = `export * from './borders'; export * from './other'; export * from './radii'; @@ -32,7 +32,7 @@ export * from './shadows'; export * from './gradients'; export * from './typography'; `; -const barrelJsColorFile = `export * from './colors';\n`; +const barrelJsColorFile = "export * from './colors';\n"; const mockedTsFile = `/* This file was generated by Supernova, don't change manually */ export const gridSpacingDesktop = '32px';\n @@ -97,8 +97,8 @@ describe('fileGenerator', () => { { path: './scss/global/', fileName: 'index.scss', content: barrelFile }, { path: './js/global/', fileName: 'index.ts', content: barrelJsFile }, // Root barrel files - { path: './scss/', fileName: '@global.scss', content: `@forward 'global';\n` }, - { path: './js/', fileName: '@global.ts', content: `export * from './global';\n` }, + { path: './scss/', fileName: '@global.scss', content: "@forward 'global';\n" }, + { path: './js/', fileName: '@global.ts', content: "export * from './global';\n" }, // Themes files { path: './scss/themes/theme-light/', fileName: '_colors.scss', content: emptyFile }, { path: './js/themes/theme-light/', fileName: 'colors.ts', content: emptyFile }, @@ -140,7 +140,7 @@ describe('fileGenerator', () => { { files: [{ fileName: 'borders', content: emptyFile }], description: 'should generate barrel file with one file', - expectedBarrelFile: `@forward 'borders';\n`, + expectedBarrelFile: "@forward 'borders';\n", }, { files: [ @@ -148,7 +148,7 @@ describe('fileGenerator', () => { { fileName: 'other', content: mockedExpectedResult }, ], description: 'should generate barrel file with multiple files', - expectedBarrelFile: `@forward 'borders';\n@forward 'other';\n`, + expectedBarrelFile: "@forward 'borders';\n@forward 'other';\n", }, { files: [ @@ -157,7 +157,7 @@ describe('fileGenerator', () => { ], description: 'should generate barrel file with one file with js output', hasJsOutput: true, - expectedBarrelFile: `export * from './borders';\nexport * from './other';\n`, + expectedBarrelFile: "export * from './borders';\nexport * from './other';\n", }, ]; @@ -190,7 +190,8 @@ describe('fileGenerator', () => { const content = generateRootThemesFileContent(themes as TokenTheme[], false); expect(content).toBe( - `theme-light: (\ncolors: theme-light.$colors,\n),\ntheme-light-inverted: (\ncolors: theme-light-inverted.$colors,\n),`, + // eslint-disable-next-line prettier/prettier, quotes -- special characters in the string + 'theme-light: (\ncolors: theme-light.$colors,\n),\ntheme-light-inverted: (\ncolors: theme-light-inverted.$colors,\n),', ); }); @@ -199,7 +200,8 @@ describe('fileGenerator', () => { const content = generateRootThemesFileContent(themes as TokenTheme[], true); expect(content).toBe( - `themeLight: {\ncolors: themeLight.colors\n},\nthemeLightInverted: {\ncolors: themeLightInverted.colors\n},`, + // eslint-disable-next-line prettier/prettier, quotes -- special characters in the string + 'themeLight: {\ncolors: themeLight.colors\n},\nthemeLightInverted: {\ncolors: themeLightInverted.colors\n},', ); }); }); @@ -209,7 +211,7 @@ describe('fileGenerator', () => { const themes = [{ name: 'theme-light' }, { name: 'theme-light-inverted' }]; const content = generateRootThemesFileImports(themes as TokenTheme[], false); - expect(content).toBe(`@use 'themes/theme-light';\n@use 'themes/theme-light-inverted';`); + expect(content).toBe("@use 'themes/theme-light';\n@use 'themes/theme-light-inverted';"); }); it('should generate root themes file imports with js output', () => { @@ -217,7 +219,7 @@ describe('fileGenerator', () => { const content = generateRootThemesFileImports(themes as TokenTheme[], true); expect(content).toBe( - `import * as themeLight from './themes/theme-light';\nimport * as themeLightInverted from './themes/theme-light-inverted';`, + "import * as themeLight from './themes/theme-light';\nimport * as themeLightInverted from './themes/theme-light-inverted';", ); }); }); @@ -226,7 +228,7 @@ describe('fileGenerator', () => { it('should generate js import statement', () => { const content = jsImportStatement('theme-light'); - expect(content).toBe(`import * as themeLight from './themes/theme-light';`); + expect(content).toBe("import * as themeLight from './themes/theme-light';"); }); }); @@ -234,7 +236,7 @@ describe('fileGenerator', () => { it('should generate scss import statement', () => { const content = scssImportStatement('theme-light'); - expect(content).toBe(`@use 'themes/theme-light';`); + expect(content).toBe("@use 'themes/theme-light';"); }); }); }); diff --git a/exporters/variables-scss/src/generators/__tests__/stylesGenerator.test.ts b/exporters/variables-scss/src/generators/__tests__/stylesGenerator.test.ts index a7bd4ba1c5..3517a94eb1 100644 --- a/exporters/variables-scss/src/generators/__tests__/stylesGenerator.test.ts +++ b/exporters/variables-scss/src/generators/__tests__/stylesGenerator.test.ts @@ -7,12 +7,12 @@ import { TokenGroup, TokenType, } from '@supernovaio/sdk-exporters'; -import { generateStylesFromTokens, tokenToStyleByType } from '../stylesGenerator'; -import { exampleDimensionAndStringTokens } from '../../../tests/fixtures/exampleDimensionAndStringTokens'; import { exampleColorsTokens } from '../../../tests/fixtures/exampleColorTokens'; +import { exampleDimensionAndStringTokens } from '../../../tests/fixtures/exampleDimensionAndStringTokens'; +import { exampleGradientTokens } from '../../../tests/fixtures/exampleGradientTokens'; import { exampleGroups } from '../../../tests/fixtures/exampleGroups'; import { exampleShadowTokens } from '../../../tests/fixtures/exampleShadowTokens'; -import { exampleGradientTokens } from '../../../tests/fixtures/exampleGradientTokens'; +import { generateStylesFromTokens, tokenToStyleByType } from '../stylesGenerator'; const mappedTokens: Map = new Map([]); const tokenGroups: Array = exampleGroups; @@ -64,47 +64,48 @@ describe('stylesGenerator', () => { description: 'dimension type token with parent prefix and js output', hasParentPrefix: true, hasJsOutput: true, - expectedStyles: `export const gridSpacingDesktop = '32px';`, + expectedStyles: "export const gridSpacingDesktop = '32px';", }, { token: exampleDimensionAndStringTokens.get('dimensionRef') as DimensionToken, description: 'dimension type token without parent prefix and js output', hasParentPrefix: false, hasJsOutput: true, - expectedStyles: `export const desktop = '32px';`, + expectedStyles: "export const desktop = '32px';", }, { token: exampleDimensionAndStringTokens.get('stringRef') as StringToken, description: 'string type token with parent prefix and js output', hasParentPrefix: true, hasJsOutput: true, - expectedStyles: `export const gridColumns = '12';`, + expectedStyles: "export const gridColumns = '12';", }, { token: exampleDimensionAndStringTokens.get('stringRef') as StringToken, description: 'string type token without parent prefix and js output', hasParentPrefix: false, hasJsOutput: true, - expectedStyles: `export const columns = '12';`, + expectedStyles: "export const columns = '12';", }, { token: exampleShadowTokens.get('shadowRef') as ShadowToken, description: 'shadow type token without parent prefix', hasParentPrefix: false, hasJsOutput: false, - expectedStyles: `$shadow-100: 0 2px 8px 0 #00000026 !default;`, + expectedStyles: '$shadow-100: 0 2px 8px 0 #00000026 !default;', }, { token: exampleGradientTokens.get('gradientRef') as GradientToken, description: 'gradient type token without parent prefix', hasParentPrefix: false, hasJsOutput: false, - expectedStyles: `$basic-overlay: linear-gradient(var(--gradient-angle, 90deg), #ffffffff 0%, #ffffff00 100%) !default;`, + expectedStyles: + '$basic-overlay: linear-gradient(var(--gradient-angle, 90deg), #ffffffff 0%, #ffffff00 100%) !default;', }, ]; it.each(dataProvider)( - `should correctly generate styles for $description`, + 'should correctly generate styles for $description', ({ token, expectedStyles, hasParentPrefix, hasJsOutput }) => { const styles = tokenToStyleByType(token, mappedTokens, tokenGroups, hasParentPrefix, hasJsOutput); @@ -129,7 +130,7 @@ describe('stylesGenerator', () => { hasJsOutput: true, hasParentPrefix: true, description: 'should generate styles from tokens with js output', - expectedStyles: `export const gridColumns = '12';\n\nexport const gridSpacingDesktop = '32px';`, + expectedStyles: "export const gridColumns = '12';\n\nexport const gridSpacingDesktop = '32px';", }, { tokens: exampleColorsTokens, @@ -137,7 +138,7 @@ describe('stylesGenerator', () => { hasJsOutput: false, hasParentPrefix: false, description: 'should generate styles from tokens with colors', - expectedStyles: `$active: #ca2026 !default;\n\n$primary: #fff !default;`, + expectedStyles: '$active: #ca2026 !default;\n\n$primary: #fff !default;', }, { tokens: exampleColorsTokens, @@ -145,7 +146,7 @@ describe('stylesGenerator', () => { hasJsOutput: true, hasParentPrefix: false, description: 'should generate styles from tokens with colors with js output', - expectedStyles: `export const active = '#ca2026';\n\nexport const primary = '#fff';`, + expectedStyles: "export const active = '#ca2026';\n\nexport const primary = '#fff';", }, { tokens: exampleShadowTokens, @@ -153,7 +154,7 @@ describe('stylesGenerator', () => { hasJsOutput: false, hasParentPrefix: false, description: 'should generate styles from tokens with shadows', - expectedStyles: `$shadow-100: 0 2px 8px 0 #00000026 !default;`, + expectedStyles: '$shadow-100: 0 2px 8px 0 #00000026 !default;', }, { tokens: exampleGradientTokens, @@ -161,7 +162,8 @@ describe('stylesGenerator', () => { hasJsOutput: false, hasParentPrefix: false, description: 'should generate styles from tokens with gradients', - expectedStyles: `$basic-overlay: linear-gradient(var(--gradient-angle, 90deg), #ffffffff 0%, #ffffff00 100%) !default;`, + expectedStyles: + '$basic-overlay: linear-gradient(var(--gradient-angle, 90deg), #ffffffff 0%, #ffffff00 100%) !default;', }, ]; diff --git a/exporters/variables-scss/src/generators/__tests__/stylesObjectGenerator.test.ts b/exporters/variables-scss/src/generators/__tests__/stylesObjectGenerator.test.ts index 05c04ff8b1..2f227aab64 100644 --- a/exporters/variables-scss/src/generators/__tests__/stylesObjectGenerator.test.ts +++ b/exporters/variables-scss/src/generators/__tests__/stylesObjectGenerator.test.ts @@ -1,19 +1,19 @@ import { Token, TokenGroup, TypographyToken } from '@supernovaio/sdk-exporters'; +import { exampleColorsTokens } from '../../../tests/fixtures/exampleColorTokens'; +import { exampleDimensionAndStringTokens } from '../../../tests/fixtures/exampleDimensionAndStringTokens'; +import { exampleGroups } from '../../../tests/fixtures/exampleGroups'; +import { exampleTypographyTokens } from '../../../tests/fixtures/exampleTypographyTokens'; import { colorGroupsReducer, createGlobalColorsObject, + createGlobalTypographyObject, createStylesObjectStructureFromTokenNameParts, - StylesObjectType, generateStylesObjectFromTokens, + handleTypographyTokens, parseGroupName, - createGlobalTypographyObject, + StylesObjectType, typographyGroupReducer, - handleTypographyTokens, } from '../stylesObjectGenerator'; -import { exampleDimensionAndStringTokens } from '../../../tests/fixtures/exampleDimensionAndStringTokens'; -import { exampleColorsTokens } from '../../../tests/fixtures/exampleColorTokens'; -import { exampleTypographyTokens } from '../../../tests/fixtures/exampleTypographyTokens'; -import { exampleGroups } from '../../../tests/fixtures/exampleGroups'; const mappedTokens: Map = new Map([]); const tokenGroups: Array = exampleGroups; @@ -93,10 +93,12 @@ describe('stylesObjectGenerator', () => { moveToTheEnd: 'true', }, headingXlargeBold: { - desktop: `{\nfontFamily: "'Inter', sans-serif",\nfontSize: '64px',\nfontStyle: 'normal',\nfontWeight: 700,\nlineHeight: 1.2,\n}`, + desktop: + "{\nfontFamily: \"'Inter', sans-serif\",\nfontSize: '64px',\nfontStyle: 'normal',\nfontWeight: 700,\nlineHeight: 1.2,\n}", }, headingXlargeBoldUnderline: { - desktop: `{\nfontFamily: "'Inter', sans-serif",\nfontSize: '64px',\nfontStyle: 'normal',\nfontWeight: 700,\nlineHeight: 1.2,\n}`, + desktop: + "{\nfontFamily: \"'Inter', sans-serif\",\nfontSize: '64px',\nfontStyle: 'normal',\nfontWeight: 700,\nlineHeight: 1.2,\n}", }, }, description: 'should generate object from typography tokens with js output', @@ -170,14 +172,17 @@ describe('stylesObjectGenerator', () => { token: exampleTypographyTokens.get('typographyRef1') as Token, expectedObject: { headingXlargeBold: { - desktop: `{\nfontFamily: "'Inter', sans-serif",\nfontSize: '64px',\nfontStyle: 'normal',\nfontWeight: 700,\nlineHeight: 1.2,\n}`, - tablet: `{\nfontFamily: "'Inter', sans-serif",\nfontSize: '32px',\nfontStyle: 'normal',\nfontWeight: 500,\nlineHeight: 1,\n}`, + desktop: + "{\nfontFamily: \"'Inter', sans-serif\",\nfontSize: '64px',\nfontStyle: 'normal',\nfontWeight: 700,\nlineHeight: 1.2,\n}", + tablet: + "{\nfontFamily: \"'Inter', sans-serif\",\nfontSize: '32px',\nfontStyle: 'normal',\nfontWeight: 500,\nlineHeight: 1,\n}", }, }, description: 'should create object structure from typography token with js output', stylesObjectRef: { headingXlargeBold: { - tablet: `{\nfontFamily: "'Inter', sans-serif",\nfontSize: '32px',\nfontStyle: 'normal',\nfontWeight: 500,\nlineHeight: 1,\n}`, + tablet: + "{\nfontFamily: \"'Inter', sans-serif\",\nfontSize: '32px',\nfontStyle: 'normal',\nfontWeight: 500,\nlineHeight: 1,\n}", }, } as StylesObjectType, hasJsOutput: true, @@ -218,7 +223,8 @@ describe('stylesObjectGenerator', () => { expectedStyles: { exampleRef: 'exampleRef', headingXlargeBold: { - desktop: `{\nfontFamily: "'Inter', sans-serif",\nfontSize: '64px',\nfontStyle: 'normal',\nfontWeight: 700,\nlineHeight: 1.2,\n}`, + desktop: + "{\nfontFamily: \"'Inter', sans-serif\",\nfontSize: '64px',\nfontStyle: 'normal',\nfontWeight: 700,\nlineHeight: 1.2,\n}", }, }, description: 'should generate object from typography tokens with js output', diff --git a/exporters/variables-scss/src/helpers/__tests__/tokenHelper.test.ts b/exporters/variables-scss/src/helpers/__tests__/tokenHelper.test.ts index cf50acef2b..1162923c3b 100644 --- a/exporters/variables-scss/src/helpers/__tests__/tokenHelper.test.ts +++ b/exporters/variables-scss/src/helpers/__tests__/tokenHelper.test.ts @@ -1,4 +1,7 @@ import { Token, TokenGroup, TypographyToken } from '@supernovaio/sdk-exporters'; +import { exampleDimensionAndStringTokens } from '../../../tests/fixtures/exampleDimensionAndStringTokens'; +import { exampleGroups } from '../../../tests/fixtures/exampleGroups'; +import { exampleTypographyTokens, expectedTypographyValue } from '../../../tests/fixtures/exampleTypographyTokens'; import { addAngleVarToGradient, addEmptyLineBetweenTokenGroups, @@ -7,9 +10,6 @@ import { tokenVariableName, typographyValue, } from '../tokenHelper'; -import { exampleDimensionAndStringTokens } from '../../../tests/fixtures/exampleDimensionAndStringTokens'; -import { exampleTypographyTokens, expectedTypographyValue } from '../../../tests/fixtures/exampleTypographyTokens'; -import { exampleGroups } from '../../../tests/fixtures/exampleGroups'; const dataProvider = [ { @@ -63,7 +63,7 @@ describe('tokenHelper', () => { const result = formatTokenStyleByOutput(name, value, true, unit); - expect(result).toBe(`export const gridSpacingDesktop = '32px';`); + expect(result).toBe("export const gridSpacingDesktop = '32px';"); }); it('should return the expected formatted token name for js output without unit', () => { @@ -72,7 +72,7 @@ describe('tokenHelper', () => { const result = formatTokenStyleByOutput(name, value, true); - expect(result).toBe(`export const gridColumns = 12;`); + expect(result).toBe('export const gridColumns = 12;'); }); it('should return the expected formatted token for zero values with unit', () => {