From 1667d9b501c8c38c4101ded36c99609a8c864de4 Mon Sep 17 00:00:00 2001 From: jbpenrath Date: Mon, 17 Apr 2023 16:35:12 +0200 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8(tokens)=20add=20scss=20generator?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a Sass generator which generate a scss file declaring colors, font families, weights, sizes and spacings as maps. --- .changeset/pink-fishes-jump.md | 5 ++ packages/tokens/package.json | 2 +- .../src/bin/Generators/SassGenerator.spec.ts | 50 ++++++++++++ .../src/bin/Generators/SassGenerator.ts | 80 +++++++++++++++++++ packages/tokens/src/bin/Generators/index.ts | 2 + .../tokens/src/bin/__mocks__/cunningham.ts | 3 + .../expected-default-cunningham-tokens.css | 1 + .../assets/expected-js-cunningham-tokens.css | 1 + ...with-utility-classes-cunningham-tokens.css | 1 + 9 files changed, 144 insertions(+), 1 deletion(-) create mode 100644 .changeset/pink-fishes-jump.md create mode 100644 packages/tokens/src/bin/Generators/SassGenerator.spec.ts create mode 100644 packages/tokens/src/bin/Generators/SassGenerator.ts diff --git a/.changeset/pink-fishes-jump.md b/.changeset/pink-fishes-jump.md new file mode 100644 index 0000000..7526782 --- /dev/null +++ b/.changeset/pink-fishes-jump.md @@ -0,0 +1,5 @@ +--- +"@openfun/cunningham-tokens": minor +--- + +Add a sass generator diff --git a/packages/tokens/package.json b/packages/tokens/package.json index e976b8e..d0653ec 100644 --- a/packages/tokens/package.json +++ b/packages/tokens/package.json @@ -28,7 +28,7 @@ "build-bin": "cd src/bin && tsc -p tsconfig.json && tsc-alias && chmod +x ../../dist/bin/Main.js", "build-lib": "cp dist/cunningham-tokens.ts src/lib && cd src/lib && tsc -p tsconfig.json", "build": "yarn build-bin && yarn build-default-theme && yarn build-lib && cd ../.. && ln -sf ../../packages/tokens/dist/bin/Main.js node_modules/.bin/cunningham", - "build-default-theme": "./dist/bin/Main.js -o dist -s html -g css,js,ts --utility-classes", + "build-default-theme": "./dist/bin/Main.js -o dist -s html -g scss,css,js,ts --utility-classes", "test": "FORCE_COLOR=1 jest --runInBand --verbose src" }, "dependencies": { diff --git a/packages/tokens/src/bin/Generators/SassGenerator.spec.ts b/packages/tokens/src/bin/Generators/SassGenerator.spec.ts new file mode 100644 index 0000000..a4a82d4 --- /dev/null +++ b/packages/tokens/src/bin/Generators/SassGenerator.spec.ts @@ -0,0 +1,50 @@ +import path from "path"; +import fs from "fs"; +import Config from "Config"; +import { run } from "ThemeGenerator"; +import { cleanup } from "tests/Utils"; + +jest.mock("../Paths", () => ({ + workPath: () => __dirname, +})); + +describe("SassGenerator", () => { + beforeAll(() => { + jest.spyOn(console, "log").mockImplementation(() => {}); + cleanup(__dirname); + }); + + afterEach(() => { + cleanup(__dirname); + }); + + it("generates valid Sass file", async () => { + const sassFile = path.join(__dirname, Config.tokenFilename + ".scss"); + expect(fs.existsSync(sassFile)).toEqual(false); + await run(["", "", "-g", "scss"]); + + expect(fs.existsSync(sassFile)).toEqual(true); + expect(fs.readFileSync(sassFile).toString()).toMatchInlineSnapshot(` + "$colors: ( + primary: #055FD2, + secondary: #DA0000 + ); + $fontFamilies: ( + base: Roboto + ); + $fontSizes: ( + m: 1rem + ); + $fontWeights: ( + medium: 400 + ); + $spacings: ( + s: 1rem + ); + $transitions: ( + ease: linear + ); + " + `); + }); +}); diff --git a/packages/tokens/src/bin/Generators/SassGenerator.ts b/packages/tokens/src/bin/Generators/SassGenerator.ts new file mode 100644 index 0000000..bfc8972 --- /dev/null +++ b/packages/tokens/src/bin/Generators/SassGenerator.ts @@ -0,0 +1,80 @@ +import path from "path"; +import { Generator } from "Generators/index"; +import Config from "Config"; +import { put } from "Utils/Files"; +import { Tokens } from "TokensGenerator"; + +export const sassGenerator: Generator = async (tokens, opts) => { + const sassContent = generateSassMaps(tokens); + const outputPath = path.join(opts.path, Config.tokenFilename + ".scss"); + put(outputPath, sassContent); +}; + +const generateSassMaps = (tokens: Tokens) => { + return [ + generateColorsSassMap(tokens), + generateFontSassMap(tokens), + generateSpacingsSassMap(tokens), + generateTransitionsSassMap(tokens), + ].join("\n"); +}; + +// Generate colors sass map with the ability to create sub map +// for a color with shades. +// Example: `primary-500: #000` will return `primary: (500: #000)` +const generateColorsSassMap = (tokens: Tokens) => { + const colors = Object.entries(tokens.theme.colors).reduce( + propertiesReducer, + {} + ); + + return `$colors: ${JSONToSassMap(colors)};`; +}; +const generateFontSassMap = (tokens: Tokens) => { + return [ + generateFontFamiliesSassMap(tokens), + generateFontSizesSassMap(tokens), + generateFontWeightsSassMap(tokens), + ].join("\n"); +}; +const generateFontFamiliesSassMap = (tokens: Tokens) => { + return `$fontFamilies: ${JSONToSassMap(tokens.theme.font.families)};`; +}; +const generateFontSizesSassMap = (tokens: Tokens) => { + return `$fontSizes: ${JSONToSassMap(tokens.theme.font.sizes)};`; +}; +const generateFontWeightsSassMap = (tokens: Tokens) => { + return `$fontWeights: ${JSONToSassMap(tokens.theme.font.weights)};`; +}; +const generateSpacingsSassMap = (tokens: Tokens) => { + return `$spacings: ${JSONToSassMap(tokens.theme.spacings)};`; +}; + +const generateTransitionsSassMap = (tokens: Tokens) => { + return `$transitions: ${JSONToSassMap(tokens.theme.transitions)};`; +}; + +function JSONToSassMap(json: Object) { + return JSON.stringify(json, null, 2) + .replace(/{/g, "(") + .replace(/}/g, ")") + .replace(/"/g, ""); +} + +function propertiesReducer( + propertyMap: Record>, + [key, value]: [string, string] +) { + const [property, subProperty] = key.split("-"); + + if (subProperty) { + if (propertyMap[property] === undefined) { + propertyMap[property] = {}; + } + (propertyMap[property] as Record)[subProperty] = value; + } else { + propertyMap[property] = value; + } + + return propertyMap; +} diff --git a/packages/tokens/src/bin/Generators/index.ts b/packages/tokens/src/bin/Generators/index.ts index 66d6a80..b771289 100644 --- a/packages/tokens/src/bin/Generators/index.ts +++ b/packages/tokens/src/bin/Generators/index.ts @@ -1,4 +1,5 @@ import { cssGenerator } from "Generators/CssGenerator"; +import { sassGenerator } from "Generators/SassGenerator"; import { jsGenerator } from "Generators/JsGenerator"; import { Tokens } from "TokensGenerator"; import { tsGenerator } from "Generators/TsGenerator"; @@ -9,6 +10,7 @@ export type Generator = ( ) => Promise; export const Generators: Record = { + scss: sassGenerator, css: cssGenerator, js: jsGenerator, ts: tsGenerator, diff --git a/packages/tokens/src/bin/__mocks__/cunningham.ts b/packages/tokens/src/bin/__mocks__/cunningham.ts index 73a7980..cc7d0e6 100644 --- a/packages/tokens/src/bin/__mocks__/cunningham.ts +++ b/packages/tokens/src/bin/__mocks__/cunningham.ts @@ -18,5 +18,8 @@ module.exports = { spacings: { s: "1rem", }, + transitions: { + ease: "linear", + }, }, }; diff --git a/packages/tokens/src/bin/tests/assets/expected-default-cunningham-tokens.css b/packages/tokens/src/bin/tests/assets/expected-default-cunningham-tokens.css index 913f10b..0238bb9 100644 --- a/packages/tokens/src/bin/tests/assets/expected-default-cunningham-tokens.css +++ b/packages/tokens/src/bin/tests/assets/expected-default-cunningham-tokens.css @@ -5,4 +5,5 @@ --c--theme--font--weights--medium: 400; --c--theme--font--families--base: Roboto; --c--theme--spacings--s: 1rem; + --c--theme--transitions--ease: linear; } diff --git a/packages/tokens/src/bin/tests/assets/expected-js-cunningham-tokens.css b/packages/tokens/src/bin/tests/assets/expected-js-cunningham-tokens.css index 3a609a1..b758474 100644 --- a/packages/tokens/src/bin/tests/assets/expected-js-cunningham-tokens.css +++ b/packages/tokens/src/bin/tests/assets/expected-js-cunningham-tokens.css @@ -5,4 +5,5 @@ --c--theme--font--weights--medium: 400; --c--theme--font--families--base: Roboto; --c--theme--spacings--s: 1rem; + --c--theme--transitions--ease: linear; } diff --git a/packages/tokens/src/bin/tests/assets/expected-with-utility-classes-cunningham-tokens.css b/packages/tokens/src/bin/tests/assets/expected-with-utility-classes-cunningham-tokens.css index c99e73d..9fad28e 100644 --- a/packages/tokens/src/bin/tests/assets/expected-with-utility-classes-cunningham-tokens.css +++ b/packages/tokens/src/bin/tests/assets/expected-with-utility-classes-cunningham-tokens.css @@ -5,6 +5,7 @@ --c--theme--font--weights--medium: 400; --c--theme--font--families--base: Roboto; --c--theme--spacings--s: 1rem; + --c--theme--transitions--ease: linear; } .clr-primary { color: var(--c--theme--colors--primary); } .clr-secondary { color: var(--c--theme--colors--secondary); } .bg-primary { background-color: var(--c--theme--colors--primary); }